diff --git a/output.png b/output.png
new file mode 100644
index 0000000..ba25a8b
Binary files /dev/null and b/output.png differ
diff --git a/package-lock.json b/package-lock.json
index 4cc797c..292ac06 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8,6 +8,7 @@
"name": "happy-site-webpack-plugin",
"version": "0.1.0",
"dependencies": {
+ "crypto": "^1.0.1",
"dayjs": "^1.11.6",
"fast-xml-parser": "^4.0.11",
"html-minifier": "^4.0.0",
@@ -206,6 +207,12 @@
"node": ">= 6"
}
},
+ "node_modules/crypto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/crypto/-/crypto-1.0.1.tgz",
+ "integrity": "sha512-VxBKmeNcqQdiUQUW2Tzq0t377b54N2bMtXO/qiLa+6eRRmmC4qT3D4OnTGoT/U6O9aklQ/jTwbOtRMTTY8G0Ig==",
+ "deprecated": "This package is no longer supported. It's now a built-in Node module. If you've depended on crypto, you should switch to the one that's built-in."
+ },
"node_modules/dayjs": {
"version": "1.11.6",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.6.tgz",
@@ -967,6 +974,11 @@
"resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz",
"integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg=="
},
+ "crypto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/crypto/-/crypto-1.0.1.tgz",
+ "integrity": "sha512-VxBKmeNcqQdiUQUW2Tzq0t377b54N2bMtXO/qiLa+6eRRmmC4qT3D4OnTGoT/U6O9aklQ/jTwbOtRMTTY8G0Ig=="
+ },
"dayjs": {
"version": "1.11.6",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.6.tgz",
diff --git a/package.json b/package.json
index a82e9f0..99cb31e 100644
--- a/package.json
+++ b/package.json
@@ -6,6 +6,7 @@
"main": "index.js",
"description": "Generating a Website from a Markdown Generator",
"dependencies": {
+ "crypto": "^1.0.1",
"dayjs": "^1.11.6",
"fast-xml-parser": "^4.0.11",
"html-minifier": "^4.0.0",
diff --git a/resources/site/blog/cliche-vegan-messenger/index.md b/resources/site/blog/cliche-vegan-messenger/index.md
deleted file mode 100644
index e30a302..0000000
--- a/resources/site/blog/cliche-vegan-messenger/index.md
+++ /dev/null
@@ -1,15 +0,0 @@
----
-title: "Cliche Vegan Messenger"
-date_published: "2022-01-10 10:00"
-view: "post.njk"
-tags:
- - tumeric
- - heard
- - bag
-media:
- teaser: 'jep.jpg'
-meta:
- description: "DSA yes plz hot chicken green juice"
- robots: "index, follow"
----
-## TEST
\ No newline at end of file
diff --git a/resources/site/blog/index.md b/resources/site/blog/index.md
deleted file mode 100644
index 988d654..0000000
--- a/resources/site/blog/index.md
+++ /dev/null
@@ -1,7 +0,0 @@
----
-title: "Blog"
-view: "blog.njk"
-meta:
- description: "DSA yes plz hot chicken green juice"
- robots: "index, follow"
----
\ No newline at end of file
diff --git a/resources/views/home.njk b/resources/views/home.njk
index 1f46c37..b209dda 100644
--- a/resources/views/home.njk
+++ b/resources/views/home.njk
@@ -2,7 +2,7 @@
{% block main %}
-
+
{{ page.content | safe }}
{% endblock %}
\ No newline at end of file
diff --git a/src/config.js b/src/config.js
new file mode 100644
index 0000000..53a8f40
--- /dev/null
+++ b/src/config.js
@@ -0,0 +1,36 @@
+/**
+ *
+ *
+ */
+
+class ConfigStore {
+
+ constructor() {
+ if (!ConfigStore.instance) {
+ ConfigStore.instance = this;
+ this._data = {}
+ }
+
+ return ConfigStore.instance;
+ }
+
+ /**
+ *
+ */
+ set(key, value) {
+ this._data[key] = value
+ }
+
+ /**
+ *
+ *
+ */
+ get(key) {
+ return this._data[key]
+ }
+}
+
+// create instance
+const instance = new ConfigStore();
+
+export default instance
\ No newline at end of file
diff --git a/src/engine.js b/src/engine.js
index 074e7b4..87c6125 100644
--- a/src/engine.js
+++ b/src/engine.js
@@ -1,7 +1,8 @@
import nunjucks from 'nunjucks'
import { minify } from 'html-minifier'
+import fs from 'fs'
-import { asset, media } from './helpers/engine.js'
+import { asset, resize } from './helpers/engine.js'
/**
* engine - handle eta.js
@@ -18,13 +19,19 @@ class Engine {
// merge options
this._options = Object.assign({}, {
autoescapes: true,
- throwOnUndefined: true
+ throwOnUndefined: true,
+ web: {
+ async: true
+ }
}, options)
this.nunjucks = nunjucks.configure(views, this._options)
- this.nunjucks.addFilter('media', function(options) {
- return media(options)
- })
+ 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, function and data from config.yml
this._defaults = {
@@ -41,12 +48,11 @@ class Engine {
* @return {string}
*
*/
- render(view, data) {
+ render(view, data, done) {
data = Object.assign({}, data, this._defaults)
- return minify(this.nunjucks.render(view, data), {
- removeComments: true,
- collapseWhitespace: true
+ this.nunjucks.render(view, data, (error, response) => {
+ done(error, response)
})
}
diff --git a/src/happySite.js b/src/happySite.js
index ae3e9f9..48a167a 100644
--- a/src/happySite.js
+++ b/src/happySite.js
@@ -8,12 +8,17 @@ import Sitemap from './sitemap.js'
import PagesQuery from './queries/pages.js'
import parseYamlFile from './parsers/yaml.js'
+import configStore from './config.js'
+
/**
+ * Main
+ *
+ *
*
* @author Björn Hase
* @license http://opensource.org/licenses/MIT The MIT License
* @link https://gitea.node001.net/HerrHase/happy-site-webpack-plugin.git
- *
+ *
*/
class HappySite {
@@ -29,6 +34,10 @@ class HappySite {
this._destination = destination
this._views = views
+ configStore.set('source', source)
+ configStore.set('destination', destination)
+ configStore.set('views', views)
+
// get config for site
if (fs.existsSync(this._source + '/site.yml')) {
const file = fs.readFileSync(this._source + '/site.yml', 'utf8')
@@ -37,6 +46,8 @@ class HappySite {
throw new Error('site.yml not found in ' + this._source + '!')
}
+ configStore.set('site', this._site)
+
this._engine = new Engine(views, this._site)
}
@@ -52,14 +63,26 @@ class HappySite {
// run through pages and generate html files
results.forEach((page) => {
- const content = page.render(this._engine)
+ page.render(this._engine, (error, content) => {
- // create directories and write file from page
- mkdirp(this._destination + page.pathname).then(() => {
- fs.writeFileSync(this._destination + page.pathname + '/' + page.filename, 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;
+ }
- sitemap.addPage(page)
+ // create directories and write file from page
+ mkdirp(this._destination + page.pathname).then(() => {
+ fs.writeFileSync(this._destination + page.pathname + '/' + page.filename, content)
+ })
+
+ sitemap.addPage(page)
+ })
})
// write sitemap
diff --git a/src/helpers/engine.js b/src/helpers/engine.js
index e408906..b858996 100644
--- a/src/helpers/engine.js
+++ b/src/helpers/engine.js
@@ -1,8 +1,7 @@
import path from 'path'
import * as fs from 'fs'
-import sharp from 'sharp'
-const basePath = path.join(path.resolve())
+import Media from './../media.js'
/**
* asset - checks manifest.json for given path and return
@@ -19,7 +18,7 @@ function asset(staticPath)
let result = staticPath
// path to mix-manifest
- const file = basePath + 'mix-manifest.json'
+ const file = path.join(path.resolve()) + 'mix-manifest.json'
if (fs.existsSync(file)) {
@@ -43,14 +42,12 @@ function asset(staticPath)
*
*/
-function media(src, options)
+async function resize(src, sizes, options, done)
{
- console.log(basePath)
- console.log(path.resolve(src))
- sharp(src)
- .toFile('output.png', (error, info) => { console.log(error) })
+ const media = new Media()
- return src
+ src = await media.resize(src, sizes, options)
+ done(null, src)
}
-export { asset, media }
\ No newline at end of file
+export { asset, resize }
\ No newline at end of file
diff --git a/src/media.js b/src/media.js
new file mode 100644
index 0000000..2a140c2
--- /dev/null
+++ b/src/media.js
@@ -0,0 +1,101 @@
+import path from 'path'
+import * as fs from 'fs'
+
+import sharp from 'sharp'
+import mkdirp from 'mkdirp'
+import crypto from 'crypto'
+import slugify from 'slugify'
+
+import configStore from './config.js'
+
+/**
+ *
+ *
+ */
+class Media {
+
+ constructor() {
+ this._DIR_ASSETS = '/assets/'
+ }
+
+ /**
+ *
+ * @param {string} srcPath
+ * @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 from 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('/')
+ }
+}
+
+export default Media
\ No newline at end of file
diff --git a/src/models/page.js b/src/models/page.js
index 69b34f8..c253364 100644
--- a/src/models/page.js
+++ b/src/models/page.js
@@ -1,6 +1,7 @@
import path from 'path'
import slugify from 'slugify'
import merge from 'lodash.merge'
+import nunjucks from 'nunjucks'
import parseMarkdownFile from './../parsers/markdown.js'
@@ -53,7 +54,7 @@ class Page {
* @return {string}
*
*/
- render(engine) {
+ render(engine, done) {
const page = Object.assign({}, this._fields)
@@ -61,11 +62,9 @@ class Page {
page.blocks = this._blocks
page.path = this.pathname + '/' + this.filename
- const result = engine.render(this._fields.view, {
+ return engine.render(this._fields.view, {
page: page
- })
-
- return result
+ }, done)
}
/**
diff --git a/web.png b/web.png
new file mode 100644
index 0000000..ba25a8b
Binary files /dev/null and b/web.png differ