diff --git a/CHANGELOG.md b/CHANGELOG.md index 6887b5c79..d9cf4e7d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,5 @@ ## v5.2.1 + Bugfix: fix publish command on windows [#695](https://github.com/idyll-lang/idyll/pull/695) ## v5.2.0 @@ -8,30 +9,34 @@ Add experimental [project create API](https://github.com/idyll-lang/idyll/pull/6 ## v5.1.0 Features: + - Adds `insertFullWidth` option to markup serializer ([#686](https://github.com/idyll-lang/idyll/pull/686)) - Adds `inlineAuthorView` option to `idyll-document` ([#681](https://github.com/idyll-lang/idyll/pull/681)) Bugfixes: -- General improvements to markup serialization ([#685](https://github.com/idyll-lang/idyll/pull/685), [#684](https://github.com/idyll-lang/idyll/pull/684), [#676](https://github.com/idyll-lang/idyll/pull/676)) + +- General improvements to markup serialization ([#685](https://github.com/idyll-lang/idyll/pull/685), [#684](https://github.com/idyll-lang/idyll/pull/684), [#676](https://github.com/idyll-lang/idyll/pull/676)) ### v5.0.1 Bugfixes: -- Improves output of `AST.toMarkup(ast)` function so that extra whitespace is not inserted on repeated calls. +- Improves output of `AST.toMarkup(ast)` function so that extra whitespace is not inserted on repeated calls. # v5.0 Features: + - Adds `fullWidthSteps` option to the scroller, to make it easier for scroller components steps to take on wider designs Bugfixes: -- Component resolver is initialized at the start of compile process and when a compiler postprocessor plugin creates a new component in components directory, it won't be available till the next build and the current build fails with component not found error. (See: https://github.com/idyll-lang/idyll/pull/610) + +- Component resolver is initialized at the start of compile process and when a compiler postprocessor plugin creates a new component in components directory, it won't be available till the next build and the current build fails with component not found error. (See: https://github.com/idyll-lang/idyll/pull/610) Breaking changes: - Update header component default behavior to use styles (background color and text color) provided by themes -- Fix the `package.json` options logic so any idyll option can be provided via package.json and +- Fix the `package.json` options logic so any idyll option can be provided via package.json and ## v4.10 diff --git a/package.json b/package.json index ef6820085..abed77302 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ }, "devDependencies": { "husky": "^1.1.3", - "lerna": "^2.0.0", + "lerna": "^2.11.0", "prettier": "1.15.1", "pretty-quick": "^1.8.0" }, diff --git a/packages/idyll-cli/package.json b/packages/idyll-cli/package.json index 345bca899..4e8e9892c 100644 --- a/packages/idyll-cli/package.json +++ b/packages/idyll-cli/package.json @@ -40,6 +40,7 @@ "bs-pretty-message": "^1.0.8", "chalk": "^2.4.1", "change-case": "^3.0.1", + "command-line-args": "^5.1.1", "cross-spawn": "^6.0.5", "csv-parse": "^4.8.2", "debug": "^3.1.0", diff --git a/packages/idyll-cli/src/index.js b/packages/idyll-cli/src/index.js index a637fc8fc..40718631f 100755 --- a/packages/idyll-cli/src/index.js +++ b/packages/idyll-cli/src/index.js @@ -1,331 +1,396 @@ -const fs = require('fs'); -const { dirname, basename, extname, join } = require('path'); -const EventEmitter = require('events'); -const mkdirp = require('mkdirp'); - -const pathBuilder = require('./path-builder'); -const configureNode = require('./node-config'); -const pipeline = require('./pipeline'); -const { ComponentResolver, DataResolver, CSSResolver } = require('./resolvers'); - -const debug = require('debug')('idyll:cli'); - -function createDirectories(paths) { - mkdirp.sync(paths.OUTPUT_DIR); - mkdirp.sync(paths.STATIC_OUTPUT_DIR); - mkdirp.sync(paths.TMP_DIR); -} - -const searchParentDirectories = packageDir => { - while (true) { - if (packageDir === join(packageDir, '..')) { - break; - } - - packageDir = join(packageDir, '..'); - const parentPackageFilePath = join(packageDir, 'package.json'); - - const parentPackageFile = fs.existsSync(parentPackageFilePath) - ? require(parentPackageFilePath) - : {}; - - if (parentPackageFile.idyll) { - return parentPackageFile.idyll; - } - } - return {}; -}; - -const idyll = (options = {}, cb) => { - const opts = Object.assign( - {}, - { - alias: {}, - watch: false, - open: true, - datasets: 'data', - minify: true, - ssr: true, - components: 'components', - static: 'static', - staticOutputDir: 'static', - defaultComponents: dirname(require.resolve('idyll-components')), - layout: 'centered', - theme: 'github', - output: 'build', - outputCSS: 'idyll_styles.css', - outputJS: 'idyll_index.js', - port: process.env.PORT || 3000, - temp: '.idyll', - template: join(__dirname, 'client', '_index.html'), - transform: [], - compiler: {}, - compileLibs: false - }, - options - ); - - const paths = pathBuilder(opts); - debug('Reading from paths:', paths); - - createDirectories(paths); - configureNode(paths); - - const inputPackage = fs.existsSync(paths.PACKAGE_FILE) - ? require(paths.PACKAGE_FILE) - : {}; - const inputConfig = inputPackage.idyll || {}; - - const parentInputConfig = searchParentDirectories(paths.INPUT_DIR); - Object.assign(opts, parentInputConfig, inputConfig, options); - - // Resolve compiler plugins: - if (opts.compiler.postProcessors) { - opts.compiler.postProcessors = opts.compiler.postProcessors.map( - processor => { - try { - return require(require.resolve(processor, { - paths: [paths.INPUT_DIR] - })); - } catch (e) { - console.log(e); - console.warn('\n\nCould not find post-processor plugin: ', processor); - } - } - ); - } - - // Resolve context: - if (opts.context) { - if (opts.context.indexOf('./') > -1) { - opts.context = join(paths.INPUT_DIR, opts.context); - } - } - - let bs; - let watchers; - - const createResolvers = () => { - return new Map([ - ['components', new ComponentResolver(opts, paths)], - ['css', new CSSResolver(opts, paths)], - ['data', new DataResolver(opts, paths)] - ]); - }; - - class IdyllInstance extends EventEmitter { - getPaths() { - return paths; - } - - getOptions() { - return opts; - } - - build(src) { - // Resolvers are recreated on each build, since new data dependencies might have been added. - const resolvers = createResolvers(); - - if (src) opts.inputString = src; - - debug('Starting the build'); - // Leaving the following timing statement in for backwards-compatibility. - if (opts.debug) console.time('Build Time'); - - pipeline - .build(opts, paths, resolvers) - .then(output => { - debug('Build completed'); - // Leaving the following timing statement in for backwards-compatibility. - if (opts.debug) console.timeEnd('Build Time'); - this.emit('update', output); - }) - .then(() => { - if (!bs && opts.watch && opts.inputFile) { - bs = require('browser-sync').create(); - // any time an input files changes we will recompile .idl source - // and write ast.json, components.js, and data.js to disk - watchers = [ - bs.watch(paths.IDYLL_INPUT_FILE, { ignoreInitial: true }, () => - inst.build() - ), - // that will cause watchify to rebuild so we just watch the output bundle file - // and reload when it is updated. Watch options are to prevent multiple change - // events since the bundle file can be somewhat large - bs.watch( - paths.JS_OUTPUT_FILE, - { awaitWriteFinish: { stabilityThreshold: 499 } }, - bs.reload - ), - // when CSS changes we reassemble and inject it - bs.watch(paths.CSS_INPUT_FILE, { ignoreInitial: true }, () => { - pipeline.updateCSS(paths, resolvers.get('css')).then(() => { - bs.reload('styles.css'); - }); - }), - // when any static files change we do a full rebuild. - bs.watch(paths.STATIC_DIR, { ignoreInitial: true }, () => - inst.build() - ) - ]; - - // Each resolver is responsible for generating a list of directories to watch for - // their corresponding data types. - if (!opts.compiler.postProcessors) { - resolvers.forEach((resolver, name) => { - let watcher = bs.watch( - resolver.getDirectories(), - { ignoreInitial: true }, - () => { - inst.build(); - } - ); - watchers.push(watcher); - }); - } - - bs.init({ - cors: true, - logLevel: 'warn', - logPrefix: 'Idyll', - notify: false, - server: [paths.OUTPUT_DIR], - ui: false, - port: opts.port, - open: opts.open, - plugins: [require('bs-pretty-message')] - }); - } - }) - .then(() => { - this.emit('complete'); - }) - .catch(error => { - // pass along errors if anyone is listening - if (this.listenerCount('error')) { - this.emit('error', error); - } else { - // otherwise dump to the console - console.error(error); - } - bs && - bs.sockets && - bs.sockets.emit('fullscreen:message', { - title: 'Error compiling Idyll project', - body: error.toString() - }); - }); - return this; - } - - // Returns an array of the default components - // Each element of the array is an object with keys 'name' and 'path' - // 'name' is the file name of the component - // 'path' is the absolute path to the component - getComponents() { - var components = []; - var defaultCompsDir = this.getPaths().DEFAULT_COMPONENT_DIRS; - var compsDir = this.getComponentsDirectory(); // grabs the `components` folder of their current directory - var componentDirs = [defaultCompsDir, compsDir]; - - componentDirs.forEach(dirs => { - dirs.forEach(dir => { - try { - fs.statSync(dir); - } catch (error) { - // for when directory doesn't exist - return; - } - fs.readdirSync(dir + '').forEach(file => { - var compName = file.replace(/\.jsx?/g, ''); - if (compName !== 'index') { - // avoid conflicts with index.js file - components.push({ - name: compName, - path: dir + '/' + file - }); - } - }); - }); - }); - return components; - } - - // Returns the directory of the `components` folder - // of this IdyllInstance - // Note: this isn't guaranteed to exist - // It just adds "component" to the directory of this idyll instance - getComponentsDirectory() { - return this.getPaths().COMPONENT_DIRS; - } - - // Adds the given component (directory) to the components used - // in this IdyllInstance - // If there is already a component for the given componentPath, - // it will be overwritten with the one from componentPath - // If there is no components/ directory, then it will be created - addComponent(componentPath) { - const componentsDirectory = this.getComponentsDirectory(); - // We grab the name of the component, and put that in the components directory - const componentFileName = basename(componentPath); - // ensure components directory exists - try { - fs.statSync(componentsDirectory[0]); - } catch (err) { - fs.mkdirSync(componentsDirectory[0]); - } - fs.copyFileSync( - componentPath, - componentsDirectory[0] + '/' + componentFileName - ); - } - - // Returns an array of the current datasets used in this IdyllInstance's data directory - getDatasets() { - var dataFolder = this.getPaths().DATA_DIR; - var defaultData = []; - fs.readdirSync(dataFolder).forEach(file => { - var fileName = file; - var datasetPath = dataFolder + '/' + file; - var extension = extname(file); - defaultData.push({ - name: fileName, - path: datasetPath, - extension: extension - }); - }); - return defaultData; - } - - // Adds a dataset to the current datasets used in this IdyllInstance - // It will be added to the `data` directory of this IdyllInstance - addDataset(datasetPath) { - const datasetDirectory = this.getPaths().DATA_DIR; - const datasetName = basename(datasetPath); - try { - fs.statSync(datasetDirectory); - } catch (err) { - fs.mkdirSync(datasetDirectory); - } - fs.copyFileSync(datasetPath, datasetDirectory + '/' + datasetName); - } - - stopWatching() { - if (watchers.length) { - watchers.forEach(w => w.close()); - watchers = null; - } - if (bs) bs.exit(); - } - } - - const inst = new IdyllInstance(); - - return inst; -}; - -idyll.getVersion = () => { - return require('../package.json').version; -}; - -module.exports = idyll; +const fs = require('fs'); +const { dirname, basename, extname, join } = require('path'); +const EventEmitter = require('events'); +const mkdirp = require('mkdirp'); +const commandLineArgs = require('command-line-args'); + +const pathBuilder = require('./path-builder'); +const configureNode = require('./node-config'); +const pipeline = require('./pipeline'); +const { ComponentResolver, DataResolver, CSSResolver } = require('./resolvers'); + +const debug = require('debug')('idyll:cli'); + +const optionDefinitions = [{ name: 'env', alias: 'e', type: String }]; +const commandLineOptions = commandLineArgs(optionDefinitions); + +function createDirectories(paths) { + mkdirp.sync(paths.OUTPUT_DIR); + mkdirp.sync(paths.STATIC_OUTPUT_DIR); + mkdirp.sync(paths.TMP_DIR); +} + +const searchParentDirectories = packageDir => { + while (true) { + if (packageDir === join(packageDir, '..')) { + break; + } + packageDir = join(packageDir, '..'); + const parentPackageFilePath = join(packageDir, 'package.json'); + + const parentPackageFile = fs.existsSync(parentPackageFilePath) + ? require(parentPackageFilePath) + : {}; + + if (parentPackageFile.idyll) { + return parentPackageFile; + } + } + return {}; +}; + +function selectIdyllConfig(inputPackage, env) { + var hasMultipleConfigs = false; // for error handling later + if (inputPackage.idyll) { + // Check for an idyll env key if array found + if (Array.isArray(inputPackage.idyll)) { + if (env == null) { + return { + idyll: inputPackage.idyll[0][1], + hasMultipleConfigs: hasMultipleConfigs + }; + } else { + for (var i in inputPackage.idyll) { + hasMultipleConfigs = true; + if (inputPackage.idyll[i][0] === env) { + return { + idyll: inputPackage.idyll[i][1], + hasMultipleConfigs: hasMultipleConfigs + }; + } + } + throw Error( + 'No matching env found out of available options. Please verify your package.json file(s) have ' + + env + ); + } + } else { + // env passed but package.json is in wrong format + if (env != null) { + throw Error('No env found matching ' + env); + } + return { + idyll: inputPackage.idyll, + hasMultipleConfigs: hasMultipleConfigs + }; + } + } + return { + idyll: {}, + hasMultipleConfigs: hasMultipleConfigs + }; +} + +const idyll = (options = {}, cb) => { + const opts = Object.assign( + {}, + { + alias: {}, + watch: false, + open: true, + datasets: 'data', + minify: true, + ssr: true, + components: 'components', + static: 'static', + staticOutputDir: 'static', + defaultComponents: dirname(require.resolve('idyll-components')), + layout: 'centered', + theme: 'github', + output: 'build', + outputCSS: 'idyll_styles.css', + outputJS: 'idyll_index.js', + port: process.env.PORT || 3000, + temp: '.idyll', + template: join(__dirname, 'client', '_index.html'), + transform: [], + compiler: {}, + compileLibs: false, + env: commandLineOptions.env + }, + options + ); + + const paths = pathBuilder(opts); + debug('Reading from paths:', paths); + + createDirectories(paths); + configureNode(paths); + + const inputPackage = fs.existsSync(paths.PACKAGE_FILE) + ? require(paths.PACKAGE_FILE) + : {}; + + if ( + commandLineOptions.env !== options.env && + (commandLineOptions.env !== undefined && options.env !== undefined) + ) { + //Should one supercede the other? + throw Error( + "Mismatch between Idyll env provided and command line arg. Please remove the Idyll({env='...',...} or the command line argument." + ); + } + + const env = commandLineOptions.env || options.env; + const inputConfig = selectIdyllConfig(inputPackage, env); + const parentInputConfig = selectIdyllConfig( + searchParentDirectories(paths.INPUT_DIR), + env + ); + if (parentInputConfig.hasMultipleConfigs && !inputConfig.hasMultipleConfigs) { + throw Error( + 'Project root has multiple config options given but the local project does not. Please add envs to the local project and use the --env parameter or remove them from the top level package.' + ); + } + Object.assign(opts, parentInputConfig.idyll, inputConfig.idyll, options); + + // Resolve compiler plugins: + if (opts.compiler.postProcessors) { + opts.compiler.postProcessors = opts.compiler.postProcessors.map( + processor => { + try { + return require(require.resolve(processor, { + paths: [paths.INPUT_DIR] + })); + } catch (e) { + console.log(e); + console.warn('\n\nCould not find post-processor plugin: ', processor); + } + } + ); + } + + // Resolve context: + if (opts.context) { + if (opts.context.indexOf('./') > -1) { + opts.context = join(paths.INPUT_DIR, opts.context); + } + } + + let bs; + let watchers; + + const createResolvers = () => { + return new Map([ + ['components', new ComponentResolver(opts, paths)], + ['css', new CSSResolver(opts, paths)], + ['data', new DataResolver(opts, paths)] + ]); + }; + + class IdyllInstance extends EventEmitter { + getPaths() { + return paths; + } + + getOptions() { + return opts; + } + + build(src) { + // Resolvers are recreated on each build, since new data dependencies might have been added. + const resolvers = createResolvers(); + + if (src) opts.inputString = src; + + debug('Starting the build'); + // Leaving the following timing statement in for backwards-compatibility. + if (opts.debug) console.time('Build Time'); + + pipeline + .build(opts, paths, resolvers) + .then(output => { + debug('Build completed'); + // Leaving the following timing statement in for backwards-compatibility. + if (opts.debug) console.timeEnd('Build Time'); + this.emit('update', output); + }) + .then(() => { + if (!bs && opts.watch && opts.inputFile) { + bs = require('browser-sync').create(); + // any time an input files changes we will recompile .idl source + // and write ast.json, components.js, and data.js to disk + watchers = [ + bs.watch(paths.IDYLL_INPUT_FILE, { ignoreInitial: true }, () => + inst.build() + ), + // that will cause watchify to rebuild so we just watch the output bundle file + // and reload when it is updated. Watch options are to prevent multiple change + // events since the bundle file can be somewhat large + bs.watch( + paths.JS_OUTPUT_FILE, + { awaitWriteFinish: { stabilityThreshold: 499 } }, + bs.reload + ), + // when CSS changes we reassemble and inject it + bs.watch(paths.CSS_INPUT_FILE, { ignoreInitial: true }, () => { + pipeline.updateCSS(paths, resolvers.get('css')).then(() => { + bs.reload('styles.css'); + }); + }), + // when any static files change we do a full rebuild. + bs.watch(paths.STATIC_DIR, { ignoreInitial: true }, () => + inst.build() + ) + ]; + + // Each resolver is responsible for generating a list of directories to watch for + // their corresponding data types. + if (!opts.compiler.postProcessors) { + resolvers.forEach((resolver, name) => { + let watcher = bs.watch( + resolver.getDirectories(), + { ignoreInitial: true }, + () => { + inst.build(); + } + ); + watchers.push(watcher); + }); + } + + bs.init({ + cors: true, + logLevel: 'warn', + logPrefix: 'Idyll', + notify: false, + server: [paths.OUTPUT_DIR], + ui: false, + port: opts.port, + open: opts.open, + plugins: [require('bs-pretty-message')] + }); + } + }) + .then(() => { + this.emit('complete'); + }) + .catch(error => { + // pass along errors if anyone is listening + if (this.listenerCount('error')) { + this.emit('error', error); + } else { + // otherwise dump to the console + console.error(error); + } + bs && + bs.sockets && + bs.sockets.emit('fullscreen:message', { + title: 'Error compiling Idyll project', + body: error.toString() + }); + }); + return this; + } + + // Returns an array of the default components + // Each element of the array is an object with keys 'name' and 'path' + // 'name' is the file name of the component + // 'path' is the absolute path to the component + getComponents() { + var components = []; + var defaultCompsDir = this.getPaths().DEFAULT_COMPONENT_DIRS; + var compsDir = this.getComponentsDirectory(); // grabs the `components` folder of their current directory + var componentDirs = [defaultCompsDir, compsDir]; + + componentDirs.forEach(dirs => { + dirs.forEach(dir => { + try { + fs.statSync(dir); + } catch (error) { + // for when directory doesn't exist + return; + } + fs.readdirSync(dir + '').forEach(file => { + var compName = file.replace(/\.jsx?/g, ''); + if (compName !== 'index') { + // avoid conflicts with index.js file + components.push({ + name: compName, + path: dir + '/' + file + }); + } + }); + }); + }); + return components; + } + + // Returns the directory of the `components` folder + // of this IdyllInstance + // Note: this isn't guaranteed to exist + // It just adds "component" to the directory of this idyll instance + getComponentsDirectory() { + return this.getPaths().COMPONENT_DIRS; + } + + // Adds the given component (directory) to the components used + // in this IdyllInstance + // If there is already a component for the given componentPath, + // it will be overwritten with the one from componentPath + // If there is no components/ directory, then it will be created + addComponent(componentPath) { + const componentsDirectory = this.getComponentsDirectory(); + // We grab the name of the component, and put that in the components directory + const componentFileName = basename(componentPath); + // ensure components directory exists + try { + fs.statSync(componentsDirectory[0]); + } catch (err) { + fs.mkdirSync(componentsDirectory[0]); + } + fs.copyFileSync( + componentPath, + componentsDirectory[0] + '/' + componentFileName + ); + } + + // Returns an array of the current datasets used in this IdyllInstance's data directory + getDatasets() { + var dataFolder = this.getPaths().DATA_DIR; + var defaultData = []; + fs.readdirSync(dataFolder).forEach(file => { + var fileName = file; + var datasetPath = dataFolder + '/' + file; + var extension = extname(file); + defaultData.push({ + name: fileName, + path: datasetPath, + extension: extension + }); + }); + return defaultData; + } + + // Adds a dataset to the current datasets used in this IdyllInstance + // It will be added to the `data` directory of this IdyllInstance + addDataset(datasetPath) { + const datasetDirectory = this.getPaths().DATA_DIR; + const datasetName = basename(datasetPath); + try { + fs.statSync(datasetDirectory); + } catch (err) { + fs.mkdirSync(datasetDirectory); + } + fs.copyFileSync(datasetPath, datasetDirectory + '/' + datasetName); + } + + stopWatching() { + if (watchers.length) { + watchers.forEach(w => w.close()); + watchers = null; + } + if (bs) bs.exit(); + } + } + + const inst = new IdyllInstance(); + + return inst; +}; + +idyll.getVersion = () => { + return require('../package.json').version; +}; + +module.exports = idyll; diff --git a/packages/idyll-cli/test/env-options/outer-project/components/CapitalPascal.js b/packages/idyll-cli/test/env-options/outer-project/components/CapitalPascal.js new file mode 100644 index 000000000..d5861b1c7 --- /dev/null +++ b/packages/idyll-cli/test/env-options/outer-project/components/CapitalPascal.js @@ -0,0 +1,11 @@ +const React = require('react'); + +class PascalComponent extends React.PureComponent { + render() { + const { hasError, updateProps, idyll, ...props } = this.props; + + return
This is a custom component
; + } +} + +module.exports = PascalComponent; diff --git a/packages/idyll-cli/test/env-options/outer-project/components/custom-component.js b/packages/idyll-cli/test/env-options/outer-project/components/custom-component.js new file mode 100644 index 000000000..39d111ab6 --- /dev/null +++ b/packages/idyll-cli/test/env-options/outer-project/components/custom-component.js @@ -0,0 +1,17 @@ +const React = require('react'); + +class CustomComponent extends React.PureComponent { + render() { + const { hasError, updateProps, idyll, ...props } = this.props; + return
This is a custom component
; + } +} + +module.exports = CustomComponent; + +module.exports.IndexedComponent = class extends React.PureComponent { + render() { + const { hasError, updateProps, idyll, ...props } = this.props; + return
This is another custom component
; + } +}; diff --git a/packages/idyll-cli/test/env-options/outer-project/components/functional-component.js b/packages/idyll-cli/test/env-options/outer-project/components/functional-component.js new file mode 100644 index 000000000..01991bcf4 --- /dev/null +++ b/packages/idyll-cli/test/env-options/outer-project/components/functional-component.js @@ -0,0 +1,5 @@ +const React = require('react'); + +module.exports = () => { + return
Let's put the fun back in functional!
; +}; diff --git a/packages/idyll-cli/test/env-options/outer-project/components/functional-default-component.js b/packages/idyll-cli/test/env-options/outer-project/components/functional-default-component.js new file mode 100644 index 000000000..47bdf47fe --- /dev/null +++ b/packages/idyll-cli/test/env-options/outer-project/components/functional-default-component.js @@ -0,0 +1,9 @@ +const React = require('react'); + +export default () => ( +
+ This is some text + + Then some more text +
+); diff --git a/packages/idyll-cli/test/env-options/outer-project/custom-theme.css b/packages/idyll-cli/test/env-options/outer-project/custom-theme.css new file mode 100644 index 000000000..ae41890f6 --- /dev/null +++ b/packages/idyll-cli/test/env-options/outer-project/custom-theme.css @@ -0,0 +1,721 @@ +@font-face { + font-family: octicons-link; + src: url(data:font/woff;charset=utf-8;base64,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) + format('woff'); +} + +.idyll-root { + -ms-text-size-adjust: 100%; + -webkit-text-size-adjust: 100%; + line-height: 1.5; + color: #24292e; + font-family: -apple-system, system-ui, BlinkMacSystemFont, 'Segoe UI', + Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', + 'Segoe UI Symbol'; + font-size: 16px; + line-height: 1.5; + word-wrap: break-word; +} + +.idyll-root .pl-c { + color: #969896; +} + +.idyll-root .pl-c1, +.idyll-root .pl-s .pl-v { + color: #0086b3; +} + +.idyll-root .pl-e, +.idyll-root .pl-en { + color: #795da3; +} + +.idyll-root .pl-smi, +.idyll-root .pl-s .pl-s1 { + color: #333; +} + +.idyll-root .pl-ent { + color: #63a35c; +} + +.idyll-root .pl-k { + color: #a71d5d; +} + +.idyll-root .pl-s, +.idyll-root .pl-pds, +.idyll-root .pl-s .pl-pse .pl-s1, +.idyll-root .pl-sr, +.idyll-root .pl-sr .pl-cce, +.idyll-root .pl-sr .pl-sre, +.idyll-root .pl-sr .pl-sra { + color: #183691; +} + +.idyll-root .pl-v, +.idyll-root .pl-smw { + color: #ed6a43; +} + +.idyll-root .pl-bu { + color: #b52a1d; +} + +.idyll-root .pl-ii { + color: #f8f8f8; + background-color: #b52a1d; +} + +.idyll-root .pl-c2 { + color: #f8f8f8; + background-color: #b52a1d; +} + +.idyll-root .pl-c2::before { + content: '^M'; +} + +.idyll-root .pl-sr .pl-cce { + font-weight: bold; + color: #63a35c; +} + +.idyll-root .pl-ml { + color: #693a17; +} + +.idyll-root .pl-mh, +.idyll-root .pl-mh .pl-en, +.idyll-root .pl-ms { + font-weight: bold; + color: #1d3e81; +} + +.idyll-root .pl-mq { + color: #008080; +} + +.idyll-root .pl-mi { + font-style: italic; + color: #333; +} + +.idyll-root .pl-mb { + font-weight: bold; + color: #333; +} + +.idyll-root .pl-md { + color: #bd2c00; + background-color: #ffecec; +} + +.idyll-root .pl-mi1 { + color: #55a532; + background-color: #eaffea; +} + +.idyll-root .pl-mc { + color: #ef9700; + background-color: #ffe3b4; +} + +.idyll-root .pl-mi2 { + color: #d8d8d8; + background-color: #808080; +} + +.idyll-root .pl-mdr { + font-weight: bold; + color: #795da3; +} + +.idyll-root .pl-mo { + color: #1d3e81; +} + +.idyll-root .pl-ba { + color: #595e62; +} + +.idyll-root .pl-sg { + color: #c0c0c0; +} + +.idyll-root .pl-corl { + text-decoration: underline; + color: #183691; +} + +.idyll-root .octicon { + display: inline-block; + vertical-align: text-top; + fill: currentColor; +} + +.idyll-root a { + background-color: transparent; + -webkit-text-decoration-skip: objects; +} + +.idyll-root a:active, +.idyll-root a:hover { + outline-width: 0; +} + +.idyll-root strong { + font-weight: inherit; +} + +.idyll-root strong { + font-weight: bolder; +} + +.idyll-root h1 { + font-size: 2em; + margin: 0.67em 0; +} + +.idyll-root img { + border-style: none; +} + +.idyll-root svg:not(:root) { + overflow: hidden; +} + +.idyll-root code, +.idyll-root kbd, +.idyll-root pre { + font-family: monospace, monospace; + font-size: 1em; +} + +.idyll-root hr { + box-sizing: content-box; + height: 0; + overflow: visible; +} + +.idyll-root input { + font: inherit; + margin: 10px 10px 20px 0; +} + +.idyll-root input { + overflow: visible; +} + +.idyll-root [type='checkbox'] { + box-sizing: border-box; + padding: 0; +} + +.idyll-root * { + box-sizing: border-box; +} + +.idyll-root input { + font-family: inherit; + font-size: inherit; + line-height: inherit; +} + +.idyll-root a { + color: #0366d6; + text-decoration: none; +} + +.idyll-root a:hover { + text-decoration: underline; +} + +.idyll-root strong { + font-weight: 600; +} + +.idyll-root hr { + height: 0; + margin: 15px 0; + overflow: hidden; + background: transparent; + border: 0; + border-bottom: 1px solid #dfe2e5; +} + +.idyll-root hr::before { + display: table; + content: ''; +} + +.idyll-root hr::after { + display: table; + clear: both; + content: ''; +} + +.idyll-root table { + border-spacing: 0; + border-collapse: collapse; +} + +.idyll-root td, +.idyll-root th { + padding: 0; +} + +.idyll-root h1, +.idyll-root h2, +.idyll-root h3, +.idyll-root h4, +.idyll-root h5, +.idyll-root h6 { + margin-top: 0; + margin-bottom: 0; +} + +.idyll-root h1 { + font-size: 32px; + font-weight: 600; +} + +.idyll-root h2 { + font-size: 24px; + font-weight: 600; +} + +.idyll-root h3 { + font-size: 20px; + font-weight: 600; +} + +.idyll-root h4 { + font-size: 16px; + font-weight: 600; +} + +.idyll-root h5 { + font-size: 14px; + font-weight: 600; +} + +.idyll-root h6 { + font-size: 12px; + font-weight: 600; +} + +.idyll-root p { + margin-top: 0; + margin-bottom: 10px; +} + +.idyll-root blockquote { + margin: 0; +} + +.idyll-root ul, +.idyll-root ol { + padding-left: 0; + margin-top: 0; + margin-bottom: 0; +} + +.idyll-root ol ol, +.idyll-root ul ol { + list-style-type: lower-roman; +} + +.idyll-root ul ul ol, +.idyll-root ul ol ol, +.idyll-root ol ul ol, +.idyll-root ol ol ol { + list-style-type: lower-alpha; +} + +.idyll-root dd { + margin-left: 0; +} + +.idyll-root code { + font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, + monospace; + font-size: 12px; +} + +.idyll-root pre { + margin-top: 0; + margin-bottom: 0; + font: 12px 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, + monospace; +} + +.idyll-root .octicon { + vertical-align: text-bottom; +} + +.idyll-root .pl-0 { + padding-left: 0 !important; +} + +.idyll-root .pl-1 { + padding-left: 4px !important; +} + +.idyll-root .pl-2 { + padding-left: 8px !important; +} + +.idyll-root .pl-3 { + padding-left: 16px !important; +} + +.idyll-root .pl-4 { + padding-left: 24px !important; +} + +.idyll-root .pl-5 { + padding-left: 32px !important; +} + +.idyll-root .pl-6 { + padding-left: 40px !important; +} + +.idyll-root::before { + display: table; + content: ''; +} + +.idyll-root::after { + display: table; + clear: both; + content: ''; +} + +.idyll-root > *:first-child { + margin-top: 0 !important; +} + +.idyll-root > *:last-child { + margin-bottom: 0 !important; +} + +.idyll-root a:not([href]) { + color: inherit; + text-decoration: none; +} + +.idyll-root .anchor { + float: left; + padding-right: 4px; + margin-left: -20px; + line-height: 1; +} + +.idyll-root .anchor:focus { + outline: none; +} + +.idyll-root p, +.idyll-root blockquote, +.idyll-root ul, +.idyll-root ol, +.idyll-root dl, +.idyll-root table, +.idyll-root pre { + margin-top: 0; + margin-bottom: 16px; +} + +.idyll-root hr { + height: 0.25em; + padding: 0; + margin: 24px 0; + background-color: #e1e4e8; + border: 0; +} + +.idyll-root blockquote { + padding: 0 1em; + color: #6a737d; + border-left: 0.25em solid #dfe2e5; +} + +.idyll-root blockquote > :first-child { + margin-top: 0; +} + +.idyll-root blockquote > :last-child { + margin-bottom: 0; +} + +.idyll-root kbd { + display: inline-block; + padding: 3px 5px; + font-size: 11px; + line-height: 10px; + color: #444d56; + vertical-align: middle; + background-color: #fafbfc; + border: solid 1px #c6cbd1; + border-bottom-color: #959da5; + border-radius: 3px; + box-shadow: inset 0 -1px 0 #959da5; +} + +.idyll-root h1, +.idyll-root h2, +.idyll-root h3, +.idyll-root h4, +.idyll-root h5, +.idyll-root h6 { + margin-top: 24px; + margin-bottom: 16px; + font-weight: 600; + line-height: 1.25; +} + +.idyll-root h1 .octicon-link, +.idyll-root h2 .octicon-link, +.idyll-root h3 .octicon-link, +.idyll-root h4 .octicon-link, +.idyll-root h5 .octicon-link, +.idyll-root h6 .octicon-link { + color: #1b1f23; + vertical-align: middle; + visibility: hidden; +} + +.idyll-root h1:hover .anchor, +.idyll-root h2:hover .anchor, +.idyll-root h3:hover .anchor, +.idyll-root h4:hover .anchor, +.idyll-root h5:hover .anchor, +.idyll-root h6:hover .anchor { + text-decoration: none; +} + +.idyll-root h1:hover .anchor .octicon-link, +.idyll-root h2:hover .anchor .octicon-link, +.idyll-root h3:hover .anchor .octicon-link, +.idyll-root h4:hover .anchor .octicon-link, +.idyll-root h5:hover .anchor .octicon-link, +.idyll-root h6:hover .anchor .octicon-link { + visibility: visible; +} + +.idyll-root h1 { + padding-bottom: 0.3em; + font-size: 2em; + border-bottom: 1px solid #eaecef; +} + +.idyll-root h2 { + padding-bottom: 0.3em; + font-size: 1.5em; + border-bottom: 1px solid #eaecef; +} + +.idyll-root h3 { + font-size: 1.25em; +} + +.idyll-root h4 { + font-size: 1em; +} + +.idyll-root h5 { + font-size: 0.875em; +} + +.idyll-root h6 { + font-size: 0.85em; + color: #6a737d; +} + +.idyll-root h1.hed, +.idyll-root h2.dek { + border-bottom: none; + padding-bottom: 0; + margin-top: 12px; +} + +.idyll-root ul, +.idyll-root ol { + padding-left: 2em; +} + +.idyll-root ul ul, +.idyll-root ul ol, +.idyll-root ol ol, +.idyll-root ol ul { + margin-top: 0; + margin-bottom: 0; +} + +.idyll-root li > p { + margin-top: 16px; +} + +.idyll-root li + li { + margin-top: 0.25em; +} + +.idyll-root dl { + padding: 0; +} + +.idyll-root dl dt { + padding: 0; + margin-top: 16px; + font-size: 1em; + font-style: italic; + font-weight: 600; +} + +.idyll-root dl dd { + padding: 0 16px; + margin-bottom: 16px; +} + +.idyll-root table { + display: block; + width: 100%; + overflow: auto; +} + +.idyll-root table th { + font-weight: 600; +} + +.idyll-root table th, +.idyll-root table td { + padding: 6px 13px; + border: 1px solid #dfe2e5; +} + +.idyll-root table tr { + background-color: #fff; + border-top: 1px solid #c6cbd1; +} + +.idyll-root table tr:nth-child(2n) { + background-color: #f6f8fa; +} + +.idyll-root img { + max-width: 100%; + box-sizing: content-box; + background-color: #fff; +} + +.idyll-root code { + padding: 0; + padding-top: 0.2em; + padding-bottom: 0.2em; + margin: 0; + font-size: 85%; + background-color: rgba(27, 31, 35, 0.05); + border-radius: 3px; +} + +.idyll-root code::before, +.idyll-root code::after { + letter-spacing: -0.2em; + content: '\00a0'; +} + +.idyll-root pre { + word-wrap: normal; +} + +.idyll-root pre > code { + padding: 0; + margin: 0; + font-size: 100%; + word-break: normal; + white-space: pre; + background: transparent; + border: 0; +} + +.idyll-root .highlight { + margin-bottom: 16px; +} + +.idyll-root .highlight pre { + margin-bottom: 0; + word-break: normal; +} + +.idyll-root .highlight pre, +.idyll-root pre { + padding: 16px; + overflow: auto; + font-size: 85%; + line-height: 1.45; + background-color: #f6f8fa; + border-radius: 3px; +} + +.idyll-root pre code { + display: inline; + max-width: auto; + padding: 0; + margin: 0; + overflow: visible; + line-height: inherit; + word-wrap: normal; + background-color: transparent; + border: 0; +} + +.idyll-root pre code::before, +.idyll-root pre code::after { + content: normal; +} + +.idyll-root .full-commit .btn-outline:not(:disabled):hover { + color: #005cc5; + border-color: #005cc5; +} + +.idyll-root kbd { + display: inline-block; + padding: 3px 5px; + font: 11px 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, + monospace; + line-height: 10px; + color: #444d56; + vertical-align: middle; + background-color: #fcfcfc; + border: solid 1px #c6cbd1; + border-bottom-color: #959da5; + border-radius: 3px; + box-shadow: inset 0 -1px 0 #959da5; +} + +.idyll-root :checked + .radio-label { + position: relative; + z-index: 1; + border-color: #0366d6; +} + +.idyll-root .task-list-item { + list-style-type: none; +} + +.idyll-root .task-list-item + .task-list-item { + margin-top: 3px; +} + +.idyll-root .task-list-item input { + margin: 0 0.2em 0.25em -1.6em; + vertical-align: middle; +} + +.idyll-root hr { + border-bottom-color: #eee; +} diff --git a/packages/idyll-cli/test/env-options/outer-project/data/example-data.json b/packages/idyll-cli/test/env-options/outer-project/data/example-data.json new file mode 100644 index 000000000..070f8e68e --- /dev/null +++ b/packages/idyll-cli/test/env-options/outer-project/data/example-data.json @@ -0,0 +1,10 @@ +[ + { + "x": 0, + "y": 0 + }, + { + "x": 1, + "y": 1 + } +] diff --git a/packages/idyll-cli/test/env-options/outer-project/data/example-file.csv b/packages/idyll-cli/test/env-options/outer-project/data/example-file.csv new file mode 100644 index 000000000..e5726765b --- /dev/null +++ b/packages/idyll-cli/test/env-options/outer-project/data/example-file.csv @@ -0,0 +1,3 @@ +"x","y" +0,0 +1,1 \ No newline at end of file diff --git a/packages/idyll-cli/test/env-options/outer-project/index.idl b/packages/idyll-cli/test/env-options/outer-project/index.idl new file mode 100644 index 000000000..b0992ba94 --- /dev/null +++ b/packages/idyll-cli/test/env-options/outer-project/index.idl @@ -0,0 +1,58 @@ +[meta title:"Page Title" description:"Short description of your project" /] + +[Header + title:"Welcome to Idyll" + subtitle:"Open index.idl to start writing" + author:"Your Name Here" + authorLink:"https://idyll-lang.github.io" /] + + +This is an Idyll file. Write text +as you please in here. To add interactivity, +you can add different components to the text. + +[data name:"myData" source:"example-data.json" /] +[data name:"myCSVData" source:"example-file.csv" /] + +[Table data:myData /] + +[Table data:myCSVData /] + +Here is how you can use a variable: + +[var name:"exampleVar" value:5 /] + +[Range min:0 max:10 value:exampleVar /] +[Display value:exampleVar /] + +```js +var code = true; +``` + +And here is a custom component: + +[CustomComponent /] + +You can use standard html tags if a +component with the same name +doesn't exist. + +[ReactSimplePieChart + slices:`[{ + color: '#7b3af5', + value: 0.1, + }, { + color: '#EAE7D6', + value: 0.9, }, + ]` /] + +[PackageJsonComponentTest /] + +This adds support for indexed components: [CustomComponent.IndexedComponent /] + +[FunctionalComponent /] + +[FunctionalDefaultComponent /] + + +[CapitalPascal /] diff --git a/packages/idyll-cli/test/env-options/outer-project/inner-project/package.json b/packages/idyll-cli/test/env-options/outer-project/inner-project/package.json new file mode 100644 index 000000000..ebc6062fd --- /dev/null +++ b/packages/idyll-cli/test/env-options/outer-project/inner-project/package.json @@ -0,0 +1,38 @@ +{ + "name": "test-project-inner", + "version": "1.0.0", + "scripts": { + "start": "idyll index.idl --watch --css styles.css --layout centered --theme github --spellcheck" + }, + "idyll": [ + [ + "default-env", + { + "layout": "none" + } + ], + [ + "my-env", + { + "alias": { + "PackageJsonComponentTest": "CustomComponent" + }, + "layout": "none" + } + ], + [ + "inner-env", + { + "alias": { + "PackageJsonComponentTest": "CustomComponent" + }, + "layout": "blog" + } + ] + ], + "dependencies": { + "idyll-component": "^1.1.0", + "react-simple-pie-chart": "^0.4.1" + }, + "devDependencies": {} +} diff --git a/packages/idyll-cli/test/env-options/outer-project/package.json b/packages/idyll-cli/test/env-options/outer-project/package.json new file mode 100644 index 000000000..6129aa198 --- /dev/null +++ b/packages/idyll-cli/test/env-options/outer-project/package.json @@ -0,0 +1,32 @@ +{ + "name": "test-project", + "version": "1.0.0", + "scripts": { + "start": "idyll index.idl --watch --css styles.css --layout centered --theme github --spellcheck" + }, + "idyll": [ + ["default-env", + { + "layout": "blog" + }], + ["my-env", + { + "alias": { + "PackageJsonComponentTest": "CustomComponent" + }, + "layout": "none" + }], + ["outer-env", + { + "alias": { + "PackageJsonComponentTest": "CustomComponent" + }, + "layout": "centered" + }] + ], + "dependencies": { + "idyll-component": "^1.1.0", + "react-simple-pie-chart": "^0.4.1" + }, + "devDependencies": {} +} diff --git a/packages/idyll-cli/test/env-options/outer-project/static/favicon.ico b/packages/idyll-cli/test/env-options/outer-project/static/favicon.ico new file mode 100755 index 000000000..7031685a9 Binary files /dev/null and b/packages/idyll-cli/test/env-options/outer-project/static/favicon.ico differ diff --git a/packages/idyll-cli/test/env-options/outer-project/styles.css b/packages/idyll-cli/test/env-options/outer-project/styles.css new file mode 100644 index 000000000..710c588e5 --- /dev/null +++ b/packages/idyll-cli/test/env-options/outer-project/styles.css @@ -0,0 +1,13 @@ +@import url('https://fonts.googleapis.com/css?family=Archivo+Black|Fira+Mono:400,500,700|Source+Sans+Pro:300,300i,400,400i,600,600i,700,700i'); + +body { + font-family: 'Source Sans Pro', sans-serif; +} + +.hed { + font-family: 'Archivo Black', sans-serif; +} + +.byline { + font-family: 'Fira Mono', monospace; +} diff --git a/packages/idyll-cli/test/env-options/test.js b/packages/idyll-cli/test/env-options/test.js new file mode 100644 index 000000000..30f99fbff --- /dev/null +++ b/packages/idyll-cli/test/env-options/test.js @@ -0,0 +1,125 @@ +jasmine.DEFAULT_TIMEOUT_INTERVAL = 30000; // 30 second timeout + +const Idyll = require('../../src'); +const fs = require('fs'); +const { join, resolve, dirname } = require('path'); + +const getFilenames = dir => { + return fs.readdirSync(dir).filter(f => f !== '.DS_Store'); +}; + +const dirToHash = dir => { + return getFilenames(dir).reduce((acc, val) => { + let fullPath = join(dir, val); + + if (fs.statSync(fullPath).isFile()) { + acc[val] = fs.readFileSync(fullPath, 'utf8'); + } else { + acc[val] = dirToHash(fullPath); + } + + return acc; + }, {}); +}; + +const PROJECT_DIR = join(__dirname, 'outer-project', 'inner-project'); + +const PROJECT_BUILD_DIR = join(PROJECT_DIR, 'build'); + +test('no env provided', () => { + const idyll = Idyll({ + inputFile: join(PROJECT_DIR, 'index.idl'), + output: PROJECT_BUILD_DIR, + htmlTemplate: join(PROJECT_DIR, '_index.html'), + components: join(PROJECT_DIR, 'components'), + datasets: join(PROJECT_DIR, 'data'), + theme: join(PROJECT_DIR, 'custom-theme.css'), + css: join(PROJECT_DIR, 'styles.css'), + googleFonts: ['Hanalei Fill'], + favicon: 'static/favicon.ico', + compiler: { + spellcheck: false + }, + minify: false + }); + + expect(idyll.getOptions()).toEqual({ + alias: {}, + compileLibs: false, + compiler: { spellcheck: false }, + components: join(PROJECT_DIR, 'components'), + css: join(PROJECT_DIR, 'styles.css'), + datasets: join(PROJECT_DIR, 'data'), + env: undefined, + defaultComponents: dirname(require.resolve('idyll-components')), + favicon: 'static/favicon.ico', + googleFonts: ['Hanalei Fill'], + htmlTemplate: join(PROJECT_DIR, '_index.html'), + inputFile: join(PROJECT_DIR, 'index.idl'), + layout: 'none', + minify: false, + open: true, + output: join(PROJECT_DIR, 'build'), + outputCSS: 'idyll_styles.css', + outputJS: 'idyll_index.js', + port: 3000, + ssr: true, + static: 'static', + staticOutputDir: "static", + temp: '.idyll', + template: resolve(join(__dirname, '/../../src/client/_index.html')), + theme: join(PROJECT_DIR, 'custom-theme.css'), + transform: [], + watch: false + }); +}); + +test('my-env provided', () => { + const idyll = Idyll({ + inputFile: join(PROJECT_DIR, 'index.idl'), + output: PROJECT_BUILD_DIR, + htmlTemplate: join(PROJECT_DIR, '_index.html'), + components: join(PROJECT_DIR, 'components'), + datasets: join(PROJECT_DIR, 'data'), + theme: join(PROJECT_DIR, 'custom-theme.css'), + css: join(PROJECT_DIR, 'styles.css'), + googleFonts: ['Hanalei Fill'], + favicon: 'static/favicon.ico', + compiler: { + spellcheck: false + }, + minify: false, + env: 'my-env' + }); + + expect(idyll.getOptions()).toEqual({ + env: 'my-env', + alias: { PackageJsonComponentTest: 'CustomComponent' }, + compileLibs: false, + compiler: { spellcheck: false }, + components: join(PROJECT_DIR, 'components'), + css: join(PROJECT_DIR, 'styles.css'), + datasets: join(PROJECT_DIR, 'data'), + env: 'my-env', + defaultComponents: dirname(require.resolve('idyll-components')), + favicon: 'static/favicon.ico', + googleFonts: ['Hanalei Fill'], + htmlTemplate: join(PROJECT_DIR, '_index.html'), + inputFile: join(PROJECT_DIR, 'index.idl'), + layout: 'none', + minify: false, + open: true, + output: join(PROJECT_DIR, 'build'), + outputCSS: 'idyll_styles.css', + outputJS: 'idyll_index.js', + port: 3000, + ssr: true, + static: 'static', + staticOutputDir: "static", + temp: '.idyll', + template: resolve(join(__dirname, '/../../src/client/_index.html')), + theme: join(PROJECT_DIR, 'custom-theme.css'), + transform: [], + watch: false + }); +}); diff --git a/packages/idyll-docs/pages/docs/configuration-and-styles.js b/packages/idyll-docs/pages/docs/configuration-and-styles.js index 41382ed52..0f8fbc6c7 100644 --- a/packages/idyll-docs/pages/docs/configuration-and-styles.js +++ b/packages/idyll-docs/pages/docs/configuration-and-styles.js @@ -199,6 +199,40 @@ export default ({ url }) => (

You can also compile an input string directly instead of a file:

{ExampleCodeB} +
+

Selecting Idyll options using the env parameter

+

+ Oftentimes it can be helpful to change your options based on where You + are running Idyll. Idyll supports an env paramter you can use either by + API or with the command-line with \`--env my-env\` +

+

+ To use the env parameter you need to change the format of package.json + to support multiple options. +

+

package.json example

+ + {`"idyll": [ + "my-env", { + "layout": "blog", + "theme": "my-custom-theme.css", + "components": ["./components/", "../some-other-components/"], + "googleFonts": ["Hanalei Fill"], + "favicon": "static/favicon.ico", + "alias": { + "VL": "IdyllVegaLite" + }], + [ + "prod-env", { + "theme": "my-custom-prod-theme.css", + }] + ]}`} + +

+ If no env is supplied and package.json is in list format, the first env + will be used by default. +

+

Continue to the next section to learn about{' '} diff --git a/yarn.lock b/yarn.lock index 8cd5c7bce..717a7a6ef 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3570,7 +3570,7 @@ command-join@^2.0.0: dependencies: "@improved/node" "^1.0.0" -command-line-args@^5.0.0: +command-line-args@^5.0.0, command-line-args@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/command-line-args/-/command-line-args-5.1.1.tgz#88e793e5bb3ceb30754a86863f0401ac92fd369a" integrity sha512-hL/eG8lrll1Qy1ezvkant+trihbGnaKaeEjj6Scyr3DN+RC7iQ5Rz84IeLERfAWDGo0HBSNAakczwgCilDXnWg== @@ -7647,7 +7647,7 @@ left-pad@^1.3.0: resolved "https://registry.yarnpkg.com/left-pad/-/left-pad-1.3.0.tgz#5b8a3a7765dfe001261dde915589e782f8c94d1e" integrity sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA== -lerna@^2.0.0: +lerna@^2.11.0: version "2.11.0" resolved "https://registry.yarnpkg.com/lerna/-/lerna-2.11.0.tgz#89b5681e286d388dda5bbbdbbf6b84c8094eff65" integrity sha512-kgM6zwe2P2tR30MYvgiLLW+9buFCm6E7o8HnRlhTgm70WVBvXVhydqv+q/MF2HrVZkCawfVtCfetyQmtd4oHhQ==