mirror of
https://github.com/locomotivemtl/locomotive-boilerplate.git
synced 2026-01-15 00:55:08 +08:00
Refactor build tasks and config file
Changed:
- Renamed 'mconfig.json' to 'loconfig.json'.
- Renamed 'concat.js' to 'concats.js' to represent flexible functionality.
- loconfig.json: Base paths are nested under "paths".
- loconfig.json: Paths for tasks are nested under "tasks".
- Refactored each task to process corresponding entries under "tasks" in 'loconfig.json'.
- watch.js: Changed concats watch to use task's includes.
Added:
- tiny-glob v0.2.9
- Utility 'glob.js' to use dynamic imports to fetch an available glob function from node modules.
- Utility 'template.js' to provide a function to render template tags (`{% ... %}`) in tasks.
- concats.js: Support for concatenating groupes of files.
- scripts.js: Support for ESBuild's "outdir" option.
This commit is contained in:
@@ -28,7 +28,7 @@ npm start
|
|||||||
```
|
```
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
Change the mentions of `locomotive-boilerplate` for your project's name in `mconfig.json`. Legacy from [modularBP](https://github.com/modularorg/modularbp).
|
Rename occurrences of `locomotive-boilerplate` with your project's name in `loconfig.json`.
|
||||||
|
|
||||||
## Build
|
## Build
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { concatVendors } from './tasks/concat.js';
|
import { concatFiles } from './tasks/concats.js';
|
||||||
import { compileScripts } from './tasks/scripts.js';
|
import { compileScripts } from './tasks/scripts.js';
|
||||||
import { compileStyles } from './tasks/styles.js' ;
|
import { compileStyles } from './tasks/styles.js' ;
|
||||||
import { compileSVGs } from './tasks/svgs.js' ;
|
import { compileSVGs } from './tasks/svgs.js' ;
|
||||||
|
|
||||||
concatVendors();
|
concatFiles();
|
||||||
compileScripts();
|
compileScripts();
|
||||||
compileStyles();
|
compileStyles();
|
||||||
compileSVGs();
|
compileSVGs();
|
||||||
|
|||||||
@@ -1,49 +0,0 @@
|
|||||||
import paths from '../mconfig.json';
|
|
||||||
import message from '../utils/message.js';
|
|
||||||
import notification from '../utils/notification.js';
|
|
||||||
import concat from 'concat';
|
|
||||||
import { readdir } from 'node:fs/promises';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Concatenates third-party JavaScript files.
|
|
||||||
*/
|
|
||||||
export async function concatVendors() {
|
|
||||||
const filename = 'vendors.js';
|
|
||||||
const outfile = paths.scripts.dest + filename;
|
|
||||||
const external = [
|
|
||||||
// Add files in node_modules example:
|
|
||||||
// 'node_modules/gsap/dist/gsap.min.js',
|
|
||||||
];
|
|
||||||
|
|
||||||
const timeLabel = `${filename} concatenated in`;
|
|
||||||
console.time(timeLabel);
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Get all files in `scripts/vendors/`
|
|
||||||
let files = await readdir(paths.scripts.vendors.src);
|
|
||||||
|
|
||||||
if (files.length) {
|
|
||||||
// Exclude files that are not JavaScript
|
|
||||||
files = files.filter((file) => file.includes('.js'));
|
|
||||||
|
|
||||||
// Prepend absolute path
|
|
||||||
files = files.map((file) => paths.scripts.vendors.src + file);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (external.length) {
|
|
||||||
files = files.concat(external);
|
|
||||||
}
|
|
||||||
|
|
||||||
await concat(files, outfile);
|
|
||||||
|
|
||||||
message(`${filename} concatenated`, 'success', timeLabel);
|
|
||||||
} catch (err) {
|
|
||||||
message(`Error concatenating ${filename}`, 'error');
|
|
||||||
message(err);
|
|
||||||
|
|
||||||
notification({
|
|
||||||
title: `${filename} concatenation failed 🚨`,
|
|
||||||
message: `${err.name}: ${err.message}`
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
45
build/tasks/concats.js
Normal file
45
build/tasks/concats.js
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
import loconfig from '../../loconfig.json';
|
||||||
|
import glob from '../utils/glob.js';
|
||||||
|
import message from '../utils/message.js';
|
||||||
|
import notification from '../utils/notification.js';
|
||||||
|
import template from '../utils/template.js';
|
||||||
|
import concat from 'concat';
|
||||||
|
import { basename } from 'node:path';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Concatenates groups of files.
|
||||||
|
*/
|
||||||
|
export async function concatFiles() {
|
||||||
|
loconfig.tasks.concats.forEach(async ({
|
||||||
|
includes,
|
||||||
|
outfile
|
||||||
|
}) => {
|
||||||
|
const filename = basename(outfile || 'undefined');
|
||||||
|
|
||||||
|
const timeLabel = `${filename} concatenated in`;
|
||||||
|
console.time(timeLabel);
|
||||||
|
|
||||||
|
try {
|
||||||
|
includes = includes.map((path) => template(path));
|
||||||
|
outfile = template(outfile);
|
||||||
|
|
||||||
|
const files = await glob(includes);
|
||||||
|
|
||||||
|
await concat(files, outfile);
|
||||||
|
|
||||||
|
if (files.length) {
|
||||||
|
message(`${filename} concatenated`, 'success', timeLabel);
|
||||||
|
} else {
|
||||||
|
message(`${filename} is empty`, 'notice', timeLabel);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
message(`Error concatenating ${filename}`, 'error');
|
||||||
|
message(err);
|
||||||
|
|
||||||
|
notification({
|
||||||
|
title: `${filename} concatenation failed 🚨`,
|
||||||
|
message: `${err.name}: ${err.message}`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -1,40 +1,58 @@
|
|||||||
import paths from '../mconfig.json';
|
import loconfig from '../../loconfig.json';
|
||||||
import message from '../utils/message.js';
|
import message from '../utils/message.js';
|
||||||
import notification from '../utils/notification.js';
|
import notification from '../utils/notification.js';
|
||||||
|
import template from '../utils/template.js';
|
||||||
import esbuild from 'esbuild';
|
import esbuild from 'esbuild';
|
||||||
|
import { basename } from 'node:path';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bundles and minifies main JavaScript files.
|
* Bundles and minifies main JavaScript files.
|
||||||
*/
|
*/
|
||||||
export async function compileScripts() {
|
export async function compileScripts() {
|
||||||
[
|
loconfig.tasks.scripts.forEach(async ({
|
||||||
'app.js',
|
includes,
|
||||||
].forEach((filename) => {
|
outdir = '',
|
||||||
const includes = [ paths.scripts.src + filename ];
|
outfile = ''
|
||||||
const outfile = paths.scripts.dest + filename;
|
}) => {
|
||||||
|
const filename = basename(outdir || outfile || 'undefined');
|
||||||
|
|
||||||
const timeLabel = `${filename} compiled in`;
|
const timeLabel = `${filename} compiled in`;
|
||||||
console.time(timeLabel);
|
console.time(timeLabel);
|
||||||
|
|
||||||
esbuild.build({
|
try {
|
||||||
entryPoints: includes,
|
includes = includes.map((path) => template(path));
|
||||||
bundle: true,
|
|
||||||
minify: true,
|
if (outdir) {
|
||||||
sourcemap: true,
|
outdir = template(outdir);
|
||||||
color: true,
|
} else if (outfile) {
|
||||||
logLevel: 'error',
|
outfile = template(outfile);
|
||||||
target: [
|
} else {
|
||||||
'es2015',
|
throw new TypeError(
|
||||||
],
|
'Expected \'outdir\' or \'outfile\''
|
||||||
outfile
|
);
|
||||||
}).catch((err) => {
|
}
|
||||||
|
|
||||||
|
await esbuild.build({
|
||||||
|
entryPoints: includes,
|
||||||
|
bundle: true,
|
||||||
|
minify: true,
|
||||||
|
sourcemap: true,
|
||||||
|
color: true,
|
||||||
|
logLevel: 'error',
|
||||||
|
target: [
|
||||||
|
'es2015',
|
||||||
|
],
|
||||||
|
outdir,
|
||||||
|
outfile
|
||||||
|
});
|
||||||
|
|
||||||
|
message(`${filename} compiled`, 'success', timeLabel);
|
||||||
|
} catch (err) {
|
||||||
// errors managments (already done in esbuild)
|
// errors managments (already done in esbuild)
|
||||||
notification({
|
notification({
|
||||||
title: `${filename} compilation failed 🚨`,
|
title: `${filename} compilation failed 🚨`,
|
||||||
message: `${err.errors[0].text} in ${err.errors[0].location.file} line ${err.errors[0].location.line}`
|
message: `${err.errors[0].text} in ${err.errors[0].location.file} line ${err.errors[0].location.line}`
|
||||||
});
|
});
|
||||||
}).then(() => {
|
}
|
||||||
message(`${filename} compiled`, 'success', timeLabel);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
import paths from '../mconfig.json';
|
import loconfig from '../../loconfig.json';
|
||||||
import message from '../utils/message.js';
|
import message from '../utils/message.js';
|
||||||
import postcss from '../utils/postcss.js';
|
|
||||||
import notification from '../utils/notification.js';
|
import notification from '../utils/notification.js';
|
||||||
|
import postcss from '../utils/postcss.js';
|
||||||
|
import template from '../utils/template.js';
|
||||||
import { writeFile } from 'node:fs/promises';
|
import { writeFile } from 'node:fs/promises';
|
||||||
|
import { basename } from 'node:path';
|
||||||
import { promisify } from 'node:util';
|
import { promisify } from 'node:util';
|
||||||
import sass from 'node-sass';
|
import sass from 'node-sass';
|
||||||
|
|
||||||
@@ -12,17 +14,19 @@ const sassRender = promisify(sass.render);
|
|||||||
* Compiles and minifies main Sass files to CSS.
|
* Compiles and minifies main Sass files to CSS.
|
||||||
*/
|
*/
|
||||||
export async function compileStyles() {
|
export async function compileStyles() {
|
||||||
[
|
loconfig.tasks.styles.forEach(async ({
|
||||||
'critical',
|
infile,
|
||||||
'main',
|
outfile
|
||||||
].forEach(async (name) => {
|
}) => {
|
||||||
const infile = paths.styles.src + name + '.scss';
|
const name = basename((outfile || 'undefined'), '.scss');
|
||||||
const outfile = paths.styles.dest + name + '.css';
|
|
||||||
|
|
||||||
const timeLabel = `${name}.css compiled in`;
|
const timeLabel = `${name}.css compiled in`;
|
||||||
console.time(timeLabel);
|
console.time(timeLabel);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
infile = template(infile);
|
||||||
|
outfile = template(outfile);
|
||||||
|
|
||||||
let result = await sassRender({
|
let result = await sassRender({
|
||||||
file: infile,
|
file: infile,
|
||||||
omitSourceMapUrl: true,
|
omitSourceMapUrl: true,
|
||||||
|
|||||||
@@ -1,35 +1,37 @@
|
|||||||
import paths from '../mconfig.json';
|
import loconfig from '../../loconfig.json';
|
||||||
import message from '../utils/message.js';
|
import message from '../utils/message.js';
|
||||||
import notification from '../utils/notification.js';
|
import notification from '../utils/notification.js';
|
||||||
|
import template from '../utils/template.js';
|
||||||
|
import { basename } from 'node:path';
|
||||||
import mixer from 'svg-mixer';
|
import mixer from 'svg-mixer';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates and transforms SVG spritesheets.
|
* Generates and transforms SVG spritesheets.
|
||||||
*/
|
*/
|
||||||
export async function compileSVGs() {
|
export async function compileSVGs() {
|
||||||
[
|
loconfig.tasks.svgs.forEach(async ({
|
||||||
{
|
|
||||||
includes: [ paths.svgs.src + '*.svg' ],
|
|
||||||
filename: 'sprite.svg'
|
|
||||||
},
|
|
||||||
].forEach(({
|
|
||||||
includes,
|
includes,
|
||||||
filename
|
outfile
|
||||||
}) => {
|
}) => {
|
||||||
const outfile = paths.scripts.dest + filename;
|
const filename = basename(outfile || 'undefined');
|
||||||
|
|
||||||
const timeLabel = `${filename} compiled in`;
|
const timeLabel = `${filename} compiled in`;
|
||||||
console.time(timeLabel);
|
console.time(timeLabel);
|
||||||
|
|
||||||
mixer(includes, {
|
try {
|
||||||
spriteConfig: {
|
includes = includes.map((path) => template(path));
|
||||||
usages: false
|
outfile = template(outfile);
|
||||||
}
|
|
||||||
}).then((result) => {
|
const result = await mixer(includes, {
|
||||||
result.write(outfile).then(() => {
|
spriteConfig: {
|
||||||
message(`${filename} compiled`, 'success', timeLabel);
|
usages: false
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}).catch((err) => {
|
|
||||||
|
await result.write(outfile);
|
||||||
|
|
||||||
|
message(`${filename} compiled`, 'success', timeLabel);
|
||||||
|
} catch (err) {
|
||||||
message(`Error compiling ${filename}`, 'error');
|
message(`Error compiling ${filename}`, 'error');
|
||||||
message(err);
|
message(err);
|
||||||
|
|
||||||
@@ -37,6 +39,6 @@ export async function compileSVGs() {
|
|||||||
title: `${filename} compilation failed 🚨`,
|
title: `${filename} compilation failed 🚨`,
|
||||||
message: `${err.name}: ${err.message}`
|
message: `${err.name}: ${err.message}`
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
75
build/utils/glob.js
Normal file
75
build/utils/glob.js
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
/**
|
||||||
|
* @file Retrieve the first available glob library.
|
||||||
|
*
|
||||||
|
* Note that options vary between libraries.
|
||||||
|
*
|
||||||
|
* Candidates:
|
||||||
|
* - {@link https://npmjs.com/package/tiny-glob tiny-glob}
|
||||||
|
* - {@link https://npmjs.com/package/globby}
|
||||||
|
* - {@link https://npmjs.com/package/fast-glob fast-glob}
|
||||||
|
* - {@link https://npmjs.com/package/glob glob}
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { promisify } from 'node:util';
|
||||||
|
|
||||||
|
const modules = [
|
||||||
|
'tiny-glob',
|
||||||
|
'globby',
|
||||||
|
'fast-glob',
|
||||||
|
'glob',
|
||||||
|
];
|
||||||
|
|
||||||
|
var glob;
|
||||||
|
|
||||||
|
for (let name of modules) {
|
||||||
|
try {
|
||||||
|
glob = await import(name);
|
||||||
|
glob = glob.default;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrap the function to ensure
|
||||||
|
* a common pattern.
|
||||||
|
*/
|
||||||
|
switch (name) {
|
||||||
|
case 'tiny-glob':
|
||||||
|
glob = createArrayableGlob(glob, {
|
||||||
|
filesOnly: true
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'glob':
|
||||||
|
glob = promisify(glob);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
break; // loop
|
||||||
|
} catch (err) {
|
||||||
|
// swallow this error; skip to the next candidate.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!glob) {
|
||||||
|
throw new TypeError(
|
||||||
|
`No glob library was found, expected one of: ${modules.join(', ')}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default glob;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a wrapper function for the glob function
|
||||||
|
* to provide support for arrays of patterns.
|
||||||
|
*
|
||||||
|
* @param {function} glob - The glob function.
|
||||||
|
* @param {object} options - The glob options.
|
||||||
|
* @return {Promise}
|
||||||
|
*/
|
||||||
|
function createArrayableGlob(glob, options) {
|
||||||
|
return (patterns, options) => {
|
||||||
|
const globs = patterns.map((pattern) => glob(pattern, options));
|
||||||
|
|
||||||
|
return Promise.all(globs).then((files) => {
|
||||||
|
return [].concat.apply([], files);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
111
build/utils/template.js
Normal file
111
build/utils/template.js
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
/**
|
||||||
|
* @file Provides simple template tags.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import loconfig from '../../loconfig.json';
|
||||||
|
|
||||||
|
const templateData = flatten({
|
||||||
|
paths: loconfig.paths
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replaces all template tags from a map of keys and values.
|
||||||
|
*
|
||||||
|
* If replacement pairs contain a mix of substrings, regular expressions,
|
||||||
|
* and functions, regular expressions are executed last.
|
||||||
|
*
|
||||||
|
* @param {string} input - The string being searched and replaced on.
|
||||||
|
* @param {object} data - An object in the form `{ 'from': 'to', … }`.
|
||||||
|
* @return {string} Returns the translated string.
|
||||||
|
*/
|
||||||
|
export default function template(input, data) {
|
||||||
|
const tags = [];
|
||||||
|
|
||||||
|
if (data) {
|
||||||
|
data = flatten(data);
|
||||||
|
} else {
|
||||||
|
data = templateData;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let tag in data) {
|
||||||
|
tags.push(escapeRegExp(tag));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tags.length === 0) {
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
|
const search = new RegExp('\\{%\\s*(' + tags.join('|') + ')\\s*%\\}', 'g');
|
||||||
|
return input.replace(search, (match, key) => {
|
||||||
|
let value = data[key];
|
||||||
|
|
||||||
|
switch (typeof value) {
|
||||||
|
case 'function':
|
||||||
|
/**
|
||||||
|
* Retrieve the offset of the matched substring `args[0]`
|
||||||
|
* and the whole string being examined `args[1]`.
|
||||||
|
*/
|
||||||
|
let args = Array.prototype.slice.call(arguments, -2);
|
||||||
|
return value.call(data, match, args[0], args[1]);
|
||||||
|
|
||||||
|
case 'string':
|
||||||
|
case 'number':
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return '';
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new object with all nested object properties
|
||||||
|
* concatenated into it recursively.
|
||||||
|
*
|
||||||
|
* Nested keys are flattened into a property path:
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* {
|
||||||
|
* a: {
|
||||||
|
* b: {
|
||||||
|
* c: 1
|
||||||
|
* }
|
||||||
|
* },
|
||||||
|
* d: 1
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* ```js
|
||||||
|
* {
|
||||||
|
* "a.b.c": 1,
|
||||||
|
* "d": 1
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @param {object} input - The object to flatten.
|
||||||
|
* @param {string} prefix - The parent key prefix.
|
||||||
|
* @param {object} target - The object that will receive the flattened properties.
|
||||||
|
* @return {object} Returns the `target` object.
|
||||||
|
*/
|
||||||
|
function flatten(input, prefix, target = {}) {
|
||||||
|
for (let key in input) {
|
||||||
|
let field = (prefix ? prefix + '.' + key : key);
|
||||||
|
|
||||||
|
if (typeof input[key] === 'object') {
|
||||||
|
flatten(input[key], field, target);
|
||||||
|
} else {
|
||||||
|
target[field] = input[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Quotes regular expression characters.
|
||||||
|
*
|
||||||
|
* @param {string} str - The input string.
|
||||||
|
* @return {string} Returns the quoted (escaped) string.
|
||||||
|
*/
|
||||||
|
function escapeRegExp(str) {
|
||||||
|
return str.replace(/[\[\]\{\}\(\)\-\*\+\?\.\,\\\^\$\|\#\s]/g, '\\$&');
|
||||||
|
}
|
||||||
@@ -1,10 +1,13 @@
|
|||||||
import paths from '../mconfig.json';
|
import loconfig from '../loconfig.json';
|
||||||
import { concatVendors } from './tasks/concat.js';
|
import { concatFiles } from './tasks/concats.js';
|
||||||
import { compileScripts } from './tasks/scripts.js';
|
import { compileScripts } from './tasks/scripts.js';
|
||||||
import { compileStyles } from './tasks/styles.js' ;
|
import { compileStyles } from './tasks/styles.js' ;
|
||||||
import { compileSVGs } from './tasks/svgs.js';
|
import { compileSVGs } from './tasks/svgs.js';
|
||||||
|
import template from './utils/template.js';
|
||||||
import server from 'browser-sync';
|
import server from 'browser-sync';
|
||||||
|
|
||||||
|
const { paths, tasks } = loconfig;
|
||||||
|
|
||||||
const serverConfig = {
|
const serverConfig = {
|
||||||
open: false,
|
open: false,
|
||||||
notify: false
|
notify: false
|
||||||
@@ -23,8 +26,9 @@ if (typeof paths.url === 'string' && paths.url.length > 0) {
|
|||||||
// Start the Browsersync server
|
// Start the Browsersync server
|
||||||
server.init(serverConfig);
|
server.init(serverConfig);
|
||||||
|
|
||||||
// Build scripts, compile styles, concat vendors and generate the svgs sprite on first hit
|
// Build scripts, compile styles, concat files,
|
||||||
concatVendors();
|
// and generate spritesheets on first hit
|
||||||
|
concatFiles();
|
||||||
compileScripts();
|
compileScripts();
|
||||||
compileStyles();
|
compileStyles();
|
||||||
compileSVGs();
|
compileSVGs();
|
||||||
@@ -48,13 +52,14 @@ server.watch(
|
|||||||
compileScripts();
|
compileScripts();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Watch scripts vendors
|
// Watch concats
|
||||||
server.watch(
|
server.watch(
|
||||||
[
|
tasks.concats.reduce(
|
||||||
paths.scripts.vendors.src + '*.js',
|
(patterns, { includes }) => patterns.concat(includes),
|
||||||
]
|
[]
|
||||||
|
).map((path) => template(path))
|
||||||
).on('change', () => {
|
).on('change', () => {
|
||||||
concatVendors();
|
concatFiles();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Watch styles
|
// Watch styles
|
||||||
|
|||||||
61
loconfig.json
Executable file
61
loconfig.json
Executable file
@@ -0,0 +1,61 @@
|
|||||||
|
{
|
||||||
|
"paths": {
|
||||||
|
"url": "locomotive-boilerplate.test",
|
||||||
|
"src": "./assets",
|
||||||
|
"dest": "./www",
|
||||||
|
"images": {
|
||||||
|
"src": "./assets/images"
|
||||||
|
},
|
||||||
|
"styles": {
|
||||||
|
"src": "./assets/styles",
|
||||||
|
"dest": "./www/assets/styles"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"src": "./assets/scripts",
|
||||||
|
"dest": "./www/assets/scripts"
|
||||||
|
},
|
||||||
|
"svgs": {
|
||||||
|
"src": "./assets/images/sprite",
|
||||||
|
"dest": "./www/assets/images"
|
||||||
|
},
|
||||||
|
"views": {
|
||||||
|
"src": "./views/boilerplate/template"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tasks": {
|
||||||
|
"concats": [
|
||||||
|
{
|
||||||
|
"includes": [
|
||||||
|
"{% paths.scripts.src %}/vendors/*.js"
|
||||||
|
],
|
||||||
|
"outfile": "{% paths.scripts.dest %}/vendors.js"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"scripts": [
|
||||||
|
{
|
||||||
|
"includes": [
|
||||||
|
"{% paths.scripts.src %}/app.js"
|
||||||
|
],
|
||||||
|
"outfile": "{% paths.scripts.dest %}/app.js"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"styles": [
|
||||||
|
{
|
||||||
|
"infile": "{% paths.styles.src %}/critical.scss",
|
||||||
|
"outfile": "{% paths.styles.dest %}/critical.css"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"infile": "{% paths.styles.src %}/main.scss",
|
||||||
|
"outfile": "{% paths.styles.dest %}/main.css"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"svgs": [
|
||||||
|
{
|
||||||
|
"includes": [
|
||||||
|
"{% paths.svgs.src %}/*.svg"
|
||||||
|
],
|
||||||
|
"outfile": "{% paths.svgs.dest %}/sprite.svg"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
24
mconfig.json
24
mconfig.json
@@ -1,24 +0,0 @@
|
|||||||
{
|
|
||||||
"url": "locomotive-boilerplate.test",
|
|
||||||
"src": "./assets/",
|
|
||||||
"dest": "./www/",
|
|
||||||
"build": "./build/",
|
|
||||||
"styles": {
|
|
||||||
"src": "./assets/styles/",
|
|
||||||
"dest": "./www/assets/styles/"
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"src": "./assets/scripts/",
|
|
||||||
"dest": "./www/assets/scripts/",
|
|
||||||
"vendors": {
|
|
||||||
"src": "./assets/scripts/vendors/"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"svgs": {
|
|
||||||
"src": "./assets/images/sprite/",
|
|
||||||
"dest": "./www/assets/images/"
|
|
||||||
},
|
|
||||||
"views": {
|
|
||||||
"src": "./views/boilerplate/template/"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
47
package-lock.json
generated
47
package-lock.json
generated
@@ -23,7 +23,8 @@
|
|||||||
"node-notifier": "^10.0.0",
|
"node-notifier": "^10.0.0",
|
||||||
"node-sass": "^6.0.1",
|
"node-sass": "^6.0.1",
|
||||||
"postcss": "^8.3.6",
|
"postcss": "^8.3.6",
|
||||||
"svg-mixer": "^2.3.14"
|
"svg-mixer": "^2.3.14",
|
||||||
|
"tiny-glob": "^0.2.9"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=14.17"
|
"node": ">=14.17"
|
||||||
@@ -2505,6 +2506,18 @@
|
|||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/globalyzer": {
|
||||||
|
"version": "0.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/globalyzer/-/globalyzer-0.1.0.tgz",
|
||||||
|
"integrity": "sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"node_modules/globrex": {
|
||||||
|
"version": "0.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz",
|
||||||
|
"integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/globule": {
|
"node_modules/globule": {
|
||||||
"version": "1.3.2",
|
"version": "1.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/globule/-/globule-1.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/globule/-/globule-1.3.2.tgz",
|
||||||
@@ -6133,6 +6146,16 @@
|
|||||||
"resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-1.2.0.tgz",
|
||||||
"integrity": "sha1-bchFBSywjr78GHRyO1jySmSMO28="
|
"integrity": "sha1-bchFBSywjr78GHRyO1jySmSMO28="
|
||||||
},
|
},
|
||||||
|
"node_modules/tiny-glob": {
|
||||||
|
"version": "0.2.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.9.tgz",
|
||||||
|
"integrity": "sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"globalyzer": "0.1.0",
|
||||||
|
"globrex": "^0.1.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/to-array": {
|
"node_modules/to-array": {
|
||||||
"version": "0.1.4",
|
"version": "0.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz",
|
||||||
@@ -8545,6 +8568,18 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"globalyzer": {
|
||||||
|
"version": "0.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/globalyzer/-/globalyzer-0.1.0.tgz",
|
||||||
|
"integrity": "sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"globrex": {
|
||||||
|
"version": "0.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz",
|
||||||
|
"integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"globule": {
|
"globule": {
|
||||||
"version": "1.3.2",
|
"version": "1.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/globule/-/globule-1.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/globule/-/globule-1.3.2.tgz",
|
||||||
@@ -11506,6 +11541,16 @@
|
|||||||
"resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-1.2.0.tgz",
|
||||||
"integrity": "sha1-bchFBSywjr78GHRyO1jySmSMO28="
|
"integrity": "sha1-bchFBSywjr78GHRyO1jySmSMO28="
|
||||||
},
|
},
|
||||||
|
"tiny-glob": {
|
||||||
|
"version": "0.2.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.9.tgz",
|
||||||
|
"integrity": "sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"globalyzer": "0.1.0",
|
||||||
|
"globrex": "^0.1.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"to-array": {
|
"to-array": {
|
||||||
"version": "0.1.4",
|
"version": "0.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz",
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
"node-notifier": "^10.0.0",
|
"node-notifier": "^10.0.0",
|
||||||
"node-sass": "^6.0.1",
|
"node-sass": "^6.0.1",
|
||||||
"postcss": "^8.3.6",
|
"postcss": "^8.3.6",
|
||||||
"svg-mixer": "^2.3.14"
|
"svg-mixer": "^2.3.14",
|
||||||
|
"tiny-glob": "^0.2.9"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user