diff --git a/cli/compiler.js b/cli/compiler.js index 766064b..9a1dadb 100644 --- a/cli/compiler.js +++ b/cli/compiler.js @@ -45,6 +45,10 @@ const matter = require("gray-matter"); const Sugar = require("sugar-date"); const livereload = require("rollup-plugin-livereload"); const svgo = require("svgo"); +const postcss = require("postcss"); +const postcssSCSS = require("postcss-scss"); +const autoprefixer = require("autoprefixer"); +const filendir = require("filendir"); const spawn = require("child_process").spawnSync; @@ -137,20 +141,15 @@ function compile(prefix) { switch (prefix) { case "images": compiler = async file => { - const imageExists = await exists(__public(file, "images")); - if (imageExists) return; - switch (path.extname(file)) { case ".svg": - const data = await fs.readFileAsync( - __current("images", file), - "utf8" - ); + const data = fs.readFileSync(__current("images", file), "utf8"); const result = await svgOptimizer.optimize(data); fs.writeFileSync(__public(file, "images"), result.data); break; default: - fs.copyAsync(__current("images", file), __public(file, "images")); + fs.copySync(__current("images", file), __public(file, "images")); + break; } }; break; @@ -170,7 +169,14 @@ function compile(prefix) { Object.assign(options, { plugins: [uglify({}, minify)] }); } else { Object.assign(options, { - plugins: [livereload({ watch: "public", verbose: false })] + plugins: [ + livereload({ + watch: "public", + verbose: false, + applyCSSLive: false, // = workaround, because it kills livereload + applyImgLive: false + }) + ] }); } @@ -199,23 +205,47 @@ function compile(prefix) { break; case "stylesheets": compiler = async file => { - let filePath = __current(prefix, file); - + const filePath = __current(prefix, file); + const outputFilePathWOExt = __public( + path.join( + "stylesheets", // compile scss to subfolder + path.dirname(file), + path.basename(file, ".scss") + ) + ); try { - let result = await sass.renderAsync({ - file: filePath, - includePaths: includePaths || [], - outputStyle: "compressed", - sourceMap: true, - outFile: __public("styles.css") + fs.readFile(filePath, (err, scss) => { + postcss([ + autoprefixer({ + browsers: [ + ">1%", + "last 4 versions", + "Firefox ESR", + "not ie < 9" + ] + }) + ]) + .process(scss, { + from: filePath, + to: `${outputFilePathWOExt}.css`, + syntax: postcssSCSS, + map: true // = inline source maps + }) + .then( + result => { + // filendir is fs wrapper - it can create directories + filendir.writeFileSync( + `${outputFilePathWOExt}.css`, + result.content + ); + }, + error => { + println(error); + } + ); }); - - output = result.css; - filename = `${path.basename(file, path.extname(file))}.css`; - - await fs.writeFileAsync(__public(filename), output); } catch (error) { - println(error.formatted); + println(error); } }; break; @@ -252,7 +282,10 @@ function compile(prefix) { }; if (path.extname(file) === ".md") { - const parentDir = path.parse(file).dir.split(path.sep).slice(-1)[0]; + const parentDir = path + .parse(file) + .dir.split(path.sep) + .slice(-1)[0]; const layout = parentDir && (await fs.pathExists(__current("layout", parentDir))) ? parentDir @@ -412,7 +445,9 @@ async function checkDirectoryStructure() { "website/stylesheets" ].map(el => path.join(cwd, el)); - const result = await Promise.resolve(paths).map(fs.pathExists).all(); + const result = await Promise.resolve(paths) + .map(fs.pathExists) + .all(); if (!result.every(_ => _)) { const tree = spawn("tree", ["-d", "-I", "node_modules"], { cwd: "." }); diff --git a/cli/server.js b/cli/server.js index ada6943..63e0bca 100644 --- a/cli/server.js +++ b/cli/server.js @@ -11,15 +11,15 @@ // See the License for the specific language governing permissions and // limitations under the License. -const Huncwot = require('huncwot'); -const chokidar = require('chokidar'); -const { compile, transform, compileAll, loadData } = require('./compiler'); -const path = require('path'); -const colors = require('colors'); +const Huncwot = require("huncwot"); +const chokidar = require("chokidar"); +const { compile, transform, compileAll, loadData } = require("./compiler"); +const path = require("path"); +const colors = require("colors"); -const { println } = require('./util'); +const { println } = require("./util"); -const debug = require('debug')('server'); +const debug = require("debug")("server"); async function recompile(file) { let fileSegments = file.split(path.sep); @@ -28,41 +28,59 @@ async function recompile(file) { debug(`file to recompile: ${file}`); if (prefix.match(/layouts|partials|data/)) { - await loadData() - await transform('pages')(); + await loadData(); + await transform("pages")(); } else if (prefix.match(/stylesheets/)) { - await transform('stylesheets')(); + await transform("stylesheets")(); + } else if (prefix.match(/images/)) { + await transform("images")(); } else { compile(prefix)(file); } } async function serve({ port, dir }) { - await compileAll({ dir }) + await compileAll({ dir }); const watcher = chokidar.watch(dir, { ignored: /[\/\\]\./, persistent: true, - cwd: 'website' + cwd: "website" }); + let scanComplete = false; watcher - .on('change', recompile) + .on("change", recompile) + // XXX "add" and "change" fires on file rename + // => 2 recompile(..) calls (maybe only with some NodeJS and OS versions) + // similar issue for example: https://github.com/paulmillr/chokidar/issues/551 + .on("add", (...params) => { + if (scanComplete) { + recompile(...params); + } + }) + .on("unlink", recompile) + .on("error", function(error) { + console.log("Error happened:", error); + }) + .on("ready", function() { + console.log("Ready for changes."); + scanComplete = true; + }); - const app = new Huncwot({ staticDir: './public' }); + const app = new Huncwot({ staticDir: "./public" }); - app.on('error', err => { - println('Error: '.red + err.message); + app.on("error", err => { + println("Error: ".red + err.message); }); app.listen(port); - - println(`---\nServer running at http://localhost:${port}`) + + println(`---\nServer running at http://localhost:${port}`); } module.exports = { - builder: _ => _ - .option('port', { alias: 'p', default: 3000 }) - .default('dir', '.'), + builder: _ => + _.option("port", { alias: "p", default: 3000 }).default("dir", "."), handler: serve }; diff --git a/package.json b/package.json index b9dd3db..d41495b 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,8 @@ "yaml", "content", "images", - "CMS" + "CMS", + "PostCSS" ], "author": { "name": "Zaiste", @@ -45,12 +46,14 @@ "url": "https://github.com/zaiste/kulfon" }, "dependencies": { + "autoprefixer": "^7.1.3", "axios": "^0.16.2", "bluebird": "^3.5.1", "chokidar": "^1.7.0", "colors": "^1.1.2", "deepmerge": "^2.0.0", "fs-extra": "^4.0.2", + "filendir": "^1.0.0", "global": "^4.3.2", "gray-matter": "^3.0.8", "highlight.js": "^9.12.0", @@ -65,6 +68,8 @@ "nunjucks": "^3.0.1", "nunjucks-markdown": "^2.0.1", "open": "^0.0.5", + "postcss": "^6.0.10", + "postcss-scss": "^1.0.2", "rollup": "^0.50.0", "rollup-plugin-livereload": "^0.6.0", "rollup-plugin-uglify": "^2.0.1", diff --git a/themes/bare/website/layouts/base.html b/themes/bare/website/layouts/base.html index 86b78ff..fead5f8 100644 --- a/themes/bare/website/layouts/base.html +++ b/themes/bare/website/layouts/base.html @@ -7,7 +7,7 @@ {% for stylesheet in stylesheets %} {% endfor %} - + {% block head %}{% endblock %}
diff --git a/themes/default/website/layouts/base.html b/themes/default/website/layouts/base.html index 6f529ed..f1fdbf0 100644 --- a/themes/default/website/layouts/base.html +++ b/themes/default/website/layouts/base.html @@ -8,7 +8,7 @@ {% for stylesheet in stylesheets %} {% endfor %} - + {% block head %}{% endblock %} diff --git a/themes/tachyons/website/images/logo.svg b/themes/tachyons/website/images/logo.svg index 05f7e69..b51429a 100644 --- a/themes/tachyons/website/images/logo.svg +++ b/themes/tachyons/website/images/logo.svg @@ -1 +1,20 @@ -LOGO \ No newline at end of file + + + diff --git a/themes/tachyons/website/layouts/base.html b/themes/tachyons/website/layouts/base.html index adc796e..3d97aee 100644 --- a/themes/tachyons/website/layouts/base.html +++ b/themes/tachyons/website/layouts/base.html @@ -8,7 +8,7 @@ {% for stylesheet in stylesheets %} {% endfor %} - + {% block head %}{% endblock %} diff --git a/themes/tachyons/website/stylesheets/extra/extra.scss b/themes/tachyons/website/stylesheets/extra/extra.scss new file mode 100644 index 0000000..2f85453 --- /dev/null +++ b/themes/tachyons/website/stylesheets/extra/extra.scss @@ -0,0 +1,3 @@ +html { + border: 3px solid black; +} diff --git a/themes/tachyons/website/stylesheets/styles.scss b/themes/tachyons/website/stylesheets/styles.scss index c171cdb..adabe0d 100644 --- a/themes/tachyons/website/stylesheets/styles.scss +++ b/themes/tachyons/website/stylesheets/styles.scss @@ -1,15 +1,17 @@ @import url('https://fonts.googleapis.com/css?family=Lato'); +@import "extra/extra.css"; * { box-sizing: border-box; } -html, body { +html, +body { margin: 0; height: 100%; min-height: 100%; font-size: 18px; - font-family: 'Lato'; + font-family: "Lato"; } body { @@ -18,12 +20,17 @@ body { flex-direction: column; } -h1, h2, h3, h4, h5, h6 { +h1, +h2, +h3, +h4, +h5, +h6 { margin: 0; } header { - background: #FEFEFE; + background: #fefefe; border-bottom: 1px solid #d9d9d9; } diff --git a/yarn.lock b/yarn.lock index 67b957d..595c948 100644 --- a/yarn.lock +++ b/yarn.lock @@ -298,6 +298,17 @@ auto-bind@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/auto-bind/-/auto-bind-1.1.0.tgz#93b864dc7ee01a326281775d5c75ca0a751e5961" +autoprefixer@^7.1.3: + version "7.1.3" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-7.1.3.tgz#0e8d337976d6f13644db9f8813b4c42f3d1ccc34" + dependencies: + browserslist "^2.4.0" + caniuse-lite "^1.0.30000718" + normalize-range "^0.1.2" + num2fraction "^1.2.2" + postcss "^6.0.10" + postcss-value-parser "^3.2.3" + ava-init@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/ava-init/-/ava-init-0.2.0.tgz#9304c8b4c357d66e3dfdae1fbff47b1199d5c55d" @@ -953,6 +964,19 @@ browser-refresh-client@^1.0.0, browser-refresh-client@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/browser-refresh-client/-/browser-refresh-client-1.1.4.tgz#8e5ff8475fe1d541d2ae81f7a1aea05ae21a6217" +browserify-zlib@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.1.4.tgz#bb35f8a519f600e0fa6b8485241c979d0141fb2d" + dependencies: + pako "~0.2.0" + +browserslist@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-2.4.0.tgz#693ee93d01e66468a6348da5498e011f578f87f8" + dependencies: + caniuse-lite "^1.0.30000718" + electron-to-chromium "^1.3.18" + buf-compare@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/buf-compare/-/buf-compare-1.0.1.tgz#fef28da8b8113a0a0db4430b0b6467b69730b34a" @@ -1021,6 +1045,10 @@ camelcase@^4.0.0, camelcase@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" +caniuse-lite@^1.0.30000718: + version "1.0.30000721" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000721.tgz#931a21a7bd85016300328d21f126d84b73437d35" + capture-stack-trace@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz#4a6fa07399c26bba47f0b2496b4d0fb408c5550d" @@ -1473,6 +1501,10 @@ ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" +electron-to-chromium@^1.3.18: + version "1.3.18" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.18.tgz#3dcc99da3e6b665f6abbc71c28ad51a2cd731a9c" + empower-core@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/empower-core/-/empower-core-0.6.1.tgz#6c187f502fcef7554d57933396aac655483772b1" @@ -1643,6 +1675,12 @@ filename-regex@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" +filendir@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/filendir/-/filendir-1.0.0.tgz#745b445afcc4970a4cdb00fd9539c77ed942adf6" + dependencies: + mkdirp "^0.5.0" + fill-range@^2.1.0: version "2.2.3" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.3.tgz#50b77dfd7e469bc7492470963699fe7a8485a723" @@ -3083,6 +3121,10 @@ normalize-path@^2.0.1: dependencies: remove-trailing-separator "^1.0.1" +normalize-range@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" + npm-run-path@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-1.0.0.tgz#f5c32bf595fe81ae927daec52e82f8b000ac3c8f" @@ -3104,6 +3146,10 @@ npm-run-path@^2.0.0: gauge "~2.7.3" set-blocking "~2.0.0" +num2fraction@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede" + number-is-nan@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" @@ -3374,6 +3420,42 @@ plur@^2.0.0: dependencies: irregular-plurals "^1.0.0" +postcss-scss@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/postcss-scss/-/postcss-scss-1.0.2.tgz#ff45cf3354b879ee89a4eb68680f46ac9bb14f94" + dependencies: + postcss "^6.0.3" + +postcss-value-parser@^3.2.3: + version "3.3.0" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz#87f38f9f18f774a4ab4c8a232f5c5ce8872a9d15" + +postcss@^6.0.10, postcss@^6.0.3: + version "6.0.10" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.10.tgz#c311b89734483d87a91a56dc9e53f15f4e6e84e4" + dependencies: + chalk "^2.1.0" + source-map "^0.5.7" + supports-color "^4.2.1" + +postgres-array@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/postgres-array/-/postgres-array-1.0.2.tgz#8e0b32eb03bf77a5c0a7851e0441c169a256a238" + +postgres-bytea@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/postgres-bytea/-/postgres-bytea-1.0.0.tgz#027b533c0aa890e26d172d47cf9ccecc521acd35" + +postgres-date@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/postgres-date/-/postgres-date-1.0.3.tgz#e2d89702efdb258ff9d9cee0fe91bd06975257a8" + +postgres-interval@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/postgres-interval/-/postgres-interval-1.1.0.tgz#1031e7bac34564132862adc9eb6c6d2f3aa75bb4" + dependencies: + xtend "^4.0.0" + prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" @@ -3953,6 +4035,10 @@ source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@~0.5.1: version "0.5.6" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" +source-map@^0.5.7: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + source-map@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.2.0.tgz#dab73fbcfc2ba819b4de03bd6f6eaa48164b3f9d" @@ -4128,6 +4214,12 @@ supports-color@^4.0.0: dependencies: has-flag "^2.0.0" +supports-color@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.2.1.tgz#65a4bb2631e90e02420dba5554c375a4754bb836" + dependencies: + has-flag "^2.0.0" + svgo@svg/svgo: version "0.7.2" resolved "https://codeload.github.com/svg/svgo/tar.gz/c943b4c3bc0b77f1f48ae70826ac9b11f58ea326"