UNPKG

@viewdo/dxp-story-cli

Version:
275 lines (214 loc) 8.22 kB
// NPM Module Dependencies const webpack = require('webpack'); const deepmerge = require('deepmerge'); const jsonConfig = require('./config/json'); const { argv } = require('yargs'); const fs = require('fs'); const ExtractTextPlugin = require('extract-text-webpack-plugin'); const { legacy = false, serve = false } = argv; const mkdirp = require('mkdirp'); const server = require('./server'); // Change when we move this over to the CLI const defaultEpisodeKey = process.env.DEFAULT_EPISODE_KEY || "default"; // Webpack Dependencies const defaultConfig = require('./config/default'); const es2015Config = require('./config/es2018'); const hasFile = (filePath) => { try { fs.accessSync(filePath, fs.constants.F_OK); return true; } catch (err) { return false; } } // Private Methods /** * If the source's css file is not a css type, this will use the extension * and add a rule to create the CSS using the transpiler. * @param {String} buildCSSFile - Style file that will create the * css * @param {Object} cssExtractor - Instance of the Webpack's Text Extractor * to pull the CSS File using this style compiler */ const _getStyleConfig = (source, episodeKey, cssExtractor) => { const hasLess = hasFile(`${source}/${episodeKey}.less`); if (hasLess) { return require(`./config/less`)(cssExtractor); } return {}; } /** * Creates a custom webpack config file to run webpack over based on what the settings * are found in the "source" object for this story. * * @param {Object} storyInfo - Information for this story to create the * webpack config file * @param {String} buildPath - Path to where the webpack files will be push to. */ const _createWebpackConfig = (sourcePath, buildPath, episodeKey, dev) => { let cssFileName = "story.css"; if (legacy) { cssFileName = "text-templates/compiled.css"; } const cssExtractor = new ExtractTextPlugin(cssFileName); const defaultWebpackConfig = defaultConfig(sourcePath, buildPath, episodeKey, cssExtractor, dev); const styleConfig = _getStyleConfig(sourcePath, episodeKey, cssExtractor); let modifiedConfig = deepmerge(defaultWebpackConfig, styleConfig); // PROPOSAL: Add to the console different JS packages maybe like vue, es2018, jsx, etc. modifiedConfig = deepmerge(modifiedConfig, es2015Config()); modifiedConfig.plugins = [...modifiedConfig.plugins, cssExtractor]; return modifiedConfig; } const _getWebpackConfigs = (story_keys, config, dev) => { const { stories, output: outputPath, source: sourcePath } = config let buildPath = outputPath; if (story_keys.length >= 1) { return story_keys.reduce((configs, storyKey) => { const { episodes = {} } = stories[storyKey]; const storyBuildPath = `${buildPath}/${storyKey}`; const storySourcePath = `${sourcePath}/${storyKey}`; mkdirp.sync(storyBuildPath); const defaultEpisodeConfigs = [ _createWebpackConfig(storySourcePath, storyBuildPath, defaultEpisodeKey, dev), jsonConfig(storySourcePath, storyBuildPath, defaultEpisodeKey, dev) ]; const episodeKeys = Object.keys(episodes); const episodeConfigs = episodeKeys.reduce((currentEpisodeConfigs, episodeKey) => { const episodeBuildPath = `${storyBuildPath}/episodes/${episodeKey}`; mkdirp.sync(episodeBuildPath); const episodeConfigs = [ _createWebpackConfig(storySourcePath, episodeBuildPath, episodeKey, dev), jsonConfig(storySourcePath, episodeBuildPath, episodeKey, dev) ]; return [ ...currentEpisodeConfigs, ...episodeConfigs ]; }, []); return [ ...configs, ...defaultEpisodeConfigs, ...episodeConfigs ]; }, []); } } const _postBuild = (story_keys, config) => { const { output: outputPath, stories, source: sourcePath } = config; story_keys.forEach((storyKey) => { const { episodes = {} } = stories[storyKey]; const srcDirectory = `${sourcePath}/${storyKey}`; const introStoryHtmlPath = `${srcDirectory}/story-intro.html`; const storyBuildPath = `${outputPath}/${storyKey}`; const cssFile = `${outputPath}/${storyKey}/story.css`; const evaluatorPath = `${storyBuildPath}/_json-evaluator.js`; // Clean up episode files. const episodeKeys = Object.keys(episodes); episodeKeys.forEach((episodeKey) => { const episodeBuildPath = `${storyBuildPath}/episodes/${episodeKey}`; const episodeEvaluatorPath = `${episodeBuildPath}/_json-evaluator.js`; const episodeStoryCss = `${episodeBuildPath}/story.css`; if (hasFile(episodeEvaluatorPath)) { fs.unlinkSync(episodeEvaluatorPath); } if (!hasFile(cssFile)) { fs.writeFileSync(episodeStoryCss, ''); } }); if (hasFile(introStoryHtmlPath)) { const introHtmlFile = fs.readFileSync(introStoryHtmlPath, 'utf-8'); fs.writeFileSync(`${storyBuildPath}/story-intro.html`, introHtmlFile); } if (!hasFile(cssFile)) { fs.writeFileSync(cssFile, ''); } if (hasFile(evaluatorPath)) { fs.unlinkSync(evaluatorPath); } }); } /** * Creates a config and then runs webpack on the various config files for * various stories. * @param {Object} config - Settings defined in the dxp-config */ module.exports = { build(story_keys, config) { process.noDeprecation = true; return new Promise((res, rej) => { const webpackConfigs = _getWebpackConfigs(story_keys, config); webpack(webpackConfigs).run((err, stats) => { _postBuild(story_keys, config); console.log(stats.toString({ colors: true })); if (stats.hasErrors()) { rej(err); return; } if (legacy) { _runLegacyCompiling(console, webpackConfigs).then(() => { res(); }); return; } res(); }); }); }, serve(config, dev) { let {stories} = config let story_keys = Object.keys(stories) const webpackConfigs = _getWebpackConfigs(story_keys, config, dev); currentServer = server(webpackConfigs, config); }, watch(config, dev) { let currentServer = {}; let init = true; let {stories} = config let story_keys = Object.keys(stories) const webpackConfigs = _getWebpackConfigs(story_keys, config, dev); if (serve) { currentServer = server(webpackConfigs, config); } webpack(webpackConfigs).watch({}, (err, stats) => { if (stats.hasErrors()) { console.log(stats.toString({ colors: true })); return; } _postBuild(story_keys, _console); if (currentServer.reload) { currentServer.reload(); } if (currentServer.openWindow && init) { currentServer.openWindow(); init = false; } if (legacy) { _runLegacyCompiling(console, webpackConfigs).then(() => { console.log(stats.toString({ colors: true })); }) .catch((err) => { console.log(err); }); return; } console.log(stats.toString({ colors: true })); }); }, postBuild: (story_keys, config) => { _postBuild(story_keys, config); } }