diff --git a/config/.babelrc b/.babelrc similarity index 58% rename from config/.babelrc rename to .babelrc index 2252777..cf61652 100644 --- a/config/.babelrc +++ b/.babelrc @@ -2,8 +2,8 @@ "presets": [ ["env", { "targets": { - "browsers": "last 3 versions", + "node": "6.5", }, - }], + }] ], } \ No newline at end of file diff --git a/config/.eslintrc b/config/.eslintrc index b4ce372..9ca667f 100644 --- a/config/.eslintrc +++ b/config/.eslintrc @@ -18,14 +18,18 @@ // Optional Enables "webextensions": false, // Enable if using Web Extensions // Optional Testing Frameworks - "jasmine": false, // Enable if using Jasmine testing framework + "jasmine": true, // Enable if using Jasmine testing framework "protractor": false, // Enable if using Protractor testing framework - "mocha": false // Enable if using Mocha testing framework + "mocha": false, // Enable if using Mocha testing framework + "jest/globals": true }, "globals": { "jQuery": true, "angular": false, // Enable if using Angular }, + "plugins": [ + "jest" + ], // Do NOT change these rules "rules": { "indent": [2, 2, {"SwitchCase": 1}], diff --git a/config/webpack-node.config.js b/config/webpack-node.config.js index 6531013..3c0cb31 100644 --- a/config/webpack-node.config.js +++ b/config/webpack-node.config.js @@ -54,19 +54,7 @@ module.exports = function getConfig(env) { { test: /\.js$/, exclude: /node_modules/, - use: { - loader: 'babel-loader', - options: { - babelrc: false, - presets: [ - ['env', { - targets: { - node: 6.5, - }, - }], - ], - }, - }, + use: 'babel-loader', }, ], }, diff --git a/dist/cli/huron-cli.js b/dist/cli/huron-cli.js index 00b9dcf..8c612a8 100755 --- a/dist/cli/huron-cli.js +++ b/dist/cli/huron-cli.js @@ -3,41 +3,41 @@ /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; - +/******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { - +/******/ /******/ // Check if module is in cache -/******/ if(installedModules[moduleId]) +/******/ if(installedModules[moduleId]) { /******/ return installedModules[moduleId].exports; - +/******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ i: moduleId, /******/ l: false, /******/ exports: {} /******/ }; - +/******/ /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); - +/******/ /******/ // Flag the module as loaded /******/ module.l = true; - +/******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } - - +/******/ +/******/ /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; - +/******/ /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; - +/******/ /******/ // identity function for calling harmony imports with the correct context /******/ __webpack_require__.i = function(value) { return value; }; - +/******/ /******/ // define getter function for harmony exports /******/ __webpack_require__.d = function(exports, name, getter) { /******/ if(!__webpack_require__.o(exports, name)) { @@ -48,7 +48,7 @@ /******/ }); /******/ } /******/ }; - +/******/ /******/ // getDefaultExport function for compatibility with non-harmony modules /******/ __webpack_require__.n = function(module) { /******/ var getter = module && module.__esModule ? @@ -57,15 +57,15 @@ /******/ __webpack_require__.d(getter, 'a', getter); /******/ return getter; /******/ }; - +/******/ /******/ // Object.prototype.hasOwnProperty.call /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; - +/******/ /******/ // __webpack_public_path__ /******/ __webpack_require__.p = "../"; - +/******/ /******/ // Load entry module and return exports -/******/ return __webpack_require__(__webpack_require__.s = 24); +/******/ return __webpack_require__(__webpack_require__.s = 25); /******/ }) /************************************************************************/ /******/ ([ @@ -96,6 +96,17 @@ module.exports = require("fs-extra"); Object.defineProperty(exports, "__esModule", { value: true }); +exports.normalizeSectionData = normalizeSectionData; +exports.writeSectionData = writeSectionData; +exports.getTemplateDataPair = getTemplateDataPair; +exports.normalizeHeader = normalizeHeader; +exports.wrapMarkup = wrapMarkup; +exports.generateFilename = generateFilename; +exports.writeFile = writeFile; +exports.removeFile = removeFile; +exports.writeSectionTemplate = writeSectionTemplate; +exports.getSection = getSection; +exports.matchKssDir = matchKssDir; /** @module cli/utilities */ const cwd = process.cwd(); // Current working directory @@ -103,270 +114,265 @@ const path = __webpack_require__(0); const fs = __webpack_require__(2); const chalk = __webpack_require__(1); // Colorize terminal output -// Exports -/* eslint-disable */ -const utils = exports.utils = { - /* eslint-enable */ - - /** - * Ensure predictable data structure for KSS section data - * - * @function normalizeSectionData - * @param {object} section - section data - * @return {object} section data - */ - normalizeSectionData(section) { - const data = section.data || section; +/** + * Ensure predictable data structure for KSS section data + * + * @function normalizeSectionData + * @param {object} section - section data + * @return {object} section data + */ +function normalizeSectionData(section) { + const data = section.data || section; - if (!data.referenceURI || '' === data.referenceURI) { - data.referenceURI = section.referenceURI(); - } + if (!data.referenceURI || '' === data.referenceURI) { + data.referenceURI = section.referenceURI(); + } - return data; - }, + return data; +} - /** - * Ensure predictable data structure for KSS section data - * - * @function writeSectionData - * @param {object} store - data store - * @param {object} section - section data - * @param {string} sectionPath - output destination for section data file - */ - writeSectionData(store, section, sectionPath = false) { - let outputPath = sectionPath; - let sectionFileInfo; +/** + * Ensure predictable data structure for KSS section data + * + * @function writeSectionData + * @param {object} store - data store + * @param {object} section - section data + * @param {string} sectionPath - output destination for section data file + */ +function writeSectionData(store, section, sectionPath = false) { + let outputPath = sectionPath; + let sectionFileInfo; - if (!outputPath && {}.hasOwnProperty.call(section, 'kssPath')) { - sectionFileInfo = path.parse(section.kssPath); - outputPath = path.join(sectionFileInfo.dir, `${sectionFileInfo.name}.json`); - } + if (!outputPath && {}.hasOwnProperty.call(section, 'kssPath')) { + sectionFileInfo = path.parse(section.kssPath); + outputPath = path.join(sectionFileInfo.dir, `${sectionFileInfo.name}.json`); + } - // Output section data - if (outputPath) { - return utils.writeFile(section.referenceURI, 'section', outputPath, JSON.stringify(section), store); - } + // Output section data + if (outputPath) { + return writeFile(section.referenceURI, 'section', outputPath, JSON.stringify(section), store); + } - console.warn( // eslint-disable-line no-console - chalk.red(`Failed to write section data for ${section.referenceURI}`)); - return false; - }, + console.warn( // eslint-disable-line no-console + chalk.red(`Failed to write section data for ${section.referenceURI}`)); + return false; +} - /** - * Find .json from a template file or vice versa - * - * @function getTemplateDataPair - * @param {object} file - file object from path.parse() - * @param {object} section - KSS section data - * @return {string} relative path to module JSON file - */ - getTemplateDataPair(file, section, store) { - const huron = store.get('config'); - const kssDir = utils.matchKssDir(file.dir, huron); +/** + * Find .json from a template file or vice versa + * + * @function getTemplateDataPair + * @param {object} file - file object from path.parse() + * @param {object} section - KSS section data + * @return {string} relative path to module JSON file + */ +function getTemplateDataPair(file, section, store) { + const huron = store.get('config'); + const kssDir = matchKssDir(file.dir, huron); - if (kssDir) { - const componentPath = path.relative(path.resolve(cwd, kssDir), file.dir); - const partnerType = '.json' === file.ext ? 'template' : 'data'; - const partnerExt = '.json' === file.ext ? huron.get('templates').extension : '.json'; + if (kssDir) { + const componentPath = path.relative(path.resolve(cwd, kssDir), file.dir); + const partnerType = '.json' === file.ext ? 'template' : 'data'; + const partnerExt = '.json' === file.ext ? huron.get('templates').extension : '.json'; - const pairPath = path.join(componentPath, utils.generateFilename(section.referenceURI, partnerType, partnerExt, store)); + const pairPath = path.join(componentPath, generateFilename(section.referenceURI, partnerType, partnerExt, store)); - return `./${pairPath}`; - } + return `./${pairPath}`; + } - return false; - }, + return false; +} - /** - * Normalize a section title for use as a filename - * - * @function normalizeHeader - * @param {string} header - section header extracted from KSS documentation - * @return {string} modified header, lowercase and words separated by dash - */ - normalizeHeader(header) { - return header.toLowerCase().replace(/\s?\W\s?/g, '-'); - }, +/** + * Normalize a section title for use as a filename + * + * @function normalizeHeader + * @param {string} header - section header extracted from KSS documentation + * @return {string} modified header, lowercase and words separated by dash + */ +function normalizeHeader(header) { + return header.toLowerCase().replace(/\s?\W\s?/g, '-'); +} - /** - * Wrap html in required template tags - * - * @function wrapMarkup - * @param {string} content - html or template markup - * @param {string} templateId - id of template (should be section reference) - * @return {string} modified HTML - */ - wrapMarkup(content, templateId) { - return ` +/** + * Wrap html in required template tags + * + * @function wrapMarkup + * @param {string} content - html or template markup + * @param {string} templateId - id of template (should be section reference) + * @return {string} modified HTML + */ +function wrapMarkup(content, templateId) { + return ` \n`; - }, +} - /** - * Generate a filename based on referenceURI, type and file object - * - * @function generateFilename - * @param {string} id - The name of the file (with extension). - * @param {string} type - the type of file output - * @param {object} ext - file extension - * @param {store} store - data store - * @return {string} Path to output file, relative to ouput dir (can be use in require statements) - */ - generateFilename(id, type, ext, store) { - // Type of file and its corresponding extension(s) - const types = store.get('types'); - const outputExt = '.scss' !== ext ? ext : '.html'; - - /* eslint-disable */ - if (-1 === types.indexOf(type)) { - console.log(`Huron data ${type} does not exist`); - return false; - } - /* eslint-enable */ +/** + * Generate a filename based on referenceURI, type and file object + * + * @function generateFilename + * @param {string} id - The name of the file (with extension). + * @param {string} type - the type of file output + * @param {object} ext - file extension + * @param {store} store - data store + * @return {string} Path to output file, relative to ouput dir (can be use in require statements) + */ +function generateFilename(id, type, ext, store) { + // Type of file and its corresponding extension(s) + const types = store.get('types'); + const outputExt = '.scss' !== ext ? ext : '.html'; + + /* eslint-disable */ + if (-1 === types.indexOf(type)) { + console.log(`Huron data ${type} does not exist`); + return false; + } + /* eslint-enable */ - return `${id}-${type}${outputExt}`; - }, + return `${id}-${type}${outputExt}`; +} - /** - * Copy an HTML file into the huron output directory. - * - * @function writeFile - * @param {string} id - The name of the file (with extension). - * @param {string} content - The content of the file to write. - * @param {string} type - the type of file output - * @param {object} store - The data store - * @return {string} Path to output file, relative to ouput dir (can be use in require statements) - */ - writeFile(id, type, filepath, content, store) { - const huron = store.get('config'); - const file = path.parse(filepath); - const filename = utils.generateFilename(id, type, file.ext, store); - const kssDir = utils.matchKssDir(filepath, huron); - - if (kssDir) { - const componentPath = path.relative(path.resolve(cwd, kssDir), file.dir); - const outputRelative = path.join(huron.get('output'), componentPath, `${filename}`); - const outputPath = path.resolve(cwd, huron.get('root'), outputRelative); - let newContent = content; - - if ('data' !== type && 'section' !== type) { - newContent = utils.wrapMarkup(content, id); - } +/** + * Copy an HTML file into the huron output directory. + * + * @function writeFile + * @param {string} id - The name of the file (with extension). + * @param {string} content - The content of the file to write. + * @param {string} type - the type of file output + * @param {object} store - The data store + * @return {string} Path to output file, relative to ouput dir (can be use in require statements) + */ +function writeFile(id, type, filepath, content, store) { + const huron = store.get('config'); + const file = path.parse(filepath); + const filename = generateFilename(id, type, file.ext, store); + const kssDir = matchKssDir(filepath, huron); - try { - fs.outputFileSync(outputPath, newContent); - console.log(chalk.green(`Writing ${outputRelative}`)); // eslint-disable-line no-console - } catch (e) { - console.log(chalk.red(`Failed to write ${outputRelative}`)); // eslint-disable-line no-console - } + if (kssDir) { + const componentPath = path.relative(path.resolve(cwd, kssDir), file.dir); + const outputRelative = path.join(huron.get('output'), componentPath, `${filename}`); + const outputPath = path.resolve(cwd, huron.get('root'), outputRelative); + let newContent = content; - return `./${outputRelative.replace(`${huron.get('output')}/`, '')}`; + if ('data' !== type && 'section' !== type) { + newContent = wrapMarkup(content, id); } - return false; - }, + try { + fs.outputFileSync(outputPath, newContent); + console.log(chalk.green(`Writing ${outputRelative}`)); // eslint-disable-line no-console + } catch (e) { + console.log(chalk.red(`Failed to write ${outputRelative}`)); // eslint-disable-line no-console + } - /** - * Delete a file in the huron output directory - * - * @function removeFile - * @param {string} filename - The name of the file (with extension). - * @param {object} store - The data store - * @return {string} Path to output file, relative to ouput dir (can be use in require statements) - */ - removeFile(id, type, filepath, store) { - const huron = store.get('config'); - const file = path.parse(filepath); - const filename = utils.generateFilename(id, type, file.ext, store); - const kssDir = utils.matchKssDir(filepath, huron); + return `./${outputRelative.replace(`${huron.get('output')}/`, '')}`; + } - if (kssDir) { - const componentPath = path.relative(path.resolve(cwd, kssDir), file.dir); - const outputRelative = path.join(huron.get('output'), componentPath, `${filename}`); - const outputPath = path.resolve(cwd, huron.get('root'), outputRelative); + return false; +} - try { - fs.removeSync(outputPath); - console.log(chalk.green(`Removing ${outputRelative}`)); // eslint-disable-line no-console - } catch (e) { - console.log( // eslint-disable-line no-console - chalk.red(`${outputRelative} does not exist or cannot be deleted`)); - } +/** + * Delete a file in the huron output directory + * + * @function removeFile + * @param {string} filename - The name of the file (with extension). + * @param {object} store - The data store + * @return {string} Path to output file, relative to ouput dir (can be use in require statements) + */ +function removeFile(id, type, filepath, store) { + const huron = store.get('config'); + const file = path.parse(filepath); + const filename = generateFilename(id, type, file.ext, store); + const kssDir = matchKssDir(filepath, huron); + + if (kssDir) { + const componentPath = path.relative(path.resolve(cwd, kssDir), file.dir); + const outputRelative = path.join(huron.get('output'), componentPath, `${filename}`); + const outputPath = path.resolve(cwd, huron.get('root'), outputRelative); - return `./${outputRelative.replace(`${huron.get('output')}/`, '')}`; + try { + fs.removeSync(outputPath); + console.log(chalk.green(`Removing ${outputRelative}`)); // eslint-disable-line no-console + } catch (e) { + console.log( // eslint-disable-line no-console + chalk.red(`${outputRelative} does not exist or cannot be deleted`)); } - return false; - }, + return `./${outputRelative.replace(`${huron.get('output')}/`, '')}`; + } - /** - * Write a template for sections - * - * @function writeSectionTemplate - * @param {string} filepath - the original template file - * @param {object} store - data store - * @return {object} updated store - */ - writeSectionTemplate(filepath, store) { - const huron = store.get('config'); - const sectionTemplate = utils.wrapMarkup(fs.readFileSync(filepath, 'utf8')); - const componentPath = './huron-sections/sections.hbs'; - const output = path.join(cwd, huron.get('root'), huron.get('output'), componentPath); + return false; +} - // Move huron script and section template into huron root - fs.outputFileSync(output, sectionTemplate); - console.log(chalk.green(`writing section template to ${output}`)); // eslint-disable-line no-console +/** + * Write a template for sections + * + * @function writeSectionTemplate + * @param {string} filepath - the original template file + * @param {object} store - data store + * @return {object} updated store + */ +function writeSectionTemplate(filepath, store) { + const huron = store.get('config'); + const sectionTemplate = wrapMarkup(fs.readFileSync(filepath, 'utf8')); + const componentPath = './huron-sections/sections.hbs'; + const output = path.join(cwd, huron.get('root'), huron.get('output'), componentPath); - return store.set('sectionTemplatePath', componentPath); - }, + // Move huron script and section template into huron root + fs.outputFileSync(output, sectionTemplate); + console.log(chalk.green(`writing section template to ${output}`)); // eslint-disable-line no-console - /** - * Request for section data based on section reference - * - * @function writeSectionTemplate - * @param {string} search - key on which to match section - * @param {field} string - field in which to look to determine section - * @param {obj} store - sections memory store - */ - getSection(search, field, store) { - const sectionValues = store.getIn(['sections', 'sectionsByPath']).valueSeq(); - let selectedSection = false; + return store.set('sectionTemplatePath', componentPath); +} - if (field) { - selectedSection = sectionValues.filter(value => value[field] === search).get(0); - } else { - selectedSection = store.getIn(['sections', 'sectionsByPath', search]); - } +/** + * Request for section data based on section reference + * + * @function writeSectionTemplate + * @param {string} search - key on which to match section + * @param {field} string - field in which to look to determine section + * @param {obj} store - sections memory store + */ +function getSection(search, field, store) { + const sectionValues = store.getIn(['sections', 'sectionsByPath']).valueSeq(); + let selectedSection = false; - return selectedSection; - }, + if (field) { + selectedSection = sectionValues.filter(value => value[field] === search).get(0); + } else { + selectedSection = store.getIn(['sections', 'sectionsByPath', search]); + } - /** - * Match which configured KSS directory the current file - * - * @function matchKssDir - * @param {string} search - key on which to match section - * @param {field} string - field in which to look to determine section - * @param {obj} sections - sections memory store - * @return {string} kssMatch - relative path to KSS directory - */ - matchKssDir(filepath, huron) { - const kssSource = huron.get('kss'); - /* eslint-disable space-unary-ops */ - const kssMatch = kssSource.filter(dir => -1 !== filepath.indexOf(dir)); - /* eslint-enable space-unary-ops */ - - if (kssMatch.length) { - return kssMatch[0]; - } + return selectedSection; +} - console.error(chalk.red(`filepath ${filepath} does not exist in any - of the configured KSS directories`)); - return false; +/** + * Find which configured KSS directory a filepath exists in + * + * @function matchKssDir + * @param {string} filepath - filepath to search for + * @param {object} huron - huron configuration + * @return {string} kssMatch - relative path to KSS directory + */ +function matchKssDir(filepath, huron) { + const kssSource = huron.get('kss'); + /* eslint-disable space-unary-ops */ + // Include forward slash in our test to make sure we're matchin a directory, not a file extension + const kssMatch = kssSource.filter(dir => filepath.includes(`/${dir}`)); + /* eslint-enable space-unary-ops */ + + if (kssMatch.length) { + return kssMatch[0]; } -}; + + console.error(chalk.red(`filepath ${filepath} does not exist in any + of the configured KSS directories`)); + + return false; +} /***/ }), /* 4 */ @@ -383,7 +389,7 @@ Object.defineProperty(exports, "__esModule", { // Requires /** @global */ -const program = __webpack_require__(17); // Easy program flags +const program = __webpack_require__(18); // Easy program flags const path = __webpack_require__(0); exports.default = program; @@ -409,9 +415,14 @@ function parseArgs() { return true; }); - program.version('1.0.1').option('-c, --huron-config [huronConfig]', '[huronConfig] for all huron options', path.resolve(__dirname, '../default-config/huron.config.js')).option('-w, --webpack-config [webpackConfig]', '[webpackConfig] for all webpack options', path.resolve(__dirname, '../default-config/webpack.config.js')).option('-p, --production', 'compile assets once for production').parse(process.argv); + program.version('1.0.1').option('-c, --huron-config [huronConfig]', '[huronConfig] for all huron options', path.resolve(__dirname, '../default-config/huron.config.js')).option('-w, --webpack-config [webpackConfig]', '[webpackConfig] for all webpack options', path.resolve(__dirname, '../default-config/webpack.config.js')).option('-p, --production', 'compile assets once for production'); program.env = envArg; + + // Only parse if we're not running tests + if (!process.env.npm_lifecycle_event || 'test' !== process.env.npm_lifecycle_event) { + program.parse(process.argv); + } } parseArgs(); @@ -433,80 +444,81 @@ module.exports = require("webpack"); Object.defineProperty(exports, "__esModule", { value: true }); -exports.templateHandler = undefined; +exports.updateTemplate = updateTemplate; +exports.deleteTemplate = deleteTemplate; var _utils = __webpack_require__(3); +var utils = _interopRequireWildcard(_utils); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + const path = __webpack_require__(0); /** @module cli/template-handler */ const fs = __webpack_require__(2); const chalk = __webpack_require__(1); -/* eslint-disable */ -const templateHandler = exports.templateHandler = { - /* eslint-enable */ - /** - * Handle update of a template or data (json) file - * - * @function updateTemplate - * @param {string} filepath - filepath of changed file (comes from gaze) - * @param {object} section - contains KSS section data - * @param {object} store - memory store - * @return {object} updated memory store - */ - updateTemplate(filepath, section, store) { - const file = path.parse(filepath); - const pairPath = _utils.utils.getTemplateDataPair(file, section, store); - const type = '.json' === file.ext ? 'data' : 'template'; - const newSection = section; - const newStore = store; - let content = false; - - try { - content = fs.readFileSync(filepath, 'utf8'); - } catch (e) { - console.log(chalk.red(`${filepath} does not exist`)); - } - - if (content) { - const requirePath = _utils.utils.writeFile(newSection.referenceURI, type, filepath, content, newStore); - newSection[`${type}Path`] = requirePath; +/** + * Handle update of a template or data (json) file + * + * @function updateTemplate + * @param {string} filepath - filepath of changed file (comes from gaze) + * @param {object} section - contains KSS section data + * @param {object} store - memory store + * @return {object} updated memory store + */ +function updateTemplate(filepath, section, store) { + const file = path.parse(filepath); + const pairPath = utils.getTemplateDataPair(file, section, store); + const type = '.json' === file.ext ? 'data' : 'template'; + const newSection = section; + const newStore = store; + let content = false; + + try { + content = fs.readFileSync(filepath, 'utf8'); + } catch (e) { + console.log(chalk.red(`${filepath} does not exist`)); + } - if ('template' === type) { - newSection.templateContent = content; + if (content) { + const requirePath = utils.writeFile(newSection.referenceURI, type, filepath, content, newStore); + newSection[`${type}Path`] = requirePath; - // Rewrite section data with template content - newSection.sectionPath = _utils.utils.writeSectionData(newStore, newSection); - } + if ('template' === type) { + newSection.templateContent = content; - return newStore.setIn(['templates', requirePath], pairPath).setIn(['sections', 'sectionsByPath', newSection.kssPath], newSection).setIn(['sections', 'sectionsByURI', newSection.referenceURI], newSection); + // Rewrite section data with template content + newSection.sectionPath = utils.writeSectionData(newStore, newSection); } - return newStore; - }, + return newStore.setIn(['templates', requirePath], pairPath).setIn(['sections', 'sectionsByPath', newSection.kssPath], newSection).setIn(['sections', 'sectionsByURI', newSection.referenceURI], newSection); + } - /** - * Handle removal of a template or data (json) file - * - * @function deleteTemplate - * @param {string} filepath - filepath of changed file (comes from gaze) - * @param {object} section - contains KSS section data - * @param {object} store - memory store - * @return {object} updated memory store - */ - deleteTemplate(filepath, section, store) { - const file = path.parse(filepath); - const type = '.json' === file.ext ? 'data' : 'template'; - const newSection = section; - const newStore = store; + return newStore; +} + +/** + * Handle removal of a template or data (json) file + * + * @function deleteTemplate + * @param {string} filepath - filepath of changed file (comes from gaze) + * @param {object} section - contains KSS section data + * @param {object} store - memory store + * @return {object} updated memory store + */ +function deleteTemplate(filepath, section, store) { + const file = path.parse(filepath); + const type = '.json' === file.ext ? 'data' : 'template'; + const newSection = section; + const newStore = store; - // Remove partner - const requirePath = _utils.utils.removeFile(newSection.referenceURI, type, filepath, newStore); - delete newSection[`${type}Path`]; + // Remove partner + const requirePath = utils.removeFile(newSection.referenceURI, type, filepath, newStore); + delete newSection[`${type}Path`]; - return newStore.deleteIn(['templates', requirePath]).setIn(['sections', 'sectionsByPath', newSection.kssPath], newSection).setIn(['sections', 'sectionsByURI', newSection.referenceURI], newSection); - } -}; + return newStore.deleteIn(['templates', requirePath]).setIn(['sections', 'sectionsByPath', newSection.kssPath], newSection).setIn(['sections', 'sectionsByURI', newSection.referenceURI], newSection); +} /***/ }), /* 7 */ @@ -640,71 +652,40 @@ var _parseArgs = __webpack_require__(4); var _parseArgs2 = _interopRequireDefault(_parseArgs); -var _generateConfig = __webpack_require__(10); - -var _generateConfig2 = _interopRequireDefault(_generateConfig); - -var _server = __webpack_require__(14); +var _server = __webpack_require__(15); var _server2 = _interopRequireDefault(_server); +var _huronStore = __webpack_require__(13); + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } // Modules const path = __webpack_require__(0); // Local imports -const Gaze = __webpack_require__(18).Gaze; -const Immutable = __webpack_require__(20); +const Gaze = __webpack_require__(19).Gaze; const chalk = __webpack_require__(1); // Colorize terminal output -// Merge Huron default webpack config with user config -const config = (0, _generateConfig2.default)(); - /** * Huron configuration object * * @global */ -const huron = config.huron; - -// Make sure the kss option is represented as an array -huron.kss = Array.isArray(huron.kss) ? huron.kss : [huron.kss]; +const huron = _huronStore.dataStructure.get('config'); /** * Available file extensions. Extensions should not include the leading '.' * * @global */ -const extensions = [huron.kssExtension, huron.templates.extension, 'html', 'json'].map(extension => extension.replace('.', '')); - -// Create initial data structure -/* eslint-disable */ -/** - * Initial structure for immutable data store - * - * @global - */ -const dataStructure = Immutable.Map({ - types: ['template', 'data', 'description', 'section', 'prototype', 'sections-template'], - config: Immutable.Map(config.huron), - sections: Immutable.Map({ - sectionsByPath: Immutable.Map({}), - sectionsByURI: Immutable.Map({}), - sorted: {} - }), - templates: Immutable.Map({}), - prototypes: Immutable.Map({}), - sectionTemplatePath: '', - referenceDelimiter: '.' -}); -/* eslint-enable */ +const extensions = [huron.get('kssExtension'), huron.get('templates').extension, 'html', 'json'].map(extension => extension.replace('.', '')); // Generate watch list for Gaze, start gaze const gazeWatch = []; // Push KSS source directories and section template to Gaze -gazeWatch.push(path.resolve(__dirname, huron.sectionTemplate)); -huron.kss.forEach(sourceDir => { +gazeWatch.push(path.resolve(__dirname, huron.get('sectionTemplate'))); +huron.get('kss').forEach(sourceDir => { let gazeDir = sourceDir; /* eslint-disable space-unary-ops */ @@ -728,7 +709,7 @@ const gaze = new Gaze(gazeWatch); * * @global */ -const store = (0, _actions.initFiles)(gaze.watched(), dataStructure); +const store = (0, _actions.initFiles)(gaze.watched(), _huronStore.dataStructure); (0, _requireTemplates.requireTemplates)(store); (0, _requireTemplates.writeStore)(store); @@ -793,7 +774,7 @@ if (!_parseArgs2.default.production) { } // Start webpack or build for production -(0, _server2.default)(config); +(0, _server2.default)(_huronStore.config); if (false) { module.hot.accept(); @@ -821,6 +802,10 @@ var _handleKss = __webpack_require__(12); var _utils = __webpack_require__(3); +var utils = _interopRequireWildcard(_utils); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + // Requires /** @module cli/actions */ @@ -882,18 +867,18 @@ function updateFile(filepath, store) { let section; if (-1 !== filepath.indexOf(huron.get('sectionTemplate'))) { - return _utils.utils.writeSectionTemplate(filepath, store); + return utils.writeSectionTemplate(filepath, store); } switch (file.ext) { // Plain HTML template, external case '.html': - section = _utils.utils.getSection(file.base, 'markup', store); + section = utils.getSection(file.base, 'markup', store); if (section) { - return _handleHtml.htmlHandler.updateTemplate(filepath, section, store); + return (0, _handleHtml.updateHTML)(filepath, section, store); } else if (-1 !== file.dir.indexOf('prototypes') && -1 !== file.name.indexOf('prototype-')) { - return _handleHtml.htmlHandler.updatePrototype(filepath, store); + return (0, _handleHtml.updatePrototype)(filepath, store); } console.log(chalk.red(`Failed to write file: ${file.name}`)); @@ -903,10 +888,10 @@ function updateFile(filepath, store) { case huron.get('templates').extension: case '.json': field = '.json' === file.ext ? 'data' : 'markup'; - section = _utils.utils.getSection(file.base, field, store); + section = utils.getSection(file.base, field, store); if (section) { - return _handleTemplates.templateHandler.updateTemplate(filepath, section, store); + return (0, _handleTemplates.updateTemplate)(filepath, section, store); } console.log( // eslint-disable-line no-console @@ -917,7 +902,7 @@ function updateFile(filepath, store) { // Will also output a template if markup is inline // Note: inline markup does _not_ support handlebars currently case huron.get('kssExtension'): - return _handleKss.kssHandler.updateKSS(filepath, store); + return (0, _handleKss.updateKSS)(filepath, store); // This should never happen if Gaze is working properly default: @@ -944,30 +929,30 @@ function deleteFile(filepath, store) { switch (file.ext) { // Plain HTML template, external case '.html': - section = _utils.utils.getSection(file.base, 'markup', store); + section = utils.getSection(file.base, 'markup', store); if (section) { - newStore = _handleHtml.htmlHandler.deleteTemplate(filepath, section, store); + newStore = (0, _handleHtml.deleteHTML)(filepath, section, store); } else if (-1 !== file.dir.indexOf('prototypes') && -1 !== file.name.indexOf('prototype-')) { - newStore = _handleHtml.htmlHandler.deletePrototype(filepath, store); + newStore = (0, _handleHtml.deletePrototype)(filepath, store); } break; case huron.get('templates').extension: case '.json': field = '.json' === file.ext ? 'data' : 'markup'; - section = _utils.utils.getSection(file.base, field, store); + section = utils.getSection(file.base, field, store); if (section) { - newStore = _handleTemplates.templateHandler.deleteTemplate(filepath, section, store); + newStore = (0, _handleTemplates.deleteTemplate)(filepath, section, store); } break; case huron.get('kssExtension'): - section = _utils.utils.getSection(filepath, false, store); + section = utils.getSection(filepath, false, store); if (section) { - newStore = _handleKss.kssHandler.deleteKSS(filepath, section, store); + newStore = (0, _handleKss.deleteKSS)(filepath, section, store); } break; @@ -996,7 +981,7 @@ var _parseArgs = __webpack_require__(4); var _parseArgs2 = _interopRequireDefault(_parseArgs); -var _requireExternal = __webpack_require__(13); +var _requireExternal = __webpack_require__(14); var _requireExternal2 = _interopRequireDefault(_requireExternal); @@ -1006,16 +991,16 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de const cwd = process.cwd(); const path = __webpack_require__(0); -const url = __webpack_require__(22); +const url = __webpack_require__(23); const fs = __webpack_require__(2); const webpack = __webpack_require__(5); -const HTMLWebpackPlugin = __webpack_require__(19); -const defaultConfig = __webpack_require__(16); -const defaultHuron = __webpack_require__(15); +const HTMLWebpackPlugin = __webpack_require__(20); +const defaultConfig = __webpack_require__(17); +const defaultHuron = __webpack_require__(16); // Require configs passed in by user from CLI -const localConfigPath = path.join(cwd, _parseArgs2.default.webpackConfig); -const localHuronPath = path.join(cwd, _parseArgs2.default.huronConfig); +const localConfigPath = !path.isAbsolute(_parseArgs2.default.webpackConfig) ? path.join(cwd, _parseArgs2.default.webpackConfig) : _parseArgs2.default.webpackConfig; +const localHuronPath = !path.isAbsolute(_parseArgs2.default.huronConfig) ? path.join(cwd, _parseArgs2.default.huronConfig) : _parseArgs2.default.huronConfig; const localConfig = (0, _requireExternal2.default)(localConfigPath); const localHuron = (0, _requireExternal2.default)(localHuronPath); @@ -1265,102 +1250,104 @@ function moveAdditionalAssets(assets, subdir = '', huron) { Object.defineProperty(exports, "__esModule", { value: true }); -exports.htmlHandler = undefined; +exports.updateHTML = updateHTML; +exports.deleteHTML = deleteHTML; +exports.updatePrototype = updatePrototype; +exports.deletePrototype = deletePrototype; var _utils = __webpack_require__(3); +var utils = _interopRequireWildcard(_utils); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + const path = __webpack_require__(0); /** @module cli/html-handler */ const fs = __webpack_require__(2); -/* eslint-disable */ -const htmlHandler = exports.htmlHandler = { - /* eslint-enable */ - - /** - * Handle update of an HMTL template - * - * @function updateTemplate - * @param {string} filepath - filepath of changed file (comes from gaze) - * @param {object} section - contains KSS section data - * @param {object} store - memory store - * @return {object} updated data store - */ - updateTemplate(filepath, section, store) { - const file = path.parse(filepath); - const content = fs.readFileSync(filepath, 'utf8'); - const newSection = section; +/** + * Handle update of an HMTL template + * + * @function updateHTML + * @param {string} filepath - filepath of changed file (comes from gaze) + * @param {object} section - contains KSS section data + * @param {object} store - memory store + * @return {object} updated data store + */ +function updateHTML(filepath, section, store) { + const file = path.parse(filepath); + const content = fs.readFileSync(filepath, 'utf8'); + const newSection = section; - if (content) { - newSection.templatePath = _utils.utils.writeFile(section.referenceURI, 'template', filepath, content, store); - newSection.templateContent = content; + if (content) { + newSection.templatePath = utils.writeFile(section.referenceURI, 'template', filepath, content, store); + newSection.templateContent = content; - // Rewrite section data with template content - newSection.sectionPath = _utils.utils.writeSectionData(store, newSection); + // Rewrite section data with template content + newSection.sectionPath = utils.writeSectionData(store, newSection); - return store.setIn(['sections', 'sectionsByPath', section.kssPath], newSection).setIn(['sections', 'sectionsByURI', section.referenceURI], newSection); - } + return store.setIn(['sections', 'sectionsByPath', section.kssPath], newSection).setIn(['sections', 'sectionsByURI', section.referenceURI], newSection); + } - console.log(`File ${file.base} could not be read`); - return store; - }, + console.log(`File ${file.base} could not be read`); + return store; +} - /** - * Handle removal of an HMTL template - * - * @function deleteTemplate - * @param {string} filepath - filepath of changed file (comes from gaze) - * @param {object} section - contains KSS section data - * @param {object} store - memory store - * @return {object} updated data store - */ - deleteTemplate(filepath, section, store) { - const newSection = section; +/** + * Handle removal of an HMTL template + * + * @function deleteHTML + * @param {string} filepath - filepath of changed file (comes from gaze) + * @param {object} section - contains KSS section data + * @param {object} store - memory store + * @return {object} updated data store + */ +function deleteHTML(filepath, section, store) { + const newSection = section; - _utils.utils.removeFile(newSection.referenceURI, 'template', filepath, store); + utils.removeFile(newSection.referenceURI, 'template', filepath, store); - delete newSection.templatePath; + delete newSection.templatePath; - return store.setIn(['sections', 'sectionsByPath', section.kssPath], newSection).setIn(['sections', 'sectionsByURI', section.referenceURI], newSection); - }, + return store.setIn(['sections', 'sectionsByPath', section.kssPath], newSection).setIn(['sections', 'sectionsByURI', section.referenceURI], newSection); +} - /** - * Handle update for a prototype file - * - * @function updatePrototype - * @param {string} filepath - filepath of changed file (comes from gaze) - * @param {object} store - memory store - * @return {object} updated data store - */ - updatePrototype(filepath, store) { - const file = path.parse(filepath); - const content = fs.readFileSync(filepath, 'utf8'); +/** + * Handle update for a prototype file + * + * @function updatePrototype + * @param {string} filepath - filepath of changed file (comes from gaze) + * @param {object} store - memory store + * @return {object} updated data store + */ +function updatePrototype(filepath, store) { + const file = path.parse(filepath); + const content = fs.readFileSync(filepath, 'utf8'); - if (content) { - const requirePath = _utils.utils.writeFile(file.name, 'prototype', filepath, content, store); + if (content) { + const requirePath = utils.writeFile(file.name, 'prototype', filepath, content, store); - return store.setIn(['prototypes', file.name], requirePath); - } + return store.setIn(['prototypes', file.name], requirePath); + } - console.log(`File ${file.base} could not be read`); - return store; - }, + console.log(`File ${file.base} could not be read`); + return store; +} - /** - * Handle removal of a prototype file - * - * @function deletePrototype - * @param {string} filepath - filepath of changed file (comes from gaze) - * @param {object} store - memory store - * @return {object} updated data store - */ - deletePrototype(filepath, store) { - const file = path.parse(filepath); - const requirePath = _utils.utils.removeFile(file.name, 'prototype', filepath, store); +/** + * Handle removal of a prototype file + * + * @function deletePrototype + * @param {string} filepath - filepath of changed file (comes from gaze) + * @param {object} store - memory store + * @return {object} updated data store + */ +function deletePrototype(filepath, store) { + const file = path.parse(filepath); + const requirePath = utils.removeFile(file.name, 'prototype', filepath, store); - return store.setIn(['prototypes', file.name], requirePath); - } -}; + return store.setIn(['prototypes', file.name], requirePath); +} /***/ }), /* 12 */ @@ -1372,319 +1359,371 @@ const htmlHandler = exports.htmlHandler = { Object.defineProperty(exports, "__esModule", { value: true }); -exports.kssHandler = undefined; +exports.updateKSS = updateKSS; +exports.deleteKSS = deleteKSS; var _utils = __webpack_require__(3); +var utils = _interopRequireWildcard(_utils); + var _handleTemplates = __webpack_require__(6); var _requireTemplates = __webpack_require__(7); +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + const path = __webpack_require__(0); /** @module cli/kss-handler */ const fs = __webpack_require__(2); -const parse = __webpack_require__(21).parse; +const parse = __webpack_require__(22).parse; const chalk = __webpack_require__(1); // Colorize terminal output -/* eslint-disable */ -const kssHandler = exports.kssHandler = { - /* eslint-enable */ +/** + * Handle update of a KSS section + * + * @function updateKSS + * @param {string} filepath - filepath of changed file (comes from gaze) + * @param {object} store - memory store + * @return {object} updated data store + */ +function updateKSS(filepath, store) { + const kssSource = fs.readFileSync(filepath, 'utf8'); + const huron = store.get('config'); + const oldSection = utils.getSection(filepath, false, store) || {}; + const file = path.parse(filepath); + let newStore = store; - /** - * Handle update of a KSS section - * - * @function updateKSS - * @param {string} filepath - filepath of changed file (comes from gaze) - * @param {object} store - memory store - * @return {object} updated data store - */ - updateKSS(filepath, store) { - const kssSource = fs.readFileSync(filepath, 'utf8'); - const huron = store.get('config'); - const oldSection = _utils.utils.getSection(filepath, false, store) || {}; - const file = path.parse(filepath); - let newStore = store; - - if (kssSource) { - const styleguide = parse(kssSource, huron.get('kssOptions')); - - if (styleguide.data.sections.length) { - const section = _utils.utils.normalizeSectionData(styleguide.data.sections[0]); - - if (section.reference && section.referenceURI) { - // Update or add section data - newStore = kssHandler.updateSectionData(filepath, section, oldSection, newStore); - - // Remove old section data if reference URI has changed - if (oldSection && oldSection.referenceURI && oldSection.referenceURI !== section.referenceURI) { - newStore = this.unsetSection(oldSection, file, newStore, false); - } - - (0, _requireTemplates.writeStore)(newStore); - console.log(chalk.green(`KSS source in ${filepath} changed or added`)); - return newStore; + if (kssSource) { + const styleguide = parse(kssSource, huron.get('kssOptions')); + + if (styleguide.data.sections.length) { + const section = utils.normalizeSectionData(styleguide.data.sections[0]); + + if (section.reference && section.referenceURI) { + // Update or add section data + newStore = updateSectionData(filepath, section, oldSection, newStore); + + // Remove old section data if reference URI has changed + if (oldSection && oldSection.referenceURI && oldSection.referenceURI !== section.referenceURI) { + newStore = unsetSection(oldSection, file, newStore, false); } - console.log(chalk.magenta(`KSS section in ${filepath} is missing a section reference`)); + (0, _requireTemplates.writeStore)(newStore); + console.log(chalk.green(`KSS source in ${filepath} changed or added`)); return newStore; } - console.log(chalk.magenta(`No KSS found in ${filepath}`)); + console.log(chalk.magenta(`KSS section in ${filepath} is missing a section reference`)); return newStore; } - if (oldSection) { - newStore = kssHandler.deleteKSS(filepath, oldSection, newStore); - } - - console.log(chalk.red(`${filepath} not found or empty`)); // eslint-disable-line no-console + console.log(chalk.magenta(`No KSS found in ${filepath}`)); return newStore; - }, + } - /** - * Handle removal of a KSS section - * - * @function deleteKSS - * @param {string} filepath - filepath of changed file (comes from gaze) - * @param {object} section - KSS section data - * @param {object} store - memory store - * @return {object} updated data store - */ - deleteKSS(filepath, section, store) { - const file = path.parse(filepath); + if (oldSection) { + newStore = deleteKSS(filepath, oldSection, newStore); + } - if (section.reference && section.referenceURI) { - // Remove section data from memory store - return kssHandler.unsetSection(section, file, store, true); - } + console.log(chalk.red(`${filepath} not found or empty`)); // eslint-disable-line no-console + return newStore; +} - return store; - }, +/** + * Handle removal of a KSS section + * + * @function deleteKSS + * @param {string} filepath - filepath of changed file (comes from gaze) + * @param {object} section - KSS section data + * @param {object} store - memory store + * @return {object} updated data store + */ +function deleteKSS(filepath, section, store) { + const file = path.parse(filepath); - /** - * Update the sections store with new data for a specific section - * - * @function updateSectionData - * @param {object} section - contains updated section data - * @param {string} kssPath - path to KSS section - * @param {object} store - memory store - * @return {object} updated data store - */ - updateSectionData(kssPath, section, oldSection, store) { - const sectionFileInfo = path.parse(kssPath); - const dataFilepath = path.join(sectionFileInfo.dir, `${sectionFileInfo.name}.json`); - const isInline = null !== section.markup.match(/<\/[^>]*>/); - const newSort = kssHandler.sortSection(store.getIn(['sections', 'sorted']), section.reference, store.get('referenceDelimiter')); - const newSection = Object.assign({}, oldSection, section); - let newStore = store; - - // Required for reference from templates and data - newSection.kssPath = kssPath; - - if (isInline) { - // Set section value if inlineTempalte() returned a path - newStore = kssHandler.updateInlineTemplate(kssPath, oldSection, newSection, newStore); - } else { - // Remove inline template, if it exists - _utils.utils.removeFile(newSection.referenceURI, 'template', kssPath, store); - // Update markup and data fields - newStore = kssHandler.updateTemplateFields(sectionFileInfo, oldSection, newSection, newStore); - } + if (section.reference && section.referenceURI) { + // Remove section data from memory store + return unsetSection(section, file, store, true); + } - // Output section description - newStore = kssHandler.updateDescription(kssPath, oldSection, newSection, newStore); + return store; +} - // Output section data to a JSON file - newSection.sectionPath = _utils.utils.writeSectionData(newStore, newSection, dataFilepath); +/** + * Update the sections store with new data for a specific section + * + * @function updateSectionData + * @param {object} section - contains updated section data + * @param {string} kssPath - path to KSS section + * @param {object} store - memory store + * @return {object} updated data store + */ +function updateSectionData(kssPath, section, oldSection, store) { + const sectionFileInfo = path.parse(kssPath); + const dataFilepath = path.join(sectionFileInfo.dir, `${sectionFileInfo.name}.json`); + const isInline = null !== section.markup.match(/<\/[^>]*>/); + const newSort = sortSection(store.getIn(['sections', 'sorted']), section.reference, store.get('referenceDelimiter')); + const newSection = Object.assign({}, oldSection, section); + let newStore = store; - // Update section sorting - return newStore.setIn(['sections', 'sorted'], newSort).setIn(['sections', 'sectionsByPath', kssPath], newSection).setIn(['sections', 'sectionsByURI', section.referenceURI], newSection); - }, + // Required for reference from templates and data + newSection.kssPath = kssPath; - /** - * Handle detection and output of inline templates, which is markup written - * in the KSS documentation itself as opposed to an external file - * - * @function updateInlineTemplate - * @param {string} oldSection - previous iteration of KSS data, if updated - * @param {object} section - KSS section data - * @return {object} updated data store with new template path info - */ - updateInlineTemplate(filepath, oldSection, section, store) { - const newSection = section; - const newStore = store; + if (isInline) { + // Set section value if inlineTempalte() returned a path + newStore = updateInlineTemplate(kssPath, oldSection, newSection, newStore); + } else { + // Remove inline template, if it exists + utils.removeFile(newSection.referenceURI, 'template', kssPath, store); + // Update markup and data fields + newStore = updateTemplateFields(sectionFileInfo, oldSection, newSection, newStore); + } - // If we have inline markup - if (this.fieldShouldOutput(oldSection, section, 'markup')) { - newSection.templatePath = _utils.utils.writeFile(section.referenceURI, 'template', filepath, section.markup, store); - newSection.templateContent = section.markup; + // Output section description + newStore = updateDescription(kssPath, oldSection, newSection, newStore); - return newStore.setIn(['sections', 'sectionsByPath', filepath], newSection).setIn(['sections', 'sectionsByURI', section.referenceURI], newSection); - } + // Output section data to a JSON file + newSection.sectionPath = utils.writeSectionData(newStore, newSection, dataFilepath); - return newStore; - }, + // Update section sorting + return newStore.setIn(['sections', 'sorted'], newSort).setIn(['sections', 'sectionsByPath', kssPath], newSection).setIn(['sections', 'sectionsByURI', section.referenceURI], newSection); +} - /** - * Handle output of section description - * - * @function updateDescription - * @param {string} oldSection - previous iteration of KSS data, if updated - * @param {object} section - KSS section data - * @return {object} updated data store with new descripton path info - */ - updateDescription(filepath, oldSection, section, store) { - const newSection = section; - const newStore = store; +/** + * Handle detection and output of inline templates, which is markup written + * in the KSS documentation itself as opposed to an external file + * + * @function updateInlineTemplate + * @param {string} oldSection - previous iteration of KSS data, if updated + * @param {object} section - KSS section data + * @return {object} updated data store with new template path info + */ +function updateInlineTemplate(filepath, oldSection, section, store) { + const newSection = section; + const newStore = store; - // If we don't have previous KSS or the KSS has been updated - if (this.fieldShouldOutput(oldSection, section, 'description')) { - // Write new description - newSection.descriptionPath = _utils.utils.writeFile(section.referenceURI, 'description', filepath, section.description, store); + // If we have inline markup + if (fieldShouldOutput(oldSection, section, 'markup')) { + newSection.templatePath = utils.writeFile(section.referenceURI, 'template', filepath, section.markup, store); + newSection.templateContent = section.markup; - return newStore.setIn(['sections', 'sectionsByPath', filepath], newSection).setIn(['sections', 'sectionsByURI', section.referenceURI], newSection); - } + return newStore.setIn(['sections', 'sectionsByPath', filepath], newSection).setIn(['sections', 'sectionsByURI', section.referenceURI], newSection); + } - return newStore; - }, + return newStore; +} - /** - * Handle Data and Markup fields - * - * @function updateTemplateFields - * @param {string} file - File data for KSS file from path.parse() - * @param {object} oldSection - outdated KSS data - * @param {object} section - KSS section data - * @param {object} store - memory store - * @return {object} KSS section data with updated asset paths - */ - updateTemplateFields(file, oldSection, section, store) { - const kssPath = path.format(file); - const newSection = section; - let filepath = ''; - let oldFilepath = ''; - let newStore = store; - - ['data', 'markup'].forEach(field => { - if (newSection[field]) { - if (oldSection[field]) { - oldFilepath = path.join(file.dir, oldSection[field]); - newStore = _handleTemplates.templateHandler.deleteTemplate(oldFilepath, oldSection, newStore); - } +/** + * Handle output of section description + * + * @function updateDescription + * @param {string} oldSection - previous iteration of KSS data, if updated + * @param {object} section - KSS section data + * @return {object} updated data store with new descripton path info + */ +function updateDescription(filepath, oldSection, section, store) { + const newSection = section; + const newStore = store; - filepath = path.join(file.dir, newSection[field]); - newStore = _handleTemplates.templateHandler.updateTemplate(filepath, newSection, newStore); - } else { - delete newSection[field]; - newStore = newStore.setIn(['sections', 'sectionsByPath', kssPath], newSection).setIn(['sections', 'sectionsByURI', newSection.referenceURI], newSection); - } - }); + // If we don't have previous KSS or the KSS has been updated + if (fieldShouldOutput(oldSection, section, 'description')) { + // Write new description + newSection.descriptionPath = utils.writeFile(section.referenceURI, 'description', filepath, section.description, store); - return newStore; - }, + return newStore.setIn(['sections', 'sectionsByPath', filepath], newSection).setIn(['sections', 'sectionsByURI', section.referenceURI], newSection); + } - /** - * Remove a section from the memory store - * - * @function unsetSection - * @param {object} section - contains updated section data - * @param {string} file - file object from path.parse() - * @param {object} store - memory store - * @param {bool} removed - has the file been removed or just the section information changed? - * @return {object} updated data store with new descripton path info - */ - unsetSection(section, file, store, removed) { - const sorted = store.getIn(['sections', 'sorted']); - const kssPath = path.format(file); - const dataFilepath = path.join(file.dir, `${file.name}.json`); - const isInline = section.markup && null !== section.markup.match(/<\/[^>]*>/); - const newSort = kssHandler.unsortSection(sorted, section.reference, store.get('referenceDelimiter')); - let newStore = store; - - // Remove old section data - _utils.utils.removeFile(section.referenceURI, 'section', dataFilepath, newStore); - - // Remove associated inline template - if (isInline) { - _utils.utils.removeFile(section.referenceURI, 'template', kssPath, newStore); - } + return newStore; +} - // Remove description template - _utils.utils.removeFile(section.referenceURI, 'description', kssPath, newStore); +/** + * Handle Data and Markup fields + * + * @function updateTemplateFields + * @param {string} file - File data for KSS file from path.parse() + * @param {object} oldSection - outdated KSS data + * @param {object} section - KSS section data + * @param {object} store - memory store + * @return {object} KSS section data with updated asset paths + */ +function updateTemplateFields(file, oldSection, section, store) { + const kssPath = path.format(file); + const newSection = section; + let filepath = ''; + let oldFilepath = ''; + let newStore = store; + + ['data', 'markup'].forEach(field => { + if (newSection[field]) { + if (oldSection[field]) { + oldFilepath = path.join(file.dir, oldSection[field]); + newStore = (0, _handleTemplates.deleteTemplate)(oldFilepath, oldSection, newStore); + } - // Remove data from sectionsByPath if file has been removed - if (removed) { - newStore = newStore.deleteIn(['sections', 'sectionsByPath', kssPath]); + filepath = path.join(file.dir, newSection[field]); + newStore = (0, _handleTemplates.updateTemplate)(filepath, newSection, newStore); + } else { + delete newSection[field]; + newStore = newStore.setIn(['sections', 'sectionsByPath', kssPath], newSection).setIn(['sections', 'sectionsByURI', newSection.referenceURI], newSection); } + }); - return newStore.deleteIn(['sections', 'sectionsByURI', section.referenceURI]).setIn(['sections', 'sorted'], newSort); - }, + return newStore; +} - /** - * Sort sections and subsections - * - * @function sortSection - * @param {object} sorted - currently sorted sections - * @param {string} reference - reference URI of section to sort - * @return {object} updated data store with new descripton path info - */ - sortSection(sorted, reference, delimiter) { - const parts = reference.split(delimiter); - const newSort = sorted[parts[0]] || {}; - const newSorted = sorted; +/** + * Remove a section from the memory store + * + * @function unsetSection + * @param {object} section - contains updated section data + * @param {string} file - file object from path.parse() + * @param {object} store - memory store + * @param {bool} removed - has the file been removed or just the section information changed? + * @return {object} updated data store with new descripton path info + */ +function unsetSection(section, file, store, removed) { + const sorted = store.getIn(['sections', 'sorted']); + const kssPath = path.format(file); + const dataFilepath = path.join(file.dir, `${file.name}.json`); + const isInline = section.markup && null !== section.markup.match(/<\/[^>]*>/); + const newSort = unsortSection(sorted, section.reference, store.get('referenceDelimiter')); + let newStore = store; + + // Remove old section data + utils.removeFile(section.referenceURI, 'section', dataFilepath, newStore); + + // Remove associated inline template + if (isInline) { + utils.removeFile(section.referenceURI, 'template', kssPath, newStore); + } + + // Remove description template + utils.removeFile(section.referenceURI, 'description', kssPath, newStore); + // Remove data from sectionsByPath if file has been removed + if (removed) { + newStore = newStore.deleteIn(['sections', 'sectionsByPath', kssPath]); + } + + return newStore.deleteIn(['sections', 'sectionsByURI', section.referenceURI]).setIn(['sections', 'sorted'], newSort); +} + +/** + * Sort sections and subsections + * + * @function sortSection + * @param {object} sorted - currently sorted sections + * @param {string} reference - reference URI of section to sort + * @return {object} updated data store with new descripton path info + */ +function sortSection(sorted, reference, delimiter) { + const parts = reference.split(delimiter); + const newSort = sorted[parts[0]] || {}; + const newSorted = sorted; + + if (1 < parts.length) { + const newParts = parts.filter((part, idx) => 0 !== idx); + newSorted[parts[0]] = sortSection(newSort, newParts.join(delimiter), delimiter); + } else { + newSorted[parts[0]] = newSort; + } + + return newSorted; +} + +/** + * Remove a section from the sorted sections + * + * @function unsortSection + * @param {object} sorted - currently sorted sections + * @param {string} reference - reference URI of section to sort + * @return {object} updated data store with new descripton path info + */ +function unsortSection(sorted, reference, delimiter) { + const parts = reference.split(delimiter); + const subsections = Object.keys(sorted[parts[0]]); + const newSorted = sorted; + + if (subsections.length) { if (1 < parts.length) { const newParts = parts.filter((part, idx) => 0 !== idx); - newSorted[parts[0]] = kssHandler.sortSection(newSort, newParts.join(delimiter), delimiter); - } else { - newSorted[parts[0]] = newSort; + newSorted[parts[0]] = unsortSection(newSorted[parts[0]], newParts.join(delimiter), delimiter); } + } else { + delete newSorted[parts[0]]; + } - return newSorted; - }, + return newSorted; +} - /** - * Remove a section from the sorted sections - * - * @function unsortSection - * @param {object} sorted - currently sorted sections - * @param {string} reference - reference URI of section to sort - * @return {object} updated data store with new descripton path info - */ - unsortSection(sorted, reference, delimiter) { - const parts = reference.split(delimiter); - const subsections = Object.keys(sorted[parts[0]]); - const newSorted = sorted; - - if (subsections.length) { - if (1 < parts.length) { - const newParts = parts.filter((part, idx) => 0 !== idx); - newSorted[parts[0]] = kssHandler.unsortSection(newSorted[parts[0]], newParts.join(delimiter), delimiter); - } - } else { - delete newSorted[parts[0]]; - } +/** + * Compare a KSS field between old and new KSS data to see if we need to output + * a new module for that field + * + * @function fieldShouldOutput + * @param {object} oldSection - currently sorted sections + * @param {object} newSection - reference URI of section to sort + * @param {string} field - KSS field to check + * @return {bool} output a new module for the KSS field + */ +function fieldShouldOutput(oldSection, newSection, field) { + return oldSection && (oldSection[field] !== newSection[field] || oldSection.referenceURI !== newSection.referenceURI) || !oldSection; +} - return newSorted; - }, +/***/ }), +/* 13 */ +/***/ (function(module, exports, __webpack_require__) { - /** - * Compare a KSS field between old and new KSS data to see if we need to output - * a new module for that field - * - * @function fieldShouldOutput - * @param {object} oldSection - currently sorted sections - * @param {object} newSection - reference URI of section to sort - * @param {string} field - KSS field to check - * @return {bool} output a new module for the KSS field - */ - fieldShouldOutput(oldSection, newSection, field) { - return oldSection && (oldSection[field] !== newSection[field] || oldSection.referenceURI !== newSection.referenceURI) || !oldSection; - } -}; +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.config = exports.dataStructure = undefined; + +var _immutable = __webpack_require__(21); + +var _generateConfig = __webpack_require__(10); + +var _generateConfig2 = _interopRequireDefault(_generateConfig); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// Create initial data structure + +// Merge Huron default webpack config with user config +const config = (0, _generateConfig2.default)(); + +// Make sure the kss option is represented as an array +config.huron.kss = Array.isArray(config.huron.kss) ? config.huron.kss : [config.huron.kss]; + +/* eslint-disable */ +/** + * Initial structure for immutable data store + * + * @global + */ +const dataStructure = (0, _immutable.Map)({ + types: ['template', 'data', 'description', 'section', 'prototype', 'sections-template'], + config: (0, _immutable.Map)(config.huron), + sections: (0, _immutable.Map)({ + sectionsByPath: (0, _immutable.Map)({}), + sectionsByURI: (0, _immutable.Map)({}), + sorted: {} + }), + templates: (0, _immutable.Map)({}), + prototypes: (0, _immutable.Map)({}), + sectionTemplatePath: '', + referenceDelimiter: '.' +}); +/* eslint-enable */ + +exports.dataStructure = dataStructure; +exports.config = config; /***/ }), -/* 13 */ +/* 14 */ /***/ (function(module, exports) { "use strict"; @@ -1701,7 +1740,7 @@ function requireExternal(requirePath) { /* eslint-enable */ /***/ }), -/* 14 */ +/* 15 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -1720,7 +1759,7 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de const webpack = __webpack_require__(5); /** @module cli/webpack-server */ -const WebpackDevServer = __webpack_require__(23); +const WebpackDevServer = __webpack_require__(24); const chalk = __webpack_require__(1); // Colorize terminal output /** @@ -1788,7 +1827,7 @@ function startWebpack(config) { } /***/ }), -/* 15 */ +/* 16 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -1811,7 +1850,7 @@ module.exports = { port: 8080, prototypes: ['index'], root: 'dist/', - sectionTemplate: path.join(__dirname, '../templates/section.hbs'), + sectionTemplate: path.join(__dirname, '../../templates/section.hbs'), templates: { rule: { test: /\.(hbs|handlebars)$/, @@ -1823,7 +1862,7 @@ module.exports = { }; /***/ }), -/* 16 */ +/* 17 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -1855,54 +1894,55 @@ module.exports = { tag: 'dom-module' } }, 'html-loader'] + // include: ['path/to/templates'] }] } }; /***/ }), -/* 17 */ +/* 18 */ /***/ (function(module, exports) { module.exports = require("commander"); /***/ }), -/* 18 */ +/* 19 */ /***/ (function(module, exports) { module.exports = require("gaze"); /***/ }), -/* 19 */ +/* 20 */ /***/ (function(module, exports) { module.exports = require("html-webpack-plugin"); /***/ }), -/* 20 */ +/* 21 */ /***/ (function(module, exports) { module.exports = require("immutable"); /***/ }), -/* 21 */ +/* 22 */ /***/ (function(module, exports) { module.exports = require("kss"); /***/ }), -/* 22 */ +/* 23 */ /***/ (function(module, exports) { module.exports = require("url"); /***/ }), -/* 23 */ +/* 24 */ /***/ (function(module, exports) { module.exports = require("webpack-dev-server"); /***/ }), -/* 24 */ +/* 25 */ /***/ (function(module, exports, __webpack_require__) { module.exports = __webpack_require__(8); diff --git a/dist/cli/huron-cli.js.map b/dist/cli/huron-cli.js.map index 0d05c5b..43590ef 100644 --- a/dist/cli/huron-cli.js.map +++ b/dist/cli/huron-cli.js.map @@ -1 +1 @@ -{"version":3,"file":"huron-cli.js","sources":["webpack:///webpack/bootstrap a06bb62c5674fd91bbe6","webpack:///external \"path\"","webpack:///external \"chalk\"","webpack:///external \"fs-extra\"","webpack:///src/cli/utils.js","webpack:///src/cli/parse-args.js","webpack:///external \"webpack\"","webpack:///src/cli/handle-templates.js","webpack:///src/cli/require-templates.js","webpack:///src/cli/huron-cli.js","webpack:///src/cli/actions.js","webpack:///src/cli/generate-config.js","webpack:///src/cli/handle-html.js","webpack:///src/cli/handle-kss.js","webpack:///src/cli/require-external.js","webpack:///src/cli/server.js","webpack:///src/default-config/huron.config.js","webpack:///src/default-config/webpack.config.js","webpack:///external \"commander\"","webpack:///external \"gaze\"","webpack:///external \"html-webpack-plugin\"","webpack:///external \"immutable\"","webpack:///external \"kss\"","webpack:///external \"url\"","webpack:///external \"webpack-dev-server\""],"sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId])\n \t\t\treturn installedModules[moduleId].exports;\n\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// identity function for calling harmony imports with the correct context\n \t__webpack_require__.i = function(value) { return value; };\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"../\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 24);\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap a06bb62c5674fd91bbe6","module.exports = require(\"path\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"path\"\n// module id = 0\n// module chunks = 0","module.exports = require(\"chalk\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"chalk\"\n// module id = 1\n// module chunks = 0","module.exports = require(\"fs-extra\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"fs-extra\"\n// module id = 2\n// module chunks = 0","/** @module cli/utilities */\n\nconst cwd = process.cwd(); // Current working directory\nconst path = require('path');\nconst fs = require('fs-extra');\nconst chalk = require('chalk'); // Colorize terminal output\n\n// Exports\n/* eslint-disable */\nexport const utils = {\n/* eslint-enable */\n\n /**\n * Ensure predictable data structure for KSS section data\n *\n * @function normalizeSectionData\n * @param {object} section - section data\n * @return {object} section data\n */\n normalizeSectionData(section) {\n const data = section.data || section;\n\n if (! data.referenceURI || '' === data.referenceURI) {\n data.referenceURI = section.referenceURI();\n }\n\n return data;\n },\n\n /**\n * Ensure predictable data structure for KSS section data\n *\n * @function writeSectionData\n * @param {object} store - data store\n * @param {object} section - section data\n * @param {string} sectionPath - output destination for section data file\n */\n writeSectionData(store, section, sectionPath = false) {\n let outputPath = sectionPath;\n let sectionFileInfo;\n\n if (! outputPath && {}.hasOwnProperty.call(section, 'kssPath')) {\n sectionFileInfo = path.parse(section.kssPath);\n outputPath = path.join(\n sectionFileInfo.dir,\n `${sectionFileInfo.name}.json`\n );\n }\n\n // Output section data\n if (outputPath) {\n return utils.writeFile(\n section.referenceURI,\n 'section',\n outputPath,\n JSON.stringify(section),\n store\n );\n }\n\n console.warn( // eslint-disable-line no-console\n chalk.red(`Failed to write section data for ${section.referenceURI}`)\n );\n return false;\n },\n\n /**\n * Find .json from a template file or vice versa\n *\n * @function getTemplateDataPair\n * @param {object} file - file object from path.parse()\n * @param {object} section - KSS section data\n * @return {string} relative path to module JSON file\n */\n getTemplateDataPair(file, section, store) {\n const huron = store.get('config');\n const kssDir = utils.matchKssDir(file.dir, huron);\n\n if (kssDir) {\n const componentPath = path.relative(\n path.resolve(cwd, kssDir),\n file.dir\n );\n const partnerType = '.json' === file.ext ? 'template' : 'data';\n const partnerExt = '.json' === file.ext ?\n huron.get('templates').extension :\n '.json';\n\n const pairPath = path.join(\n componentPath,\n utils.generateFilename(\n section.referenceURI,\n partnerType,\n partnerExt,\n store\n )\n );\n\n return `./${pairPath}`;\n }\n\n return false;\n },\n\n /**\n * Normalize a section title for use as a filename\n *\n * @function normalizeHeader\n * @param {string} header - section header extracted from KSS documentation\n * @return {string} modified header, lowercase and words separated by dash\n */\n normalizeHeader(header) {\n return header\n .toLowerCase()\n .replace(/\\s?\\W\\s?/g, '-');\n },\n\n /**\n * Wrap html in required template tags\n *\n * @function wrapMarkup\n * @param {string} content - html or template markup\n * @param {string} templateId - id of template (should be section reference)\n * @return {string} modified HTML\n */\n wrapMarkup(content, templateId) {\n return `\n\n\\n`;\n },\n\n /**\n * Generate a filename based on referenceURI, type and file object\n *\n * @function generateFilename\n * @param {string} id - The name of the file (with extension).\n * @param {string} type - the type of file output\n * @param {object} ext - file extension\n * @param {store} store - data store\n * @return {string} Path to output file, relative to ouput dir (can be use in require statements)\n */\n generateFilename(id, type, ext, store) {\n // Type of file and its corresponding extension(s)\n const types = store.get('types');\n const outputExt = '.scss' !== ext ? ext : '.html';\n\n /* eslint-disable */\n if (-1 === types.indexOf(type)) {\n console.log(`Huron data ${type} does not exist`);\n return false;\n }\n /* eslint-enable */\n\n return `${id}-${type}${outputExt}`;\n },\n\n /**\n * Copy an HTML file into the huron output directory.\n *\n * @function writeFile\n * @param {string} id - The name of the file (with extension).\n * @param {string} content - The content of the file to write.\n * @param {string} type - the type of file output\n * @param {object} store - The data store\n * @return {string} Path to output file, relative to ouput dir (can be use in require statements)\n */\n writeFile(id, type, filepath, content, store) {\n const huron = store.get('config');\n const file = path.parse(filepath);\n const filename = utils.generateFilename(id, type, file.ext, store);\n const kssDir = utils.matchKssDir(filepath, huron);\n\n if (kssDir) {\n const componentPath = path.relative(\n path.resolve(cwd, kssDir),\n file.dir\n );\n const outputRelative = path.join(\n huron.get('output'),\n componentPath,\n `${filename}`\n );\n const outputPath = path.resolve(cwd, huron.get('root'), outputRelative);\n let newContent = content;\n\n if ('data' !== type && 'section' !== type) {\n newContent = utils.wrapMarkup(content, id);\n }\n\n try {\n fs.outputFileSync(outputPath, newContent);\n console.log(chalk.green(`Writing ${outputRelative}`)); // eslint-disable-line no-console\n } catch (e) {\n console.log(chalk.red(`Failed to write ${outputRelative}`)); // eslint-disable-line no-console\n }\n\n return `./${outputRelative.replace(`${huron.get('output')}/`, '')}`;\n }\n\n return false;\n },\n\n /**\n * Delete a file in the huron output directory\n *\n * @function removeFile\n * @param {string} filename - The name of the file (with extension).\n * @param {object} store - The data store\n * @return {string} Path to output file, relative to ouput dir (can be use in require statements)\n */\n removeFile(id, type, filepath, store) {\n const huron = store.get('config');\n const file = path.parse(filepath);\n const filename = utils.generateFilename(id, type, file.ext, store);\n const kssDir = utils.matchKssDir(filepath, huron);\n\n if (kssDir) {\n const componentPath = path.relative(\n path.resolve(cwd, kssDir),\n file.dir\n );\n const outputRelative = path.join(\n huron.get('output'),\n componentPath,\n `${filename}`\n );\n const outputPath = path.resolve(cwd, huron.get('root'), outputRelative);\n\n try {\n fs.removeSync(outputPath);\n console.log(chalk.green(`Removing ${outputRelative}`)); // eslint-disable-line no-console\n } catch (e) {\n console.log( // eslint-disable-line no-console\n chalk.red(`${outputRelative} does not exist or cannot be deleted`)\n );\n }\n\n return `./${outputRelative.replace(`${huron.get('output')}/`, '')}`;\n }\n\n return false;\n },\n\n /**\n * Write a template for sections\n *\n * @function writeSectionTemplate\n * @param {string} filepath - the original template file\n * @param {object} store - data store\n * @return {object} updated store\n */\n writeSectionTemplate(filepath, store) {\n const huron = store.get('config');\n const sectionTemplate = utils.wrapMarkup(fs.readFileSync(filepath, 'utf8'));\n const componentPath = './huron-sections/sections.hbs';\n const output = path.join(\n cwd,\n huron.get('root'),\n huron.get('output'),\n componentPath\n );\n\n // Move huron script and section template into huron root\n fs.outputFileSync(output, sectionTemplate);\n console.log(chalk.green(`writing section template to ${output}`)); // eslint-disable-line no-console\n\n return store.set('sectionTemplatePath', componentPath);\n },\n\n /**\n * Request for section data based on section reference\n *\n * @function writeSectionTemplate\n * @param {string} search - key on which to match section\n * @param {field} string - field in which to look to determine section\n * @param {obj} store - sections memory store\n */\n getSection(search, field, store) {\n const sectionValues = store\n .getIn(['sections', 'sectionsByPath'])\n .valueSeq();\n let selectedSection = false;\n\n if (field) {\n selectedSection = sectionValues\n .filter((value) => value[field] === search)\n .get(0);\n } else {\n selectedSection = store.getIn(['sections', 'sectionsByPath', search]);\n }\n\n return selectedSection;\n },\n\n /**\n * Match which configured KSS directory the current file\n *\n * @function matchKssDir\n * @param {string} search - key on which to match section\n * @param {field} string - field in which to look to determine section\n * @param {obj} sections - sections memory store\n * @return {string} kssMatch - relative path to KSS directory\n */\n matchKssDir(filepath, huron) {\n const kssSource = huron.get('kss');\n /* eslint-disable space-unary-ops */\n const kssMatch = kssSource.filter((dir) => -1 !== filepath.indexOf(dir));\n /* eslint-enable space-unary-ops */\n\n if (kssMatch.length) {\n return kssMatch[0];\n }\n\n console.error(\n chalk.red(`filepath ${filepath} does not exist in any\n of the configured KSS directories`)\n );\n return false;\n },\n};\n\n\n\n// WEBPACK FOOTER //\n// src/cli/utils.js","/** @module cli/parse-arguments */\n/* eslint-disable space-unary-ops */\n\n// Requires\n/** @global */\nconst program = require('commander'); // Easy program flags\nconst path = require('path');\n\nexport default program;\n\n/**\n * Process huron CLI arguments\n *\n * @function parseArgs\n * @example node huron/dist/cli/huron-cli.js --config 'client/config/webpack.config.js' --production\n */\nfunction parseArgs() {\n const envArg = {};\n\n process.argv = process.argv.filter((arg) => {\n if (-1 !== arg.indexOf('--env')) {\n const envParts = arg\n .split('.')[1]\n .split('=');\n\n envArg[envParts[0]] = envParts[1] || true;\n return false;\n }\n\n return true;\n });\n\n program.version('1.0.1')\n .option(\n '-c, --huron-config [huronConfig]',\n '[huronConfig] for all huron options',\n path.resolve(__dirname, '../default-config/huron.config.js')\n )\n .option(\n '-w, --webpack-config [webpackConfig]',\n '[webpackConfig] for all webpack options',\n path.resolve(__dirname, '../default-config/webpack.config.js')\n )\n .option('-p, --production', 'compile assets once for production')\n .parse(process.argv);\n\n program.env = envArg;\n}\n\nparseArgs();\n/* eslint-enable */\n\n\n\n// WEBPACK FOOTER //\n// src/cli/parse-args.js","module.exports = require(\"webpack\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"webpack\"\n// module id = 5\n// module chunks = 0","/** @module cli/template-handler */\nimport { utils } from './utils';\n\nconst path = require('path');\nconst fs = require('fs-extra');\nconst chalk = require('chalk');\n\n/* eslint-disable */\nexport const templateHandler = {\n/* eslint-enable */\n /**\n * Handle update of a template or data (json) file\n *\n * @function updateTemplate\n * @param {string} filepath - filepath of changed file (comes from gaze)\n * @param {object} section - contains KSS section data\n * @param {object} store - memory store\n * @return {object} updated memory store\n */\n updateTemplate(filepath, section, store) {\n const file = path.parse(filepath);\n const pairPath = utils.getTemplateDataPair(file, section, store);\n const type = '.json' === file.ext ? 'data' : 'template';\n const newSection = section;\n const newStore = store;\n let content = false;\n\n try {\n content = fs.readFileSync(filepath, 'utf8');\n } catch (e) {\n console.log(chalk.red(`${filepath} does not exist`));\n }\n\n if (content) {\n const requirePath = utils.writeFile(\n newSection.referenceURI,\n type,\n filepath,\n content,\n newStore\n );\n newSection[`${type}Path`] = requirePath;\n\n if ('template' === type) {\n newSection.templateContent = content;\n\n // Rewrite section data with template content\n newSection.sectionPath = utils.writeSectionData(newStore, newSection);\n }\n\n return newStore\n .setIn(\n ['templates', requirePath],\n pairPath\n )\n .setIn(\n ['sections', 'sectionsByPath', newSection.kssPath],\n newSection\n )\n .setIn(\n ['sections', 'sectionsByURI', newSection.referenceURI],\n newSection\n );\n }\n\n return newStore;\n },\n\n /**\n * Handle removal of a template or data (json) file\n *\n * @function deleteTemplate\n * @param {string} filepath - filepath of changed file (comes from gaze)\n * @param {object} section - contains KSS section data\n * @param {object} store - memory store\n * @return {object} updated memory store\n */\n deleteTemplate(filepath, section, store) {\n const file = path.parse(filepath);\n const type = '.json' === file.ext ? 'data' : 'template';\n const newSection = section;\n const newStore = store;\n\n // Remove partner\n const requirePath = utils.removeFile(\n newSection.referenceURI,\n type,\n filepath,\n newStore\n );\n delete newSection[`${type}Path`];\n\n return newStore\n .deleteIn(['templates', requirePath])\n .setIn(\n ['sections', 'sectionsByPath', newSection.kssPath],\n newSection\n )\n .setIn(\n ['sections', 'sectionsByURI', newSection.referenceURI],\n newSection\n );\n },\n};\n\n\n\n// WEBPACK FOOTER //\n// src/cli/handle-templates.js","/** @module cli/require-templates */\n\nconst path = require('path');\nconst fs = require('fs-extra');\n\nconst cwd = process.cwd();\nconst huronScript = fs.readFileSync(\n path.join(__dirname, '../web/huron.js'),\n 'utf8'\n);\n\n/**\n * Write code for requiring all generated huron assets\n * Note: prepended and appended code in this file should roughly follow es5 syntax for now,\n * as it will not pass through the Huron internal babel build nor can we assume the user is\n * working with babel.\n *\n * @function requireTemplates\n * @param {object} store - memory store\n */\nexport const requireTemplates = function requireTemplates(store) {\n const huron = store.get('config');\n const outputPath = path.join(cwd, huron.get('root'), 'huron-assets');\n const requireRegex = new RegExp(`\\\\.html|\\\\.json|\\\\${\n huron.get('templates').extension\n }$`);\n const requirePath = `'../${huron.get('output')}'`;\n\n // Initialize templates, js, css and HMR acceptance logic\n const prepend = `\nvar store = require('./huron-store.js');\nvar assets = require.context(${requirePath}, true, ${requireRegex});\nvar modules = {};\n\nassets.keys().forEach(function(key) {\n modules[key] = assets(key);\n});\n\nif (module.hot) {\n module.hot.accept(\n assets.id,\n () => {\n var newAssets = require.context(\n ${requirePath},\n true,\n ${requireRegex}\n );\n var newModules = newAssets.keys()\n .map((key) => {\n return [key, newAssets(key)];\n })\n .filter((newModule) => {\n return modules[newModule[0]] !== newModule[1];\n });\n\n updateStore(require('./huron-store.js'));\n\n newModules.forEach((module) => {\n modules[module[0]] = module[1];\n hotReplace(module[0], module[1], modules);\n });\n }\n );\n\n module.hot.accept(\n './huron-store.js',\n () => {\n updateStore(require('./huron-store.js'));\n }\n );\n}\\n`;\n\n const append = `\nfunction hotReplace(key, module, modules) {\n insert.modules = modules;\n if (key === store.sectionTemplatePath) {\n insert.cycleSections();\n } else {\n insert.inserted = [];\n insert.loadModule(key, module, false);\n }\n};\n\nfunction updateStore(newStore) {\n insert.store = newStore;\n}\\n`;\n\n // Write the contents of this script.\n // @todo lint this file.\n fs.outputFileSync(\n path.join(outputPath, 'huron.js'),\n `/*eslint-disable*/\\n\n${prepend}\\n\\n${huronScript}\\n\\n${append}\\n\n/*eslint-enable*/\\n`\n );\n};\n\n/**\n * Output entire data store to a JS object and handle if any KSS data has changed\n *\n * @function writeStore\n * @param {object} store - memory store\n * @param {string} changed - filepath of changed KSS section, if applicable\n */\nexport const writeStore = function writeStore(store) {\n const huron = store.get('config');\n const outputPath = path.join(cwd, huron.get('root'), 'huron-assets');\n\n // Write updated data store\n // @todo lint this file.\n fs.outputFileSync(\n path.join(outputPath, 'huron-store.js'),\n `/*eslint-disable*/\n module.exports = ${JSON.stringify(store.toJSON())}\n /*eslint-disable*/\\n`\n );\n};\n\n\n\n\n// WEBPACK FOOTER //\n// src/cli/require-templates.js","// Local imports\nimport { initFiles, updateFile, deleteFile } from './actions';\nimport { requireTemplates, writeStore } from './require-templates';\nimport program from './parse-args';\nimport generateConfig from './generate-config';\nimport startWebpack from './server';\n\n// Modules\nconst path = require('path');\nconst Gaze = require('gaze').Gaze;\nconst Immutable = require('immutable');\nconst chalk = require('chalk'); // Colorize terminal output\n\n// Merge Huron default webpack config with user config\nconst config = generateConfig();\n\n/**\n * Huron configuration object\n *\n * @global\n */\nconst huron = config.huron;\n\n// Make sure the kss option is represented as an array\nhuron.kss = Array.isArray(huron.kss) ?\n huron.kss :\n [huron.kss];\n\n/**\n * Available file extensions. Extensions should not include the leading '.'\n *\n * @global\n */\nconst extensions = [\n huron.kssExtension,\n huron.templates.extension,\n 'html',\n 'json',\n].map((extension) => extension.replace('.', ''));\n\n// Create initial data structure\n/* eslint-disable */\n/**\n * Initial structure for immutable data store\n *\n * @global\n */\nconst dataStructure = Immutable.Map({\n types: [\n 'template',\n 'data',\n 'description',\n 'section',\n 'prototype',\n 'sections-template',\n ],\n config: Immutable.Map(config.huron),\n sections: Immutable.Map({\n sectionsByPath: Immutable.Map({}),\n sectionsByURI: Immutable.Map({}),\n sorted: {},\n }),\n templates: Immutable.Map({}),\n prototypes: Immutable.Map({}),\n sectionTemplatePath: '',\n referenceDelimiter: '.',\n});\n/* eslint-enable */\n\n// Generate watch list for Gaze, start gaze\nconst gazeWatch = [];\n\n// Push KSS source directories and section template to Gaze\ngazeWatch.push(path.resolve(__dirname, huron.sectionTemplate));\nhuron.kss.forEach((sourceDir) => {\n let gazeDir = sourceDir;\n\n /* eslint-disable space-unary-ops */\n if ('/' === sourceDir.slice(-1)) {\n gazeDir = sourceDir.slice(0, -1);\n }\n /* eslint-enable space-unary-ops */\n\n gazeWatch.push(\n `${gazeDir}/**/*.+(${extensions.join('|')})`\n );\n});\n\n/**\n * Gaze instance for watching all files, including KSS, html, hbs/template, and JSON\n *\n * @global\n */\nconst gaze = new Gaze(gazeWatch);\n\n/**\n * Initialize data store with files from gaze and original data structure\n *\n * @global\n */\nconst store = initFiles(gaze.watched(), dataStructure);\n\nrequireTemplates(store);\nwriteStore(store);\n\nif (! program.production) {\n /** @module cli/gaze */\n let newStore = store;\n\n /**\n * Anonymous handler for Gaze 'changed' event indicating a file has changed\n *\n * @callback changed\n * @listens gaze:changed\n * @param {string} filepath - absolute path of changed file\n */\n gaze.on('changed', (filepath) => {\n newStore = updateFile(filepath, newStore);\n console.log(chalk.green(`${filepath} updated!`));\n });\n\n /**\n * Anonymous handler for Gaze 'added' event indicating a file has been added to the watched directories\n *\n * @callback added\n * @listens gaze:added\n * @param {string} filepath - absolute path of changed file\n */\n gaze.on('added', (filepath) => {\n newStore = updateFile(filepath, newStore);\n writeStore(newStore);\n console.log(chalk.blue(`${filepath} added!`));\n });\n\n /**\n * Anonymous handler for Gaze 'renamed' event indicating a file has been renamed\n *\n * @callback renamed\n * @listens gaze:renamed\n * @param {string} filepath - absolute path of changed file\n */\n gaze.on('renamed', (newPath, oldPath) => {\n newStore = deleteFile(oldPath, newStore);\n newStore = updateFile(newPath, newStore);\n writeStore(newStore);\n console.log(chalk.blue(`${newPath} added!`));\n });\n\n /**\n * Anonymous handler for Gaze 'deleted' event indicating a file has been removed\n *\n * @callback deleted\n * @listens gaze:deleted\n * @param {string} filepath - absolute path of changed file\n */\n gaze.on('deleted', (filepath) => {\n newStore = deleteFile(filepath, newStore);\n writeStore(newStore);\n console.log(chalk.red(`${filepath} deleted`));\n });\n} else {\n gaze.close();\n}\n\n// Start webpack or build for production\nstartWebpack(config);\n\nif (module.hot) {\n module.hot.accept();\n}\n\n\n\n// WEBPACK FOOTER //\n// src/cli/huron-cli.js","/** @module cli/actions */\n\n// Imports\nimport { htmlHandler } from './handle-html';\nimport { templateHandler } from './handle-templates';\nimport { kssHandler } from './handle-kss';\nimport { utils } from './utils';\n\n// Requires\nconst path = require('path');\nconst chalk = require('chalk'); // Colorize terminal output\n\n// EXPORTED FUNCTIONS\n\n/**\n * Recursively loop through initial watched files list from Gaze.\n *\n * @param {object} data - object containing directory and file paths\n * @param {object} store - memory store\n * @param {object} huron - huron configuration options\n * @return {object} newStore - map object of entire data store\n */\nexport function initFiles(data, store, depth = 0) {\n const type = Object.prototype.toString.call(data);\n let newStore = store;\n let info;\n let files;\n\n switch (type) {\n case '[object Object]':\n files = Object.keys(data);\n newStore = files.reduce(\n (prevStore, file) => initFiles(data[file], prevStore, depth),\n newStore\n );\n break;\n\n case '[object Array]':\n newStore = data.reduce(\n (prevStore, file) => initFiles(file, prevStore, depth),\n newStore\n );\n break;\n\n case '[object String]':\n info = path.parse(data);\n if (info.ext) {\n newStore = updateFile(data, store);\n }\n break;\n\n default:\n break;\n }\n\n return newStore;\n}\n\n/**\n * Logic for updating and writing file information based on file type (extension)\n *\n * @param {string} filepath - path to updated file. usually passed in from Gaze\n * @param {object} store - memory store\n * @return {object} store - map object of map object of entire data store\n */\nexport function updateFile(filepath, store) {\n const huron = store.get('config');\n const file = path.parse(filepath);\n let field;\n let section;\n\n if (- 1 !== filepath.indexOf(huron.get('sectionTemplate'))) {\n return utils.writeSectionTemplate(filepath, store);\n }\n\n switch (file.ext) {\n // Plain HTML template, external\n case '.html':\n section = utils.getSection(file.base, 'markup', store);\n\n if (section) {\n return htmlHandler.updateTemplate(filepath, section, store);\n } else if (\n - 1 !== file.dir.indexOf('prototypes') &&\n - 1 !== file.name.indexOf('prototype-')\n ) {\n return htmlHandler.updatePrototype(filepath, store);\n }\n\n console.log(chalk.red(`Failed to write file: ${file.name}`));\n break;\n\n // Handlebars template, external\n case huron.get('templates').extension:\n case '.json':\n field = ('.json' === file.ext) ? 'data' : 'markup';\n section = utils.getSection(file.base, field, store);\n\n if (section) {\n return templateHandler.updateTemplate(filepath, section, store);\n }\n\n console.log( // eslint-disable-line no-console\n chalk.red(`Could not find associated KSS section for ${filepath}`)\n );\n break;\n\n // KSS documentation (default extension is `.css`)\n // Will also output a template if markup is inline\n // Note: inline markup does _not_ support handlebars currently\n case huron.get('kssExtension'):\n return kssHandler.updateKSS(filepath, store);\n\n // This should never happen if Gaze is working properly\n default:\n return store;\n }\n\n return store;\n}\n\n/**\n * Logic for deleting file information and files based on file type (extension)\n *\n * @param {string} filepath - path to updated file. usually passed in from Gaze\n * @param {object} store - memory store\n * @return {object} newStore - map object of map object of entire data store\n */\nexport function deleteFile(filepath, store) {\n const huron = store.get('config');\n const file = path.parse(filepath);\n let field = '';\n let section = null;\n let newStore = store;\n\n switch (file.ext) {\n // Plain HTML template, external\n case '.html':\n section = utils.getSection(file.base, 'markup', store);\n\n if (section) {\n newStore = htmlHandler.deleteTemplate(filepath, section, store);\n } else if (\n - 1 !== file.dir.indexOf('prototypes') &&\n - 1 !== file.name.indexOf('prototype-')\n ) {\n newStore = htmlHandler.deletePrototype(filepath, store);\n }\n break;\n\n case huron.get('templates').extension:\n case '.json':\n field = ('.json' === file.ext) ? 'data' : 'markup';\n section = utils.getSection(file.base, field, store);\n\n if (section) {\n newStore = templateHandler.deleteTemplate(filepath, section, store);\n }\n break;\n\n case huron.get('kssExtension'):\n section = utils.getSection(filepath, false, store);\n\n if (section) {\n newStore = kssHandler.deleteKSS(filepath, section, store);\n }\n break;\n\n default:\n console.warn( // eslint-disable-line no-console\n chalk.red(`Could not delete: ${file.name}`)\n );\n break;\n }\n\n return newStore;\n}\n\n\n\n// WEBPACK FOOTER //\n// src/cli/actions.js","/** @module cli/generate-config */\n\nimport program from './parse-args';\nimport requireExternal from './require-external';\n\nconst cwd = process.cwd();\nconst path = require('path');\nconst url = require('url');\nconst fs = require('fs-extra');\nconst webpack = require('webpack');\nconst HTMLWebpackPlugin = require('html-webpack-plugin');\nconst defaultConfig = require('../default-config/webpack.config');\nconst defaultHuron = require('../default-config/huron.config');\n\n// Require configs passed in by user from CLI\nconst localConfigPath = path.join(cwd, program.webpackConfig);\nconst localHuronPath = path.join(cwd, program.huronConfig);\nconst localConfig = requireExternal(localConfigPath);\nconst localHuron = requireExternal(localHuronPath);\n\n/**\n * Generate a mutant hybrid of the huron default webpack config and your local webpack config\n *\n * @function generateConfig\n * @param {object} config - local webpack config\n * @return {object} newConfig - updated data store\n */\nexport default function generateConfig() {\n let newConfig = localConfig;\n let newHuron = localHuron;\n\n // Execute config function, if provided\n if ('function' === typeof newConfig) {\n newConfig = newConfig(program.env);\n }\n\n // Execute huron config function, if provided\n if ('function' === typeof newHuron) {\n newHuron = newHuron(program.env);\n }\n\n newHuron = Object.assign({}, defaultHuron, newHuron);\n\n // Set ouput options\n newConfig.output = Object.assign({}, defaultConfig.output, newConfig.output);\n newConfig.output.path = path.resolve(cwd, newHuron.root);\n if (! program.production) {\n newConfig.output.publicPath = `http://localhost:${newHuron.port}/${newHuron.root}`;\n } else {\n newConfig.output.publicPath = '';\n }\n\n // configure entries\n newConfig = configureEntries(newHuron, newConfig);\n\n // configure plugins\n newConfig = configurePlugins(newHuron, newConfig);\n\n // configure loaders\n newConfig = configureLoaders(newHuron, newConfig);\n\n // Add HTMLWebpackPlugin for each configured prototype\n newConfig = configurePrototypes(newHuron, newConfig);\n\n // Remove existing devServer settings\n delete newConfig.devServer;\n\n return {\n huron: newHuron,\n webpack: newConfig,\n };\n}\n\n/**\n * Configure and manage webpack entry points\n *\n * @param {object} huron - huron configuration object\n * @param {object} config - webpack configuration object\n * @return {object} newConfig - updated data store\n */\nfunction configureEntries(huron, config) {\n const entry = config.entry[huron.entry];\n const newConfig = config;\n\n newConfig.entry = {};\n if (! program.production) {\n newConfig.entry[huron.entry] = [\n `webpack-dev-server/client?http://localhost:${huron.port}`,\n 'webpack/hot/dev-server',\n path.join(cwd, huron.root, 'huron-assets/huron'),\n ].concat(entry);\n } else {\n newConfig.entry[huron.entry] = [\n path.join(cwd, huron.root, 'huron-assets/huron'),\n ].concat(entry);\n }\n\n return newConfig;\n}\n\n/**\n * Configure and manage webpack plugins\n *\n * @param {object} huron - huron configuration object\n * @param {object} config - webpack configuration object\n * @return {object} newConfig - updated data store\n */\nfunction configurePlugins(huron, config) {\n const newConfig = config;\n\n newConfig.plugins = config.plugins || [];\n\n if (! program.production) {\n if (newConfig.plugins && newConfig.plugins.length) {\n newConfig.plugins = newConfig.plugins.filter(\n (plugin) => 'HotModuleReplacementPlugin' !== plugin.constructor.name &&\n 'NamedModulesPlugin' !== plugin.constructor.name\n );\n }\n newConfig.plugins = newConfig.plugins\n .concat([\n new webpack.HotModuleReplacementPlugin(),\n new webpack.NamedModulesPlugin(),\n ]);\n }\n\n return newConfig;\n}\n\n/**\n * Configure and manage webpack loaders\n *\n * @param {object} huron - huron configuration object\n * @param {object} config - webpack configuration object\n * @return {object} newConfig - updated data store\n */\nfunction configureLoaders(huron, config) {\n // Manage loaders\n const templatesLoader = huron.templates.rule || {};\n const newConfig = config;\n\n templatesLoader.include = [path.join(cwd, huron.root)];\n newConfig.module = newConfig.module || {};\n newConfig.module.rules = newConfig.module.rules ||\n newConfig.module.loaders ||\n [];\n newConfig.module.rules.push(\n {\n test: /\\.html$/,\n use: 'html-loader',\n include: [path.join(cwd, huron.root)],\n },\n templatesLoader\n );\n\n return newConfig;\n}\n\n/**\n * Create an HTML webpack plugin for each configured prototype\n *\n * @param {object} huron - huron configuration object\n * @param {object} config - webpack configuration object\n * @return {object} newConfig - updated data store\n */\nfunction configurePrototypes(huron, config) {\n const wrapperTemplate = fs.readFileSync(\n path.join(__dirname, '../../templates/prototype-template.ejs'),\n 'utf8'\n );\n\n const defaultHTMLPluginOptions = {\n title: '',\n window: huron.window,\n js: [],\n css: [],\n filename: 'index.html',\n template: path.join(\n cwd,\n huron.root,\n 'huron-assets/prototype-template.ejs'\n ),\n inject: false,\n chunks: [huron.entry],\n };\n const newConfig = config;\n\n // Write prototype template file for HTML webpack plugin\n fs.outputFileSync(\n path.join(cwd, huron.root, 'huron-assets/prototype-template.ejs'),\n wrapperTemplate\n );\n\n huron.prototypes.forEach((prototype) => {\n const newPrototype = prototype;\n let opts = {};\n\n // Merge configured settings with default settings\n if ('string' === typeof prototype) {\n opts = Object.assign({}, defaultHTMLPluginOptions, {\n title: prototype,\n filename: `${prototype}.html`,\n });\n } else if (\n 'object' === typeof prototype &&\n {}.hasOwnProperty.call(prototype, 'title')\n ) {\n // Create filename based on configured title if not provided\n if (! prototype.filename) {\n newPrototype.filename = `${prototype.title}.html`;\n }\n\n // Move css assets for this prototype,\n // reset css option with new file paths\n if (prototype.css) {\n newPrototype.css = moveAdditionalAssets(prototype.css, 'css', huron);\n }\n\n // Move js assets for this prototype,\n // reset js option with new file paths\n if (prototype.js) {\n newPrototype.js = moveAdditionalAssets(prototype.js, 'js', huron);\n }\n\n opts = Object.assign({}, defaultHTMLPluginOptions, newPrototype);\n }\n\n // Move global css assets,\n // reset css option with new file paths\n if (huron.css.length) {\n opts.css = opts.css.concat(\n moveAdditionalAssets(huron.css, 'css', huron)\n );\n }\n\n // Move global js assets,\n // reset js option with new file paths\n if (huron.js.length) {\n opts.js = opts.js.concat(\n moveAdditionalAssets(huron.js, 'js', huron)\n );\n }\n\n // Push a new plugin for each configured prototype\n if (Object.keys(opts).length) {\n newConfig.plugins.push(\n new HTMLWebpackPlugin(opts)\n );\n }\n });\n\n return newConfig;\n}\n\n/**\n * Move relative (and local) js and css assets provided in huron options\n *\n * @param {array|string} assets - array of assets or single asset\n * @param {string} subdir - subdirectory in huron root from which to load additional asset\n * @param {object} huron - huron configuration object\n * @return {array} assetResults - paths to js and css assets\n */\nfunction moveAdditionalAssets(assets, subdir = '', huron) {\n const currentAssets = [].concat(assets);\n const assetResults = [];\n\n currentAssets.forEach((asset) => {\n const assetInfo = path.parse(asset);\n const assetURL = url.parse(asset);\n const sourcePath = path.join(cwd, asset);\n const outputPath = path.resolve(cwd, huron.root, subdir, assetInfo.base);\n const loadPath = program.production ?\n path.join(subdir, assetInfo.base) :\n path.join('/', subdir, assetInfo.base); // Use absolute path in development\n let contents = false;\n\n if (\n ! path.isAbsolute(asset) &&\n ! assetURL.protocol\n ) {\n try {\n contents = fs.readFileSync(sourcePath);\n } catch (e) {\n console.warn(`could not read ${sourcePath}`);\n }\n\n if (contents) {\n fs.outputFileSync(outputPath, contents);\n assetResults.push(loadPath);\n }\n } else {\n assetResults.push(asset);\n }\n });\n\n return assetResults;\n}\n\n\n\n// WEBPACK FOOTER //\n// src/cli/generate-config.js","/** @module cli/html-handler */\n\nimport { utils } from './utils';\n\nconst path = require('path');\nconst fs = require('fs-extra');\n\n/* eslint-disable */\nexport const htmlHandler = {\n/* eslint-enable */\n\n /**\n * Handle update of an HMTL template\n *\n * @function updateTemplate\n * @param {string} filepath - filepath of changed file (comes from gaze)\n * @param {object} section - contains KSS section data\n * @param {object} store - memory store\n * @return {object} updated data store\n */\n updateTemplate(filepath, section, store) {\n const file = path.parse(filepath);\n const content = fs.readFileSync(filepath, 'utf8');\n const newSection = section;\n\n if (content) {\n newSection.templatePath = utils.writeFile(\n section.referenceURI,\n 'template',\n filepath,\n content,\n store\n );\n newSection.templateContent = content;\n\n // Rewrite section data with template content\n newSection.sectionPath = utils.writeSectionData(store, newSection);\n\n return store\n .setIn(\n ['sections', 'sectionsByPath', section.kssPath],\n newSection\n )\n .setIn(\n ['sections', 'sectionsByURI', section.referenceURI],\n newSection\n );\n }\n\n console.log(`File ${file.base} could not be read`);\n return store;\n },\n\n /**\n * Handle removal of an HMTL template\n *\n * @function deleteTemplate\n * @param {string} filepath - filepath of changed file (comes from gaze)\n * @param {object} section - contains KSS section data\n * @param {object} store - memory store\n * @return {object} updated data store\n */\n deleteTemplate(filepath, section, store) {\n const newSection = section;\n\n utils.removeFile(\n newSection.referenceURI,\n 'template',\n filepath,\n store\n );\n\n delete newSection.templatePath;\n\n return store\n .setIn(\n ['sections', 'sectionsByPath', section.kssPath],\n newSection\n )\n .setIn(\n ['sections', 'sectionsByURI', section.referenceURI],\n newSection\n );\n },\n\n /**\n * Handle update for a prototype file\n *\n * @function updatePrototype\n * @param {string} filepath - filepath of changed file (comes from gaze)\n * @param {object} store - memory store\n * @return {object} updated data store\n */\n updatePrototype(filepath, store) {\n const file = path.parse(filepath);\n const content = fs.readFileSync(filepath, 'utf8');\n\n if (content) {\n const requirePath = utils.writeFile(\n file.name,\n 'prototype',\n filepath,\n content,\n store\n );\n\n return store.setIn(\n ['prototypes', file.name],\n requirePath\n );\n }\n\n console.log(`File ${file.base} could not be read`);\n return store;\n },\n\n /**\n * Handle removal of a prototype file\n *\n * @function deletePrototype\n * @param {string} filepath - filepath of changed file (comes from gaze)\n * @param {object} store - memory store\n * @return {object} updated data store\n */\n deletePrototype(filepath, store) {\n const file = path.parse(filepath);\n const requirePath = utils.removeFile(\n file.name,\n 'prototype',\n filepath,\n store\n );\n\n return store.setIn(\n ['prototypes', file.name],\n requirePath\n );\n },\n};\n\n\n\n// WEBPACK FOOTER //\n// src/cli/handle-html.js","/** @module cli/kss-handler */\n\nimport { utils } from './utils';\nimport { templateHandler } from './handle-templates';\nimport { writeStore } from './require-templates';\n\nconst path = require('path');\nconst fs = require('fs-extra');\nconst parse = require('kss').parse;\nconst chalk = require('chalk'); // Colorize terminal output\n\n/* eslint-disable */\nexport const kssHandler = {\n/* eslint-enable */\n\n /**\n * Handle update of a KSS section\n *\n * @function updateKSS\n * @param {string} filepath - filepath of changed file (comes from gaze)\n * @param {object} store - memory store\n * @return {object} updated data store\n */\n updateKSS(filepath, store) {\n const kssSource = fs.readFileSync(filepath, 'utf8');\n const huron = store.get('config');\n const oldSection = utils.getSection(filepath, false, store) || {};\n const file = path.parse(filepath);\n let newStore = store;\n\n if (kssSource) {\n const styleguide = parse(kssSource, huron.get('kssOptions'));\n\n if (styleguide.data.sections.length) {\n const section = utils.normalizeSectionData(\n styleguide.data.sections[0]\n );\n\n if (section.reference && section.referenceURI) {\n // Update or add section data\n newStore = kssHandler.updateSectionData(\n filepath,\n section,\n oldSection,\n newStore\n );\n\n // Remove old section data if reference URI has changed\n if (oldSection &&\n oldSection.referenceURI &&\n oldSection.referenceURI !== section.referenceURI\n ) {\n newStore = this.unsetSection(oldSection, file, newStore, false);\n }\n\n writeStore(newStore);\n console.log(\n chalk.green(\n `KSS source in ${filepath} changed or added`\n )\n );\n return newStore;\n }\n\n console.log(\n chalk.magenta(\n `KSS section in ${filepath} is missing a section reference`\n )\n );\n return newStore;\n }\n\n console.log(chalk.magenta(`No KSS found in ${filepath}`));\n return newStore;\n }\n\n if (oldSection) {\n newStore = kssHandler.deleteKSS(filepath, oldSection, newStore);\n }\n\n console.log(chalk.red(`${filepath} not found or empty`)); // eslint-disable-line no-console\n return newStore;\n },\n\n /**\n * Handle removal of a KSS section\n *\n * @function deleteKSS\n * @param {string} filepath - filepath of changed file (comes from gaze)\n * @param {object} section - KSS section data\n * @param {object} store - memory store\n * @return {object} updated data store\n */\n deleteKSS(filepath, section, store) {\n const file = path.parse(filepath);\n\n if (section.reference && section.referenceURI) {\n // Remove section data from memory store\n return kssHandler.unsetSection(section, file, store, true);\n }\n\n return store;\n },\n\n /**\n * Update the sections store with new data for a specific section\n *\n * @function updateSectionData\n * @param {object} section - contains updated section data\n * @param {string} kssPath - path to KSS section\n * @param {object} store - memory store\n * @return {object} updated data store\n */\n updateSectionData(kssPath, section, oldSection, store) {\n const sectionFileInfo = path.parse(kssPath);\n const dataFilepath = path.join(\n sectionFileInfo.dir,\n `${sectionFileInfo.name}.json`\n );\n const isInline = null !== section.markup.match(/<\\/[^>]*>/);\n const newSort = kssHandler.sortSection(\n store.getIn(['sections', 'sorted']),\n section.reference,\n store.get('referenceDelimiter')\n );\n const newSection = Object.assign({}, oldSection, section);\n let newStore = store;\n\n // Required for reference from templates and data\n newSection.kssPath = kssPath;\n\n if (isInline) {\n // Set section value if inlineTempalte() returned a path\n newStore = kssHandler.updateInlineTemplate(\n kssPath,\n oldSection,\n newSection,\n newStore\n );\n } else {\n // Remove inline template, if it exists\n utils.removeFile(\n newSection.referenceURI,\n 'template',\n kssPath,\n store\n );\n // Update markup and data fields\n newStore = kssHandler.updateTemplateFields(\n sectionFileInfo,\n oldSection,\n newSection,\n newStore\n );\n }\n\n // Output section description\n newStore = kssHandler.updateDescription(\n kssPath,\n oldSection,\n newSection,\n newStore\n );\n\n // Output section data to a JSON file\n newSection.sectionPath = utils.writeSectionData(\n newStore,\n newSection,\n dataFilepath\n );\n\n // Update section sorting\n return newStore\n .setIn(\n ['sections', 'sorted'],\n newSort\n )\n .setIn(\n ['sections', 'sectionsByPath', kssPath],\n newSection\n )\n .setIn(\n ['sections', 'sectionsByURI', section.referenceURI],\n newSection\n );\n },\n\n /**\n * Handle detection and output of inline templates, which is markup written\n * in the KSS documentation itself as opposed to an external file\n *\n * @function updateInlineTemplate\n * @param {string} oldSection - previous iteration of KSS data, if updated\n * @param {object} section - KSS section data\n * @return {object} updated data store with new template path info\n */\n updateInlineTemplate(filepath, oldSection, section, store) {\n const newSection = section;\n const newStore = store;\n\n // If we have inline markup\n if (this.fieldShouldOutput(oldSection, section, 'markup')) {\n newSection.templatePath = utils.writeFile(\n section.referenceURI,\n 'template',\n filepath,\n section.markup,\n store\n );\n newSection.templateContent = section.markup;\n\n return newStore\n .setIn(\n ['sections', 'sectionsByPath', filepath],\n newSection\n )\n .setIn(\n ['sections', 'sectionsByURI', section.referenceURI],\n newSection\n );\n }\n\n return newStore;\n },\n\n /**\n * Handle output of section description\n *\n * @function updateDescription\n * @param {string} oldSection - previous iteration of KSS data, if updated\n * @param {object} section - KSS section data\n * @return {object} updated data store with new descripton path info\n */\n updateDescription(filepath, oldSection, section, store) {\n const newSection = section;\n const newStore = store;\n\n // If we don't have previous KSS or the KSS has been updated\n if (this.fieldShouldOutput(oldSection, section, 'description')) {\n // Write new description\n newSection.descriptionPath = utils.writeFile(\n section.referenceURI,\n 'description',\n filepath,\n section.description,\n store\n );\n\n return newStore\n .setIn(\n ['sections', 'sectionsByPath', filepath],\n newSection\n )\n .setIn(\n ['sections', 'sectionsByURI', section.referenceURI],\n newSection\n );\n }\n\n return newStore;\n },\n\n /**\n * Handle Data and Markup fields\n *\n * @function updateTemplateFields\n * @param {string} file - File data for KSS file from path.parse()\n * @param {object} oldSection - outdated KSS data\n * @param {object} section - KSS section data\n * @param {object} store - memory store\n * @return {object} KSS section data with updated asset paths\n */\n updateTemplateFields(file, oldSection, section, store) {\n const kssPath = path.format(file);\n const newSection = section;\n let filepath = '';\n let oldFilepath = '';\n let newStore = store;\n\n ['data', 'markup'].forEach((field) => {\n if (newSection[field]) {\n if (oldSection[field]) {\n oldFilepath = path.join(file.dir, oldSection[field]);\n newStore = templateHandler.deleteTemplate(\n oldFilepath,\n oldSection,\n newStore\n );\n }\n\n filepath = path.join(file.dir, newSection[field]);\n newStore = templateHandler.updateTemplate(\n filepath,\n newSection,\n newStore\n );\n } else {\n delete newSection[field];\n newStore = newStore\n .setIn(\n ['sections', 'sectionsByPath', kssPath],\n newSection\n )\n .setIn(\n ['sections', 'sectionsByURI', newSection.referenceURI],\n newSection\n );\n }\n });\n\n return newStore;\n },\n\n /**\n * Remove a section from the memory store\n *\n * @function unsetSection\n * @param {object} section - contains updated section data\n * @param {string} file - file object from path.parse()\n * @param {object} store - memory store\n * @param {bool} removed - has the file been removed or just the section information changed?\n * @return {object} updated data store with new descripton path info\n */\n unsetSection(section, file, store, removed) {\n const sorted = store.getIn(['sections', 'sorted']);\n const kssPath = path.format(file);\n const dataFilepath = path.join(file.dir, `${file.name}.json`);\n const isInline = section.markup &&\n null !== section.markup.match(/<\\/[^>]*>/);\n const newSort = kssHandler.unsortSection(\n sorted,\n section.reference,\n store.get('referenceDelimiter')\n );\n let newStore = store;\n\n // Remove old section data\n utils.removeFile(\n section.referenceURI,\n 'section',\n dataFilepath,\n newStore\n );\n\n // Remove associated inline template\n if (isInline) {\n utils.removeFile(section.referenceURI, 'template', kssPath, newStore);\n }\n\n // Remove description template\n utils.removeFile(section.referenceURI, 'description', kssPath, newStore);\n\n // Remove data from sectionsByPath if file has been removed\n if (removed) {\n newStore = newStore.deleteIn(['sections', 'sectionsByPath', kssPath]);\n }\n\n return newStore\n .deleteIn(['sections', 'sectionsByURI', section.referenceURI])\n .setIn(['sections', 'sorted'], newSort);\n },\n\n /**\n * Sort sections and subsections\n *\n * @function sortSection\n * @param {object} sorted - currently sorted sections\n * @param {string} reference - reference URI of section to sort\n * @return {object} updated data store with new descripton path info\n */\n sortSection(sorted, reference, delimiter) {\n const parts = reference.split(delimiter);\n const newSort = sorted[parts[0]] || {};\n const newSorted = sorted;\n\n if (1 < parts.length) {\n const newParts = parts.filter((part, idx) => 0 !== idx);\n newSorted[parts[0]] = kssHandler.sortSection(\n newSort,\n newParts.join(delimiter),\n delimiter\n );\n } else {\n newSorted[parts[0]] = newSort;\n }\n\n return newSorted;\n },\n\n /**\n * Remove a section from the sorted sections\n *\n * @function unsortSection\n * @param {object} sorted - currently sorted sections\n * @param {string} reference - reference URI of section to sort\n * @return {object} updated data store with new descripton path info\n */\n unsortSection(sorted, reference, delimiter) {\n const parts = reference.split(delimiter);\n const subsections = Object.keys(sorted[parts[0]]);\n const newSorted = sorted;\n\n if (subsections.length) {\n if (1 < parts.length) {\n const newParts = parts.filter((part, idx) => 0 !== idx);\n newSorted[parts[0]] = kssHandler.unsortSection(\n newSorted[parts[0]],\n newParts.join(delimiter),\n delimiter\n );\n }\n } else {\n delete newSorted[parts[0]];\n }\n\n return newSorted;\n },\n\n /**\n * Compare a KSS field between old and new KSS data to see if we need to output\n * a new module for that field\n *\n * @function fieldShouldOutput\n * @param {object} oldSection - currently sorted sections\n * @param {object} newSection - reference URI of section to sort\n * @param {string} field - KSS field to check\n * @return {bool} output a new module for the KSS field\n */\n fieldShouldOutput(oldSection, newSection, field) {\n return (oldSection &&\n (oldSection[field] !== newSection[field] ||\n oldSection.referenceURI !== newSection.referenceURI)\n ) ||\n ! oldSection;\n },\n};\n\n\n\n// WEBPACK FOOTER //\n// src/cli/handle-kss.js","// Necessary to remove require statement from Webpack processing preserve it in output\n/* eslint-disable import/no-dynamic-require, global-require */\nexport default function requireExternal(requirePath) {\n return require(requirePath);\n}\n/* eslint-enable */\n\n\n\n// WEBPACK FOOTER //\n// src/cli/require-external.js","/** @module cli/webpack-server */\n\nimport program from './parse-args';\n\nconst webpack = require('webpack');\nconst WebpackDevServer = require('webpack-dev-server');\nconst chalk = require('chalk'); // Colorize terminal output\n\n/**\n * Spin up webpack-dev-server or, if production flag is set, run webpack a single time\n *\n * @function startWebpack\n * @param {object} config - webpack configuration, preprocessed by {@link module:cli/generate-config generateConfig}\n * @see {@link module:cli/generate-config generateConfig}\n */\nexport default function startWebpack(config) {\n const huron = config.huron;\n const webpackConfig = config.webpack;\n const compiler = webpack(webpackConfig);\n\n if (program.progress) {\n compiler.apply(\n new webpack.ProgressPlugin(\n (percentage, msg) => {\n console.log(`${(percentage * 100)}% `, msg);\n }\n )\n );\n }\n\n if (program.production) {\n compiler.run((err, stats) => {\n const info = stats.toJson();\n\n if (err) {\n console.log(err);\n }\n\n if (stats.hasErrors()) {\n console.error(\n chalk.red(\n 'Webpack encountered errors during compile: ',\n info.errors\n )\n );\n }\n\n if (stats.hasWarnings()) {\n console.error(\n chalk.yellow(\n 'Webpack encountered warnings during compile: ', info.warnings\n )\n );\n }\n });\n } else {\n const server = new WebpackDevServer(compiler, {\n hot: true,\n quiet: false,\n noInfo: false,\n stats: {\n colors: true,\n hash: false,\n version: false,\n assets: false,\n chunks: false,\n modules: false,\n reasons: false,\n children: false,\n source: false,\n },\n contentBase: huron.root,\n publicPath: `http://localhost:${huron.port}/${huron.root}`,\n });\n server.listen(\n huron.port,\n 'localhost',\n (err) => {\n if (err) {\n return console.log(err);\n }\n\n console.log(`Listening at http://localhost:${huron.port}/`);\n return true;\n }\n );\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// src/cli/server.js","const path = require('path');\n\nmodule.exports = {\n css: [],\n entry: 'huron',\n js: [],\n kss: 'css/',\n kssExtension: '.css',\n kssOptions: {\n multiline: true,\n markdown: true,\n custom: ['data'],\n },\n output: 'partials',\n port: 8080,\n prototypes: ['index'],\n root: 'dist/',\n sectionTemplate: path.join(__dirname, '../templates/section.hbs'),\n templates: {\n rule: {\n test: /\\.(hbs|handlebars)$/,\n use: 'handlebars-template-loader',\n },\n extension: '.hbs',\n },\n window: {},\n};\n\n\n\n// WEBPACK FOOTER //\n// src/default-config/huron.config.js","const webpack = require('webpack');\nconst path = require('path');\n\nmodule.exports = {\n entry: {},\n output: {\n // path: [huron root directory],\n filename: '[name].js',\n chunkFilename: '[name].chunk.min.js',\n },\n plugins: [\n new webpack.HotModuleReplacementPlugin(),\n new webpack.NamedModulesPlugin(),\n ],\n resolve: {\n modulesDirectories: [\n path.resolve(__dirname, '../src/js'),\n ],\n },\n resolveLoader: {\n modulesDirectories: [\n 'web_loaders',\n 'web_modules',\n 'node_loaders',\n 'node_modules',\n path.resolve(__dirname, '../node_modules'),\n ],\n },\n module: {\n rules: [\n {\n test: /\\.html?$/,\n use: [\n {\n loader: 'dom-loader',\n options: {\n tag: 'dom-module',\n },\n },\n 'html-loader',\n ],\n // include: ['path/to/templates']\n },\n ],\n },\n};\n\n\n\n// WEBPACK FOOTER //\n// src/default-config/webpack.config.js","module.exports = require(\"commander\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"commander\"\n// module id = 17\n// module chunks = 0","module.exports = require(\"gaze\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"gaze\"\n// module id = 18\n// module chunks = 0","module.exports = require(\"html-webpack-plugin\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"html-webpack-plugin\"\n// module id = 19\n// module chunks = 0","module.exports = require(\"immutable\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"immutable\"\n// module id = 20\n// module chunks = 0","module.exports = require(\"kss\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"kss\"\n// module id = 21\n// module chunks = 0","module.exports = require(\"url\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"url\"\n// module id = 22\n// module chunks = 0","module.exports = require(\"webpack-dev-server\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"webpack-dev-server\"\n// module id = 23\n// module chunks = 0"],"mappings":";AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;AChEA;;;;;;ACAA;;;;;;ACAA;;;;;;;;;;;;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;AAQA;AACA;AACA;AACA;AACA;AACA;AACA;AAIA;AACA;AACA;AACA;AACA;AAOA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;;;;;;;;AAQA;AACA;AACA;AACA;AACA;AACA;AAIA;AACA;AACA;AAGA;AACA;AASA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;AAOA;AACA;AAGA;AACA;AACA;;;;;;;;AAQA;AACA;AACA;AACA;;AAFA;AAKA;AACA;AACA;;;;;;;;;;AAUA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;AAUA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAIA;AAKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;AAQA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAIA;AAKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;AAQA;AACA;AACA;AACA;AACA;AACA;AAMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;AAQA;AACA;AAGA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;AASA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AAvTA;;;;;;;;;;;;ACTA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;AAMA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAaA;AACA;AACA;AACA;;;;;;;ACjDA;;;;;;;;;;;;;;ACCA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;AASA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAaA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;AASA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAMA;AACA;AACA;AAUA;AA9FA;;;;;;;;;;;;ACRA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAIA;;;;;;;;;AASA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;;AAEA;;;;;;;;;;;;AAYA;;AAEA;;;;;;;;;;;;;;;;;;;;;;;;;AAhBA;AACA;AA0CA;;;;;;;;;;;;;AAAA;AACA;AAcA;AACA;AACA;AAGA;AAHA;AAMA;AACA;AACA;;;;;;;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AAHA;AAMA;;;;;;;;;ACnHA;AACA;AAAA;AACA;AAAA;AACA;;;AAAA;AACA;;;AAAA;AACA;;;;;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;AAKA;AACA;AACA;AACA;AACA;AAGA;;;;;AAKA;AACA;AAMA;AACA;AACA;;;;;AAKA;AACA;AAQA;AACA;AACA;AACA;AACA;AAHA;AAKA;AACA;AACA;AACA;AAlBA;AAoBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;;;;;AAKA;AACA;AACA;;;;;AAKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;AAOA;AACA;AACA;AACA;AACA;AACA;;;;;;;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;AClJA;AA2CA;AA+DA;AACA;AA9HA;AACA;AAAA;AACA;AAAA;AACA;AAAA;AACA;AACA;AARA;AACA;AACA;AAOA;AACA;AACA;AACA;AACA;AACA;;;;;;;;AAQA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAIA;AACA;AACA;AACA;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAxBA;AACA;AA0BA;AACA;AACA;AACA;;;;;;;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAxCA;AACA;AA0CA;AACA;AACA;AACA;;;;;;;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AArCA;AACA;AAuCA;;;;;;;;;;;;;ACpJA;AACA;AA1BA;AACA;;;AAAA;AACA;;;;;AAJA;AACA;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAFA;AAIA;AACA;AACA;;;;;;;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AAKA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;;;;;;;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAIA;AACA;AAKA;AACA;AACA;AACA;AACA;AACA;;;;;;;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AAEA;AACA;AACA;AAHA;AACA;AAOA;AACA;AACA;AACA;;;;;;;AAOA;AACA;AACA;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AAKA;AACA;AAZA;AAcA;AACA;AACA;AACA;AACA;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAFA;AAIA;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;AAQA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;ACrSA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;AASA;AACA;AACA;AACA;AACA;AACA;AACA;AAOA;AACA;AACA;AACA;AACA;AACA;AASA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;AASA;AACA;AACA;AACA;AACA;AAMA;AACA;AACA;AASA;AACA;AACA;;;;;;;;AAQA;AACA;AACA;AACA;AACA;AACA;AACA;AAOA;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;AAQA;AACA;AACA;AACA;AAMA;AAIA;AAjIA;;;;;;;;;;;;;;ACNA;AACA;AAAA;AACA;AAAA;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;AAQA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AAMA;AACA;AAIA;AACA;AACA;AACA;AACA;AAKA;AACA;AACA;AACA;AAKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;AASA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;AASA;AACA;AACA;AAIA;AACA;AAKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAMA;AACA;AACA;AAMA;AACA;AAMA;AACA;AACA;AACA;AACA;AAMA;AACA;AACA;AAKA;AACA;AAaA;AACA;AACA;;;;;;;;;AASA;AACA;AACA;AACA;AACA;AACA;AACA;AAOA;AACA;AACA;AASA;AACA;AACA;AACA;AACA;AACA;;;;;;;;AAQA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAOA;AASA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;AAUA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAKA;AACA;AACA;AACA;AAKA;AACA;AACA;AASA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;AAUA;AACA;AACA;AACA;AACA;AAEA;AAKA;AACA;AACA;AACA;AACA;AAMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;;;;;;;;AAQA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;AAQA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;AAUA;AACA;AAKA;AAtaA;;;;;;;;;;;ACVA;AAFA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;ACWA;AACA;AAdA;AACA;;;;;AACA;AACA;AAAA;AACA;AACA;AACA;;;;;;;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAMA;AACA;AACA;AACA;AAKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AATA;AAWA;AACA;AAhBA;AAkBA;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;;;;;;;;;;ACtFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAHA;AAKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAFA;AAIA;AALA;AAOA;AAvBA;;;;;;;;;ACFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAHA;AAKA;AAIA;AACA;AADA;AAKA;AACA;AADA;AASA;AACA;AAEA;AACA;AAEA;AACA;AACA;AADA;AAFA;AAHA;AAFA;AAzBA;;;;;;ACHA;;;;;;ACAA;;;;;;ACAA;;;;;;ACAA;;;;;;ACAA;;;;;;ACAA;;;;;;ACAA;;;;;;;;;;","sourceRoot":""} \ No newline at end of file +{"version":3,"file":"huron-cli.js","sources":["webpack:///webpack/bootstrap c39ca41aeebe852abcea","webpack:///external \"path\"","webpack:///external \"chalk\"","webpack:///external \"fs-extra\"","webpack:///src/cli/utils.js","webpack:///src/cli/parse-args.js","webpack:///external \"webpack\"","webpack:///src/cli/handle-templates.js","webpack:///src/cli/require-templates.js","webpack:///src/cli/huron-cli.js","webpack:///src/cli/actions.js","webpack:///src/cli/generate-config.js","webpack:///src/cli/handle-html.js","webpack:///src/cli/handle-kss.js","webpack:///src/cli/huron-store.js","webpack:///src/cli/require-external.js","webpack:///src/cli/server.js","webpack:///src/default-config/huron.config.js","webpack:///src/default-config/webpack.config.js","webpack:///external \"commander\"","webpack:///external \"gaze\"","webpack:///external \"html-webpack-plugin\"","webpack:///external \"immutable\"","webpack:///external \"kss\"","webpack:///external \"url\"","webpack:///external \"webpack-dev-server\""],"sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// identity function for calling harmony imports with the correct context\n \t__webpack_require__.i = function(value) { return value; };\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"../\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 25);\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap c39ca41aeebe852abcea","module.exports = require(\"path\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"path\"\n// module id = 0\n// module chunks = 0","module.exports = require(\"chalk\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"chalk\"\n// module id = 1\n// module chunks = 0","module.exports = require(\"fs-extra\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"fs-extra\"\n// module id = 2\n// module chunks = 0","/** @module cli/utilities */\n\nconst cwd = process.cwd(); // Current working directory\nconst path = require('path');\nconst fs = require('fs-extra');\nconst chalk = require('chalk'); // Colorize terminal output\n\n/**\n * Ensure predictable data structure for KSS section data\n *\n * @function normalizeSectionData\n * @param {object} section - section data\n * @return {object} section data\n */\nexport function normalizeSectionData(section) {\n const data = section.data || section;\n\n if (! data.referenceURI || '' === data.referenceURI) {\n data.referenceURI = section.referenceURI();\n }\n\n return data;\n}\n\n/**\n * Ensure predictable data structure for KSS section data\n *\n * @function writeSectionData\n * @param {object} store - data store\n * @param {object} section - section data\n * @param {string} sectionPath - output destination for section data file\n */\nexport function writeSectionData(store, section, sectionPath = false) {\n let outputPath = sectionPath;\n let sectionFileInfo;\n\n if (! outputPath && {}.hasOwnProperty.call(section, 'kssPath')) {\n sectionFileInfo = path.parse(section.kssPath);\n outputPath = path.join(\n sectionFileInfo.dir,\n `${sectionFileInfo.name}.json`\n );\n }\n\n // Output section data\n if (outputPath) {\n return writeFile(\n section.referenceURI,\n 'section',\n outputPath,\n JSON.stringify(section),\n store\n );\n }\n\n console.warn( // eslint-disable-line no-console\n chalk.red(`Failed to write section data for ${section.referenceURI}`)\n );\n return false;\n}\n\n/**\n * Find .json from a template file or vice versa\n *\n * @function getTemplateDataPair\n * @param {object} file - file object from path.parse()\n * @param {object} section - KSS section data\n * @return {string} relative path to module JSON file\n */\nexport function getTemplateDataPair(file, section, store) {\n const huron = store.get('config');\n const kssDir = matchKssDir(file.dir, huron);\n\n if (kssDir) {\n const componentPath = path.relative(\n path.resolve(cwd, kssDir),\n file.dir\n );\n const partnerType = '.json' === file.ext ? 'template' : 'data';\n const partnerExt = '.json' === file.ext ?\n huron.get('templates').extension :\n '.json';\n\n const pairPath = path.join(\n componentPath,\n generateFilename(\n section.referenceURI,\n partnerType,\n partnerExt,\n store\n )\n );\n\n return `./${pairPath}`;\n }\n\n return false;\n}\n\n/**\n * Normalize a section title for use as a filename\n *\n * @function normalizeHeader\n * @param {string} header - section header extracted from KSS documentation\n * @return {string} modified header, lowercase and words separated by dash\n */\nexport function normalizeHeader(header) {\n return header\n .toLowerCase()\n .replace(/\\s?\\W\\s?/g, '-');\n}\n\n/**\n * Wrap html in required template tags\n *\n * @function wrapMarkup\n * @param {string} content - html or template markup\n * @param {string} templateId - id of template (should be section reference)\n * @return {string} modified HTML\n */\nexport function wrapMarkup(content, templateId) {\n return `\n\n\\n`;\n}\n\n/**\n * Generate a filename based on referenceURI, type and file object\n *\n * @function generateFilename\n * @param {string} id - The name of the file (with extension).\n * @param {string} type - the type of file output\n * @param {object} ext - file extension\n * @param {store} store - data store\n * @return {string} Path to output file, relative to ouput dir (can be use in require statements)\n */\nexport function generateFilename(id, type, ext, store) {\n // Type of file and its corresponding extension(s)\n const types = store.get('types');\n const outputExt = '.scss' !== ext ? ext : '.html';\n\n /* eslint-disable */\n if (-1 === types.indexOf(type)) {\n console.log(`Huron data ${type} does not exist`);\n return false;\n }\n /* eslint-enable */\n\n return `${id}-${type}${outputExt}`;\n}\n\n/**\n * Copy an HTML file into the huron output directory.\n *\n * @function writeFile\n * @param {string} id - The name of the file (with extension).\n * @param {string} content - The content of the file to write.\n * @param {string} type - the type of file output\n * @param {object} store - The data store\n * @return {string} Path to output file, relative to ouput dir (can be use in require statements)\n */\nexport function writeFile(id, type, filepath, content, store) {\n const huron = store.get('config');\n const file = path.parse(filepath);\n const filename = generateFilename(id, type, file.ext, store);\n const kssDir = matchKssDir(filepath, huron);\n\n if (kssDir) {\n const componentPath = path.relative(\n path.resolve(cwd, kssDir),\n file.dir\n );\n const outputRelative = path.join(\n huron.get('output'),\n componentPath,\n `${filename}`\n );\n const outputPath = path.resolve(cwd, huron.get('root'), outputRelative);\n let newContent = content;\n\n if ('data' !== type && 'section' !== type) {\n newContent = wrapMarkup(content, id);\n }\n\n try {\n fs.outputFileSync(outputPath, newContent);\n console.log(chalk.green(`Writing ${outputRelative}`)); // eslint-disable-line no-console\n } catch (e) {\n console.log(chalk.red(`Failed to write ${outputRelative}`)); // eslint-disable-line no-console\n }\n\n return `./${outputRelative.replace(`${huron.get('output')}/`, '')}`;\n }\n\n return false;\n}\n\n/**\n * Delete a file in the huron output directory\n *\n * @function removeFile\n * @param {string} filename - The name of the file (with extension).\n * @param {object} store - The data store\n * @return {string} Path to output file, relative to ouput dir (can be use in require statements)\n */\nexport function removeFile(id, type, filepath, store) {\n const huron = store.get('config');\n const file = path.parse(filepath);\n const filename = generateFilename(id, type, file.ext, store);\n const kssDir = matchKssDir(filepath, huron);\n\n if (kssDir) {\n const componentPath = path.relative(\n path.resolve(cwd, kssDir),\n file.dir\n );\n const outputRelative = path.join(\n huron.get('output'),\n componentPath,\n `${filename}`\n );\n const outputPath = path.resolve(cwd, huron.get('root'), outputRelative);\n\n try {\n fs.removeSync(outputPath);\n console.log(chalk.green(`Removing ${outputRelative}`)); // eslint-disable-line no-console\n } catch (e) {\n console.log( // eslint-disable-line no-console\n chalk.red(`${outputRelative} does not exist or cannot be deleted`)\n );\n }\n\n return `./${outputRelative.replace(`${huron.get('output')}/`, '')}`;\n }\n\n return false;\n}\n\n/**\n * Write a template for sections\n *\n * @function writeSectionTemplate\n * @param {string} filepath - the original template file\n * @param {object} store - data store\n * @return {object} updated store\n */\nexport function writeSectionTemplate(filepath, store) {\n const huron = store.get('config');\n const sectionTemplate = wrapMarkup(fs.readFileSync(filepath, 'utf8'));\n const componentPath = './huron-sections/sections.hbs';\n const output = path.join(\n cwd,\n huron.get('root'),\n huron.get('output'),\n componentPath\n );\n\n // Move huron script and section template into huron root\n fs.outputFileSync(output, sectionTemplate);\n console.log(chalk.green(`writing section template to ${output}`)); // eslint-disable-line no-console\n\n return store.set('sectionTemplatePath', componentPath);\n}\n\n/**\n * Request for section data based on section reference\n *\n * @function writeSectionTemplate\n * @param {string} search - key on which to match section\n * @param {field} string - field in which to look to determine section\n * @param {obj} store - sections memory store\n */\nexport function getSection(search, field, store) {\n const sectionValues = store\n .getIn(['sections', 'sectionsByPath'])\n .valueSeq();\n let selectedSection = false;\n\n if (field) {\n selectedSection = sectionValues\n .filter((value) => value[field] === search)\n .get(0);\n } else {\n selectedSection = store.getIn(['sections', 'sectionsByPath', search]);\n }\n\n return selectedSection;\n}\n\n/**\n * Find which configured KSS directory a filepath exists in\n *\n * @function matchKssDir\n * @param {string} filepath - filepath to search for\n * @param {object} huron - huron configuration\n * @return {string} kssMatch - relative path to KSS directory\n */\nexport function matchKssDir(filepath, huron) {\n const kssSource = huron.get('kss');\n /* eslint-disable space-unary-ops */\n // Include forward slash in our test to make sure we're matchin a directory, not a file extension\n const kssMatch = kssSource.filter((dir) => filepath.includes(`/${dir}`));\n /* eslint-enable space-unary-ops */\n\n if (kssMatch.length) {\n return kssMatch[0];\n }\n\n console.error(\n chalk.red(`filepath ${filepath} does not exist in any\n of the configured KSS directories`)\n );\n\n return false;\n}\n\n\n\n// WEBPACK FOOTER //\n// src/cli/utils.js","/** @module cli/parse-arguments */\n/* eslint-disable space-unary-ops */\n\n// Requires\n/** @global */\nconst program = require('commander'); // Easy program flags\nconst path = require('path');\n\nexport default program;\n\n/**\n * Process huron CLI arguments\n *\n * @function parseArgs\n * @example node huron/dist/cli/huron-cli.js --config 'client/config/webpack.config.js' --production\n */\nfunction parseArgs() {\n const envArg = {};\n\n process.argv = process.argv.filter((arg) => {\n if (-1 !== arg.indexOf('--env')) {\n const envParts = arg\n .split('.')[1]\n .split('=');\n\n envArg[envParts[0]] = envParts[1] || true;\n return false;\n }\n\n return true;\n });\n\n program.version('1.0.1')\n .option(\n '-c, --huron-config [huronConfig]',\n '[huronConfig] for all huron options',\n path.resolve(__dirname, '../default-config/huron.config.js')\n )\n .option(\n '-w, --webpack-config [webpackConfig]',\n '[webpackConfig] for all webpack options',\n path.resolve(__dirname, '../default-config/webpack.config.js')\n )\n .option('-p, --production', 'compile assets once for production');\n\n program.env = envArg;\n\n // Only parse if we're not running tests\n if (\n ! process.env.npm_lifecycle_event ||\n 'test' !== process.env.npm_lifecycle_event\n ) {\n program.parse(process.argv);\n }\n}\n\nparseArgs();\n/* eslint-enable */\n\n\n\n// WEBPACK FOOTER //\n// src/cli/parse-args.js","module.exports = require(\"webpack\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"webpack\"\n// module id = 5\n// module chunks = 0","/** @module cli/template-handler */\nimport * as utils from './utils';\n\nconst path = require('path');\nconst fs = require('fs-extra');\nconst chalk = require('chalk');\n\n/**\n * Handle update of a template or data (json) file\n *\n * @function updateTemplate\n * @param {string} filepath - filepath of changed file (comes from gaze)\n * @param {object} section - contains KSS section data\n * @param {object} store - memory store\n * @return {object} updated memory store\n */\nexport function updateTemplate(filepath, section, store) {\n const file = path.parse(filepath);\n const pairPath = utils.getTemplateDataPair(file, section, store);\n const type = '.json' === file.ext ? 'data' : 'template';\n const newSection = section;\n const newStore = store;\n let content = false;\n\n try {\n content = fs.readFileSync(filepath, 'utf8');\n } catch (e) {\n console.log(chalk.red(`${filepath} does not exist`));\n }\n\n if (content) {\n const requirePath = utils.writeFile(\n newSection.referenceURI,\n type,\n filepath,\n content,\n newStore\n );\n newSection[`${type}Path`] = requirePath;\n\n if ('template' === type) {\n newSection.templateContent = content;\n\n // Rewrite section data with template content\n newSection.sectionPath = utils.writeSectionData(newStore, newSection);\n }\n\n return newStore\n .setIn(\n ['templates', requirePath],\n pairPath\n )\n .setIn(\n ['sections', 'sectionsByPath', newSection.kssPath],\n newSection\n )\n .setIn(\n ['sections', 'sectionsByURI', newSection.referenceURI],\n newSection\n );\n }\n\n return newStore;\n}\n\n/**\n * Handle removal of a template or data (json) file\n *\n * @function deleteTemplate\n * @param {string} filepath - filepath of changed file (comes from gaze)\n * @param {object} section - contains KSS section data\n * @param {object} store - memory store\n * @return {object} updated memory store\n */\nexport function deleteTemplate(filepath, section, store) {\n const file = path.parse(filepath);\n const type = '.json' === file.ext ? 'data' : 'template';\n const newSection = section;\n const newStore = store;\n\n // Remove partner\n const requirePath = utils.removeFile(\n newSection.referenceURI,\n type,\n filepath,\n newStore\n );\n delete newSection[`${type}Path`];\n\n return newStore\n .deleteIn(['templates', requirePath])\n .setIn(\n ['sections', 'sectionsByPath', newSection.kssPath],\n newSection\n )\n .setIn(\n ['sections', 'sectionsByURI', newSection.referenceURI],\n newSection\n );\n}\n\n\n\n// WEBPACK FOOTER //\n// src/cli/handle-templates.js","/** @module cli/require-templates */\n\nconst path = require('path');\nconst fs = require('fs-extra');\n\nconst cwd = process.cwd();\nconst huronScript = fs.readFileSync(\n path.join(__dirname, '../web/huron.js'),\n 'utf8'\n);\n\n/**\n * Write code for requiring all generated huron assets\n * Note: prepended and appended code in this file should roughly follow es5 syntax for now,\n * as it will not pass through the Huron internal babel build nor can we assume the user is\n * working with babel.\n *\n * @function requireTemplates\n * @param {object} store - memory store\n */\nexport const requireTemplates = function requireTemplates(store) {\n const huron = store.get('config');\n const outputPath = path.join(cwd, huron.get('root'), 'huron-assets');\n const requireRegex = new RegExp(`\\\\.html|\\\\.json|\\\\${\n huron.get('templates').extension\n }$`);\n const requirePath = `'../${huron.get('output')}'`;\n\n // Initialize templates, js, css and HMR acceptance logic\n const prepend = `\nvar store = require('./huron-store.js');\nvar assets = require.context(${requirePath}, true, ${requireRegex});\nvar modules = {};\n\nassets.keys().forEach(function(key) {\n modules[key] = assets(key);\n});\n\nif (module.hot) {\n module.hot.accept(\n assets.id,\n () => {\n var newAssets = require.context(\n ${requirePath},\n true,\n ${requireRegex}\n );\n var newModules = newAssets.keys()\n .map((key) => {\n return [key, newAssets(key)];\n })\n .filter((newModule) => {\n return modules[newModule[0]] !== newModule[1];\n });\n\n updateStore(require('./huron-store.js'));\n\n newModules.forEach((module) => {\n modules[module[0]] = module[1];\n hotReplace(module[0], module[1], modules);\n });\n }\n );\n\n module.hot.accept(\n './huron-store.js',\n () => {\n updateStore(require('./huron-store.js'));\n }\n );\n}\\n`;\n\n const append = `\nfunction hotReplace(key, module, modules) {\n insert.modules = modules;\n if (key === store.sectionTemplatePath) {\n insert.cycleSections();\n } else {\n insert.inserted = [];\n insert.loadModule(key, module, false);\n }\n};\n\nfunction updateStore(newStore) {\n insert.store = newStore;\n}\\n`;\n\n // Write the contents of this script.\n // @todo lint this file.\n fs.outputFileSync(\n path.join(outputPath, 'huron.js'),\n `/*eslint-disable*/\\n\n${prepend}\\n\\n${huronScript}\\n\\n${append}\\n\n/*eslint-enable*/\\n`\n );\n};\n\n/**\n * Output entire data store to a JS object and handle if any KSS data has changed\n *\n * @function writeStore\n * @param {object} store - memory store\n * @param {string} changed - filepath of changed KSS section, if applicable\n */\nexport const writeStore = function writeStore(store) {\n const huron = store.get('config');\n const outputPath = path.join(cwd, huron.get('root'), 'huron-assets');\n\n // Write updated data store\n // @todo lint this file.\n fs.outputFileSync(\n path.join(outputPath, 'huron-store.js'),\n `/*eslint-disable*/\n module.exports = ${JSON.stringify(store.toJSON())}\n /*eslint-disable*/\\n`\n );\n};\n\n\n\n\n// WEBPACK FOOTER //\n// src/cli/require-templates.js","// Local imports\nimport { initFiles, updateFile, deleteFile } from './actions';\nimport { requireTemplates, writeStore } from './require-templates';\nimport program from './parse-args';\nimport startWebpack from './server';\nimport { dataStructure, config } from './huron-store';\n\n// Modules\nconst path = require('path');\nconst Gaze = require('gaze').Gaze;\nconst chalk = require('chalk'); // Colorize terminal output\n\n/**\n * Huron configuration object\n *\n * @global\n */\nconst huron = dataStructure.get('config');\n\n/**\n * Available file extensions. Extensions should not include the leading '.'\n *\n * @global\n */\nconst extensions = [\n huron.get('kssExtension'),\n huron.get('templates').extension,\n 'html',\n 'json',\n].map((extension) => extension.replace('.', ''));\n\n// Generate watch list for Gaze, start gaze\nconst gazeWatch = [];\n\n// Push KSS source directories and section template to Gaze\ngazeWatch.push(path.resolve(__dirname, huron.get('sectionTemplate')));\nhuron.get('kss').forEach((sourceDir) => {\n let gazeDir = sourceDir;\n\n /* eslint-disable space-unary-ops */\n if ('/' === sourceDir.slice(-1)) {\n gazeDir = sourceDir.slice(0, -1);\n }\n /* eslint-enable space-unary-ops */\n\n gazeWatch.push(\n `${gazeDir}/**/*.+(${extensions.join('|')})`\n );\n});\n\n/**\n * Gaze instance for watching all files, including KSS, html, hbs/template, and JSON\n *\n * @global\n */\nconst gaze = new Gaze(gazeWatch);\n\n/**\n * Initialize data store with files from gaze and original data structure\n *\n * @global\n */\nconst store = initFiles(gaze.watched(), dataStructure);\n\nrequireTemplates(store);\nwriteStore(store);\n\nif (! program.production) {\n /** @module cli/gaze */\n let newStore = store;\n\n /**\n * Anonymous handler for Gaze 'changed' event indicating a file has changed\n *\n * @callback changed\n * @listens gaze:changed\n * @param {string} filepath - absolute path of changed file\n */\n gaze.on('changed', (filepath) => {\n newStore = updateFile(filepath, newStore);\n console.log(chalk.green(`${filepath} updated!`));\n });\n\n /**\n * Anonymous handler for Gaze 'added' event indicating a file has been added to the watched directories\n *\n * @callback added\n * @listens gaze:added\n * @param {string} filepath - absolute path of changed file\n */\n gaze.on('added', (filepath) => {\n newStore = updateFile(filepath, newStore);\n writeStore(newStore);\n console.log(chalk.blue(`${filepath} added!`));\n });\n\n /**\n * Anonymous handler for Gaze 'renamed' event indicating a file has been renamed\n *\n * @callback renamed\n * @listens gaze:renamed\n * @param {string} filepath - absolute path of changed file\n */\n gaze.on('renamed', (newPath, oldPath) => {\n newStore = deleteFile(oldPath, newStore);\n newStore = updateFile(newPath, newStore);\n writeStore(newStore);\n console.log(chalk.blue(`${newPath} added!`));\n });\n\n /**\n * Anonymous handler for Gaze 'deleted' event indicating a file has been removed\n *\n * @callback deleted\n * @listens gaze:deleted\n * @param {string} filepath - absolute path of changed file\n */\n gaze.on('deleted', (filepath) => {\n newStore = deleteFile(filepath, newStore);\n writeStore(newStore);\n console.log(chalk.red(`${filepath} deleted`));\n });\n} else {\n gaze.close();\n}\n\n// Start webpack or build for production\nstartWebpack(config);\n\nif (module.hot) {\n module.hot.accept();\n}\n\n\n\n// WEBPACK FOOTER //\n// src/cli/huron-cli.js","/** @module cli/actions */\n\n// Imports\nimport {\n updateHTML,\n deleteHTML,\n updatePrototype,\n deletePrototype,\n} from './handle-html';\nimport { updateTemplate, deleteTemplate } from './handle-templates';\nimport { updateKSS, deleteKSS } from './handle-kss';\nimport * as utils from './utils';\n\n// Requires\nconst path = require('path');\nconst chalk = require('chalk'); // Colorize terminal output\n\n// EXPORTED FUNCTIONS\n\n/**\n * Recursively loop through initial watched files list from Gaze.\n *\n * @param {object} data - object containing directory and file paths\n * @param {object} store - memory store\n * @param {object} huron - huron configuration options\n * @return {object} newStore - map object of entire data store\n */\nexport function initFiles(data, store, depth = 0) {\n const type = Object.prototype.toString.call(data);\n let newStore = store;\n let info;\n let files;\n\n switch (type) {\n case '[object Object]':\n files = Object.keys(data);\n newStore = files.reduce(\n (prevStore, file) => initFiles(data[file], prevStore, depth),\n newStore\n );\n break;\n\n case '[object Array]':\n newStore = data.reduce(\n (prevStore, file) => initFiles(file, prevStore, depth),\n newStore\n );\n break;\n\n case '[object String]':\n info = path.parse(data);\n if (info.ext) {\n newStore = updateFile(data, store);\n }\n break;\n\n default:\n break;\n }\n\n return newStore;\n}\n\n/**\n * Logic for updating and writing file information based on file type (extension)\n *\n * @param {string} filepath - path to updated file. usually passed in from Gaze\n * @param {object} store - memory store\n * @return {object} store - map object of map object of entire data store\n */\nexport function updateFile(filepath, store) {\n const huron = store.get('config');\n const file = path.parse(filepath);\n let field;\n let section;\n\n if (- 1 !== filepath.indexOf(huron.get('sectionTemplate'))) {\n return utils.writeSectionTemplate(filepath, store);\n }\n\n switch (file.ext) {\n // Plain HTML template, external\n case '.html':\n section = utils.getSection(file.base, 'markup', store);\n\n if (section) {\n return updateHTML(filepath, section, store);\n } else if (\n - 1 !== file.dir.indexOf('prototypes') &&\n - 1 !== file.name.indexOf('prototype-')\n ) {\n return updatePrototype(filepath, store);\n }\n\n console.log(chalk.red(`Failed to write file: ${file.name}`));\n break;\n\n // Handlebars template, external\n case huron.get('templates').extension:\n case '.json':\n field = ('.json' === file.ext) ? 'data' : 'markup';\n section = utils.getSection(file.base, field, store);\n\n if (section) {\n return updateTemplate(filepath, section, store);\n }\n\n console.log( // eslint-disable-line no-console\n chalk.red(`Could not find associated KSS section for ${filepath}`)\n );\n break;\n\n // KSS documentation (default extension is `.css`)\n // Will also output a template if markup is inline\n // Note: inline markup does _not_ support handlebars currently\n case huron.get('kssExtension'):\n return updateKSS(filepath, store);\n\n // This should never happen if Gaze is working properly\n default:\n return store;\n }\n\n return store;\n}\n\n/**\n * Logic for deleting file information and files based on file type (extension)\n *\n * @param {string} filepath - path to updated file. usually passed in from Gaze\n * @param {object} store - memory store\n * @return {object} newStore - map object of map object of entire data store\n */\nexport function deleteFile(filepath, store) {\n const huron = store.get('config');\n const file = path.parse(filepath);\n let field = '';\n let section = null;\n let newStore = store;\n\n switch (file.ext) {\n // Plain HTML template, external\n case '.html':\n section = utils.getSection(file.base, 'markup', store);\n\n if (section) {\n newStore = deleteHTML(filepath, section, store);\n } else if (\n - 1 !== file.dir.indexOf('prototypes') &&\n - 1 !== file.name.indexOf('prototype-')\n ) {\n newStore = deletePrototype(filepath, store);\n }\n break;\n\n case huron.get('templates').extension:\n case '.json':\n field = ('.json' === file.ext) ? 'data' : 'markup';\n section = utils.getSection(file.base, field, store);\n\n if (section) {\n newStore = deleteTemplate(filepath, section, store);\n }\n break;\n\n case huron.get('kssExtension'):\n section = utils.getSection(filepath, false, store);\n\n if (section) {\n newStore = deleteKSS(filepath, section, store);\n }\n break;\n\n default:\n console.warn( // eslint-disable-line no-console\n chalk.red(`Could not delete: ${file.name}`)\n );\n break;\n }\n\n return newStore;\n}\n\n\n\n// WEBPACK FOOTER //\n// src/cli/actions.js","/** @module cli/generate-config */\n\nimport program from './parse-args';\nimport requireExternal from './require-external';\n\nconst cwd = process.cwd();\nconst path = require('path');\nconst url = require('url');\nconst fs = require('fs-extra');\nconst webpack = require('webpack');\nconst HTMLWebpackPlugin = require('html-webpack-plugin');\nconst defaultConfig = require('../default-config/webpack.config');\nconst defaultHuron = require('../default-config/huron.config');\n\n// Require configs passed in by user from CLI\nconst localConfigPath = ! path.isAbsolute(program.webpackConfig) ?\n path.join(cwd, program.webpackConfig) :\n program.webpackConfig;\nconst localHuronPath = ! path.isAbsolute(program.huronConfig) ?\n path.join(cwd, program.huronConfig) :\n program.huronConfig;\nconst localConfig = requireExternal(localConfigPath);\nconst localHuron = requireExternal(localHuronPath);\n\n/**\n * Generate a mutant hybrid of the huron default webpack config and your local webpack config\n *\n * @function generateConfig\n * @param {object} config - local webpack config\n * @return {object} newConfig - updated data store\n */\nexport default function generateConfig() {\n let newConfig = localConfig;\n let newHuron = localHuron;\n\n // Execute config function, if provided\n if ('function' === typeof newConfig) {\n newConfig = newConfig(program.env);\n }\n\n // Execute huron config function, if provided\n if ('function' === typeof newHuron) {\n newHuron = newHuron(program.env);\n }\n\n newHuron = Object.assign({}, defaultHuron, newHuron);\n\n // Set ouput options\n newConfig.output = Object.assign({}, defaultConfig.output, newConfig.output);\n newConfig.output.path = path.resolve(cwd, newHuron.root);\n if (! program.production) {\n newConfig.output.publicPath = `http://localhost:${newHuron.port}/${newHuron.root}`;\n } else {\n newConfig.output.publicPath = '';\n }\n\n // configure entries\n newConfig = configureEntries(newHuron, newConfig);\n\n // configure plugins\n newConfig = configurePlugins(newHuron, newConfig);\n\n // configure loaders\n newConfig = configureLoaders(newHuron, newConfig);\n\n // Add HTMLWebpackPlugin for each configured prototype\n newConfig = configurePrototypes(newHuron, newConfig);\n\n // Remove existing devServer settings\n delete newConfig.devServer;\n\n return {\n huron: newHuron,\n webpack: newConfig,\n };\n}\n\n/**\n * Configure and manage webpack entry points\n *\n * @param {object} huron - huron configuration object\n * @param {object} config - webpack configuration object\n * @return {object} newConfig - updated data store\n */\nfunction configureEntries(huron, config) {\n const entry = config.entry[huron.entry];\n const newConfig = config;\n\n newConfig.entry = {};\n if (! program.production) {\n newConfig.entry[huron.entry] = [\n `webpack-dev-server/client?http://localhost:${huron.port}`,\n 'webpack/hot/dev-server',\n path.join(cwd, huron.root, 'huron-assets/huron'),\n ].concat(entry);\n } else {\n newConfig.entry[huron.entry] = [\n path.join(cwd, huron.root, 'huron-assets/huron'),\n ].concat(entry);\n }\n\n return newConfig;\n}\n\n/**\n * Configure and manage webpack plugins\n *\n * @param {object} huron - huron configuration object\n * @param {object} config - webpack configuration object\n * @return {object} newConfig - updated data store\n */\nfunction configurePlugins(huron, config) {\n const newConfig = config;\n\n newConfig.plugins = config.plugins || [];\n\n if (! program.production) {\n if (newConfig.plugins && newConfig.plugins.length) {\n newConfig.plugins = newConfig.plugins.filter(\n (plugin) => 'HotModuleReplacementPlugin' !== plugin.constructor.name &&\n 'NamedModulesPlugin' !== plugin.constructor.name\n );\n }\n newConfig.plugins = newConfig.plugins\n .concat([\n new webpack.HotModuleReplacementPlugin(),\n new webpack.NamedModulesPlugin(),\n ]);\n }\n\n return newConfig;\n}\n\n/**\n * Configure and manage webpack loaders\n *\n * @param {object} huron - huron configuration object\n * @param {object} config - webpack configuration object\n * @return {object} newConfig - updated data store\n */\nfunction configureLoaders(huron, config) {\n // Manage loaders\n const templatesLoader = huron.templates.rule || {};\n const newConfig = config;\n\n templatesLoader.include = [path.join(cwd, huron.root)];\n newConfig.module = newConfig.module || {};\n newConfig.module.rules = newConfig.module.rules ||\n newConfig.module.loaders ||\n [];\n newConfig.module.rules.push(\n {\n test: /\\.html$/,\n use: 'html-loader',\n include: [path.join(cwd, huron.root)],\n },\n templatesLoader\n );\n\n return newConfig;\n}\n\n/**\n * Create an HTML webpack plugin for each configured prototype\n *\n * @param {object} huron - huron configuration object\n * @param {object} config - webpack configuration object\n * @return {object} newConfig - updated data store\n */\nfunction configurePrototypes(huron, config) {\n const wrapperTemplate = fs.readFileSync(\n path.join(__dirname, '../../templates/prototype-template.ejs'),\n 'utf8'\n );\n\n const defaultHTMLPluginOptions = {\n title: '',\n window: huron.window,\n js: [],\n css: [],\n filename: 'index.html',\n template: path.join(\n cwd,\n huron.root,\n 'huron-assets/prototype-template.ejs'\n ),\n inject: false,\n chunks: [huron.entry],\n };\n const newConfig = config;\n\n // Write prototype template file for HTML webpack plugin\n fs.outputFileSync(\n path.join(cwd, huron.root, 'huron-assets/prototype-template.ejs'),\n wrapperTemplate\n );\n\n huron.prototypes.forEach((prototype) => {\n const newPrototype = prototype;\n let opts = {};\n\n // Merge configured settings with default settings\n if ('string' === typeof prototype) {\n opts = Object.assign({}, defaultHTMLPluginOptions, {\n title: prototype,\n filename: `${prototype}.html`,\n });\n } else if (\n 'object' === typeof prototype &&\n {}.hasOwnProperty.call(prototype, 'title')\n ) {\n // Create filename based on configured title if not provided\n if (! prototype.filename) {\n newPrototype.filename = `${prototype.title}.html`;\n }\n\n // Move css assets for this prototype,\n // reset css option with new file paths\n if (prototype.css) {\n newPrototype.css = moveAdditionalAssets(prototype.css, 'css', huron);\n }\n\n // Move js assets for this prototype,\n // reset js option with new file paths\n if (prototype.js) {\n newPrototype.js = moveAdditionalAssets(prototype.js, 'js', huron);\n }\n\n opts = Object.assign({}, defaultHTMLPluginOptions, newPrototype);\n }\n\n // Move global css assets,\n // reset css option with new file paths\n if (huron.css.length) {\n opts.css = opts.css.concat(\n moveAdditionalAssets(huron.css, 'css', huron)\n );\n }\n\n // Move global js assets,\n // reset js option with new file paths\n if (huron.js.length) {\n opts.js = opts.js.concat(\n moveAdditionalAssets(huron.js, 'js', huron)\n );\n }\n\n // Push a new plugin for each configured prototype\n if (Object.keys(opts).length) {\n newConfig.plugins.push(\n new HTMLWebpackPlugin(opts)\n );\n }\n });\n\n return newConfig;\n}\n\n/**\n * Move relative (and local) js and css assets provided in huron options\n *\n * @param {array|string} assets - array of assets or single asset\n * @param {string} subdir - subdirectory in huron root from which to load additional asset\n * @param {object} huron - huron configuration object\n * @return {array} assetResults - paths to js and css assets\n */\nfunction moveAdditionalAssets(assets, subdir = '', huron) {\n const currentAssets = [].concat(assets);\n const assetResults = [];\n\n currentAssets.forEach((asset) => {\n const assetInfo = path.parse(asset);\n const assetURL = url.parse(asset);\n const sourcePath = path.join(cwd, asset);\n const outputPath = path.resolve(cwd, huron.root, subdir, assetInfo.base);\n const loadPath = program.production ?\n path.join(subdir, assetInfo.base) :\n path.join('/', subdir, assetInfo.base); // Use absolute path in development\n let contents = false;\n\n if (\n ! path.isAbsolute(asset) &&\n ! assetURL.protocol\n ) {\n try {\n contents = fs.readFileSync(sourcePath);\n } catch (e) {\n console.warn(`could not read ${sourcePath}`);\n }\n\n if (contents) {\n fs.outputFileSync(outputPath, contents);\n assetResults.push(loadPath);\n }\n } else {\n assetResults.push(asset);\n }\n });\n\n return assetResults;\n}\n\n\n\n// WEBPACK FOOTER //\n// src/cli/generate-config.js","/** @module cli/html-handler */\nimport * as utils from './utils';\n\nconst path = require('path');\nconst fs = require('fs-extra');\n\n/**\n * Handle update of an HMTL template\n *\n * @function updateHTML\n * @param {string} filepath - filepath of changed file (comes from gaze)\n * @param {object} section - contains KSS section data\n * @param {object} store - memory store\n * @return {object} updated data store\n */\nexport function updateHTML(filepath, section, store) {\n const file = path.parse(filepath);\n const content = fs.readFileSync(filepath, 'utf8');\n const newSection = section;\n\n if (content) {\n newSection.templatePath = utils.writeFile(\n section.referenceURI,\n 'template',\n filepath,\n content,\n store\n );\n newSection.templateContent = content;\n\n // Rewrite section data with template content\n newSection.sectionPath = utils.writeSectionData(store, newSection);\n\n return store\n .setIn(\n ['sections', 'sectionsByPath', section.kssPath],\n newSection\n )\n .setIn(\n ['sections', 'sectionsByURI', section.referenceURI],\n newSection\n );\n }\n\n console.log(`File ${file.base} could not be read`);\n return store;\n}\n\n/**\n * Handle removal of an HMTL template\n *\n * @function deleteHTML\n * @param {string} filepath - filepath of changed file (comes from gaze)\n * @param {object} section - contains KSS section data\n * @param {object} store - memory store\n * @return {object} updated data store\n */\nexport function deleteHTML(filepath, section, store) {\n const newSection = section;\n\n utils.removeFile(\n newSection.referenceURI,\n 'template',\n filepath,\n store\n );\n\n delete newSection.templatePath;\n\n return store\n .setIn(\n ['sections', 'sectionsByPath', section.kssPath],\n newSection\n )\n .setIn(\n ['sections', 'sectionsByURI', section.referenceURI],\n newSection\n );\n}\n\n/**\n * Handle update for a prototype file\n *\n * @function updatePrototype\n * @param {string} filepath - filepath of changed file (comes from gaze)\n * @param {object} store - memory store\n * @return {object} updated data store\n */\nexport function updatePrototype(filepath, store) {\n const file = path.parse(filepath);\n const content = fs.readFileSync(filepath, 'utf8');\n\n if (content) {\n const requirePath = utils.writeFile(\n file.name,\n 'prototype',\n filepath,\n content,\n store\n );\n\n return store.setIn(\n ['prototypes', file.name],\n requirePath\n );\n }\n\n console.log(`File ${file.base} could not be read`);\n return store;\n}\n\n/**\n * Handle removal of a prototype file\n *\n * @function deletePrototype\n * @param {string} filepath - filepath of changed file (comes from gaze)\n * @param {object} store - memory store\n * @return {object} updated data store\n */\nexport function deletePrototype(filepath, store) {\n const file = path.parse(filepath);\n const requirePath = utils.removeFile(\n file.name,\n 'prototype',\n filepath,\n store\n );\n\n return store.setIn(\n ['prototypes', file.name],\n requirePath\n );\n}\n\n\n\n// WEBPACK FOOTER //\n// src/cli/handle-html.js","/** @module cli/kss-handler */\n\nimport * as utils from './utils';\nimport { updateTemplate, deleteTemplate } from './handle-templates';\nimport { writeStore } from './require-templates';\n\nconst path = require('path');\nconst fs = require('fs-extra');\nconst parse = require('kss').parse;\nconst chalk = require('chalk'); // Colorize terminal output\n\n/**\n * Handle update of a KSS section\n *\n * @function updateKSS\n * @param {string} filepath - filepath of changed file (comes from gaze)\n * @param {object} store - memory store\n * @return {object} updated data store\n */\nexport function updateKSS(filepath, store) {\n const kssSource = fs.readFileSync(filepath, 'utf8');\n const huron = store.get('config');\n const oldSection = utils.getSection(filepath, false, store) || {};\n const file = path.parse(filepath);\n let newStore = store;\n\n if (kssSource) {\n const styleguide = parse(kssSource, huron.get('kssOptions'));\n\n if (styleguide.data.sections.length) {\n const section = utils.normalizeSectionData(\n styleguide.data.sections[0]\n );\n\n if (section.reference && section.referenceURI) {\n // Update or add section data\n newStore = updateSectionData(\n filepath,\n section,\n oldSection,\n newStore\n );\n\n // Remove old section data if reference URI has changed\n if (oldSection &&\n oldSection.referenceURI &&\n oldSection.referenceURI !== section.referenceURI\n ) {\n newStore = unsetSection(oldSection, file, newStore, false);\n }\n\n writeStore(newStore);\n console.log(\n chalk.green(\n `KSS source in ${filepath} changed or added`\n )\n );\n return newStore;\n }\n\n console.log(\n chalk.magenta(\n `KSS section in ${filepath} is missing a section reference`\n )\n );\n return newStore;\n }\n\n console.log(chalk.magenta(`No KSS found in ${filepath}`));\n return newStore;\n }\n\n if (oldSection) {\n newStore = deleteKSS(filepath, oldSection, newStore);\n }\n\n console.log(chalk.red(`${filepath} not found or empty`)); // eslint-disable-line no-console\n return newStore;\n}\n\n/**\n * Handle removal of a KSS section\n *\n * @function deleteKSS\n * @param {string} filepath - filepath of changed file (comes from gaze)\n * @param {object} section - KSS section data\n * @param {object} store - memory store\n * @return {object} updated data store\n */\nexport function deleteKSS(filepath, section, store) {\n const file = path.parse(filepath);\n\n if (section.reference && section.referenceURI) {\n // Remove section data from memory store\n return unsetSection(section, file, store, true);\n }\n\n return store;\n}\n\n/**\n * Update the sections store with new data for a specific section\n *\n * @function updateSectionData\n * @param {object} section - contains updated section data\n * @param {string} kssPath - path to KSS section\n * @param {object} store - memory store\n * @return {object} updated data store\n */\nfunction updateSectionData(kssPath, section, oldSection, store) {\n const sectionFileInfo = path.parse(kssPath);\n const dataFilepath = path.join(\n sectionFileInfo.dir,\n `${sectionFileInfo.name}.json`\n );\n const isInline = null !== section.markup.match(/<\\/[^>]*>/);\n const newSort = sortSection(\n store.getIn(['sections', 'sorted']),\n section.reference,\n store.get('referenceDelimiter')\n );\n const newSection = Object.assign({}, oldSection, section);\n let newStore = store;\n\n // Required for reference from templates and data\n newSection.kssPath = kssPath;\n\n if (isInline) {\n // Set section value if inlineTempalte() returned a path\n newStore = updateInlineTemplate(\n kssPath,\n oldSection,\n newSection,\n newStore\n );\n } else {\n // Remove inline template, if it exists\n utils.removeFile(\n newSection.referenceURI,\n 'template',\n kssPath,\n store\n );\n // Update markup and data fields\n newStore = updateTemplateFields(\n sectionFileInfo,\n oldSection,\n newSection,\n newStore\n );\n }\n\n // Output section description\n newStore = updateDescription(\n kssPath,\n oldSection,\n newSection,\n newStore\n );\n\n // Output section data to a JSON file\n newSection.sectionPath = utils.writeSectionData(\n newStore,\n newSection,\n dataFilepath\n );\n\n // Update section sorting\n return newStore\n .setIn(\n ['sections', 'sorted'],\n newSort\n )\n .setIn(\n ['sections', 'sectionsByPath', kssPath],\n newSection\n )\n .setIn(\n ['sections', 'sectionsByURI', section.referenceURI],\n newSection\n );\n}\n\n/**\n * Handle detection and output of inline templates, which is markup written\n * in the KSS documentation itself as opposed to an external file\n *\n * @function updateInlineTemplate\n * @param {string} oldSection - previous iteration of KSS data, if updated\n * @param {object} section - KSS section data\n * @return {object} updated data store with new template path info\n */\nfunction updateInlineTemplate(filepath, oldSection, section, store) {\n const newSection = section;\n const newStore = store;\n\n // If we have inline markup\n if (fieldShouldOutput(oldSection, section, 'markup')) {\n newSection.templatePath = utils.writeFile(\n section.referenceURI,\n 'template',\n filepath,\n section.markup,\n store\n );\n newSection.templateContent = section.markup;\n\n return newStore\n .setIn(\n ['sections', 'sectionsByPath', filepath],\n newSection\n )\n .setIn(\n ['sections', 'sectionsByURI', section.referenceURI],\n newSection\n );\n }\n\n return newStore;\n}\n\n/**\n * Handle output of section description\n *\n * @function updateDescription\n * @param {string} oldSection - previous iteration of KSS data, if updated\n * @param {object} section - KSS section data\n * @return {object} updated data store with new descripton path info\n */\nfunction updateDescription(filepath, oldSection, section, store) {\n const newSection = section;\n const newStore = store;\n\n // If we don't have previous KSS or the KSS has been updated\n if (fieldShouldOutput(oldSection, section, 'description')) {\n // Write new description\n newSection.descriptionPath = utils.writeFile(\n section.referenceURI,\n 'description',\n filepath,\n section.description,\n store\n );\n\n return newStore\n .setIn(\n ['sections', 'sectionsByPath', filepath],\n newSection\n )\n .setIn(\n ['sections', 'sectionsByURI', section.referenceURI],\n newSection\n );\n }\n\n return newStore;\n}\n\n/**\n * Handle Data and Markup fields\n *\n * @function updateTemplateFields\n * @param {string} file - File data for KSS file from path.parse()\n * @param {object} oldSection - outdated KSS data\n * @param {object} section - KSS section data\n * @param {object} store - memory store\n * @return {object} KSS section data with updated asset paths\n */\nfunction updateTemplateFields(file, oldSection, section, store) {\n const kssPath = path.format(file);\n const newSection = section;\n let filepath = '';\n let oldFilepath = '';\n let newStore = store;\n\n ['data', 'markup'].forEach((field) => {\n if (newSection[field]) {\n if (oldSection[field]) {\n oldFilepath = path.join(file.dir, oldSection[field]);\n newStore = deleteTemplate(\n oldFilepath,\n oldSection,\n newStore\n );\n }\n\n filepath = path.join(file.dir, newSection[field]);\n newStore = updateTemplate(\n filepath,\n newSection,\n newStore\n );\n } else {\n delete newSection[field];\n newStore = newStore\n .setIn(\n ['sections', 'sectionsByPath', kssPath],\n newSection\n )\n .setIn(\n ['sections', 'sectionsByURI', newSection.referenceURI],\n newSection\n );\n }\n });\n\n return newStore;\n}\n\n/**\n * Remove a section from the memory store\n *\n * @function unsetSection\n * @param {object} section - contains updated section data\n * @param {string} file - file object from path.parse()\n * @param {object} store - memory store\n * @param {bool} removed - has the file been removed or just the section information changed?\n * @return {object} updated data store with new descripton path info\n */\nfunction unsetSection(section, file, store, removed) {\n const sorted = store.getIn(['sections', 'sorted']);\n const kssPath = path.format(file);\n const dataFilepath = path.join(file.dir, `${file.name}.json`);\n const isInline = section.markup &&\n null !== section.markup.match(/<\\/[^>]*>/);\n const newSort = unsortSection(\n sorted,\n section.reference,\n store.get('referenceDelimiter')\n );\n let newStore = store;\n\n // Remove old section data\n utils.removeFile(\n section.referenceURI,\n 'section',\n dataFilepath,\n newStore\n );\n\n // Remove associated inline template\n if (isInline) {\n utils.removeFile(section.referenceURI, 'template', kssPath, newStore);\n }\n\n // Remove description template\n utils.removeFile(section.referenceURI, 'description', kssPath, newStore);\n\n // Remove data from sectionsByPath if file has been removed\n if (removed) {\n newStore = newStore.deleteIn(['sections', 'sectionsByPath', kssPath]);\n }\n\n return newStore\n .deleteIn(['sections', 'sectionsByURI', section.referenceURI])\n .setIn(['sections', 'sorted'], newSort);\n}\n\n/**\n * Sort sections and subsections\n *\n * @function sortSection\n * @param {object} sorted - currently sorted sections\n * @param {string} reference - reference URI of section to sort\n * @return {object} updated data store with new descripton path info\n */\nfunction sortSection(sorted, reference, delimiter) {\n const parts = reference.split(delimiter);\n const newSort = sorted[parts[0]] || {};\n const newSorted = sorted;\n\n if (1 < parts.length) {\n const newParts = parts.filter((part, idx) => 0 !== idx);\n newSorted[parts[0]] = sortSection(\n newSort,\n newParts.join(delimiter),\n delimiter\n );\n } else {\n newSorted[parts[0]] = newSort;\n }\n\n return newSorted;\n}\n\n/**\n * Remove a section from the sorted sections\n *\n * @function unsortSection\n * @param {object} sorted - currently sorted sections\n * @param {string} reference - reference URI of section to sort\n * @return {object} updated data store with new descripton path info\n */\nfunction unsortSection(sorted, reference, delimiter) {\n const parts = reference.split(delimiter);\n const subsections = Object.keys(sorted[parts[0]]);\n const newSorted = sorted;\n\n if (subsections.length) {\n if (1 < parts.length) {\n const newParts = parts.filter((part, idx) => 0 !== idx);\n newSorted[parts[0]] = unsortSection(\n newSorted[parts[0]],\n newParts.join(delimiter),\n delimiter\n );\n }\n } else {\n delete newSorted[parts[0]];\n }\n\n return newSorted;\n}\n\n/**\n * Compare a KSS field between old and new KSS data to see if we need to output\n * a new module for that field\n *\n * @function fieldShouldOutput\n * @param {object} oldSection - currently sorted sections\n * @param {object} newSection - reference URI of section to sort\n * @param {string} field - KSS field to check\n * @return {bool} output a new module for the KSS field\n */\nfunction fieldShouldOutput(oldSection, newSection, field) {\n return (oldSection &&\n (oldSection[field] !== newSection[field] ||\n oldSection.referenceURI !== newSection.referenceURI)\n ) ||\n ! oldSection;\n}\n\n\n\n// WEBPACK FOOTER //\n// src/cli/handle-kss.js","import { Map } from 'immutable';\nimport generateConfig from './generate-config';\n// Create initial data structure\n\n// Merge Huron default webpack config with user config\nconst config = generateConfig();\n\n// Make sure the kss option is represented as an array\nconfig.huron.kss = Array.isArray(config.huron.kss) ?\n config.huron.kss :\n [config.huron.kss];\n\n/* eslint-disable */\n/**\n * Initial structure for immutable data store\n *\n * @global\n */\nconst dataStructure = Map({\n types: [\n 'template',\n 'data',\n 'description',\n 'section',\n 'prototype',\n 'sections-template',\n ],\n config: Map(config.huron),\n sections: Map({\n sectionsByPath: Map({}),\n sectionsByURI: Map({}),\n sorted: {},\n }),\n templates: Map({}),\n prototypes: Map({}),\n sectionTemplatePath: '',\n referenceDelimiter: '.',\n});\n/* eslint-enable */\n\nexport { dataStructure, config };\n\n\n\n// WEBPACK FOOTER //\n// src/cli/huron-store.js","// Necessary to remove require statement from Webpack processing preserve it in output\n/* eslint-disable import/no-dynamic-require, global-require */\nexport default function requireExternal(requirePath) {\n return require(requirePath);\n}\n/* eslint-enable */\n\n\n\n// WEBPACK FOOTER //\n// src/cli/require-external.js","/** @module cli/webpack-server */\n\nimport program from './parse-args';\n\nconst webpack = require('webpack');\nconst WebpackDevServer = require('webpack-dev-server');\nconst chalk = require('chalk'); // Colorize terminal output\n\n/**\n * Spin up webpack-dev-server or, if production flag is set, run webpack a single time\n *\n * @function startWebpack\n * @param {object} config - webpack configuration, preprocessed by {@link module:cli/generate-config generateConfig}\n * @see {@link module:cli/generate-config generateConfig}\n */\nexport default function startWebpack(config) {\n const huron = config.huron;\n const webpackConfig = config.webpack;\n const compiler = webpack(webpackConfig);\n\n if (program.progress) {\n compiler.apply(\n new webpack.ProgressPlugin(\n (percentage, msg) => {\n console.log(`${(percentage * 100)}% `, msg);\n }\n )\n );\n }\n\n if (program.production) {\n compiler.run((err, stats) => {\n const info = stats.toJson();\n\n if (err) {\n console.log(err);\n }\n\n if (stats.hasErrors()) {\n console.error(\n chalk.red(\n 'Webpack encountered errors during compile: ',\n info.errors\n )\n );\n }\n\n if (stats.hasWarnings()) {\n console.error(\n chalk.yellow(\n 'Webpack encountered warnings during compile: ', info.warnings\n )\n );\n }\n });\n } else {\n const server = new WebpackDevServer(compiler, {\n hot: true,\n quiet: false,\n noInfo: false,\n stats: {\n colors: true,\n hash: false,\n version: false,\n assets: false,\n chunks: false,\n modules: false,\n reasons: false,\n children: false,\n source: false,\n },\n contentBase: huron.root,\n publicPath: `http://localhost:${huron.port}/${huron.root}`,\n });\n server.listen(\n huron.port,\n 'localhost',\n (err) => {\n if (err) {\n return console.log(err);\n }\n\n console.log(`Listening at http://localhost:${huron.port}/`);\n return true;\n }\n );\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// src/cli/server.js","const path = require('path');\n\nmodule.exports = {\n css: [],\n entry: 'huron',\n js: [],\n kss: 'css/',\n kssExtension: '.css',\n kssOptions: {\n multiline: true,\n markdown: true,\n custom: ['data'],\n },\n output: 'partials',\n port: 8080,\n prototypes: ['index'],\n root: 'dist/',\n sectionTemplate: path.join(__dirname, '../../templates/section.hbs'),\n templates: {\n rule: {\n test: /\\.(hbs|handlebars)$/,\n use: 'handlebars-template-loader',\n },\n extension: '.hbs',\n },\n window: {},\n};\n\n\n\n// WEBPACK FOOTER //\n// src/default-config/huron.config.js","const webpack = require('webpack');\nconst path = require('path');\n\nmodule.exports = {\n entry: {},\n output: {\n // path: [huron root directory],\n filename: '[name].js',\n chunkFilename: '[name].chunk.min.js',\n },\n plugins: [\n new webpack.HotModuleReplacementPlugin(),\n new webpack.NamedModulesPlugin(),\n ],\n resolve: {\n modulesDirectories: [\n path.resolve(__dirname, '../src/js'),\n ],\n },\n resolveLoader: {\n modulesDirectories: [\n 'web_loaders',\n 'web_modules',\n 'node_loaders',\n 'node_modules',\n path.resolve(__dirname, '../node_modules'),\n ],\n },\n module: {\n rules: [\n {\n test: /\\.html?$/,\n use: [\n {\n loader: 'dom-loader',\n options: {\n tag: 'dom-module',\n },\n },\n 'html-loader',\n ],\n // include: ['path/to/templates']\n },\n ],\n },\n};\n\n\n\n// WEBPACK FOOTER //\n// src/default-config/webpack.config.js","module.exports = require(\"commander\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"commander\"\n// module id = 18\n// module chunks = 0","module.exports = require(\"gaze\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"gaze\"\n// module id = 19\n// module chunks = 0","module.exports = require(\"html-webpack-plugin\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"html-webpack-plugin\"\n// module id = 20\n// module chunks = 0","module.exports = require(\"immutable\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"immutable\"\n// module id = 21\n// module chunks = 0","module.exports = require(\"kss\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"kss\"\n// module id = 22\n// module chunks = 0","module.exports = require(\"url\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"url\"\n// module id = 23\n// module chunks = 0","module.exports = require(\"webpack-dev-server\");\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"webpack-dev-server\"\n// module id = 24\n// module chunks = 0"],"mappings":";AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;A;;;;AChEA;;;;;;ACAA;;;;;;ACAA;;;;;;;;;;;;ACcA;AAkBA;AAqCA;AAqCA;AAcA;AAkBA;AAyBA;AA4CA;AAyCA;AA0BA;AAyBA;AA3SA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;AAQA;AACA;AACA;AACA;AACA;AACA;AACA;AAIA;AACA;AACA;AACA;AACA;AAOA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;;;;;;;;AAQA;AACA;AACA;AACA;AACA;AACA;AAIA;AACA;AACA;AAGA;AACA;AASA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;AAOA;AACA;AAGA;AACA;AACA;;;;;;;;AAQA;AACA;AACA;AACA;;AAFA;AAKA;AACA;AACA;;;;;;;;;;AAUA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;AAUA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAIA;AAKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;AAQA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAIA;AAKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;AAQA;AACA;AACA;AACA;AACA;AACA;AAMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;AAQA;AACA;AAGA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;AAQA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;;;;;;;;;;;;AC5TA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;AAMA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAYA;AACA;AACA;AACA;AAIA;AACA;AACA;AACA;AACA;AACA;;;;;;ACzDA;;;;;;;;;;;;ACgBA;AA0DA;AACA;AA1EA;AACA;AADA;AACA;;;AACA;AACA;AAAA;AACA;AACA;AACA;;;;;;;;;AASA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAaA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;AASA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAMA;AACA;AACA;AAUA;;;;;;;;;;;;ACnGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAIA;;;;;;;;;AASA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;;AAEA;;;;;;;;;;;;AAYA;;AAEA;;;;;;;;;;;;;;;;;;;;;;;;;AAhBA;AACA;AA0CA;;;;;;;;;;;;;AAAA;AACA;AAcA;AACA;AACA;AAGA;AAHA;AAMA;AACA;AACA;;;;;;;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AAHA;AAMA;;;;;;;;;ACnHA;AACA;AAAA;AACA;AAAA;AACA;;;AAAA;AACA;;;AAAA;AACA;;;AACA;AACA;AACA;AAAA;AACA;AACA;AACA;;;;;AAKA;AACA;AACA;;;;;AAKA;AACA;AAMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;;;;;AAKA;AACA;AACA;;;;;AAKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;AAOA;AACA;AACA;AACA;AACA;AACA;;;;;;;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;ACxGA;AA2CA;AA+DA;AACA;AAnIA;AACA;AAKA;AACA;AAAA;AACA;AAAA;AACA;AADA;AACA;;;AACA;AAbA;AACA;AACA;AAYA;AACA;AACA;AACA;AACA;AACA;;;;;;;;AAQA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAIA;AACA;AACA;AACA;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAxBA;AACA;AA0BA;AACA;AACA;AACA;;;;;;;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAxCA;AACA;AA0CA;AACA;AACA;AACA;;;;;;;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AArCA;AACA;AAuCA;AACA;;;;;;;;;;;;ACtJA;AACA;AA9BA;AACA;;;AAAA;AACA;;;;;AAJA;AACA;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AAGA;AACA;AACA;AACA;;;;;;;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAFA;AAIA;AACA;AACA;;;;;;;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AAKA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;;;;;;;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAIA;AACA;AAKA;AACA;AACA;AACA;AACA;AACA;;;;;;;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AAEA;AACA;AACA;AAHA;AACA;AAOA;AACA;AACA;AACA;;;;;;;AAOA;AACA;AACA;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AAKA;AACA;AAZA;AAcA;AACA;AACA;AACA;AACA;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAFA;AAIA;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;AAQA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;AC7RA;AA0CA;AA+BA;AA+BA;AACA;AAvHA;AACA;AADA;AACA;;;AACA;AACA;AAAA;AACA;AACA;;;;;;;;;AASA;AACA;AACA;AACA;AACA;AACA;AACA;AAOA;AACA;AACA;AACA;AACA;AACA;AASA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;AASA;AACA;AACA;AACA;AACA;AAMA;AACA;AACA;AASA;AACA;AACA;;;;;;;;AAQA;AACA;AACA;AACA;AACA;AACA;AACA;AAOA;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;AAQA;AACA;AACA;AACA;AAMA;AAIA;;;;;;;;;;;;ACjHA;AAsEA;AACA;AAxFA;AACA;AADA;AACA;AAAA;AACA;AAAA;AACA;;;AACA;AACA;AAAA;AACA;AACA;AACA;AACA;;;;;;;;AAQA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;AACA;AAMA;AACA;AAIA;AACA;AACA;AACA;AACA;AAKA;AACA;AACA;AACA;AAKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;AASA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;AASA;AACA;AACA;AAIA;AACA;AAKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAMA;AACA;AACA;AAMA;AACA;AAMA;AACA;AACA;AACA;AACA;AAMA;AACA;AACA;AAKA;AACA;AAaA;AACA;AACA;;;;;;;;;AASA;AACA;AACA;AACA;AACA;AACA;AACA;AAOA;AACA;AACA;AASA;AACA;AACA;AACA;AACA;AACA;;;;;;;;AAQA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAOA;AASA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;AAUA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAKA;AACA;AACA;AACA;AAKA;AACA;AACA;AASA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;AAUA;AACA;AACA;AACA;AACA;AAEA;AAKA;AACA;AACA;AACA;AACA;AAMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AACA;;;;;;;;AAQA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;AAQA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;AAUA;AACA;AAKA;;;;;;;;;;;;;;AC9aA;AACA;AAAA;AACA;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;;;;;AAKA;AACA;AAQA;AACA;AACA;AACA;AACA;AAHA;AAKA;AACA;AACA;AACA;AAlBA;AAoBA;AACA;AACA;AAAA;;;;;;;;;;;ACtCA;AAFA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;ACUA;AACA;AAdA;AACA;;;;;AACA;AACA;AAAA;AACA;AACA;AACA;;;;;;;AAOA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAMA;AACA;AACA;AACA;AAKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AATA;AAWA;AACA;AAhBA;AAkBA;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;;;;;;;;;ACvFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAHA;AAKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAFA;AAIA;AALA;AAOA;AAvBA;;;;;;;;;ACFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAHA;AAKA;AAIA;AACA;AADA;AAKA;AACA;AADA;AASA;AACA;AAEA;AACA;AAEA;AACA;AACA;AADA;AAFA;AAQA;AAXA;AAFA;AAzBA;;;;;;ACHA;;;;;;ACAA;;;;;;ACAA;;;;;;ACAA;;;;;;ACAA;;;;;;ACAA;;;;;;ACAA;;;;;;;;;;A","sourceRoot":""} \ No newline at end of file diff --git a/dist/huron-assets/prototype-template.ejs b/dist/huron-assets/prototype-template.ejs new file mode 100644 index 0000000..218dc1f --- /dev/null +++ b/dist/huron-assets/prototype-template.ejs @@ -0,0 +1,50 @@ + + manifest="<%= htmlWebpackPlugin.files.manifest %>"<% } %>> + + + <%= htmlWebpackPlugin.options.title || 'Huron' %> prototype + <% if (htmlWebpackPlugin.files.favicon) { %> + + <% } %> + <% for (var script in htmlWebpackPlugin.options.js) { %> + + <% } %> + <% for (var stylesheet in htmlWebpackPlugin.options.css) { %> + + <% } %> + + <% for (var css in htmlWebpackPlugin.files.css) { %> + + <% } %> + <% if (htmlWebpackPlugin.options.window) { %> + + <% } %> + + +<% if (htmlWebpackPlugin.options.unsupportedBrowser) { %> + +
+ Sorry, your browser is not supported. Please upgrade to + the latest version or switch your browser to use this site. + See outdatedbrowser.com + for options. +
+<% } %> +<% if (htmlWebpackPlugin.options.appMountId) { %> +
+<% } %> +<% if (htmlWebpackPlugin.options.appMountIds && htmlWebpackPlugin.options.appMountIds.length > 0) { %> + <% for (var index in htmlWebpackPlugin.options.appMountIds) { %> +
+ <% } %> +<% } %> +
+<% for (var chunk in htmlWebpackPlugin.files.chunks) { %> + +<% } %> + + \ No newline at end of file diff --git a/dist/web/huron.js b/dist/web/huron.js index 5ce0ab7..cb7304f 100644 --- a/dist/web/huron.js +++ b/dist/web/huron.js @@ -1,14 +1,6 @@ 'use strict'; -var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -var md5 = require('js-md5'); +const md5 = require('js-md5'); /* eslint-disable no-underscore-dangle */ // Accept the huron.js module for Huron development @@ -21,11 +13,9 @@ if (module.hot) { * into an element with attribute [huron-id] corresponding to the reference URI of the target KSS section, * and [huron-type] corresponding with the required KSS field */ +class InsertNodes { -var InsertNodes = function () { - function InsertNodes(modules, store) { - _classCallCheck(this, InsertNodes); - + constructor(modules, store) { /** webpack module list in which keys are relative require paths and values are the module contents */ this._modules = modules; /** array of module keys */ @@ -59,750 +49,648 @@ var InsertNodes = function () { * @param {object} meta - module metadata * @return {string} rendered - the modified HTML module */ + static applyModifier(modifier, meta) { + let rendered = false; + let data = meta.data; + + if (data) { + // If we have a modifier, use it, otherwise use the entire data set + if (modifier && meta.data[modifier]) { + data = Object.assign({}, meta.data[modifier], { modifier }); + } + rendered = meta.render(data); + } else { + rendered = meta.render(); + } - _createClass(InsertNodes, [{ - key: 'cycleModules', + return rendered; + } + /** + * Get markup from any type of module (html, json or template) + * + * @param {string} content - String corresponding to markup + * @return {object} el.firstElementChild - HTML module + */ + static convertToElement(content) { + const el = document.createElement('div'); - /** - * Replace all template markers with the actual template markup. - * - * @param {string} context - The hash context for the module - * @param {object} filter - Filter for modules. Fields explained in the filterModules() function docs - */ - value: function cycleModules() { - var _this = this; + el.innerHTML = content; + return el.firstElementChild; + } - var context = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; - var filter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + /** + * Filter module object by module key or module type + * + * @param {object} filter - Filter for modules. Options: + * @param {string} filter.property - Which property to filter ('key' or 'type') + * @param {array} filter.values - Values for property + * @param {bool} filter.include - Whether the values should be included or excluded (true = include, false = exclude) + * @param {object} moduleMeta - Filter for modules. Fields explained in the filterModules() function docs + * @return {bool} match - determine if modules need to be filtered + */ + static filterModules(filter, moduleMeta) { + let match = true; - var moduleList = {}; - var elementList = context; + // Check if we should filter out any modules + if ('object' === typeof filter && {}.hasOwnProperty.call(filter, 'property') && {}.hasOwnProperty.call(filter, 'values') && {}.hasOwnProperty.call(filter, 'include')) { + match = filter.values.filter(value => moduleMeta[filter.property] === value); + return Boolean(match.length) === filter.include; + } - // We're replacing top-level elements - if (!elementList) { - this.regenCache(); + console.log(` // eslint-disable-line no-console + filter ${filter} is not in a valid format. + module filters must include 'property', 'values', and 'include' properties + `); - // Find all top-level huron placeholders - elementList = [].concat(_toConsumableArray(document.querySelectorAll('[data-huron-id][data-huron-type]'))); - } + return match; + } - moduleList = this.getModuleListFromTags(elementList); + /** + * Generate a hash string from a module key + * + * @param {string} key - module key (require path) to convert into a hash + * @return {string} key - generated MD5 Hash + */ + static generateModuleHash(key) { + return md5(key); + } - // Loop through modules array - Object.keys(moduleList).forEach(function (key) { - var module = _this._modules[key]; - var replaceElements = moduleList[key]; + /** + * Retrieve a data attribute from a tag using one of two methods + * + * @param {HTMLElement} tag - DOM node on which to check for a data attribute + * @param {string} attr - attribute to check for + * @returns {string} data - contents of data attribute + */ + static getDataAttribute(tag, attr) { + let data = false; - _this.loadModule(key, module, replaceElements, true, filter); - }); + // Check if element has dataset and, if so, use it + if (tag.dataset) { + data = tag.dataset[attr]; } - /** - * Helper for reloading sections only - */ - - }, { - key: 'cycleSections', - value: function cycleSections() { - this.cycleModules(false, { - property: 'type', - values: ['section'], - include: true - }); + // Fallback to getAttribute for ugly old Safari + if (!data && tag.getAttribute) { + data = tag.getAttribute(`data-${attr}`); } - /** - * Reload styleguide sections and menu helpers - */ - - }, { - key: 'cycleStyleguide', - value: function cycleStyleguide() { - var sectionsQuery = document.querySelector('[huron-sections]'); - var menuQuery = document.querySelector('[huron-menu]'); - - // Sections - if (sectionsQuery) { - sectionsQuery.innerHTML = ''; - this.outputSections(null, sectionsQuery); - this.cycleSections(); - } - - // Menu - if (menuQuery) { - menuQuery.innerHTML = ''; - - if (null === document.querySelector('.section-menu__expand')) { - var menuTrigger = document.createElement('button'); - - menuTrigger.classList.add('section-menu__expand'); - menuTrigger.innerHTML = 'Sections Menu'; - document.body.insertBefore(menuQuery.appendChild(menuTrigger), document.body.childNodes[0]); - - // Add menu trigger handler - menuTrigger.addEventListener('click', function () { - document.body.classList.toggle('section-menu-open'); - }); - } + return data; + } - // Create menu - this.outputMenu(null, menuQuery); - } + /** + * Check if this tag is a styleguide helper + * + * @param {object} tag - tag to check + * @param {object} meta - module metadata + * @return {bool} + */ + static isSectionHelper(tag, meta) { + if ('prototype' === meta.type) { + return tag.hasAttribute('huron-sections') || tag.hasAttribute('huron-menu'); } - /** - * Get module metadata from a module require path - * - * @param {string} key - Module require path - * @return {object} containing module id, module type, key and the module contents - */ - - }, { - key: 'getMetaFromPath', - value: function getMetaFromPath(key, module) { - var _this2 = this; - - var sections = this._sections.sectionsByPath; - var templateTypes = this._types.filter(function (type) { - return 'prototype' !== type; - }); - var id = false; - var type = false; - - /* eslint-disable space-unary-ops */ - if (-1 !== key.indexOf('./prototypes')) { - /* eslint-enable space-unary-ops */ - var prototype = Object.keys(this._prototypes).filter(function (name) { - return _this2._prototypes[name] === key; - }); - - if (prototype.length) { - id = prototype[0]; - type = 'prototype'; - } - } else if (key === this._sectionTemplatePath) { - id = 'sections-template'; - type = 'sections-template'; - } else { - var testTypes = []; - var testSections = Object.keys(sections).filter(function (section) { - var tempTypes = templateTypes.filter(function (currentType) { - return sections[section][currentType + 'Path'] === key; - }); - - if (tempTypes.length) { - testTypes = tempTypes; - return true; - } - - return false; - }); - - if (testSections && testSections.length && testTypes && testTypes.length) { - id = sections[testSections[0]].referenceURI; - type = testTypes[0]; - } - } + return false; + } - if (id && type) { - var hashKey = 'data' === type ? this._templates[key] : key; - var renderData = this.getModuleRender(type, key, module); - var hash = InsertNodes.generateModuleHash(hashKey); + /** + * Replace all template markers with the actual template markup. + * + * @param {string} context - The hash context for the module + * @param {object} filter - Filter for modules. Fields explained in the filterModules() function docs + */ + cycleModules(context = false, filter = false) { + let moduleList = {}; + let elementList = context; - if (renderData) { - return Object.assign({ id: id, type: type, key: key, hash: hash, module: module }, renderData); - } - } + // We're replacing top-level elements + if (!elementList) { + this.regenCache(); - console.warn( // eslint-disable-line no-console - 'Module \'' + key + '\' does not exist on the page\n or is no longer in use'); - return false; + // Find all top-level huron placeholders + elementList = [...document.querySelectorAll('[data-huron-id][data-huron-type]')]; } - /** - * Check if a tag is a huron placeholder and, if so, - * return its associated module key - * - * @param {object} tag - tag to check - * @return {bool} associated module key - */ - - }, { - key: 'getModuleKeyFromTag', - value: function getModuleKeyFromTag(tag) { - // Safari/webkit has some trouble parsing dataset in certain cases. - // This is a fallback method of accessing the same data. - var type = InsertNodes.getDataAttribute(tag, 'huron-type'); - var id = InsertNodes.getDataAttribute(tag, 'huron-id'); - var section = this._sections.sectionsByURI[id]; - - if (id && type) { - if (section) { - return section[type + 'Path']; - } else if ('prototype' === type) { - return this._prototypes[id]; - } - } + moduleList = this.getModuleListFromTags(elementList); - return false; - } + // Loop through modules array + Object.keys(moduleList).forEach(key => { + const module = this._modules[key]; + const replaceElements = moduleList[key]; - /** - * Check if an array of elements contains a Huron placeholder - * - * @param {array} tags - array of DOM nodes - * @param {bool} recurse - should we recurse this function with a new array - * @return {object} moduleList - Huron placeholder DOM node - */ + this.loadModule(key, module, replaceElements, true, filter); + }); + } - }, { - key: 'getModuleListFromTags', - value: function getModuleListFromTags(elements) { - var _this3 = this; + /** + * Helper for reloading sections only + */ + cycleSections() { + this.cycleModules(false, { + property: 'type', + values: ['section'], + include: true + }); + } - var recurse = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; + /** + * Reload styleguide sections and menu helpers + */ + cycleStyleguide() { + const sectionsQuery = document.querySelector('[huron-sections]'); + const menuQuery = document.querySelector('[huron-menu]'); + + // Sections + if (sectionsQuery) { + sectionsQuery.innerHTML = ''; + this.outputSections(null, sectionsQuery); + this.cycleSections(); + } - var moduleList = {}; - var newList = {}; + // Menu + if (menuQuery) { + menuQuery.innerHTML = ''; - if (elements && elements.length) { - elements.forEach(function (element) { - var moduleKey = _this3.getModuleKeyFromTag(element); + if (null === document.querySelector('.section-menu__expand')) { + const menuTrigger = document.createElement('button'); - if (moduleKey) { - if (!moduleList[moduleKey]) { - moduleList[moduleKey] = []; - } - moduleList[moduleKey].push(element); - } else if (recurse) { - newList = _this3.getModuleListFromTags([].concat(_toConsumableArray(element.querySelectorAll('[data-huron-id][data-huron-type]'))), false); + menuTrigger.classList.add('section-menu__expand'); + menuTrigger.innerHTML = 'Sections Menu'; + document.body.insertBefore(menuQuery.appendChild(menuTrigger), document.body.childNodes[0]); - Object.keys(newList).forEach(function (key) { - moduleList[key] = moduleList[key] ? moduleList[key].concat(newList[key]) : newList[key]; - }); - } + // Add menu trigger handler + menuTrigger.addEventListener('click', () => { + document.body.classList.toggle('section-menu-open'); }); } - return moduleList; + // Create menu + this.outputMenu(null, menuQuery); } + } - /** - * Transform every module into a predictable object - * - * @param {object} type - Module metadata - * @param {mixed} module - Module contents - * @return {object} containing render function, render data and module id - */ - - }, { - key: 'getModuleRender', - value: function getModuleRender(type, key, module) { - var render = false; - var data = false; - - if ('template' === type && 'function' === typeof module) { - // It's a render function for a template - render = module; - data = this._modules[this._templates[key]]; - } else if ('sections-template' === type && 'function' === typeof module) { - // It's a kss section template - render = module; - } else if ('section' === type && 'object' === (typeof module === 'undefined' ? 'undefined' : _typeof(module))) { - // It's section data - render = this._modules[this._sectionTemplatePath]; - data = module; - } else if (('template' === type || 'description' === type || 'prototype' === type) && 'string' === typeof module) { - // it's straight HTML - render = function render() { - return module; - }; - } else if ('data' === type && 'object' === (typeof module === 'undefined' ? 'undefined' : _typeof(module))) { - // It's a data file (.json) - render = this._modules[this._templates[key]]; - data = module; - } - - // Only need render, as data will be left empty for static HTML - if (render) { - return { render: render, data: data }; + /** + * Get module metadata from a module require path + * + * @param {string} key - Module require path + * @return {object} containing module id, module type, key and the module contents + */ + getMetaFromPath(key, module) { + const sections = this._sections.sectionsByPath; + const templateTypes = this._types.filter(type => 'prototype' !== type); + let id = false; + let type = false; + + /* eslint-disable space-unary-ops */ + if (-1 !== key.indexOf('./prototypes')) { + /* eslint-enable space-unary-ops */ + const prototype = Object.keys(this._prototypes).filter(name => this._prototypes[name] === key); + + if (prototype.length) { + id = prototype[0]; + type = 'prototype'; } + } else if (key === this._sectionTemplatePath) { + id = 'sections-template'; + type = 'sections-template'; + } else { + let testTypes = []; + const testSections = Object.keys(sections).filter(section => { + const tempTypes = templateTypes.filter(currentType => sections[section][`${currentType}Path`] === key); + + if (tempTypes.length) { + testTypes = tempTypes; + return true; + } - return false; - } + return false; + }); - /** - * Replace all sections. For hot reloading use when the section template has changed. - * - * @param {object} replaceElements - The context (e.g. document) that you will query for the template ID to replace - * @param {string} key - Module require path - * @param {mixed} module - Module contents - * @param {bool} cached - Whether or not to use cached values for module replacement - * @param {object} filter - Filter for modules. Fields explained in the filterModules() function docs - */ - - }, { - key: 'loadModule', - value: function loadModule(key, module, replaceElements) { - var cached = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false; - var filter = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false; - - var shouldLoad = true; - var moduleMeta = false; - - // Check if we should load from internal module metadata cache - if (cached) { - moduleMeta = this.meta[key]; - } else { - moduleMeta = this.meta[key] = this.getMetaFromPath(key, module); + if (testSections && testSections.length && testTypes && testTypes.length) { + id = sections[testSections[0]].referenceURI; + type = testTypes[0]; } + } - if (moduleMeta) { - if (filter) { - shouldLoad = InsertNodes.filterModules(filter, moduleMeta); - } + if (id && type) { + const hashKey = 'data' === type ? this._templates[key] : key; + const renderData = this.getModuleRender(type, key, module); + const hash = InsertNodes.generateModuleHash(hashKey); - if (shouldLoad) { - this.replaceTemplate(moduleMeta, replaceElements); - } + if (renderData) { + return Object.assign({ id, type, key, hash, module }, renderData); } } - /* - * Helper function for inserting styleguide sections. - * - * Recurses over sorted styleguide sections and inserts a