Created
May 9, 2018 01:39
-
-
Save jpravetz/39b5c86a4c8b8501ea9472993f2b7315 to your computer and use it in GitHub Desktop.
Aurelia CLI Task to Generate Webpack-compatible index.js files under the src/resources folder
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import gulp from 'gulp'; | |
import project from '../aurelia.json'; | |
import fs from 'fs'; | |
import Path from 'path'; | |
import util from 'util'; | |
/** | |
* Task generates webpack compatible index.js files under the src/resources folder, | |
* recursively descending and including every file that is found. | |
* To exclude files in a particular folder, add their names to a .resourceignore file in that | |
* folder. | |
*/ | |
const MODE = { | |
skipEmptyFolder: false, | |
config: true, | |
resources: false, | |
local: { | |
config: true, | |
resource: false | |
} | |
}; | |
const REGEX = { | |
index: /^index.(js|mjs|ts)$/i, | |
js: /\.(js|mjs|ts)$/i, | |
html: /\.(ejs|pug|jade|html)$/i, | |
base: /([^\/\.]+)\.[a-zA-Z0-9]+$/, | |
sep: /[,\s]+/ | |
}; | |
function fileBase (path) { | |
let m = path.match(REGEX.base); | |
if (m && m[1]) { | |
return m[1]; | |
} | |
} | |
function toCamelCase (str) { | |
return str.split('-').map(function (word, index) { | |
if (index === 0) { | |
return word.toLowerCase(); | |
} | |
return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase(); | |
}).join(''); | |
} | |
/** | |
* Reads the list of files to exclude, found in folder/.resourceignore file. | |
* This file should contain a white-space delimited list of file names, minus their extensions. | |
* @param root | |
* @returns {Promise<any>} | |
*/ | |
function readExclusions (root) { | |
return new Promise((resolve, reject) => { | |
let ignorePath = Path.resolve(root, '.resourceignore'); | |
fsStat(ignorePath) | |
.then((stat) => { | |
if (stat.isFile()) { | |
return fsReadFile(ignorePath) | |
.then((resp) => { | |
if (resp) { | |
let exclusions = String(resp).trim().split(REGEX.sep); | |
resolve(exclusions); | |
} | |
resolve([]); | |
}) | |
.catch((err) => { | |
resolve([]); | |
}); | |
} else { | |
resolve([]); | |
} | |
}) | |
.catch((err) => { | |
resolve([]); | |
}); | |
}); | |
} | |
const fsStat = util.promisify(fs.stat); | |
const fsReaddir = util.promisify(fs.readdir); | |
const fsReadFile = util.promisify(fs.readFile); | |
const fsWriteFile = util.promisify(fs.writeFile); | |
function runOnFolder (root, level) { | |
let exclusions = []; | |
let imports = []; | |
let resources = {}; | |
return Promise.resolve() | |
.then(() => { | |
return readExclusions(root); | |
}) | |
.then((resp) => { | |
exclusions = resp; | |
return fsReaddir(root); | |
}) | |
.then((files) => { | |
let jobs = []; | |
files.forEach(file => { | |
let path = Path.resolve(root, file); | |
let job = fsStat(path) | |
.then((stat) => { | |
if (stat.isDirectory()) { | |
imports.push(file); | |
return runOnFolder(path); | |
} else if (stat.isFile() && !REGEX.index.test(file)) { | |
let base = fileBase(file); | |
if (!exclusions.includes(base)) { | |
['js', 'html'].forEach(type => { | |
if (REGEX[type].test(file)) { | |
resources[base] = resources[base] ? resources[base] : {}; | |
resources[base][type] = true; | |
} | |
}); | |
} | |
} | |
}); | |
jobs.push(job); | |
}); | |
return Promise.all(jobs); | |
}) | |
.then((resp) => { | |
let len = Object.keys(resources).length; | |
if (MODE.skipEmptyFolder && !imports.length && !len) { | |
console.log('Skipping folder ', root); | |
return Promise.resolve(); | |
} | |
let buf = Buffer.alloc(4096); | |
let offset = 0; | |
if (len) { | |
offset += buf.write('import {PLATFORM} from \'aurelia-pal\';\n\n', offset); | |
} | |
if (imports.length) { | |
imports.forEach(name => { | |
offset += buf.write(`import ${toCamelCase(name)} from './${name}/index';\n`, offset); | |
}); | |
offset += buf.write('\n', offset); | |
} | |
if (MODE.resource) { | |
if (len) { | |
offset += buf.write('let resources = [\n', offset); | |
let idx = 0; | |
Object.keys(resources).forEach(key => { | |
let comma = (++idx < len) ? ',' : ''; | |
let resource = resources[key].js ? key : `${key}.pug`; | |
offset += buf.write(` PLATFORM.moduleName('./${resource}')${comma}\n`, offset); | |
}); | |
offset += buf.write('];\n', offset); | |
} else { | |
offset += buf.write('let resources = [];\n', offset); | |
} | |
if (MODE.resources) { | |
offset += buf.write('\nexport default resources;\n', offset); | |
} | |
} | |
if (MODE.config) { | |
offset += buf.write('const configure = function (config) {\n', offset); | |
if (len) { | |
Object.keys(resources).forEach(key => { | |
let resource = resources[key].js ? key : `${key}.pug`; | |
offset += buf.write(` config.globalResources(PLATFORM.moduleName('./${resource}'));\n`, offset); | |
}); | |
} | |
imports.forEach(name => { | |
offset += buf.write(` ${toCamelCase(name)}(config);\n`, offset); | |
}); | |
offset += buf.write('};\n', offset); | |
offset += buf.write('\nexport default configure;\n', offset); | |
} | |
// if( imports.length ) { | |
// imports.forEach(name => { | |
// offset += buf.write(`${name}.forEach(\n`, offset); | |
// }); | |
// } | |
let indexFile = Path.resolve(root, 'index.js'); | |
console.log('Generating ', indexFile); | |
return fsWriteFile(indexFile, buf.slice(0, offset)); | |
}); | |
} | |
function runMaker (done) { | |
let path = Path.resolve(project.paths.root, project.paths.resources); | |
runOnFolder(path, 0) | |
.then((resp) => { | |
done(); | |
}) | |
.catch((err) => { | |
done(err); | |
}); | |
} | |
const run = gulp.series(runMaker); | |
export {run as default}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment