1
0
mirror of https://github.com/locomotivemtl/locomotive-boilerplate.git synced 2026-01-15 00:55:08 +08:00

Add support for task options

Added support for customizing processors in `scripts.js` (esbuild), `styles.js` (node-sass, postcss, autoprefixer), and `svgs.js` (svg-mixer), via arguments for the exported task functions.

Added:
- Constants to decouple shared default options, options for development, and options for production.
- Constants to export default options for development and production as an array of arguments to pass to task functions.

Changed:
- watch.js to apply development args to tasks
This commit is contained in:
Chauncey McAskill
2021-09-21 17:33:32 -04:00
parent 6ded72bc79
commit 9e3d304654
6 changed files with 218 additions and 50 deletions

View File

@@ -1,7 +1,7 @@
import loconfig from '../../loconfig.json';
import message from '../utils/message.js';
import notification from '../utils/notification.js';
import postcss, { autoprefixer } from '../utils/postcss.js';
import postcss, { pluginsMap as postcssPluginsMap } from '../utils/postcss.js';
import template from '../utils/template.js';
import { writeFile } from 'node:fs/promises';
import { basename } from 'node:path';
@@ -10,16 +10,91 @@ import sass from 'node-sass';
const sassRender = promisify(sass.render);
const isPostCSSAvailable = (postcss && autoprefixer);
let postcssProcessor;
/**
* @const {object} defaultSassOptions - The default shared Sass options.
* @const {object} developmentSassOptions - The predefined Sass options for development.
* @const {object} productionSassOptions - The predefined Sass options for production.
*/
export const defaultSassOptions = {
omitSourceMapUrl: true,
sourceMap: true,
sourceMapContents: true,
};
export const developmentSassOptions = Object.assign({}, defaultSassOptions, {
outputStyle: 'expanded',
});
export const productionSassOptions = Object.assign({}, defaultSassOptions, {
outputStyle: 'compressed',
});
/**
* @const {object} defaultPostCSSOptions - The default shared PostCSS options.
* @const {object} developmentPostCSSOptions - The predefined PostCSS options for development.
* @const {object} productionPostCSSOptions - The predefined PostCSS options for production.
*/
export const defaultPostCSSOptions = {
processor: {
map: {
annotation: false,
inline: false,
sourcesContent: true,
},
},
};
export const developmentPostCSSOptions = Object.assign({}, defaultPostCSSOptions);
export const productionPostCSSOptions = Object.assign({}, defaultPostCSSOptions);
/**
* @const {object} developmentStylesArgs - The predefined `compileStyles()` options for development.
* @const {object} productionStylesArgs - The predefined `compileStyles()` options for production.
*/
export const developmentStylesArgs = [
developmentSassOptions,
developmentPostCSSOptions,
];
export const productionStylesArgs = [
productionSassOptions,
productionPostCSSOptions,
];
/**
* Compiles and minifies main Sass files to CSS.
*
* @todo Add deep merge of `postcssOptions` to better support customization
* of default processor options.
*
* @async
* @param {object} [sassOptions=null] - Customize the Sass render API options.
* If `null`, default production options are used.
* @param {object|boolean} [postcssOptions=null] - Customize the PostCSS processor API options.
* If `null`, default production options are used.
* If `false`, PostCSS processing will be ignored.
* @return {Promise}
*/
export default async function compileStyles() {
export default async function compileStyles(sassOptions = null, postcssOptions = null) {
if (sassOptions == null) {
sassOptions = productionSassOptions;
} else if (
sassOptions !== developmentSassOptions &&
sassOptions !== productionSassOptions
) {
sassOptions = Object.assign({}, defaultSassOptions, sassOptions);
}
if (postcss) {
if (postcssOptions == null) {
postcssOptions = productionPostCSSOptions;
} else if (
postcssOptions !== false &&
postcssOptions !== developmentSassOptions &&
postcssOptions !== productionSassOptions
) {
postcssOptions = Object.assign({}, defaultPostCSSOptions, postcssOptions);
}
}
loconfig.tasks.styles.forEach(async ({
infile,
outfile
@@ -33,31 +108,26 @@ export default async function compileStyles() {
infile = template(infile);
outfile = template(outfile);
let result = await sassRender({
let result = await sassRender(Object.assign({}, sassOptions, {
file: infile,
omitSourceMapUrl: true,
outFile: outfile,
outputStyle: 'compressed',
sourceMap: true,
sourceMapContents: true
});
}));
if (isPostCSSAvailable) {
if (postcss && postcssOptions) {
if (typeof postcssProcessor === 'undefined') {
postcssProcessor = postcss([
autoprefixer,
]);
postcssProcessor = createPostCSSProcessor(
postcssPluginsMap,
postcssOptions
);
}
result = await postcssProcessor.process(result.css, {
from: outfile,
to: outfile,
map: {
annotation: false,
inline: false,
sourcesContent: true
}
});
result = await postcssProcessor.process(
result.css,
Object.assign({}, postcssOptions.processor, {
from: outfile,
to: outfile,
})
);
if (result.warnings) {
const warnings = result.warnings();
@@ -112,3 +182,32 @@ export default async function compileStyles() {
}
});
};
/**
* Creates a PostCSS Processor with the given plugins and options.
*
* @param {array<(function|object)>|object<string, (function|object)>} pluginsListOrMap -
* A list or map of plugins.
* If a map of plugins, the plugin name looks up `options`.
* @param {object} options - The PostCSS options.
*/
function createPostCSSProcessor(pluginsListOrMap, options)
{
let plugins;
if (Array.isArray(pluginsListOrMap)) {
plugins = pluginsListOrMap;
} else {
plugins = [];
for (let [ name, plugin ] of Object.entries(pluginsListOrMap)) {
if (name in options) {
plugin = plugin[name](options[name]);
}
plugins.push(plugin);
}
}
return postcss(plugins);
}