From 832d3e20554fe3a0fd718f68bd273bc96bb0f3fa Mon Sep 17 00:00:00 2001 From: HerrHase Date: Sun, 12 Feb 2023 14:49:54 +0100 Subject: [PATCH] adding --- README.md | 202 +----------------- example/site/_images/test.jpeg | Bin 67258 -> 0 bytes example/site/about.md | 17 -- example/site/blog.md | 6 - example/site/index.md | 21 -- example/site/json.yml | 6 - example/site/post.md | 11 - example/site/post2.md | 13 -- example/site/recipes/index.md | 7 - .../site/recipes/noodles/_blocks/hero-1.md | 1 - .../site/recipes/noodles/_blocks/hero-2.md | 1 - example/site/recipes/noodles/index.md | 7 - example/site/rss.md | 5 - example/site/site.yml | 5 - example/views/blog.njk | 15 -- example/views/helpers/meta.njk | 30 --- example/views/layout.njk | 54 ----- example/views/page.njk | 5 - example/views/post.njk | 5 - example/views/rss.njk | 51 ----- index.js | 4 +- package.json | 29 +-- ressources/_blocks/block-1.md | 14 -- ressources/_blocks/block-2.md | 14 -- ressources/default.md | 17 -- src/config.js | 52 ----- src/engines/helpers.js | 53 ----- src/engines/nunjucks.js | 99 --------- src/factories/block.js | 49 ----- src/factories/media.js | 99 --------- src/factories/page.js | 111 ---------- src/factories/sitemap.js | 111 ---------- src/parsers/markdown.js | 42 ---- src/parsers/yaml.js | 25 --- src/queries/blocks.js | 130 ----------- src/queries/pages.js | 188 ---------------- src/siteomat.js | 118 ---------- test.js | 8 - test/blocks.js | 24 --- test/parserMarkdown.js | 41 ---- 40 files changed, 11 insertions(+), 1679 deletions(-) delete mode 100644 example/site/_images/test.jpeg delete mode 100644 example/site/about.md delete mode 100644 example/site/blog.md delete mode 100644 example/site/index.md delete mode 100644 example/site/json.yml delete mode 100644 example/site/post.md delete mode 100644 example/site/post2.md delete mode 100644 example/site/recipes/index.md delete mode 100644 example/site/recipes/noodles/_blocks/hero-1.md delete mode 100644 example/site/recipes/noodles/_blocks/hero-2.md delete mode 100644 example/site/recipes/noodles/index.md delete mode 100644 example/site/rss.md delete mode 100644 example/site/site.yml delete mode 100644 example/views/blog.njk delete mode 100644 example/views/helpers/meta.njk delete mode 100644 example/views/layout.njk delete mode 100644 example/views/page.njk delete mode 100644 example/views/post.njk delete mode 100644 example/views/rss.njk delete mode 100644 ressources/_blocks/block-1.md delete mode 100644 ressources/_blocks/block-2.md delete mode 100644 ressources/default.md delete mode 100644 src/config.js delete mode 100644 src/engines/helpers.js delete mode 100644 src/engines/nunjucks.js delete mode 100644 src/factories/block.js delete mode 100644 src/factories/media.js delete mode 100644 src/factories/page.js delete mode 100644 src/factories/sitemap.js delete mode 100644 src/parsers/markdown.js delete mode 100644 src/parsers/yaml.js delete mode 100644 src/queries/blocks.js delete mode 100644 src/queries/pages.js delete mode 100644 src/siteomat.js delete mode 100644 test.js delete mode 100644 test/blocks.js delete mode 100644 test/parserMarkdown.js diff --git a/README.md b/README.md index 5cb429f..3c544d7 100644 --- a/README.md +++ b/README.md @@ -1,39 +1,20 @@ # Site-O-Mat Webpack Plugin -A Webpack Plugin for generating a Website as Html-Files from a Markdown-File Structure. - -Why? The Main reason i had to update some Websites, but realize there were no benefit -to use a Full CMS or Headless CMS like Directus. Rendering the same pages that a rarely updated -seems like a waste of energy. Why not generate from a hierarchical file structure. Luckily i -i had development a CMS, a few years ago, that runs on Markdown Files it had been never -finished, it was a proof of concept. - -## Roadmap - -Next will be, - -* Some Tests -* Filtering for Queries -* Standalone, handle Webpack only as wrapper - -Maybe later, - -* Integrate Eta.js and LiquidJS -* Hooks for handle generic content +A Webpack Plugin that wraps [@site-o-mat/core](https://gitea.node001.net/site-o-mat/core). ## Installation Setup this registry in your project .npmrc file: ``` -@helpers:registry=https://gitea.node001.net/api/packages/HerrHase/npm/ +@helpers:registry=https://gitea.node001.net/api/packages/site-o-mat/npm/ ``` Install with npm or yarn ``` -npm i --save-dev @helpers/siteomat-webpack-plugin -yarn add --dev @helpers/siteomat-webpack-plugin +npm i --save-dev @site-o-mat/webpack-plugin +yarn add --dev @site-o-mat/webpack-plugin ``` ## Configuration @@ -41,7 +22,7 @@ yarn add --dev @helpers/siteomat-webpack-plugin Basic Usage: ``` -const SiteomatWebpackPlugin = require('siteomat-webpack-plugin') +const SiteomatWebpackPlugin = require('@site-o-mat/webpack-plugin') plugins: [ new SiteomatWebpackPlugin( @@ -64,176 +45,3 @@ plugins: [ ) ] ``` - -| Name | Type | Default | Description | -|-------------|-----------|---------|-------------| -| destination | {String} | null | If not set, it will use the public path | -| htmlMinify | {Boolean} | true | Minify Html and remove all Whitespace | - -## Pages - -Pages are Markdown-Files, they are separates in two parts. First part is a yaml-Section, - -``` ---- -title: "health goth DIY tattooed" -view: "home.njk" -meta: - description: "La" -media: - teaser: - src: "_images/test.jpeg" - alt: "cold-pressed" ---- -``` - -The yaml-Section will be parsed as an Object and available in the Templates. The -second part of the File will be parsed as Markdown, but it could be also empty. - -Default type for Pages is **html**. - -## Nesting - -A Page can be a single Markdown-File, or a Directory with a index-File inside. -The Name of a file or a directory will the name of the html-File. To create Sub-pages, -create Sub-directories. - -This Structure, - -``` -index.md -about-me.md -blog -└ index.md - belly-polaroid-subway.md -``` - -will be, - -``` -index.html -about-me.html -blog.html -blog/belly-polaroid-subway.html -``` - -## Blocks - -Each Page can have Blocks. Blocks are like Pages, but they are only accessible -for a single Page. To add Blocks to a page, add a "_blocks"-Directory -to the Directory of the Page. - -Markdown-Files in a "_blocks"-Directory will be automatic accessible for a Page. The yaml-Section is Optional. - -``` -recipes -└ index.md - _blocks - └ hero-1.md - hero-2.md - hero-3.md -``` - -Blocks will be Grouped by there name, and sorted by the number at the end. The "hero"-Files -can be used like this, - -``` -{% hero in page.blocks.hero %} - {{ hero.content }} -{% endFor %} -``` - -## Queries - -Queries can be used in Templates to get Pages. - -### Pages - -Basic Usage: - -``` -pageQuery.find() -``` - -or with options, - -| Name | Type | Default | Description | -|-------------|-----------|---------|-------------| -| parent | {String} | / | Directory for start query | -| deep | {Integer} | -1 | Deep of Recursive | -| orderBy | {Array} | null | Name of field sorting, a "-" in front of the. Nested fields are also possible. | -| limit | {Integer} | null | Limit results | -| filter | {Object} | null | Filtering results by Fields in yaml | - -#### Filter - -Basic Usage: - -``` -{ - : { - : - } -} -``` - -| Name | Description | -|-------------|-------------| -| _eq | Equal Value | - -## Sitemap - -Sitemap will be generating by Pages. Pages will be only add to Sitemap, if the have meta-robots is set -to "index". Pages default is "index". - -## Templates - -At this Time only [https://mozilla.github.io/nunjucks/](Nunjunks) is used for Templating. - -### Nunjunks - -#### Functions - -##### asset(path) - -This function handle manifest-File from [https://laravel-mix.com/](Laravel-Mix). - -``` - -``` - -#### Filters - -##### resize - -The Filter is using [https://github.com/lovell/sharp](sharp), for crop, resize and -optimize Images. The Filter needs a relative Path in the File Structure. - -Basic Usage: - -``` -{% page.teaser.src | resize({ 'width': '300' }) %} -``` - -Add options: - -``` -{% page.teaser.src | resize({ 'width': '300' }, { sigma: 2 }) %} -``` - -## Json - -Results from PageQuery can also be created as json-File. The can use with a -simple API [https://gitea.node001.net/HerrHase/siteomat-api](https://gitea.node001.net/HerrHase/siteomat-api). Create a -File "json.yml" and add options. - -Basic Usage: - -``` -posts: - orderBy: - - '-date_published' - filter: - view: - _eq: 'post.njk' -``` diff --git a/example/site/_images/test.jpeg b/example/site/_images/test.jpeg deleted file mode 100644 index 028d66e4a881b7c9c3dc9d4db84500c95a86c2cf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 67258 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 Hd<{09ct@J=)D=*s< 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 -

- {{ post.title }} -

- -{% endfor %} - -{% endblock %} diff --git a/example/views/helpers/meta.njk b/example/views/helpers/meta.njk deleted file mode 100644 index 362b7dc..0000000 --- a/example/views/helpers/meta.njk +++ /dev/null @@ -1,30 +0,0 @@ -{# handle meta in templates #} - -{% macro meta(page, site) %} - {% if (page.meta) %} - - {% set hasCannocial = false %} - - {% for key, content in page.meta %} - - - {# check for index in robots if set page has canonical #} - {% if (key === 'robots' and content.indexOf('index') !== -1 and content.indexOf('noindex') === -1) %} - {% set hasCannocial = true %} - {% endif %} - {% endfor %} - - {# check if page has canonical #} - {% if (hasCannocial) %} - {% set http = 'http' %} - - {% if (site.https) %} - {% set http = site.https %} - {% endif %} - - - - {% endif %} - - {% endif %} -{% endmacro %} \ No newline at end of file diff --git a/example/views/layout.njk b/example/views/layout.njk deleted file mode 100644 index 2222f58..0000000 --- a/example/views/layout.njk +++ /dev/null @@ -1,54 +0,0 @@ -{% import "helpers/meta.njk" as helpers %} - - - - - - - {{ site.title }} | {{ page.title }} - - - {{ helpers.meta(page, site) }} - - - - - {% block addHead %}{% endblock %} - - - - - - -
-
-
-
- {% block main %}{% endblock %} -
-
-
-
- -
-
-
-
- MIT License -
-
-
-
- - - {% block addFooter %}{% endblock %} - - \ No newline at end of file diff --git a/example/views/page.njk b/example/views/page.njk deleted file mode 100644 index e3728e2..0000000 --- a/example/views/page.njk +++ /dev/null @@ -1,5 +0,0 @@ -{% extends('layout.njk') %} - -{% block main %} -{{ page.content | safe }} -{% endblock %} \ No newline at end of file diff --git a/example/views/post.njk b/example/views/post.njk deleted file mode 100644 index e3728e2..0000000 --- a/example/views/post.njk +++ /dev/null @@ -1,5 +0,0 @@ -{% extends('layout.njk') %} - -{% block main %} -{{ page.content | safe }} -{% endblock %} \ No newline at end of file diff --git a/example/views/rss.njk b/example/views/rss.njk deleted file mode 100644 index fd6b357..0000000 --- a/example/views/rss.njk +++ /dev/null @@ -1,51 +0,0 @@ -{% set posts = pageQuery.find({ orderBy: [ '-date_published' ], limit: 10, filter: { view: { _eq: 'post.njk' } } }) %} -{% set http = 'http' %} -{% if (site.https) %} - {% set http = 'https' %} -{% endif %} - - - - {{ site.title }} - - {{ http }}://{{ site.domain }} - - {% if site.description %} - {{ site.description }} - {% endif %} - - {{ dayjs() }} - {{ site.language }}-{{ site.language | upper }} - hourly - 1 - https://gitea.node001.net/HerrHase/siteomat-webpack-plugin - {% for post in posts %} - - {{ post.title }} - {{ http }}://{{ site.domain }}{{ post.path }} - {{ dayjs(post.date_published) }} - - {% if post.excerpt %} - - {{ post.excerpt }} - - {% endif %} - - - - - - {{ http }}://{{ site.domain }}{{ post.path }} - - {% endfor %} - - diff --git a/index.js b/index.js index c0fa109..ecaae62 100644 --- a/index.js +++ b/index.js @@ -1,4 +1,4 @@ -const Siteomat = require('./src/siteomat.js') +const Siteomat = require('@site-o-mat/core') const fs = require('fs') /** @@ -48,4 +48,4 @@ class SiteomatWebpackPlugin { } } -module.exports = SiteomatWebpackPlugin \ No newline at end of file +module.exports = SiteomatWebpackPlugin diff --git a/package.json b/package.json index 4867d4d..c69d6c9 100644 --- a/package.json +++ b/package.json @@ -1,36 +1,15 @@ { - "name": "@helpers/siteomat-webpack-plugin", - "version": "0.5.0", + "name": "@site-o-mat/webpack-plugin", + "version": "0.1.0", "build": "webpack", "author": "Björn Hase ", "main": "index.js", "repository": { "type": "git", - "url": "git@gitea.node001.net:HerrHase/siteomat-webpack-plugin.git" - }, - "scripts": { - "test": "mocha" + "url": "git@gitea.node001.net:site-o-mat/webpack-plugin.git" }, "description": "A Webpack Plugin for generating a Website as Html-Files from a Markdown File Structure", "dependencies": { - "@helpers/siteomat-query": "^0.1.0", - "assign-deep": "^1.0.1", - "crypto": "^1.0.1", - "dayjs": "^1.11.6", - "fast-xml-parser": "^4.0.11", - "html-minifier": "^4.0.0", - "js-yaml": "^4.1.0", - "lodash.merge": "^4.6.2", - "lodash.orderby": "^4.6.0", - "marked": "^4.1.1", - "mkdirp": "^1.0.4", - "nunjucks": "^3.2.3", - "sharp": "^0.31.1", - "slugify": "^1.6.5", - "yaml": "^2.1.3" - }, - "devDependencies": { - "chai": "^4.3.7", - "mocha": "^10.2.0" + "@site-o-mat/core": "^0.1.0" } } diff --git a/ressources/_blocks/block-1.md b/ressources/_blocks/block-1.md deleted file mode 100644 index e149f96..0000000 --- a/ressources/_blocks/block-1.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: "health goth DIY tattooed" ---- -## Normcore cold-pressed ramps DSA - -Normcore cold-pressed ramps DSA yes plz hot chicken green juice succulents leggings messenger bag truffaut iceland pabst ethical godard. Semiotics air plant marfa, drinking vinegar authentic iceland pug fit cloud bread cronut kickstarter glossier crucifix tumeric. Chicharrones polaroid flexitarian, seitan lumbersexual viral fam master cleanse four dollar toast scenester. Succulents poutine vegan keffiyeh meh, health goth DIY tattooed. Praxis roof party celiac chartreuse banjo butcher you probably haven't heard of them schlitz beard. Ethical tattooed kinfolk, cliche vegan messenger bag mukbang dreamcatcher cloud bread farm-to-table gatekeep trust fund. - -## Palo santo leggings normcore aesthetic - -bicycle rights sartorial godard slow-carb thundercats art party cray JOMO. Truffaut four dollar toast hoodie pour-over. Fanny pack iPhone jean shorts tote bag, master cleanse succulents tbh fixie gatekeep pok pok letterpress cornhole. Dreamcatcher tattooed hot chicken gatekeep, glossier salvia 8-bit cred. Fit lomo chillwave cold-pressed humblebrag narwhal. Meggings edison bulb fanny pack irony af pug pok pok whatever vexillologist vibecession cred butcher trust fund chia. - -## Bitters kale chips chambray activated charcoal - -wolf keffiyeh hell of selfies. Wolf readymade shoreditch flexitarian venmo single-origin coffee, knausgaard fit actually street art cold-pressed iPhone gatekeep. Migas bruh adaptogen semiotics marfa pickled yuccie. Locavore normcore lomo, shoreditch fashion axe actually glossier iPhone photo booth blue bottle DIY XOXO williamsburg. Pinterest whatever taxidermy, kale chips prism XOXO schlitz twee tote bag woke swag. Wayfarers fashion axe heirloom humblebrag synth. Whatever succulents PBR&B, pop-up enamel pin echo park tonx stumptown taiyaki. diff --git a/ressources/_blocks/block-2.md b/ressources/_blocks/block-2.md deleted file mode 100644 index e149f96..0000000 --- a/ressources/_blocks/block-2.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: "health goth DIY tattooed" ---- -## Normcore cold-pressed ramps DSA - -Normcore cold-pressed ramps DSA yes plz hot chicken green juice succulents leggings messenger bag truffaut iceland pabst ethical godard. Semiotics air plant marfa, drinking vinegar authentic iceland pug fit cloud bread cronut kickstarter glossier crucifix tumeric. Chicharrones polaroid flexitarian, seitan lumbersexual viral fam master cleanse four dollar toast scenester. Succulents poutine vegan keffiyeh meh, health goth DIY tattooed. Praxis roof party celiac chartreuse banjo butcher you probably haven't heard of them schlitz beard. Ethical tattooed kinfolk, cliche vegan messenger bag mukbang dreamcatcher cloud bread farm-to-table gatekeep trust fund. - -## Palo santo leggings normcore aesthetic - -bicycle rights sartorial godard slow-carb thundercats art party cray JOMO. Truffaut four dollar toast hoodie pour-over. Fanny pack iPhone jean shorts tote bag, master cleanse succulents tbh fixie gatekeep pok pok letterpress cornhole. Dreamcatcher tattooed hot chicken gatekeep, glossier salvia 8-bit cred. Fit lomo chillwave cold-pressed humblebrag narwhal. Meggings edison bulb fanny pack irony af pug pok pok whatever vexillologist vibecession cred butcher trust fund chia. - -## Bitters kale chips chambray activated charcoal - -wolf keffiyeh hell of selfies. Wolf readymade shoreditch flexitarian venmo single-origin coffee, knausgaard fit actually street art cold-pressed iPhone gatekeep. Migas bruh adaptogen semiotics marfa pickled yuccie. Locavore normcore lomo, shoreditch fashion axe actually glossier iPhone photo booth blue bottle DIY XOXO williamsburg. Pinterest whatever taxidermy, kale chips prism XOXO schlitz twee tote bag woke swag. Wayfarers fashion axe heirloom humblebrag synth. Whatever succulents PBR&B, pop-up enamel pin echo park tonx stumptown taiyaki. diff --git a/ressources/default.md b/ressources/default.md deleted file mode 100644 index 997e599..0000000 --- a/ressources/default.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: "health goth DIY tattooed" -view: "page.njk" -meta: - description: "DSA yes plz hot chicken green juice" ---- -## Normcore cold-pressed ramps DSA - -Normcore cold-pressed ramps DSA yes plz hot chicken green juice succulents leggings messenger bag truffaut iceland pabst ethical godard. Semiotics air plant marfa, drinking vinegar authentic iceland pug fit cloud bread cronut kickstarter glossier crucifix tumeric. Chicharrones polaroid flexitarian, seitan lumbersexual viral fam master cleanse four dollar toast scenester. Succulents poutine vegan keffiyeh meh, health goth DIY tattooed. Praxis roof party celiac chartreuse banjo butcher you probably haven't heard of them schlitz beard. Ethical tattooed kinfolk, cliche vegan messenger bag mukbang dreamcatcher cloud bread farm-to-table gatekeep trust fund. - -## Palo santo leggings normcore aesthetic - -bicycle rights sartorial godard slow-carb thundercats art party cray JOMO. Truffaut four dollar toast hoodie pour-over. Fanny pack iPhone jean shorts tote bag, master cleanse succulents tbh fixie gatekeep pok pok letterpress cornhole. Dreamcatcher tattooed hot chicken gatekeep, glossier salvia 8-bit cred. Fit lomo chillwave cold-pressed humblebrag narwhal. Meggings edison bulb fanny pack irony af pug pok pok whatever vexillologist vibecession cred butcher trust fund chia. - -## Bitters kale chips chambray activated charcoal - -wolf keffiyeh hell of selfies. Wolf readymade shoreditch flexitarian venmo single-origin coffee, knausgaard fit actually street art cold-pressed iPhone gatekeep. Migas bruh adaptogen semiotics marfa pickled yuccie. Locavore normcore lomo, shoreditch fashion axe actually glossier iPhone photo booth blue bottle DIY XOXO williamsburg. Pinterest whatever taxidermy, kale chips prism XOXO schlitz twee tote bag woke swag. Wayfarers fashion axe heirloom humblebrag synth. Whatever succulents PBR&B, pop-up enamel pin echo park tonx stumptown taiyaki. diff --git a/src/config.js b/src/config.js deleted file mode 100644 index ef28012..0000000 --- a/src/config.js +++ /dev/null @@ -1,52 +0,0 @@ -/** - * ConfigStore - * - * - * - * @author Björn Hase - * @license http://opensource.org/licenses/MIT The MIT License - * @link https://gitea.node001.net/HerrHase/siteomat-webpack-plugin.git - * - */ -class ConfigStore { - - constructor() { - if (!ConfigStore.instance) { - ConfigStore.instance = this; - this._data = {} - } - - return ConfigStore.instance; - } - - /** - * set value by key - * - * @param {String} key - * @param {String|Object} value - * - */ - set(key, value) { - this._data[key] = value - } - - /** - * get value by key - * - * @param {String} key - * @return {String|Object} - */ - get(key) { - - if (!this._data?.[key]) { - throw new Error(key + ' not found in ConfigStore!') - } - - return this._data[key] - } -} - -// create instance -const instance = new ConfigStore(); - -module.exports = instance \ No newline at end of file diff --git a/src/engines/helpers.js b/src/engines/helpers.js deleted file mode 100644 index fba26db..0000000 --- a/src/engines/helpers.js +++ /dev/null @@ -1,53 +0,0 @@ -const path = require('path') -const fs = require('fs') - -const Media = require('./../factories/media.js') - -/** - * asset - checks manifest.json for given path and return - * file path with id for cache busting - * - * - * @param {String} publicPath - * - */ - -function asset(staticPath) { - - // getting basePath - let result = staticPath - - // path to mix-manifest - const file = path.join(path.resolve()) + 'mix-manifest.json' - - if (fs.existsSync(file)) { - - const manifest = fs.readFileSync(file) - const files = JSON.parse(manifest) - - if (files[staticPath]) { - result = files[staticPath] - } - } - - return result -} - -/** - * asset - checks manifest.json for given path and return - * file path with id for cache busting - * - * - * @param {String} publicPath - * - */ - -async function resize(src, sizes, options, done) -{ - const media = new Media() - - src = await media.resize(src, sizes, options) - done(null, src) -} - -module.exports = { asset, resize } \ No newline at end of file diff --git a/src/engines/nunjucks.js b/src/engines/nunjucks.js deleted file mode 100644 index aaccfd8..0000000 --- a/src/engines/nunjucks.js +++ /dev/null @@ -1,99 +0,0 @@ -const nunjucks = require('nunjucks') -const fs = require('fs') -const assign = require('assign-deep') -const { minify } = require('html-minifier') - -const configStore = require('./../config.js') -const { asset, resize } = require('./helpers.js') -const PageQuery = require('./../queries/pages.js') -const dayjs = require('dayjs') - -/** - * nunjucks - * - * - * @author Björn Hase - * @license http://opensource.org/licenses/MIT The MIT License - * @link https://gitea.node001.net/HerrHase/siteomat-webpack-plugin.git - * - */ -class Engine { - - /** - * - * - * @param {string} views - * @param {object} site - * @param {object} options - * - */ - constructor(views, site, options) { - - // merge data - this._options = assign({}, { - autoescapes: true, - throwOnUndefined: true - }, options) - - this.nunjucks = nunjucks.configure(views, this._options) - - // add filter: resize - this.nunjucks.addFilter('resize', (...args) => { - const done = args.pop() - const options = args?.[2] ? {} : args[2] - - resize(args[0], args[1], options, done) - }, true) - - // adding defaults for view, data from site.yml, functions and pageQuery - this._defaults = { - site: site, - asset: asset, - dayjs: dayjs, - pageQuery: new PageQuery(configStore.get('source')) - } - } - - /** - * render - * - * @param {object} page - * @param {function} done - * - */ - render(page, done) { - - // merge data - const data = assign({ - page: page - }, this._defaults) - - this.nunjucks.render(data.page.view, data, (error, response) => { - - if (error) { - console.error(error) - } - - const options = configStore.get('options') - - // if options minifyHtml is set, minify html, but only if page has type html - if (options.minifyHtml === true && data.page.type === 'html') { - response = minify(response, { - removeComments: true, - collapseWhitespace: true, - keepClosingSlash: true, - removeOptionalTags: false - }) - - // remove empty lines - } else { - response = response.replace(/^(?:[\t ]*(?:\r?\n|\r))+/gm, '') - } - - done(error, response) - }) - } - -} - -module.exports = Engine \ No newline at end of file diff --git a/src/factories/block.js b/src/factories/block.js deleted file mode 100644 index 4234165..0000000 --- a/src/factories/block.js +++ /dev/null @@ -1,49 +0,0 @@ -const path = require('path') -const parseMarkdownFile = require('./../parsers/markdown.js') - -const assign = require('assign-deep') - -/** - * Block - * - * parsed markdown-file that can - * contains fields as yaml - * - * @author Björn Hase - * @license http://opensource.org/licenses/MIT The MIT License - * @link https://gitea.node001.net/HerrHase/siteomat-webpack-plugin.git - * - */ - -class Block { - - /** - * - * - * @param {string} fileString - * - */ - constructor(fileString) { - - // parse string of file - const parsedFile = parseMarkdownFile(fileString) - - // getting parsed data - this._content = parsedFile.content - this._fields = parsedFile.fields - } - - /** - * - * - * @return {object} - * - */ - get() { - return assign({ - 'content': this._content - }, this._fields) - } -} - -module.exports = Block \ No newline at end of file diff --git a/src/factories/media.js b/src/factories/media.js deleted file mode 100644 index 9fe420f..0000000 --- a/src/factories/media.js +++ /dev/null @@ -1,99 +0,0 @@ -const path = require('path') -const fs = require('fs') -const sharp = require('sharp') -const mkdirp = require('mkdirp') -const crypto = require('crypto') -const slugify = require('slugify') - -const configStore = require('./../config.js') - -/** - * - * - */ -class Media { - - constructor() { - this._DIR_ASSETS = '/assets/' - } - - /** - * - * @param {string} src - * @param {object} sizes - * @param {Object} [options={}] - * @return {string} - * - */ - async resize(src, sizes, options = {}) { - - this._extension = path.extname(src) - this._filename = slugify(path.basename(src, this._extension)) - - this._process = await sharp(configStore.get('source') + '/' + src) - - // resize without options and with options - if (Object.getOwnPropertyNames(options).length === 0) { - await this._process - .resize(sizes) - } else { - this._process - .resize(sizes, options) - } - - // optimize - this._optimize() - - const fileBuffer = await this._process - .toBuffer() - - const relativeDestinationPath = this._DIR_ASSETS + this._resolveRelativeDestinationPath(fileBuffer) - - // create directories and write file - mkdirp.sync(configStore.get('destination') + relativeDestinationPath) - fs.writeFileSync(configStore.get('destination') + relativeDestinationPath + '/' + this._filename + this._extension, fileBuffer) - - return relativeDestinationPath + '/' + this._filename + this._extension - } - - /** - * @TODO much nicer to add a hook system so behavior can be change - * - * - * @param {string} extension - * - */ - _optimize() { - if (this._extension === '.gif') { - this._process - .gif({ - reoptimise: true - }) - } else { - - // change extension - this._extension = '.webp' - this._process - .webp({ - lossless: true - }) - } - } - - /** - * resolve path to write file, hash will be get = fileBuffer and - * - * - * @param {object} fileBuffer - * @return {string} - * - */ - _resolveRelativeDestinationPath(fileBuffer) { - const hash = crypto.createHash('sha1') - hash.update(fileBuffer) - - return hash.digest('hex').match(new RegExp('.{1,8}', 'g')).join('/') - } -} - -module.exports = Media \ No newline at end of file diff --git a/src/factories/page.js b/src/factories/page.js deleted file mode 100644 index 814eaf3..0000000 --- a/src/factories/page.js +++ /dev/null @@ -1,111 +0,0 @@ -const path = require('path') -const slugify = require('slugify') -const merge = require('lodash.merge') -const nunjucks = require('nunjucks') -const assign = require('assign-deep') - -const parseMarkdownFile = require('./../parsers/markdown.js') - -/** - * Page - * - * - * @author Björn Hase - * @license http://opensource.org/licenses/MIT The MIT License - * @link https://gitea.node001.net/HerrHase/siteomat-webpack-plugin.git - * - */ - -class Page { - - /** - * - * - * @param {object} file - * @param {string} parent - * @param {string} fileString - * @param {object} [blocks=null] - * - */ - constructor(file, parent, fileString, blocks = {}) { - - // parse file - const result = parseMarkdownFile(fileString) - - // fields merge by default values - this._fields = merge({ - view: 'page.njk', - type: 'html', - meta: { - robots: 'index' - } - }, result.fields) - - // adding filename for html as pathname and relative path in structure - this._filename = this._resolveFilename(file) - this._pathname = this._resolvePathname(parent) - - this._content = result.content - this._blocks = blocks - } - - /** - * create Page Object - * - * - * @return {object} - * - */ - get() { - return assign({ - 'content' : this._content, - 'blocks' : this._blocks, - 'path' : this._pathname + '/' + this._filename, - 'filename' : this._filename, - 'pathname' : this._pathname - }, this._fields) - } - - /** - * create html-filename = filename - * - * @param {string} file - * @return {string} - * - */ - _resolveFilename(file) { - - let filename = file.name - - if (filename === 'index.md') { - filename = 'index' - } else { - if (path.extname(filename) === '.md') { - filename = filename.replace('.md', '') - } - - filename = slugify(filename) - } - - return filename + '.' + this._fields.type - } - - /** - * pathname = parent - * - * @param {string} parent - * @return {string} - * - */ - _resolvePathname(parent) { - let pathname = parent - - if (parent === '/') { - pathname = '' - } - - return pathname - } -} - -module.exports = Page \ No newline at end of file diff --git a/src/factories/sitemap.js b/src/factories/sitemap.js deleted file mode 100644 index 1fd12f7..0000000 --- a/src/factories/sitemap.js +++ /dev/null @@ -1,111 +0,0 @@ -const { XMLParser, XMLBuilder, XMLValidator} = require('fast-xml-parser') -const dayjs = require('dayjs') - -/** - * - * - * @author Björn Hase - * @license http://opensource.org/licenses/MIT The MIT License - * @link https://gitea.node001.net/HerrHase/siteomat-webpack-plugin.git - * - */ -class Sitemap { - - /** - * - * - * @param {[type]} site - * @param {[type]} pages - * - */ - constructor(site) { - this._site = site - this._urls = [] - } - - /** - * adding page to urls of sitemap, check if page is valid for sitemap - * - * @param {object} page - * - */ - addPage(page) { - if (this._isValid(page)) { - this._urls.push({ - loc: 'https://' + this._site.domain + page.pathname + '/' + page.filename, - lastmod: dayjs().format() - }) - } - } - - /** - * get xml as string - * - * @return {string} - * - */ - getXmlAsString() { - return this._createXml(this._urls) - } - - /** - * check if robots has a noindex - * - * @param {object} page - * @return {boolean} - * - */ - _isValid(page) { - - let result = true - - if (page.meta) { - page.meta = Object.entries(page.meta) - page.meta.forEach((meta) => { - if (meta['name'] === 'robots' && meta['content'].includes('noindex')) { - result = false - return; - } - }) - } - - if (page.type !== 'html') { - result = false - } - - return result - } - - /** - * create xml with urls and return it as string - * - * @param {object} urls - * @return {string} - * - */ - _createXml(urls) { - - // builder for XML - const builder = new XMLBuilder({ - format: true, - processEntities: false, - ignoreAttributes: false, - attributeNamePrefix: '@' - }) - - const xmlString = builder.build({ - '?xml': { - '@version': '1.0', - '@encoding': 'UTF-8' - }, - 'urlset': { - '@xmlns': 'http://www.sitemaps.org/schemas/sitemap/0.9', - 'url': urls - } - }) - - return xmlString - } -} - -module.exports = Sitemap \ No newline at end of file diff --git a/src/parsers/markdown.js b/src/parsers/markdown.js deleted file mode 100644 index 8a3cb93..0000000 --- a/src/parsers/markdown.js +++ /dev/null @@ -1,42 +0,0 @@ -const yaml = require('js-yaml') -const { marked } = require('marked') - -/** - * parse string of file, parse yaml and parse markdown - * - * @author Björn Hase - * @license http://opensource.org/licenses/MIT The MIT License - * @link https://gitea.node001.net/HerrHase/siteomat-webpack-plugin.git - * - */ - -function parseMarkdownFile(fileString) { - - // regex get yaml section and markdown - // thanks to, https://github.com/getgrav/grav - const regex = new RegExp(/^(---\n(.+?)\n---){0,}(.*)$/gs) - const matches = regex.exec(fileString) - - const result = { - fields: undefined, - content: '' - } - - // check if yaml section not exists throw error - if (matches?.[2]) { - try { - result.fields = yaml.load(matches[2]) - } catch (error) { - throw new Error('Yaml has errors!') - } - } - - // if markdown section exits parse it to html 6565 - if (matches?.[3]) { - result.content = marked.parse(matches[3]) - } - - return result -} - -module.exports = parseMarkdownFile \ No newline at end of file diff --git a/src/parsers/yaml.js b/src/parsers/yaml.js deleted file mode 100644 index 7b988e3..0000000 --- a/src/parsers/yaml.js +++ /dev/null @@ -1,25 +0,0 @@ -const yaml = require('js-yaml') - -/** - * parse string of file and only parse yaml - * - * @author Björn Hase - * @license http://opensource.org/licenses/MIT The MIT License - * @link https://gitea.node001.net/HerrHase/siteomat-webpack-plugin.git - * - */ - -function parseYamlFile(file) { - - let config - - try { - config = yaml.load(file) - } catch (error) { - throw new Error('parseYamlFile: Yaml has errors!') - } - - return config -} - -module.exports = parseYamlFile \ No newline at end of file diff --git a/src/queries/blocks.js b/src/queries/blocks.js deleted file mode 100644 index baba849..0000000 --- a/src/queries/blocks.js +++ /dev/null @@ -1,130 +0,0 @@ -const fs = require('fs') -const path = require('path') - -const BlockFactory = require('./../factories/block.js') - -/** - * search, filter and find pages - * - * - * @author Björn Hase - * @license http://opensource.org/licenses/MIT The MIT License - * @link https://gitea.node001.net/HerrHase/siteomat-webpack-plugin.git - * - */ - -class Blocks { - - /** - * - * - * @param {string} dirPath - * - */ - constructor(dirPath) { - - this.FILE_EXTENSION = '.md' - this.DIRECTORY_BLOCKS = '_blocks' - - this._dirPath = dirPath + '/' + this.DIRECTORY_BLOCKS; - this._results = {} - } - - /** - * - * - * @return {array} - */ - find() { - - if (fs.existsSync(this._dirPath)) { - this._findFiles(this._dirPath) - } - - return this._results - } - - /** - * find files - * - * @param {string} dirPath - * @param {Object} [parent = ''] - * - */ - _findFiles(dirPath, parent = '') { - - // - const files = fs.readdirSync(dirPath, { - withFileTypes: true - }) - - files.forEach((file) => { - - // skip for file that is not markdown - if (file.isFile() && path.extname(file.name) !== this.FILE_EXTENSION) { - return; - } - - // if directory going deep - if (file.isDirectory()) { - this._findFiles(dirPath, parent + '/' + file.name) - } - - // get file - const fileString = this._getFile(file, dirPath + parent) - - // skip if empty - if (!fileString) { - return; - } - - // create page object and add to page - const block = new BlockFactory(fileString) - const blockname = this._parseBlockname(file.name) - - if (!this._results[blockname]) { - this._results[blockname] = [] - } - - this._results[blockname].push(block.get()) - }) - } - - /** - * remove '.md' and also ordering number = filename - * - * @param {string} filename - * @return {string} - * - */ - _parseBlockname(filename) { - const regex = new RegExp(/[-_]?[0-9]*\b.md\b$/) - return filename.replace(regex, '') - } - - /** - * get file content - * - * @param {string} slug - * @param {string} sourcePath - * @return {mixed} - * - */ - _getFile(file, dirPath) { - - // file - let result = null - - // path of file, first try with slug - let filePath = dirPath + '/' + file.name - - if (fs.existsSync(filePath) && file.isFile()) { - result = fs.readFileSync(filePath, 'utf8') - } - - return result - } - -} - -module.exports =Blocks \ No newline at end of file diff --git a/src/queries/pages.js b/src/queries/pages.js deleted file mode 100644 index f674ca6..0000000 --- a/src/queries/pages.js +++ /dev/null @@ -1,188 +0,0 @@ -const fs = require('fs') -const path = require('path') -const { - Filter, orderBy, reduce -} = require('@helpers/siteomat-query') - -const PageFactory = require('./../factories/page.js') -const BlocksQuery = require('./../queries/blocks.js') - -/** - * Pages - search, filter and find pages - * - * @author Björn Hase - * @license http://opensource.org/licenses/MIT The MIT License - * @link https://gitea.node001.net/HerrHase/siteomat-webpack-plugin.git - * - */ - -class Pages { - - /** - * - * - * @param {string} dirPath - * - */ - constructor(dirPath) { - - // constants - this.FILE_EXTENSION = '.md' - this.FILE_INDEX = 'index' - this.DIRECTORY_BLOCKS = '_blocks' - - // default options for find - this._options = { - parent: '', - deep: -1 - } - - this._dirPath = dirPath - this._results = [] - } - - /** - * find pages - * - * @param {Object} [options={}] - * @return {array} - * - */ - find(options = {}) { - this._results = [] - this._count = 0 - - options = Object.assign({}, this._options, options) - - if (options.filter) { - this._filter = new Filter(options.filter) - } - - this._findFiles(this._dirPath, options) - - // - if (options.orderBy && options.orderBy.length > 0) { - this.results = orderBy(options.orderBy, this._results) - } - - if (options.limit || options.offset) { - this._results = reduce(options, this._results) - } - - return this._results - } - - /** - * find files - * - * @param {[type]} dirPath [description] - * @param {Object} [parameters={}] [description] - * @param {Object} [options={}] [description] - * @return {[type]} - * - */ - _findFiles(dirPath, options) { - - // getting all files - const files = fs.readdirSync(dirPath + options.parent, { - withFileTypes: true - }) - - files.forEach((file) => { - - // skip for file that is not markdown - if (file.isFile() && path.extname(file.name) !== this.FILE_EXTENSION ) { - return; - } - - // skip for file that is index but not root - if (file.isFile() && file.name === (this.FILE_INDEX + this.FILE_EXTENSION) && options.parent !== '') { - return; - } - - // skip for directory that contains partials - if (file.isDirectory() && file.name === this.DIRECTORY_BLOCKS) { - return; - } - - // if directory going deep - if (file.isDirectory() && (options.deep > 0 || options.deep === -1)) { - - if (options.deep > 0) { - options.deep-- - } - - const childrenOptions = Object.assign({}, options, { - 'parent': options.parent + '/' + file.name - }) - - this._findFiles(dirPath, childrenOptions) - } - - // get file - const content = this._getFile(file, dirPath + options.parent) - - // skip if empty - if (!content) { - return; - } - - // check if - const blocks = this._getBlocks(dirPath + options.parent + '/' + file.name) - - // create page object and add to page - const page = new PageFactory(file, options.parent, content, blocks) - - // check for filters and skip - if (this._filter && !this._filter.validate(page.get())) { - return; - } - - this._results.push(page.get()) - }) - } - - /** - * - * - * @param {string} dirPath - * @return {array} - * - */ - _getBlocks(dirPath) { - const blocksQuery = new BlocksQuery(dirPath) - return blocksQuery.find() - } - - /** - * get file content - * - * @param {string} slug - * @param {string} sourcePath - * @return {mixed} - * - */ - _getFile(file, dirPath) { - - // file - let result = null - - // path of file, first try with slug - let filePath = dirPath + '/' + file.name - - if (fs.existsSync(filePath) && file.isFile()) { - result = fs.readFileSync(filePath, 'utf8') - } else { - filePath = dirPath + '/' + file.name + '/' + this.FILE_INDEX + this.FILE_EXTENSION - - if (fs.existsSync(filePath)) { - result = fs.readFileSync(filePath, 'utf8') - } - } - - return result - } - -} - -module.exports = Pages diff --git a/src/siteomat.js b/src/siteomat.js deleted file mode 100644 index b4aab02..0000000 --- a/src/siteomat.js +++ /dev/null @@ -1,118 +0,0 @@ -const fs = require('fs') -const path = require('path') -const mkdirp = require('mkdirp') -const assign = require('assign-deep') - -const configStore = require('./config.js') - -const Engine = require('./engines/nunjucks.js') -const Sitemap = require('./factories/sitemap.js') - -const PagesQuery = require('./queries/pages.js') -const parseYamlFile = require('./parsers/yaml.js') - -/** - * Siteomat - * - * - * - * @author Björn Hase - * @license http://opensource.org/licenses/MIT The MIT License - * @link https://gitea.node001.net/HerrHase/siteomat-webpack-plugin.git - * - */ -class Siteomat { - - /** - * - * - * @param {string} source - * @param {string} destination - * - */ - constructor(source, views, options = {}) { - - if (options.destination === undefined) { - throw new Error('Destination is undefined') - } - - this._source = source - this._views = views - this._destination = options.destination - - // fill singleton for configuration - configStore.set('source', source) - configStore.set('destination', this._destination) - configStore.set('views', views) - configStore.set('options', assign({ - 'minifyHtml': true - }, options)) - - // get config for site - if (fs.existsSync(this._source + '/site.yml')) { - const file = fs.readFileSync(this._source + '/site.yml', 'utf8') - this._site = parseYamlFile(file) - } else { - throw new Error('site.yml not found in ' + this._source + '!') - } - - if (fs.existsSync(this._source + '/json.yml')) { - const file = fs.readFileSync(this._source + '/json.yml', 'utf8') - this._json = parseYamlFile(file) - } - - configStore.set('site', this._site) - - this._engine = new Engine(views, this._site) - } - - /** - * let it rain \o/ - * - */ - run() { - const query = new PagesQuery(this._source) - const results = query.find() - - const sitemap = new Sitemap(this._site) - - // run through pages and generate html files - results.forEach((page, index) => { - this._engine.render(page, (error, content) => { - - // show errors - if (error) { - console.error(error) - } - - // if no content show error message - if (!content) { - console.error('Error! Rendering Page ' + '"' + page.filename + '" is null') - return; - } - - // create directories and write file = page - mkdirp(this._destination + page.pathname).then(() => { - fs.writeFileSync(this._destination + page.pathname + '/' + page.filename, content) - }) - - sitemap.addPage(page) - - // if run is finish, write sitemap.xml - if ((index + 1) === results.length) { - fs.writeFileSync(this._destination + '/sitemap.xml', sitemap.getXmlAsString()) - } - - }) - }) - - if (this._json) { - for (const [name, options] of Object.entries(this._json)) { - const json = query.find(options) - fs.writeFileSync(this._destination + '/' + name + '.json', JSON.stringify(json)) - } - } - } -} - -module.exports = Siteomat diff --git a/test.js b/test.js deleted file mode 100644 index 721a0c9..0000000 --- a/test.js +++ /dev/null @@ -1,8 +0,0 @@ -const Siteomat = require('./src/siteomat.js') - -const siteomat = new Siteomat('./example/site', './example/views', { - 'destination': './public', - 'minifyHtml': false -}) - -siteomat.run() diff --git a/test/blocks.js b/test/blocks.js deleted file mode 100644 index 812bf60..0000000 --- a/test/blocks.js +++ /dev/null @@ -1,24 +0,0 @@ -const { assert } = require('chai') -const fs = require('fs') - -describe('Blocks', function () { - - // get function parseMarkdownFile - const BlocksQuery = require('./../src/queries/blocks.js') - - const blocksQuery = new BlocksQuery('./ressources') - const results = blocksQuery.find() - - // check results - it('block is array', function() { - assert.isArray(results.block) - }) - - it('block has length of 2', function() { - assert.equal(results.block.length, 2) - }) - - it('title in first block are equal', function() { - assert.equal(results.block[0].title, 'health goth DIY tattooed') - }) -}) diff --git a/test/parserMarkdown.js b/test/parserMarkdown.js deleted file mode 100644 index 88ee59f..0000000 --- a/test/parserMarkdown.js +++ /dev/null @@ -1,41 +0,0 @@ -const { assert } = require('chai') -const fs = require('fs') - -describe('Parser Markdown', function () { - - // default file - const markdownData = fs.readFileSync('./ressources/default.md', 'utf8') - - // get function parseMarkdownFile - const parseMarkdownFile = require('./../src/parsers/markdown.js') - - // start parsing - const result = parseMarkdownFile(markdownData) - - // check results - it('fields exists', function() { - assert.notEqual(result.fields, undefined) - }) - - it('fields is object', function() { - assert.isObject(result.fields) - }) - - it('fields are valid', function() { - assert.deepEqual(result.fields, { - title: 'health goth DIY tattooed', - view: 'page.njk', - meta: { - description: 'DSA yes plz hot chicken green juice' - } - }) - }) - - it('content exists', function() { - assert.notEqual(result.content, '') - }) - - it('content has html', function() { - assert.match(result.content, /

Normcore cold-pressed ramps DSA<\/h2>/) - }) -})