UNPKG

amie

Version:

Amalgamation Made Insanely Easy. A tool to easily amalgamate stuff!

105 lines (94 loc) 3.41 kB
'use strict'; const fs = require('fs'); const path = require('path'); const async = require('async'); const defaultOptions = require('../config/defaultOptions'); let amie = { includeRegex: /^[ \t]*#[ \t]*include[ \t]/, systemIncludeRegex: /<(.+?)>/, userIncludeRegex: /"(.+?)"/ }; /** * Will process a single line of code. Effectively handling includes. * * @param {String} root Directory of the current folder. For relative includes. * @param {String} line Current line to process. * @param {Function} callback Callback to to call with the new line. */ amie.processLine = function(line, opts, callback) { if (amie.includeRegex.test(line)) { const match = amie.userIncludeRegex.exec(line); if (!match) return callback(null, line); let includePaths = []; if (opts.rootIncludePath) includePaths.push(opts.rootIncludePath); includePaths = includePaths.concat(opts.includePaths); async.detectSeries(includePaths, (filePath, done) => { fs.access(path.resolve(filePath, match[1]), (err) => done(null, !err)); }, (err, includePath) => { if (err) return callback(err); if (!includePath) return callback(new Error(`Unable to find file '${match[1]}'`)); const file = path.resolve(includePath, match[1]); amie.doFile(file, opts, callback); }); } else { callback(null, line); } }; /** * Amalgamate a string content. * * @param {String} content Content to process. * @param {Function} callback The callback to call once the process is done. */ amie.doString = function(content, opts, callback) { let lines = content.split('\n'); async.map(lines, (line, done) => amie.processLine(line, opts, done), (err, res) => callback(err, res ? res.join('\n') : undefined)); }; /** * Amalgamate a single file. * * @param {String} inputFile Path to the file to amalgamate. * @param {Function} callback The callback to call once the file is done. */ amie.doFile = function(inputFile, opts, callback) { let handle = function (err, data) { if (err) return callback(err); if (opts.caching) opts.cache[inputFile] = data; opts.rootIncludePath = path.dirname(inputFile); amie.doString(data, opts, callback); }; if (opts.caching && opts.cache[inputFile]) return handle(null, opts.cache[inputFile]); fs.readFile(inputFile, 'utf8', handle); }; /** * Main function used to amalgamate stuff. * * @param {AmieOptions} options Object defining the options for the engine. * @param {Function} callback The callback to call once amalgamated. */ amie.amalgamate = function(options, callback) { const opts = Object.assign({}, defaultOptions, options); const input = opts.input; const output = opts.output; const doer = opts.fromString ? amie.doString : amie.doFile; opts.rootIncludePath = ''; opts.cache = {}; doer(input, opts, (err, data) => { if (err) return callback(err); if (!output) { return callback(null, data); } // If an error occurred, we still pass the computed data to the callback. fs.writeFile(output, data, (err) => callback(err, data)); }); }; module.exports = amie.amalgamate;