From 6ca289017f31ffc21158a2dadd958f49f06a6335 Mon Sep 17 00:00:00 2001 From: "Jocelyn Badgley (Twipped)" Date: Fri, 28 Feb 2020 09:15:21 -0800 Subject: [PATCH] Now building scss within the content processor --- gulp/content/actions.js | 7 ++ gulp/content/index.js | 2 + gulp/content/resolve.js | 38 ++++----- gulp/content/scss.js | 84 ++++++++++++++++++++ gulp/index.js | 9 +-- gulp/scss.js | 59 -------------- package-lock.json | 170 ---------------------------------------- package.json | 3 +- scss/style.scss | 1 + 9 files changed, 116 insertions(+), 257 deletions(-) create mode 100644 gulp/content/scss.js delete mode 100644 gulp/scss.js diff --git a/gulp/content/actions.js b/gulp/content/actions.js index 3027384..f9037c0 100644 --- a/gulp/content/actions.js +++ b/gulp/content/actions.js @@ -33,6 +33,13 @@ const actions = { return body; }, + async write ({ output, content }) { + output = resolve(output); + await fs.ensureDir(path.dirname(output)); + await fs.writeFile(output, content); + return Buffer.from(content); + }, + async image (options) { const output = resolve(options.output); const contents = await readFile(options.input); diff --git a/gulp/content/index.js b/gulp/content/index.js index 8e7a454..6869aef 100644 --- a/gulp/content/index.js +++ b/gulp/content/index.js @@ -10,6 +10,7 @@ const evaluate = require('./evaluate'); const { resolve } = require('./resolve'); const favicon = require('./favicon'); +const scss = require('./scss'); const svg = require('./svg'); exports.everything = function (prod = false) { @@ -28,6 +29,7 @@ exports.everything = function (prod = false) { // compile all tasks to be completed const tasks = await Promise.all([ PublicFiles.tasks, + scss(prod), svg(prod), favicon(prod), ]); diff --git a/gulp/content/resolve.js b/gulp/content/resolve.js index 32d10ae..dd235e2 100644 --- a/gulp/content/resolve.js +++ b/gulp/content/resolve.js @@ -34,6 +34,9 @@ const EXT = exports.EXT = { HBS: '.hbs', HTML: '.html', XML: '.xml', + CSS: '.css', + SCSS: '.scss', + JS: '.js', }; const { @@ -47,21 +50,11 @@ const { HBS, HTML, XML, + CSS, + SCSS, + JS, } = EXT; -exports.RE = { - JPG: re(/.jpg$/), - JPEG: re(/.jpeg$/), - PNG: re(/.png$/), - GIF: re(/.gif$/), - MP4: re(/.mp4$/), - M4V: re(/.m4v$/), - MD: re(/.md$/), - HBS: re(/.hbs$/), - HTML: re(/.html$/), - XML: re(/.xml$/), -}; - const NORMALIZE_EXT = { [JPG]: JPEG, [M4V]: MP4, @@ -79,6 +72,7 @@ const isHandlebars = exports.isHandlebars = is(XML, HBS, HTML); const isMarkdown = exports.isMarkdown = is(MD); const isPage = exports.isPage = is(isHandlebars, isMarkdown); const isAsset = exports.isAsset = is(isImage, isVideo); +const isArtifact = exports.isArtifact = is(CSS, SCSS, JS); exports.isCleanUrl = is(HBS, MD); @@ -88,6 +82,8 @@ const TYPE = exports.TYPE = { VIDEO: 'VIDEO', HANDLEBARS: 'HANDLEBARS', MARKDOWN: 'MARKDOWN', + SCRIPT: 'SCRIPT', + STYLE: 'STYLE', OTHER: 'OTHER', }; @@ -96,19 +92,23 @@ exports.type = dictMatch({ [TYPE.HANDLEBARS]: isHandlebars, [TYPE.MARKDOWN]: isMarkdown, [TYPE.VIDEO]: isVideo, + [TYPE.SCRIPT]: is(JS), + [TYPE.STYLE]: is(SCSS, CSS), }, TYPE.OTHER); const KIND = exports.KIND = { - PAGE: 'PAGE', - ASSET: 'ASSET', - OTHER: 'OTHER', + PAGE: 'PAGE', + ASSET: 'ASSET', + ARTIFACT: 'ARTIFACT', + OTHER: 'OTHER', }; exports.kind = dictMatch({ - [KIND.ASSET]: isAsset, - [KIND.PAGE]: isPage, + [KIND.ASSET]: isAsset, + [KIND.PAGE]: isPage, + [KIND.ARTIFACT]: isArtifact, }, KIND.OTHER); @@ -129,7 +129,7 @@ exports.engine = dictMatch({ exports.readFile = function readFile (fpath) { fpath = exports.resolve(fpath); return fs.readFile(fpath).catch((err) => { - throw new Error(err.trace); + throw new Error(err.message); }); }; diff --git a/gulp/content/scss.js b/gulp/content/scss.js new file mode 100644 index 0000000..718dd5b --- /dev/null +++ b/gulp/content/scss.js @@ -0,0 +1,84 @@ +const glob = require('../lib/glob'); +const { ROOT, readFile, resolve } = require('./resolve'); +const actions = require('./actions'); +const File = require('./file'); +const sass = require('node-sass'); +const Promise = require('bluebird'); +const postcss = require('postcss'); +const autoprefixer = require('autoprefixer'); +const crass = require('crass'); + + +module.exports = exports = async function styles (prod) { + const files = await Promise.map(glob('scss/*.scss', { cwd: ROOT, nodir: true }), async (filepath) => { + const f = new Sass(filepath); + if (f.preprocessed) return false; + await f.load(prod); + return f; + }).filter(Boolean); + + const tasks = files.map((f) => f.tasks()).flat(); + + return tasks; +}; + +class Sass extends File { + + _dir (dir) { + dir = dir.split('/'); + if (dir[0] === 'scss') dir.shift(); + dir.unshift('css'); + return dir; + } + + async load (prod) { + let contents = (await readFile(this.input).catch(() => null)).toString('utf8'); + + for (const [ match, fpath ] of contents.matchAll(/\|(.+?)\|/)) { + const insert = await readFile(fpath); + contents = contents.replace(match, insert); + } + + const sassOptions = { + data: contents, + file: resolve(this.input), + includePaths: [ + resolve(this.cwd), + resolve('node_modules'), + ], + sourceMapEmbed: true, + }; + + let { css } = await (new Promise((resolve, reject) => { // eslint-disable-line no-shadow + sass.render(sassOptions, (err, result) => ( + err ? reject(err) : resolve(result) + )); + })); + + if (prod) { + css = (await postcss([ autoprefixer ]).process(css, { + from: this.input, + to: this.out, + map: { inline: true }, + })).css; + + var parsed = crass.parse(css); + parsed = parsed.optimize({ O1: true }); + // if (options.pretty) parsed = parsed.pretty(); + css = Buffer.from(parsed.toString()); + } + + this.content = css; + } + + tasks () { + return [ { + input: this.input, + output: this.out, + content: this.content, + action: actions.write, + nocache: true, + } ]; + } + +} diff --git a/gulp/index.js b/gulp/index.js index f95f0b3..4563634 100644 --- a/gulp/index.js +++ b/gulp/index.js @@ -8,10 +8,7 @@ var content = require('./content'); const everything = content.everything(); everything.prod = content.everything(true); -exports.everything = everything; - -var scssTask = require('./scss'); -exports.scss = scssTask; +exports.go = series(everything); var jsTask = require('./scripts'); exports.js = jsTask; @@ -28,13 +25,11 @@ exports.cloudfront = cloudfront; /** **************************************************************************************************************** **/ var prodBuildTask = parallel( - scssTask.prod, jsTask.prod, everything.prod, ); var devBuildTask = parallel( - scssTask, jsTask, everything, ); @@ -56,9 +51,9 @@ function watcher () { watch([ 'public/**/*', 'templates/*.{md,hbs,html}', + 'scss/*.scss', ], everything); - watch('scss/*.scss', scssTask); watch('js/*.js', jsTask); var forever = require('forever'); diff --git a/gulp/scss.js b/gulp/scss.js deleted file mode 100644 index fdabe06..0000000 --- a/gulp/scss.js +++ /dev/null @@ -1,59 +0,0 @@ - -const path = require('path'); -const { src, dest } = require('gulp'); -const scss = require('gulp-sass'); -const rev = require('gulp-rev'); -const asyncthrough = require('./lib/through'); -const crass = require('./lib/crass'); -const concat = require('gulp-concat'); -const merge = require('merge-stream'); -const postcss = require('gulp-postcss'); -const autoprefixer = require('autoprefixer'); - -// const minifyCSS = require('gulp-minify-css'); - - -const ROOT = path.dirname(__dirname); -const DEST = 'dist/css'; - -module.exports = exports = function buildScss () { - - const scssStream = src([ 'scss/*.scss', '!scss/_*.scss' ]) - .pipe(scss({ - includePaths: [ path.join(ROOT, 'node_modules') ], - })); - - return merge( - scssStream, - src([ - require.resolve('magnific-popup/dist/magnific-popup.css'), - ]), - ) - .pipe(concat('style.css')) - .pipe(postcss([ - autoprefixer(), - ])) - .pipe(dest(DEST)); -}; - -exports.prod = function buildScssForProd () { - return exports() - .pipe(crass()) - .pipe(dest(DEST)) - .pipe(rev()) - .pipe(dest(DEST)) - .pipe(asyncthrough(async (stream, file) => { - // Change rev's original base path back to the public root so that it uses the full - // path as the original file name key in the manifest - var base = path.resolve(ROOT, 'dist'); - file.revOrigBase = base; - file.base = base; - - stream.push(file); - })) - .pipe(rev.manifest({ - merge: true, // Merge with the existing manifest if one exists - })) - .pipe(dest('.')) - ; -}; diff --git a/package-lock.json b/package-lock.json index 8f42d25..d8f61d6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1349,32 +1349,6 @@ "tape": "~2.3.2" } }, - "caller-callsite": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", - "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=", - "dev": true, - "requires": { - "callsites": "^2.0.0" - }, - "dependencies": { - "callsites": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", - "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", - "dev": true - } - } - }, - "caller-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", - "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=", - "dev": true, - "requires": { - "caller-callsite": "^2.0.0" - } - }, "callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -1902,46 +1876,6 @@ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true }, - "cosmiconfig": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", - "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", - "dev": true, - "requires": { - "import-fresh": "^2.0.0", - "is-directory": "^0.3.1", - "js-yaml": "^3.13.1", - "parse-json": "^4.0.0" - }, - "dependencies": { - "import-fresh": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", - "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", - "dev": true, - "requires": { - "caller-path": "^2.0.0", - "resolve-from": "^3.0.0" - } - }, - "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", - "dev": true, - "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - } - }, - "resolve-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", - "dev": true - } - } - }, "crass": { "version": "0.12.3", "resolved": "https://registry.npmjs.org/crass/-/crass-0.12.3.tgz", @@ -4693,19 +4627,6 @@ } } }, - "gulp-postcss": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/gulp-postcss/-/gulp-postcss-8.0.0.tgz", - "integrity": "sha512-Wtl6vH7a+8IS/fU5W9IbOpcaLqKxd5L1DUOzaPmlnCbX1CrG0aWdwVnC3Spn8th0m8D59YbysV5zPUe1n/GJYg==", - "dev": true, - "requires": { - "fancy-log": "^1.3.2", - "plugin-error": "^1.0.1", - "postcss": "^7.0.2", - "postcss-load-config": "^2.0.0", - "vinyl-sourcemaps-apply": "^0.2.1" - } - }, "gulp-rev": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/gulp-rev/-/gulp-rev-9.0.0.tgz", @@ -4740,49 +4661,6 @@ } } }, - "gulp-sass": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/gulp-sass/-/gulp-sass-4.0.2.tgz", - "integrity": "sha512-q8psj4+aDrblJMMtRxihNBdovfzGrXJp1l4JU0Sz4b/Mhsi2DPrKFYCGDwjIWRENs04ELVHxdOJQ7Vs98OFohg==", - "dev": true, - "requires": { - "chalk": "^2.3.0", - "lodash.clonedeep": "^4.3.2", - "node-sass": "^4.8.3", - "plugin-error": "^1.0.1", - "replace-ext": "^1.0.0", - "strip-ansi": "^4.0.0", - "through2": "^2.0.0", - "vinyl-sourcemaps-apply": "^0.2.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - }, - "through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - } - } - }, "gulplog": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", @@ -5127,15 +5005,6 @@ "queue": "6.0.1" } }, - "import-cwd": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-2.1.0.tgz", - "integrity": "sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk=", - "dev": true, - "requires": { - "import-from": "^2.1.0" - } - }, "import-fresh": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", @@ -5146,23 +5015,6 @@ "resolve-from": "^4.0.0" } }, - "import-from": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/import-from/-/import-from-2.1.0.tgz", - "integrity": "sha1-M1238qev/VOqpHHUuAId7ja387E=", - "dev": true, - "requires": { - "resolve-from": "^3.0.0" - }, - "dependencies": { - "resolve-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", - "dev": true - } - } - }, "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -5377,12 +5229,6 @@ } } }, - "is-directory": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", - "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", - "dev": true - }, "is-extendable": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", @@ -5677,12 +5523,6 @@ "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", "dev": true }, - "json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, "json-schema": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", @@ -7290,16 +7130,6 @@ } } }, - "postcss-load-config": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-2.1.0.tgz", - "integrity": "sha512-4pV3JJVPLd5+RueiVVB+gFOAa7GWc25XQcMp86Zexzke69mKf6Nx9LRcQywdz7yZI9n1udOxmLuAwTBypypF8Q==", - "dev": true, - "requires": { - "cosmiconfig": "^5.0.0", - "import-cwd": "^2.0.0" - } - }, "postcss-value-parser": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.0.3.tgz", diff --git a/package.json b/package.json index d1a347e..1b045f5 100644 --- a/package.json +++ b/package.json @@ -55,9 +55,7 @@ "gulp-concat": "~2.6.1", "gulp-filter": "~6.0.0", "gulp-minify": "~3.1.0", - "gulp-postcss": "~8.0.0", "gulp-rev": "~9.0.0", - "gulp-sass": "~4.0.2", "handlebars": "~4.7.3", "hbs-kit": "~1.2.0", "html-minifier-terser": "~5.0.4", @@ -76,6 +74,7 @@ "plugin-error": "~1.0.1", "png-to-ico": "~2.0.6", "popper.js": "~1.16.0", + "postcss": "~7.0.27", "rev-hash": "~3.0.0", "rev-path": "~2.0.0", "rollup": "~1.31.1", diff --git a/scss/style.scss b/scss/style.scss index 4de4b1f..8ba521a 100644 --- a/scss/style.scss +++ b/scss/style.scss @@ -102,3 +102,4 @@ $header-full-height: 100px; @import "./markup"; @import "./pager"; +|node_modules/magnific-popup/dist/magnific-popup.css|