diff --git a/.eslintrc b/.eslintrc index f2463e9b6..c445390a4 100644 --- a/.eslintrc +++ b/.eslintrc @@ -83,6 +83,10 @@ "space-infix-ops": 1, "valid-typeof": 2, "vars-on-top": 0, - "wrap-iife": [2, "inside"] + "wrap-iife": [2, "inside"], + "prefer-const": ["error", { + "destructuring": "any", + "ignoreReadBeforeAssign": false + }] } } diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 3e44b6493..aee9a60ce 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -1,29 +1,61 @@ -# Contributing to Pattern Lab Node +Contributing to Pattern Lab Node +================================ + If you'd like to contribute to Pattern Lab Node, please do so! There is always a lot of ground to cover and something for your wheelhouse. No pull request is too small. Check out any [up for grabs issues](https://github.com/pattern-lab/patternlab-node/labels/up%20for%20grabs) as a good way to get your feet wet, or add some more unit tests. -## Developing Locally +Developing Locally +------------------ The best way to make changes to the Pattern Lab Node core and test them is through your existing edition. -* Fork this repository on Github. -* Create a new branch in your fork and push your changes in that fork. -* `npm install` -* `npm link` -* `cd /path/to/your/edition` -* `npm link patternlab-node` +- Fork this repository on Github. +- Create a new branch in your fork and push your changes in that fork. +- `npm install` +- `npm link` +- `cd /path/to/your/edition` +- `npm link patternlab-node` + +Guidelines +---------- + +- *ALWAYS* submit pull requests against the [dev branch](https://github.com/pattern-lab/patternlab-node/tree/dev). If this does not occur, I will first, try to redirect you gently, second, attempt to redirect the target branch myself, thirdly, port over your contribution manually if time allows, and/or lastly, close your pull request. If you have a major feature to stabilize over time, talk to @bmuenzenmeyer via an issue about making a dedicated `feature-branch` +- Keep your pull requests concise and limited to **ONE** substantive change at a time. This makes reviewing and testing so much easier. +- Commits should reference the issue you are adressing. For any Pull Request that you send, use the template provided. +- Commits are best formatted using the [conventional commits pattern](https://conventionalcommits.org/). +- If you can, add some unit tests using the existing patterns in the `./test` directory +- Large enhancements should begin with opening an issue. This will result in a more systematic way for us to review your contribution and determine if a [specifcation discussion](https://github.com/pattern-lab/the-spec/issues) needs to occur. +- Mention the issue number in commits, so anyone can see to which issue your changes belong to. For instance: + - `#123 Fix resolving patterns in pattern_hunter` + - `Feature #42: improve improbability drive` + +Coding style +------------ -## Guidelines +Two files combine within the project to define and maintain our coding style. -* _ALWAYS_ submit pull requests against the [dev branch](https://github.com/pattern-lab/patternlab-node/tree/dev). If this does not occur, I will first, try to redirect you gently, second, port over your contribution manually if time allows, and/or third, close your pull request. If you have a major feature to stabilize over time, talk to @bmuenzenmeyer via an issue about making a dedicated `feature-branch` -* Please keep your pull requests concise and limited to **ONE** substantive change at a time. This makes reviewing and testing so much easier. -* Commits should reference the issue you are adressing. For any Pull Request that you send, use the template provided. -* If you can, add some unit tests using the existing patterns in the `./test` directory -* Large enhancements should begin with opening an issue. This will result in a more systematic way for us to review your contribution and determine if a [specifcation discussion](https://github.com/pattern-lab/the-spec/issues) needs to occur. +- The `.editorconfig` controls spaces / tabs within supported editors. Check out their [site](http://editorconfig.org/). +- The `.eslintrc` defines our javascript standards. Some editors will evaluate this real-time - otherwise it's run using `grunt|gulp build` -## Coding style -Two files combine within the project to define and maintain our coding style. +Tests +----- + +Add unit and integration tests if you can. It's always nice if our code coverage improves bit by bit (literally!). We are using [Node Tap](http://www.node-tap.org/) as test framework and [Rewire](https://github.com/jhnns/rewire) for mocking things like file system access. + +Branching Scheme +---------------- + +![branching scheme](branching-scheme.png) Currently Pattern Lab has the following branches: + +- **master** contains the latext stable, released version +- **dev**: for development. *Target pull requests against this branch.* +- **feature-branches** for larger changes. Allows merging all changes into both `dev` easily. +- **long running branches** for changes that involve major changes to the code, architecture and take a lot of time (i.e. making Pattern Lab async) + +New features are typically cut off of `dev` branch. When `dev` is stable cut releases by merging `dev` to `master` and creating a release tag. + +Gitter.im Chat +============== -* The `.editorconfig` controls spaces / tabs within supported editors. Check out their [site](http://editorconfig.org/). -* The `.eslintrc` defines our javascript standards. Some editors will evaluate this real-time - otherwise it's run using `grunt|gulp build` +If you have any questions or you would like to help, feel free to ask on [our Gitter.im channel](https://gitter.im/pattern-lab/node) :smiley: diff --git a/.github/branching-scheme.png b/.github/branching-scheme.png new file mode 100644 index 000000000..9d7b7628a Binary files /dev/null and b/.github/branching-scheme.png differ diff --git a/.github/gitgraph/README.md b/.github/gitgraph/README.md new file mode 100644 index 000000000..02cc14ca4 --- /dev/null +++ b/.github/gitgraph/README.md @@ -0,0 +1,8 @@ +Generating a new graph +====================== + +This folder uses http://gitgraphjs.com/ for generating the git graph model. + +1. Change `patternlab-flow.js` to your needs according to the documentation on http://gitgraphjs.com/ +2. Open branching-scheme.html in browse, right click the graph and "Save as...". +3. Overwrite `/.github/branching-scheme.png` diff --git a/.github/gitgraph/branching-scheme.html b/.github/gitgraph/branching-scheme.html new file mode 100644 index 000000000..32d2ffb80 --- /dev/null +++ b/.github/gitgraph/branching-scheme.html @@ -0,0 +1,17 @@ + + + + + + + + + + + + diff --git a/.github/gitgraph/patternlab-flow.js b/.github/gitgraph/patternlab-flow.js new file mode 100644 index 000000000..79872b09a --- /dev/null +++ b/.github/gitgraph/patternlab-flow.js @@ -0,0 +1,212 @@ +var graphConfig = new GitGraph.Template({ + colors: [ "#9993FF", "#47E8D4", "#6BDB52", "#F85BB5", "#FFA657", "#FFCCAA", "#F85BB5" ], + branch: { + lineWidth: 3, + spacingX: 60, + mergeStyle: "straight", + showLabel: true, // display branch names on graph + labelFont: "normal 10pt Arial", + labelRotation: 0, + color: "black" + }, + commit: { + spacingY: -30, + dot: { + size: 8, + strokeColor: "#000000", + strokeWidth: 4 + }, + tag: { + font: "normal 10pt Arial", + color: "yellow" + }, + message: { + color: "black", + font: "normal 12pt Arial", + displayAuthor: false, + displayBranch: false, + displayHash: false, + } + }, + arrow: { + size: 8, + offset: 3, + + } +}); + +var config = { + template: graphConfig, + mode: "extended", + orientation: "horizontal" +}; + +var bugFixCommit = { + messageAuthorDisplay: false, + messageBranchDisplay: false, + messageHashDisplay: false, + message: "Bug fix commit(s)" +}; + +var stabilizationCommit = { + messageAuthorDisplay: false, + messageBranchDisplay: false, + messageHashDisplay: false, + message: "Release stabilization commit(s)" +}; + +// You can manually fix columns to control the display. +var i = 0; +var longRunningCol = i++; +var featureV3Col = i++; +var developV3Col = i++; +var featureCol = i++; +var developCol = i++; +var releaseCol = i++; +var masterCol = i++; + +var gitgraph = new GitGraph(config); + +var master = gitgraph.branch({ + name: "master", + column: masterCol +}); +master.commit("Initial commit"); + +var develop = gitgraph.branch({ + parentBranch: master, + name: "dev", + column: developCol +}); + +var developV3 = gitgraph.branch({ + parentBranch: master, + name: "dev-3.0", + column: developV3Col +}); + + +var longRunning = gitgraph.branch({ + parentBranch: master, + name: "long-running-improvement", + column: longRunningCol +}); + +develop.commit({ + messageDisplay: false +}); +developV3.commit({ + messageDisplay: false +}); + +longRunning.commit({ + messageDisplay: false +}); +longRunning.merge(developV3); + +var feature1 = gitgraph.branch({ + parentBranch: develop, + name: "feature/1-description", + column: featureCol +}); +feature1.commit("#1 A feature to go into v2.8.0").commit({ + messageDisplay: false +}); +develop.merge(feature1); +feature1.commit("Small Bugfix").commit({ + messageDisplay: false +}); +feature1.merge(develop); + + +var feature3X = gitgraph.branch({ + parentBranch: developV3, + name: "feature/42-feature-for-3-x-only", + column: featureV3Col +}); +feature3X.commit("#42 A feature to go into v3.X").commit({ + messageDisplay: false +}); +feature3X.merge(developV3); + + +var feature2 = gitgraph.branch({ + parentBranch: develop, + name: "feature/2-description", + column: featureCol +}); +feature2.commit("#2 Another feature to go into v2.8.0").commit({ + messageDisplay: false +}); +feature2.merge(develop); +feature2.merge(developV3); + +develop.merge(master,{ + dotStrokeWidth: 10, + message: "Release v2.8.1 tagged", + tag: "v2.8.1" +}); + + +develop.commit({ + messageDisplay: false +}); + + +longRunning.commit({ + messageDisplay: false +}); + +developV3.merge(longRunning); + +longRunning.commit({ + messageDisplay: false +}); + +var feature3 = gitgraph.branch({ + parentBranch: develop, + name: "bugfix/3-description", + column: featureCol +}); + +feature3.commit("A feature to go into v2.8.0").commit({ + messageDisplay: false +}); +feature3.merge(develop); + +longRunning.merge(developV3); + +developV3.commit({ + messageDisplay: false, + dotStrokeWidth: 10 +}); + + +develop.commit({ + messageDisplay: false +}); + +develop.commit({ + messageDisplay: false +}); + +develop.merge(master, { + dotStrokeWidth: 10, + message: "Release v2.9.0 tagged", + tag: "v2.9.0" +}); + +develop.commit({ + messageDisplay: false, + dotStrokeWidth: 10 +}); + +developV3.checkout(); + +/* +developV3.merge(master, { + dotStrokeWidth: 10, + message: "Release v3.0.0 tagged", + tag: "v3.0.0" +}); +*/ diff --git a/.gitignore b/.gitignore index d1ddc139e..4e141e644 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ public !test/patterns/public/.gitkeep !test/patterns/testDependencyGraph.json .nyc_output/ +.vscode/ diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 000000000..7fcfe2dcd --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +6.11.3 diff --git a/.travis.yml b/.travis.yml index 6d447035b..70c7614d6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,12 +3,12 @@ language: node_js node_js: - node - 6 - - 4 before_install: - phantomjs --version before_script: + - npm install patternengine-node-mustache - npm install patternengine-node-underscore - npm install patternengine-node-handlebars - npm install patternengine-node-twig @@ -17,6 +17,7 @@ branches: only: - master - dev + - dev-3.0 notifications: webhooks: diff --git a/README.md b/README.md index 9eb9eed3b..7a215c591 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![Pattern Lab Logo](/patternlab.png "Pattern Lab Logo") -[![Build Status](https://travis-ci.org/pattern-lab/patternlab-node.svg?branch=master)](https://travis-ci.org/pattern-lab/patternlab-node) ![current release](https://img.shields.io/github/release/pattern-lab/patternlab-node.svg) ![license](https://img.shields.io/github/license/pattern-lab/patternlab-node.svg) [![Join the chat at Gitter](https://badges.gitter.im/pattern-lab/node.svg)](https://gitter.im/pattern-lab/node) +[![Build Status](https://travis-ci.org/pattern-lab/patternlab-node.svg?branch=master)](https://travis-ci.org/pattern-lab/patternlab-node) ![current release](https://img.shields.io/github/release/pattern-lab/patternlab-node.svg) ![license](https://img.shields.io/github/license/pattern-lab/patternlab-node.svg) [![Coverage Status](https://coveralls.io/repos/github/pattern-lab/patternlab-node/badge.svg?branch=master)](https://coveralls.io/github/pattern-lab/patternlab-node?branch=master) [![Join the chat at Gitter](https://badges.gitter.im/pattern-lab/node.svg)](https://gitter.im/pattern-lab/node) # Pattern Lab Node Core @@ -21,28 +21,83 @@ Pattern Lab Node wouldn't be what it is today without the support of the communi ## Installation -Pattern Lab Node Core is designed to be consumed, and by default is included as a dependency within two example [Node Editions](https://github.com/pattern-lab?utf8=%E2%9C%93&query=edition-node). +Pattern Lab Node can be used different ways. Editions are **example** pairings of Pattern Lab code and do not always have an upgrade path or simple means to run as a dependency within a larger project. Users wishing to be most current and have the greatest flexibility are encouraged to consume `patternlab-node` directly. Users wanting to learn more about Pattern Lab and have a tailored default experience are encouraged to start with an Edition. Both methods still expect to interact with other elements of the [Pattern Lab Ecosystem](#ecosystem). +### Direct Consumption + +As of Pattern Lab Node 3.X, `patternlab-node` can run standalone, without the need for task runners like gulp or grunt. + +`npm install patternlab-node` + +See [Usage](#Usage) for more information. + +### Editions + +For users wanting a more pre-packaged experience several editions are available. * [Pattern Lab/Node: Gulp Edition](https://github.com/pattern-lab/edition-node-gulp) contains info how to get started within a Gulp task running environment. * [Pattern Lab/Node: Grunt Edition](https://github.com/pattern-lab/edition-node-grunt) contains info how to get started within a Grunt task running environment. +* [Pattern Lab/Node: Vanilla Edition](https://github.com/pattern-lab/edition-node) contains info how to get started within a pure node environment. +* [Pattern Lab/Node: Webpack Edition](https://github.com/Comcast/patternlab-edition-node-webpack) contains info how to get started within a webpack environment. + >Thanks to the team at Comcast for open-sourcing this stellar work! + +## Ecosystem ![Pattern Lab Ecosystem](http://patternlab.io/assets/pattern-lab-2-image_18-large-opt.png) -Core, and Editions, are part of the [Pattern Lab Ecosystem](http://patternlab.io/docs/advanced-ecosystem-overview.html). With this architecture, we encourage people to write and maintain their own editions. +Core, and Editions, are part of the [Pattern Lab Ecosystem](http://patternlab.io/docs/advanced-ecosystem-overview.html). With this architecture, we encourage people to write and maintain their own Editions, Starterkits, and even PatternEngines. ## Usage +`patternlab-node` can be required within any Node environment, taking in a configuration file at instantiation. + ``` javascript + const config = require('./patternlab-config.json'); const patternlab = require('patternlab-node')(config); -patternlab.build(doneCallBack, boolCleanOutputDir); + + +// build, optionally watching or choosing incremental builds +patternlab.build({ + cleanPublic: true, + watch: true +}); + +// or build, watch, and then self-host +patternlab.serve({ + cleanPublic: true +}); + ``` -* Read more about configuration via `patternlab-config.json`: https://github.com/pattern-lab/patternlab-node/wiki/Configuration -* The rest of the [api / command line interface](https://github.com/pattern-lab/patternlab-node/wiki/Command-Line-Interface) is documented in the wiki, and already implemented for you within [Node Editions](https://github.com/pattern-lab?utf8=%E2%9C%93&query=edition-node). -A [full-featured command line interface](https://github.com/pattern-lab/patternlab-node-cli) is in the works, courtesy of [@raphaelokon](https://github.com/raphaelokon). +* Read more about [configuration](https://github.com/pattern-lab/patternlab-node/wiki/Configuration) via `patternlab-config.json`. +* Read more about the rest of [api](https://github.com/pattern-lab/patternlab-node/wiki/Public-API), and already implemented for you within [Editions](#editions). + +* A full-featured [command line interface](https://github.com/pattern-lab/patternlab-node-cli) is also available courtesy of [@raphaelokon](https://github.com/raphaelokon). + + +### Events + +Many [events](https://github.com/pattern-lab/patternlab-node/wiki/Creating-Plugins#events) are emitted during Pattern Lab operations, originally built to support plugins. Below is a sample, allowing users to be informed of asset or pattern changes. + +``` javascript + +patternlab.serve(...); + +patternlab.events.on('patternlab-asset-change', (data) => { + console.log(data); // {file: 'path/to/file.css', dest: 'path/to/destination'} +}); + +patternlab.events.on('patternlab-pattern-change', (data) => { + console.log(data); // {file: 'path/to/file.ext'} +}); + +patternlab.events.on('patternlab-global-change', (data) => { + console.log(data); // {file: 'path/to/file.ext'} +}); + +``` ## Development Installation / Workflow @@ -54,7 +109,7 @@ cd /patternlab-node git clone https://github.com/pattern-lab/patternlab-node.git npm install npm link -cd location/of/edition +cd location/of/editionOrSourceAndConfig npm link patternlab-node ``` @@ -63,7 +118,7 @@ The above is a bit verbose, but illustrates: 1. how to clone this repository to an arbitrary location 2. install all dependencies (run `npm install --dev` if your NODE_ENV is production for some reason) 3. setup the `npm link` to your local copy -4. use the local copy of patternlab-node in your edition +4. use the local copy of patternlab-node in your edition / working directory > Make sure to change to whichever branch you intend to hack on or test within your cloned repository, such as `dev` or `bugfix/fixes-broken-unittest` diff --git a/core/lib/annotation_exporter.js b/core/lib/annotation_exporter.js index bd9cb72e8..4f4cb426a 100644 --- a/core/lib/annotation_exporter.js +++ b/core/lib/annotation_exporter.js @@ -1,14 +1,14 @@ -"use strict"; +'use strict'; +const path = require('path'); +const glob = require('glob'); +const fs = require('fs-extra'); +const _ = require('lodash'); +const mp = require('./markdown_parser'); -var path = require('path'), - glob = require('glob'), - fs = require('fs-extra'), - _ = require('lodash'), - mp = require('./markdown_parser'); +const annotations_exporter = function (pl) { -var annotations_exporter = function (pl) { - - var paths = pl.config.paths; + const paths = pl.config.paths; + let oldAnnotations; /* Returns the array of comments that used to be wrapped in raw JS. @@ -16,7 +16,7 @@ var annotations_exporter = function (pl) { function parseAnnotationsJS() { //attempt to read the file try { - var oldAnnotations = fs.readFileSync(path.resolve(paths.source.annotations, 'annotations.js'), 'utf8'); + oldAnnotations = fs.readFileSync(path.resolve(paths.source.annotations, 'annotations.js'), 'utf8'); } catch (ex) { if (pl.config.debug) { console.log('annotations.js file missing from ' + paths.source.annotations + '. This may be expected.'); @@ -39,8 +39,8 @@ var annotations_exporter = function (pl) { } function buildAnnotationMD(annotationsYAML, markdown_parser) { - var annotation = {}; - var markdownObj = markdown_parser.parse(annotationsYAML); + const annotation = {}; + const markdownObj = markdown_parser.parse(annotationsYAML); annotation.el = markdownObj.el || markdownObj.selector; annotation.title = markdownObj.title; @@ -49,16 +49,16 @@ var annotations_exporter = function (pl) { } function parseMDFile(annotations, parser) { - var annotations = annotations; - var markdown_parser = parser; + //let annotations = annotations; + const markdown_parser = parser; return function (filePath) { - var annotationsMD = fs.readFileSync(path.resolve(filePath), 'utf8'); + const annotationsMD = fs.readFileSync(path.resolve(filePath), 'utf8'); //take the annotation snippets and split them on our custom delimiter - var annotationsYAML = annotationsMD.split('~*~'); - for (var i = 0; i < annotationsYAML.length; i++) { - var annotation = buildAnnotationMD(annotationsYAML[i], markdown_parser); + const annotationsYAML = annotationsMD.split('~*~'); + for (let i = 0; i < annotationsYAML.length; i++) { + const annotation = buildAnnotationMD(annotationsYAML[i], markdown_parser); annotations.push(annotation); } return false; @@ -69,17 +69,17 @@ var annotations_exporter = function (pl) { Converts the *.md file yaml list into an array of annotations */ function parseAnnotationsMD() { - var markdown_parser = new mp(); - var annotations = []; - var mdFiles = glob.sync(paths.source.annotations + '/*.md'); + const markdown_parser = new mp(); + const annotations = []; + const mdFiles = glob.sync(paths.source.annotations + '/*.md'); mdFiles.forEach(parseMDFile(annotations, markdown_parser)); return annotations; } function gatherAnnotations() { - var annotationsJS = parseAnnotationsJS(); - var annotationsMD = parseAnnotationsMD(); + const annotationsJS = parseAnnotationsJS(); + const annotationsMD = parseAnnotationsMD(); return _.unionBy(annotationsJS, annotationsMD, 'el'); } diff --git a/core/lib/asset_copy.js b/core/lib/asset_copy.js new file mode 100644 index 000000000..9ac0d7a3c --- /dev/null +++ b/core/lib/asset_copy.js @@ -0,0 +1,228 @@ +"use strict"; +const _ = require('lodash'); +const path = require('path'); +const process = require('process'); + +let copy = require('recursive-copy'); // eslint-disable-line prefer-const +let chokidar = require('chokidar'); // eslint-disable-line prefer-const + +const asset_copier = () => { + + const transform_paths = (directories) => { + //create array with all source keys minus our blacklist + const dirs = {}; + const blackList = ['root', 'patterns', 'data', 'meta', 'annotations', 'patternlabFiles']; + _.each(directories.source, (dir, key) => { + + if (blackList.includes(key)) { + return; + } + + if (!dirs.key) { + dirs[key] = {}; + } + }); + + // loop through all source keys + _.each(dirs, (dir, key) => { + // add source key path + dirs[key].source = directories.source[key]; + + // add public key path + dirs[key].public = directories.public[key]; + }); + return dirs; + }; + + const copyFile = (p, dest, options) => { + copy( + p, + dest, + options + ).on(copy.events.COPY_FILE_COMPLETE, () => { + if (options.debug) { + console.log(`Moved ${p} to ${dest}`); + } + options.emitter.emit('patternlab-asset-change', { + file: p, + dest: dest + }); + }); + }; + + const asset_copy = (assetDirectories, patternlab, options) => { + + //take our configured paths and sanitize best we can to only the assets + const dirs = transform_paths(assetDirectories); + + //find out where we are + const basePath = path.resolve(process.cwd()); + + const copyOptions = + { + overwrite: true, + emitter: patternlab.events, + debug: patternlab.config.debug + }; + + //loop through each directory asset object (source / public pairing) + _.each(dirs, (dir, key) => { + + //if we want to watch files, do so, otherwise just copy each file + if (options.watch) { + if (patternlab.config.debug) { + console.log(`Pattern Lab is watching ${path.resolve(basePath, dir.source)} for changes`); + } + + if (patternlab.watchers[key]) { + patternlab.watchers[key].close(); + } + + const assetWatcher = chokidar.watch( + path.resolve(basePath, dir.source), + { + ignored: /(^|[\/\\])\../, + ignoreInitial: false, + awaitWriteFinish : { + stabilityThreshold: 200, + pollInterval: 100 + } + } + ); + + //watch for changes and copy + assetWatcher.on('addDir', (p) => { + const destination = path.resolve(basePath, dir.public + '/' + path.basename(p)); + copyFile(p, destination, copyOptions); + }).on('add', (p) => { + const destination = path.resolve(basePath, dir.public + '/' + path.basename(p)); + copyFile(p, destination, copyOptions); + }).on('change', (p) => { + const destination = path.resolve(basePath, dir.public + '/' + path.basename(p)); + copyFile(p, destination, copyOptions); + }); + + patternlab.watchers[key] = assetWatcher; + + } else { + //just copy + const destination = path.resolve(basePath, dir.public); + copyFile(dir.source, destination, copyOptions); + } + }); + + // copy the styleguide + copyFile(assetDirectories.source.styleguide, assetDirectories.public.root, copyOptions); + + // copy the favicon + copyFile(`${assetDirectories.source.root}/favicon.ico`, `${assetDirectories.public.root}/favicon.ico`, copyOptions); + + //we need to special case patterns/**/*.md|.json|.pattern-extensions as well as the global structures + if (options.watch) { + + // watch global structures, such as _data/* and _meta/ + const globalSources = [assetDirectories.source.data, assetDirectories.source.meta]; + const globalPaths = globalSources.map(globalSource => path.join( + basePath, + globalSource, + '*' + )); + + _.each(globalPaths, (globalPath) => { + + if (patternlab.config.debug) { + console.log(`Pattern Lab is watching ${globalPath} for changes`); + } + + if (patternlab.watchers[globalPath]) { + patternlab.watchers[globalPath].close(); + } + + const globalWatcher = chokidar.watch( + path.resolve(globalPath), + { + ignored: /(^|[\/\\])\../, + ignoreInitial: true, + awaitWriteFinish : { + stabilityThreshold: 200, + pollInterval: 100 + } + } + ); + + //watch for changes and rebuild + globalWatcher.on('addDir', (p) => { + patternlab.events.emit('patternlab-global-change', { + file: p + }); + }) + .on('add', (p) => { + patternlab.events.emit('patternlab-global-change', { + file: p + }); + }).on('change', (p) => { + patternlab.events.emit('patternlab-global-change', { + file: p + }); + }); + + patternlab.watchers[globalPath] = globalWatcher; + + }); + + // watch patterns + const baseFileExtensions = ['.json', '.yml', '.yaml', '.md']; + const patternWatches = baseFileExtensions.concat(patternlab.engines.getSupportedFileExtensions()).map( + dotExtension => path.join( + basePath, + assetDirectories.source.patterns, + `/**/*${dotExtension}` + ) + ); + _.each(patternWatches, (patternWatchPath) => { + if (patternlab.config.debug) { + console.log(`Pattern Lab is watching ${patternWatchPath} for changes`); + } + + const patternWatcher = chokidar.watch( + path.resolve(patternWatchPath), + { + ignored: /(^|[\/\\])\../, + ignoreInitial: true, + awaitWriteFinish : { + stabilityThreshold: 200, + pollInterval: 100 + } + } + ); + + //watch for changes and rebuild + patternWatcher.on('addDir', (p) => { + patternlab.events.emit('patternlab-pattern-change', { + file: p + }); + }).on('add', (p) => { + patternlab.events.emit('patternlab-pattern-change', { + file: p + }); + }).on('change', (p) => { + patternlab.events.emit('patternlab-pattern-change', { + file: p + }); + }); + }); + } + }; + + return { + copyAssets: (assetDirectories, patternlab, options) => { + asset_copy(assetDirectories, patternlab, options); + }, + transformConfigPaths: (paths) => { + return transform_paths(paths); + } + }; + +}; + +module.exports = asset_copier; diff --git a/core/lib/changes_hunter.js b/core/lib/changes_hunter.js index 3b98f9a9c..f92666abd 100644 --- a/core/lib/changes_hunter.js +++ b/core/lib/changes_hunter.js @@ -1,12 +1,12 @@ -"use strict"; -const fs = require("fs-extra"), - CompileState = require('./object_factory').CompileState; +'use strict'; +const fs = require("fs-extra"); +const CompileState = require('./object_factory').CompileState; /** * For detecting changed patterns. * @constructor */ -let ChangesHunter = function () { +const ChangesHunter = function () { }; ChangesHunter.prototype = { @@ -24,11 +24,11 @@ ChangesHunter.prototype = { checkBuildState: function (pattern, patternlab) { //write the compiled template to the public patterns directory - let renderedTemplatePath = + const renderedTemplatePath = patternlab.config.paths.public.patterns + pattern.getPatternLink(patternlab, 'rendered'); //write the compiled template to the public patterns directory - let markupOnlyPath = + const markupOnlyPath = patternlab.config.paths.public.patterns + pattern.getPatternLink(patternlab, 'markupOnly'); if (!pattern.compileState) { @@ -45,7 +45,7 @@ ChangesHunter.prototype = { // Prevent error message if file does not exist fs.accessSync(renderedFile, fs.F_OK) ); - let outputLastModified = fs.statSync(renderedTemplatePath).mtime.getTime(); + const outputLastModified = fs.statSync(renderedTemplatePath).mtime.getTime(); if (pattern.lastModified && outputLastModified > pattern.lastModified) { pattern.compileState = CompileState.CLEAN; @@ -55,7 +55,7 @@ ChangesHunter.prototype = { pattern.compileState = CompileState.NEEDS_REBUILD; } - let node = patternlab.graph.node(pattern); + const node = patternlab.graph.node(pattern); // Make the pattern known to the PatternGraph and remember its compileState if (!node) { @@ -78,7 +78,7 @@ ChangesHunter.prototype = { checkLastModified: function (currentPattern, file) { if (file) { try { - let stat = fs.statSync(file); + const stat = fs.statSync(file); // Needs recompile whenever one of the patterns files (template, json, pseudopatterns) changed currentPattern.lastModified = diff --git a/core/lib/data_loader.js b/core/lib/data_loader.js index 84044eefd..2dbf185a2 100644 --- a/core/lib/data_loader.js +++ b/core/lib/data_loader.js @@ -39,7 +39,7 @@ function loadDataFromFolder(dataFilesPath, excludeFileNames, fsDep) { const dataFilesFullPath = dataFilesPath + '*.{json,yml,yaml}', excludeFullPath = dataFilesPath + excludeFileNames + '.{json,yml,yaml}'; - let globOptions = {}; + const globOptions = {}; if (excludeFileNames) { globOptions.ignore = [excludeFullPath]; } @@ -48,7 +48,7 @@ function loadDataFromFolder(dataFilesPath, excludeFileNames, fsDep) { let mergeObject = {}; dataFiles.forEach(function (filePath) { - let jsonData = yaml.safeLoad(fsDep.readFileSync(path.resolve(filePath), 'utf8')); + const jsonData = yaml.safeLoad(fsDep.readFileSync(path.resolve(filePath), 'utf8')); mergeObject = _.merge(mergeObject, jsonData); }); diff --git a/core/lib/lineage_hunter.js b/core/lib/lineage_hunter.js index d20db5771..7c61be98d 100644 --- a/core/lib/lineage_hunter.js +++ b/core/lib/lineage_hunter.js @@ -1,30 +1,30 @@ -"use strict"; +'use strict'; +const extend = require("util")._extend; -var extend = require("util")._extend; +const lineage_hunter = function () { -var lineage_hunter = function () { + function findlineage(pattern, patternlab) { - var pa = require('./pattern_assembler'); + const pa = require('./pattern_assembler'); + const pattern_assembler = new pa(); - function findlineage(pattern, patternlab) { // As we are adding edges from pattern to ancestor patterns, ensure it is known to the graph patternlab.graph.add(pattern); - var pattern_assembler = new pa(); //find the {{> template-name }} within patterns - var matches = pattern.findPartials(); + const matches = pattern.findPartials(); if (matches !== null) { matches.forEach(function (match) { //get the ancestorPattern - var ancestorPattern = pattern_assembler.getPartial(pattern.findPartial(match), patternlab); + const ancestorPattern = pattern_assembler.getPartial(pattern.findPartial(match), patternlab); if (ancestorPattern && pattern.lineageIndex.indexOf(ancestorPattern.patternPartial) === -1) { //add it since it didnt exist pattern.lineageIndex.push(ancestorPattern.patternPartial); //create the more complex patternLineage object too - var l = { + const l = { "lineagePattern": ancestorPattern.patternPartial, "lineagePath": "../../patterns/" + ancestorPattern.patternLink }; @@ -44,7 +44,7 @@ var lineage_hunter = function () { ancestorPattern.lineageRIndex.push(pattern.patternPartial); //create the more complex patternLineage object in reverse - var lr = { + const lr = { "lineagePattern": pattern.patternPartial, "lineagePath": "../../patterns/" + pattern.patternLink }; @@ -69,7 +69,7 @@ var lineage_hunter = function () { * @param graph {PatternGraph} */ function setPatternState(direction, pattern, targetPattern, graph) { - var index = null; + let index = null; if (direction === 'fromPast') { index = graph.lineage(pattern); } else { @@ -77,7 +77,7 @@ var lineage_hunter = function () { } // if the request came from the past, apply target pattern state to current pattern lineage - for (var i = 0; i < index.length; i++) { + for (let i = 0; i < index.length; i++) { if (index[i].patternPartial === targetPattern.patternPartial) { index[i].lineageState = targetPattern.patternState; } @@ -87,36 +87,36 @@ var lineage_hunter = function () { function cascadePatternStates(patternlab) { - for (var i = 0; i < patternlab.patterns.length; i++) { - var pattern = patternlab.patterns[i]; + for (let i = 0; i < patternlab.patterns.length; i++) { + const pattern = patternlab.patterns[i]; //for each pattern with a defined state if (pattern.patternState) { - var lineage = patternlab.graph.lineage(pattern); + const lineage = patternlab.graph.lineage(pattern); if (lineage && lineage.length > 0) { //find all lineage - patterns being consumed by this one - for (var h = 0; h < lineage.length; h++) { + for (let h = 0; h < lineage.length; h++) { // Not needed, the graph already knows the concrete pattern - // var lineagePattern = pattern_assembler.getPartial(lineageIndex[h], patternlab); + // let lineagePattern = pattern_assembler.getPartial(lineageIndex[h], patternlab); setPatternState('fromFuture', lineage[h], pattern, patternlab.graph); } } - var lineageR = patternlab.graph.lineageR(pattern); + const lineageR = patternlab.graph.lineageR(pattern); if (lineageR && lineageR.length > 0) { //find all reverse lineage - that is, patterns consuming this one - for (var j = 0; j < lineageR.length; j++) { + for (let j = 0; j < lineageR.length; j++) { - var lineageRPattern = lineageR[j]; + const lineageRPattern = lineageR[j]; //only set patternState if pattern.patternState "is less than" the lineageRPattern.patternstate //or if lineageRPattern.patternstate (the consuming pattern) does not have a state //this makes patternlab apply the lowest common ancestor denominator - let patternStateCascade = patternlab.config.patternStateCascade; - let patternStateIndex = patternStateCascade.indexOf(pattern.patternState); - let patternReverseStateIndex = patternStateCascade.indexOf(lineageRPattern.patternState); + const patternStateCascade = patternlab.config.patternStateCascade; + const patternStateIndex = patternStateCascade.indexOf(pattern.patternState); + const patternReverseStateIndex = patternStateCascade.indexOf(lineageRPattern.patternState); if (lineageRPattern.patternState === '' || (patternStateIndex < patternReverseStateIndex)) { if (patternlab.config.debug) { diff --git a/core/lib/list_item_hunter.js b/core/lib/list_item_hunter.js index d04b6d0a7..7ffe450de 100644 --- a/core/lib/list_item_hunter.js +++ b/core/lib/list_item_hunter.js @@ -1,21 +1,20 @@ "use strict"; -var list_item_hunter = function () { - - var extend = require('util')._extend, - pa = require('./pattern_assembler'), - smh = require('./style_modifier_hunter'), - plutils = require('./utilities'), - jsonCopy = require('./json_copy'), - Pattern = require('./object_factory').Pattern; - - var pattern_assembler = new pa(), - style_modifier_hunter = new smh(), - items = ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten', 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen', 'twenty']; +const list_item_hunter = function () { + const extend = require('util')._extend; + const _ = require('lodash'); + const pa = require('./pattern_assembler'); + const smh = require('./style_modifier_hunter'); + const jsonCopy = require('./json_copy'); + const Pattern = require('./object_factory').Pattern; + + const pattern_assembler = new pa(); + const style_modifier_hunter = new smh(); + const items = ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten', 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen', 'twenty']; function processListItemPartials(pattern, patternlab) { //find any listitem blocks - var matches = pattern.findListItems(); + const matches = pattern.findListItems(); if (matches !== null) { matches.forEach(function (liMatch) { @@ -25,14 +24,14 @@ var list_item_hunter = function () { } //find the boundaries of the block - var loopNumberString = liMatch.split('.')[1].split('}')[0].trim(); - var end = liMatch.replace('#', '/'); - var patternBlock = pattern.template.substring(pattern.template.indexOf(liMatch) + liMatch.length, pattern.template.indexOf(end)).trim(); + const loopNumberString = liMatch.split('.')[1].split('}')[0].trim(); + const end = liMatch.replace('#', '/'); + const patternBlock = pattern.template.substring(pattern.template.indexOf(liMatch) + liMatch.length, pattern.template.indexOf(end)).trim(); //build arrays that repeat the block, however large we need to - var repeatedBlockTemplate = []; - var repeatedBlockHtml = ''; - for (var i = 0; i < items.indexOf(loopNumberString); i++) { + const repeatedBlockTemplate = []; + let repeatedBlockHtml = ''; + for (let i = 0; i < items.indexOf(loopNumberString); i++) { if (patternlab.config.debug) { console.log('list item(s) in pattern', pattern.patternPartial, 'adding', patternBlock, 'to repeatedBlockTemplate'); } @@ -40,7 +39,7 @@ var list_item_hunter = function () { } //check for a local listitems.json file - var listData; + let listData; try { listData = jsonCopy(patternlab.listitems, 'config.paths.source.data listitems'); } catch (err) { @@ -48,19 +47,19 @@ var list_item_hunter = function () { console.log(err); } - listData = plutils.mergeData(listData, pattern.listitems); + listData = _.merge(listData, pattern.listitems); listData = pattern_assembler.parse_data_links_specific(patternlab, listData, 'listitems.json + any pattern listitems.json'); //iterate over each copied block, rendering its contents along with pattenlab.listitems[i] - for (var i = 0; i < repeatedBlockTemplate.length; i++) { + for (let i = 0; i < repeatedBlockTemplate.length; i++) { - var thisBlockTemplate = repeatedBlockTemplate[i]; - var thisBlockHTML = ""; + let thisBlockTemplate = repeatedBlockTemplate[i]; + let thisBlockHTML = ""; //combine listItem data with pattern data with global data - var itemData = listData['' + items.indexOf(loopNumberString)]; //this is a property like "2" - var globalData; - var localData; + const itemData = listData['' + items.indexOf(loopNumberString)]; //this is a property like "2" + let globalData; + let localData; try { globalData = jsonCopy(patternlab.data, 'config.paths.source.data global data'); localData = jsonCopy(pattern.jsonFileData, `${pattern.patternPartial} data`); @@ -69,23 +68,23 @@ var list_item_hunter = function () { console.log(err); } - var allData = plutils.mergeData(globalData, localData); - allData = plutils.mergeData(allData, itemData !== undefined ? itemData[i] : {}); //itemData could be undefined if the listblock contains no partial, just markup + let allData = _.merge(globalData, localData); + allData = _.merge(allData, itemData !== undefined ? itemData[i] : {}); //itemData could be undefined if the listblock contains no partial, just markup allData.link = extend({}, patternlab.data.link); //check for partials within the repeated block - var foundPartials = Pattern.createEmpty({'template': thisBlockTemplate}).findPartials(); + const foundPartials = Pattern.createEmpty({'template': thisBlockTemplate}).findPartials(); if (foundPartials && foundPartials.length > 0) { - for (var j = 0; j < foundPartials.length; j++) { + for (let j = 0; j < foundPartials.length; j++) { //get the partial - var partialName = foundPartials[j].match(/([\w\-\.\/~]+)/g)[0]; - var partialPattern = pattern_assembler.getPartial(partialName, patternlab); + const partialName = foundPartials[j].match(/([\w\-\.\/~]+)/g)[0]; + const partialPattern = pattern_assembler.getPartial(partialName, patternlab); //create a copy of the partial so as to not pollute it after the get_pattern_by_key call. - var cleanPartialPattern; + let cleanPartialPattern; try { cleanPartialPattern = JSON.parse(JSON.stringify(partialPattern)); cleanPartialPattern = jsonCopy(partialPattern, `partial pattern ${partialName}`); @@ -119,7 +118,7 @@ var list_item_hunter = function () { } //replace the block with our generated HTML - var repeatingBlock = pattern.extendedTemplate.substring(pattern.extendedTemplate.indexOf(liMatch), pattern.extendedTemplate.indexOf(end) + end.length); + const repeatingBlock = pattern.extendedTemplate.substring(pattern.extendedTemplate.indexOf(liMatch), pattern.extendedTemplate.indexOf(end) + end.length); pattern.extendedTemplate = pattern.extendedTemplate.replace(repeatingBlock, repeatedBlockHtml); //update the extendedTemplate in the partials object in case this pattern is consumed later diff --git a/core/lib/markdown_parser.js b/core/lib/markdown_parser.js index 495e0d181..68fcfa68d 100644 --- a/core/lib/markdown_parser.js +++ b/core/lib/markdown_parser.js @@ -1,9 +1,8 @@ -"use strict"; +'use strict'; +const md = require('markdown-it')(); +const yaml = require('js-yaml'); -var md = require('markdown-it')(); -var yaml = require('js-yaml'); - -var markdown_parser = function () { +const markdown_parser = function () { /** * Converts a markdown block with frontmatter (each is optional, technically) to a well-formed object. @@ -11,18 +10,18 @@ var markdown_parser = function () { * @returns an object with any frontmatter keys, plus a .markdown key */ function parseMarkdownBlock(block) { - var returnObject = {}; + let returnObject = {}; try { //for each block process the yaml frontmatter and markdown - var frontmatterRE = /---\r?\n{1}([\s\S]*)---\r?\n{1}([\s\S]*)+/gm; - var chunks = frontmatterRE.exec(block); + const frontmatterRE = /---\r?\n{1}([\s\S]*)---\r?\n{1}([\s\S]*)+/gm; + const chunks = frontmatterRE.exec(block); if (chunks) { //we got some frontmatter if (chunks && chunks[1]) { //parse the yaml if we got it - var frontmatter = chunks[1]; + const frontmatter = chunks[1]; returnObject = yaml.safeLoad(frontmatter); } diff --git a/core/lib/object_factory.js b/core/lib/object_factory.js index 488b6fa13..78479e0b3 100644 --- a/core/lib/object_factory.js +++ b/core/lib/object_factory.js @@ -1,20 +1,27 @@ -"use strict"; - -var patternEngines = require('./pattern_engines'); -var path = require('path'); -var extend = require('util')._extend; +'use strict'; +const patternEngines = require('./pattern_engines'); +const path = require('path'); +const extend = require('util')._extend; // patternPrefixMatcher is intended to match the leading maybe-underscore, // zero or more digits, and maybe-dash at the beginning of a pattern file name we can hack them // off and get at the good part. -var patternPrefixMatcher = /^_?(\d+-)?/; +const patternPrefixMatcher = /^_?(\d+-)?/; // Pattern properties - -var Pattern = function (relPath, data, patternlab) { - // We expect relPath to be the path of the pattern template, relative to the - // root of the pattern tree. Parse out the path parts and save the useful ones. - var pathObj = path.parse(path.normalize(relPath)); +/** + * Pattern constructor + * @constructor + */ +const Pattern = function (relPath, data, patternlab) { + /** + * We expect relPath to be the path of the pattern template, relative to the + * root of the pattern tree. Parse out the path parts and save the useful ones. + * @param {relPath} relative directory + * @param {data} The JSON used to render values in the pattern. + * @param {patternlab} rendered html files for the pattern + */ + const pathObj = path.parse(path.normalize(relPath)); this.relPath = path.normalize(relPath); // '00-atoms/00-global/00-colors.mustache' this.fileName = pathObj.name; // '00-colors' this.subdir = pathObj.dir; // '00-atoms/00-global' @@ -114,8 +121,8 @@ Pattern.prototype = { // Should look something like '00-atoms-00-global-00-colors/00-atoms-00-global-00-colors.html' getPatternLink: function (patternlab, suffixType, customfileExtension) { // if no suffixType is provided, we default to rendered - var suffixConfig = patternlab.config.outputFileSuffixes; - var suffix = suffixType ? suffixConfig[suffixType] : suffixConfig.rendered; + const suffixConfig = patternlab.config.outputFileSuffixes; + const suffix = suffixType ? suffixConfig[suffixType] : suffixConfig.rendered; if (suffixType === 'rawTemplate') { return this.name + path.sep + this.name + suffix + this.fileExtension; @@ -165,7 +172,7 @@ Pattern.createEmpty = function (customProps, patternlab) { } } - var pattern = new Pattern(relPath, null, patternlab); + const pattern = new Pattern(relPath, null, patternlab); return extend(pattern, customProps); }; @@ -173,11 +180,11 @@ Pattern.createEmpty = function (customProps, patternlab) { // parameters that replace the positional parameters that the Pattern // constructor takes. Pattern.create = function (relPath, data, customProps, patternlab) { - var newPattern = new Pattern(relPath || '', data || null, patternlab); + const newPattern = new Pattern(relPath || '', data || null, patternlab); return extend(newPattern, customProps); }; -var CompileState = { +const CompileState = { NEEDS_REBUILD: "needs rebuild", BUILDING: "building", CLEAN: "clean" diff --git a/core/lib/parameter_hunter.js b/core/lib/parameter_hunter.js index d9c94e597..f236f5e31 100644 --- a/core/lib/parameter_hunter.js +++ b/core/lib/parameter_hunter.js @@ -1,14 +1,13 @@ -"use strict"; +'use strict'; -var parameter_hunter = function () { - - var extend = require('util')._extend, - pa = require('./pattern_assembler'), - smh = require('./style_modifier_hunter'), - plutils = require('./utilities'), - style_modifier_hunter = new smh(), - jsonCopy = require('./json_copy'), - pattern_assembler = new pa(); +const parameter_hunter = function () { + const extend = require('util')._extend; + const _ = require('lodash'); + const jsonCopy = require('./json_copy'); + const pa = require('./pattern_assembler'); + const smh = require('./style_modifier_hunter'); + const style_modifier_hunter = new smh(); + const pattern_assembler = new pa(); /** * This function is really to accommodate the lax JSON-like syntax allowed by @@ -54,14 +53,14 @@ var parameter_hunter = function () { * @returns {string} paramStringWellFormed */ function paramToJson(pString, patternlab) { - var colonPos = -1; - var keys = []; - var paramString = pString; // to not reassign param - var paramStringWellFormed; - var quotePos = -1; - var regex; - var values = []; - var wrapper; + let colonPos = -1; + const keys = []; + let paramString = pString; // to not reassign param + let paramStringWellFormed; + let quotePos = -1; + let regex; + const values = []; + let wrapper; // attempt to parse the data in case it is already well formed JSON try { @@ -181,7 +180,7 @@ var parameter_hunter = function () { //build paramStringWellFormed string for JSON parsing paramStringWellFormed = '{'; - for (var i = 0; i < keys.length; i++) { + for (let i = 0; i < keys.length; i++) { //keys //replace single-quote wrappers with double-quotes @@ -251,8 +250,8 @@ var parameter_hunter = function () { //compile this partial immeadiately, essentially consuming it. pattern.parameteredPartials.forEach(function (pMatch) { //find the partial's name and retrieve it - var partialName = pMatch.match(/([\w\-\.\/~]+)/g)[0]; - var partialPattern = pattern_assembler.getPartial(partialName, patternlab); + const partialName = pMatch.match(/([\w\-\.\/~]+)/g)[0]; + const partialPattern = pattern_assembler.getPartial(partialName, patternlab); //if we retrieved a pattern we should make sure that its extendedTemplate is reset. looks to fix #190 partialPattern.extendedTemplate = partialPattern.template; @@ -262,14 +261,14 @@ var parameter_hunter = function () { } //strip out the additional data, convert string to JSON. - var leftParen = pMatch.indexOf('('); - var rightParen = pMatch.lastIndexOf(')'); - var paramString = '{' + pMatch.substring(leftParen + 1, rightParen) + '}'; - var paramStringWellFormed = paramToJson(paramString, patternlab); + const leftParen = pMatch.indexOf('('); + const rightParen = pMatch.lastIndexOf(')'); + const paramString = '{' + pMatch.substring(leftParen + 1, rightParen) + '}'; + const paramStringWellFormed = paramToJson(paramString, patternlab); - var paramData = {}; - var globalData = {}; - var localData = {}; + let paramData = {}; + let globalData = {}; + let localData = {}; try { paramData = JSON.parse(paramStringWellFormed); @@ -280,8 +279,12 @@ var parameter_hunter = function () { console.log(err); } - var allData = plutils.mergeData(globalData, localData); - allData = plutils.mergeData(allData, paramData); + // resolve any pattern links that might be present + paramData = pattern_assembler.parse_data_links_specific(patternlab, paramData, pattern.patternPartial); + + //combine all data: GLOBAL DATA => PATTERN.JSON DATA => PARAMETER DATA + let allData = _.merge(globalData, localData); + allData = _.merge(allData, paramData); //if the partial has pattern parameters itself, we need to handle those findparameters(partialPattern, patternlab); @@ -294,7 +297,7 @@ var parameter_hunter = function () { //extend pattern data links into link for pattern link shortcuts to work. we do this locally and globally allData.link = extend({}, patternlab.data.link); - var renderedPartial = pattern_assembler.renderPattern(partialPattern.extendedTemplate, allData, patternlab.partials); + const renderedPartial = pattern_assembler.renderPattern(partialPattern.extendedTemplate, allData, patternlab.partials); //remove the parameter from the partial and replace it with the rendered partial + paramData pattern.extendedTemplate = pattern.extendedTemplate.replace(pMatch, renderedPartial); diff --git a/core/lib/pattern_assembler.js b/core/lib/pattern_assembler.js index 1015a0d6d..701ef908d 100644 --- a/core/lib/pattern_assembler.js +++ b/core/lib/pattern_assembler.js @@ -1,26 +1,28 @@ "use strict"; -var path = require('path'), - _ = require('lodash'), - fs = require('fs-extra'), - Pattern = require('./object_factory').Pattern, - CompileState = require('./object_factory').CompileState, - pph = require('./pseudopattern_hunter'), - mp = require('./markdown_parser'), - plutils = require('./utilities'), - dataLoader = require('./data_loader')(), - patternEngines = require('./pattern_engines'), - lh = require('./lineage_hunter'), - lih = require('./list_item_hunter'), - smh = require('./style_modifier_hunter'), - ph = require('./parameter_hunter'), - jsonCopy = require('./json_copy'), - ch = require('./changes_hunter'); - +const path = require('path'); +const _ = require('lodash'); +const Pattern = require('./object_factory').Pattern; +const CompileState = require('./object_factory').CompileState; +const pph = require('./pseudopattern_hunter'); +const mp = require('./markdown_parser'); +const plutils = require('./utilities'); +const patternEngines = require('./pattern_engines'); +const lh = require('./lineage_hunter'); +const lih = require('./list_item_hunter'); +const smh = require('./style_modifier_hunter'); +const ph = require('./parameter_hunter'); +const ch = require('./changes_hunter'); +const jsonCopy = require('./json_copy'); +const da = require('./data_loader'); const markdown_parser = new mp(); const changes_hunter = new ch(); +const dataLoader = new da(); + +//this is mocked in unit tests +let fs = require('fs-extra'); //eslint-disable-line prefer-const -var pattern_assembler = function () { +const pattern_assembler = function () { // HELPER FUNCTIONS function getPartial(partialName, patternlab) { @@ -62,7 +64,7 @@ var pattern_assembler = function () { list.push(container.listitems[item]); } } - container.listItemArray = plutils.shuffle(list); + container.listItemArray = _.shuffle(list); for (var i = 1; i <= container.listItemArray.length; i++) { var tempItems = []; @@ -78,21 +80,7 @@ var pattern_assembler = function () { } } - /* - * Deprecated in favor of .md 'status' frontmatter inside a pattern. Still used for unit tests at this time. - * Will be removed in future versions - */ - function setState(pattern, patternlab, displayDeprecatedWarning) { - if (patternlab.config.patternStates && patternlab.config.patternStates[pattern.patternPartial]) { - - if (displayDeprecatedWarning) { - plutils.error("Deprecation Warning: Using patternlab-config.json patternStates object will be deprecated in favor of the state frontmatter key associated with individual pattern markdown files."); - console.log("This feature will still work in it's current form this release (but still be overridden by the new parsing method), and will be removed in the future."); - } - pattern.patternState = patternlab.config.patternStates[pattern.patternPartial]; - } - } function addPattern(pattern, patternlab) { @@ -128,9 +116,10 @@ var pattern_assembler = function () { } else { patternlab.partials[pattern.patternPartial] = pattern.patternDesc; } - patternlab.graph.add(pattern); - patternlab.patterns.push(pattern); + //patterns sorted by name so the patterntype and patternsubtype is adhered to for menu building + patternlab.patterns.splice(_.sortedIndexBy(patternlab.patterns, pattern, 'name'), 0, pattern); + patternlab.graph.add(pattern); } } @@ -162,7 +151,7 @@ var pattern_assembler = function () { var markdownFileContents = fs.readFileSync(markdownFileName, 'utf8'); var markdownObject = markdown_parser.parse(markdownFileContents); - if (!plutils.isObjectEmpty(markdownObject)) { + if (!_.isEmpty(markdownObject)) { //set keys and markdown itself currentPattern.patternDescExists = true; currentPattern.patternDesc = markdownObject.markdown; @@ -253,7 +242,9 @@ var pattern_assembler = function () { addPattern(pattern, patternlab); } - function processPatternIterative(relPath, patternlab) { + // loads a pattern from disk, creates a Pattern object from it and + // all its associated files, and records it in patternlab.patterns[] + function loadPatternIterative(relPath, patternlab) { var relativeDepth = (relPath.match(/\w(?=\\)|\w(?=\/)/g) || []).length; if (relativeDepth > 2) { @@ -294,10 +285,8 @@ var pattern_assembler = function () { console.log(err); } } - } - var pseudopattern_hunter = new pph(); //extract some information var filename = fileObject.base; @@ -320,13 +309,10 @@ var pattern_assembler = function () { return currentPattern; } - //see if this file has a state - setState(currentPattern, patternlab, true); - //look for a json file for this template try { var jsonFilename = path.resolve(patternsPath, currentPattern.subdir, currentPattern.fileName); - let configData = dataLoader.loadDataFromFile(jsonFilename, fs); + const configData = dataLoader.loadDataFromFile(jsonFilename, fs); if (configData) { currentPattern.jsonFileData = configData; @@ -343,7 +329,7 @@ var pattern_assembler = function () { //look for a listitems.json file for this template try { var listJsonFileName = path.resolve(patternsPath, currentPattern.subdir, currentPattern.fileName + ".listitems"); - let listItemsConfig = dataLoader.loadDataFromFile(listJsonFileName, fs); + const listItemsConfig = dataLoader.loadDataFromFile(listJsonFileName, fs); if (listItemsConfig) { currentPattern.listitems = listItemsConfig; @@ -381,12 +367,24 @@ var pattern_assembler = function () { //add currentPattern to patternlab.patterns array addPattern(currentPattern, patternlab); - //look for a pseudo pattern by checking if there is a file containing same name, with ~ in it, ending in .json - pseudopattern_hunter.find_pseudopatterns(currentPattern, patternlab); - return currentPattern; } + // This is now solely for analysis; loading of the pattern file is + // above, in loadPatternIterative() + function processPatternIterative(pattern, patternlab) { + //look for a pseudo pattern by checking if there is a file + //containing same name, with ~ in it, ending in .json + return pph.find_pseudopatterns(pattern, patternlab).then(() => { + //find any stylemodifiers that may be in the current pattern + pattern.stylePartials = pattern.findPartialsWithStyleModifiers(); + + //find any pattern parameters that may be in the current pattern + pattern.parameteredPartials = pattern.findPartialsWithPatternParameters(); + return pattern; + }).catch(plutils.reportError('There was an error in processPatternIterative():')); + } + function processPatternRecursive(file, patternlab) { //find current pattern in patternlab object using var file as a partial @@ -572,9 +570,6 @@ var pattern_assembler = function () { find_list_items: function (pattern) { return pattern.findListItems(); }, - setPatternState: function (pattern, patternlab, displayDeprecatedWarning) { - setState(pattern, patternlab, displayDeprecatedWarning); - }, addPattern: function (pattern, patternlab) { addPattern(pattern, patternlab); }, @@ -587,8 +582,11 @@ var pattern_assembler = function () { renderPattern: function (template, data, partials) { return renderPattern(template, data, partials); }, - process_pattern_iterative: function (file, patternlab) { - return processPatternIterative(file, patternlab); + load_pattern_iterative: function (file, patternlab) { + return loadPatternIterative(file, patternlab); + }, + process_pattern_iterative: function (pattern, patternlab) { + return processPatternIterative(pattern, patternlab); }, process_pattern_recursive: function (file, patternlab, additionalData) { processPatternRecursive(file, patternlab, additionalData); diff --git a/core/lib/pattern_engines.js b/core/lib/pattern_engines.js index c316cec9d..7582b4ea7 100644 --- a/core/lib/pattern_engines.js +++ b/core/lib/pattern_engines.js @@ -1,11 +1,10 @@ // special shoutout to Geoffrey Pursell for single-handedly making Pattern Lab Node Pattern Engines possible! 'use strict'; - -var path = require('path'); -var diveSync = require('diveSync'); +const path = require('path'); +const diveSync = require('diveSync'); const chalk = require('chalk'); -var engineMatcher = /^patternengine-node-(.*)$/; -var enginesDirectories = [ +const engineMatcher = /^patternengine-node-(.*)$/; +const enginesDirectories = [ { displayName: 'the core', path: path.resolve(__dirname, '..', '..', 'node_modules') @@ -15,31 +14,26 @@ var enginesDirectories = [ path: path.join(process.cwd(), 'node_modules') } ]; -var PatternEngines; // the main export object -var engineNameForExtension; // generated mapping of extension to engine name - - -// free "private" functions, for internal setup only // given a path: return the engine name if the path points to a valid engine // module directory, or false if it doesn't function isEngineModule(filePath) { - var baseName = path.basename(filePath); - var engineMatch = baseName.match(engineMatcher); + const baseName = path.basename(filePath); + const engineMatch = baseName.match(engineMatcher); if (engineMatch) { return engineMatch[1]; } return false; } function findEngineModulesInDirectory(dir) { - var foundEngines = []; + const foundEngines = []; diveSync(dir, { recursive: false, directories: true }, function (err, filePath) { if (err) { throw err; } - var foundEngineName = isEngineModule(filePath); + const foundEngineName = isEngineModule(filePath); if (foundEngineName) { foundEngines.push({ name: foundEngineName, @@ -51,57 +45,6 @@ function findEngineModulesInDirectory(dir) { return foundEngines; } -// Try to load engines! We scan for engines at each path specified above. This -// function is kind of a big deal. -function loadAllEngines(enginesObject) { - enginesDirectories.forEach(function (engineDirectory) { - var enginesInThisDir = findEngineModulesInDirectory(engineDirectory.path); - console.log(chalk.bold(`Loading engines from ${engineDirectory.displayName}...\n`)); - - // find all engine-named things in this directory and try to load them, - // unless it's already been loaded. - enginesInThisDir.forEach(function (engineDiscovery) { - var errorMessage; - var successMessage = chalk.green("good to go"); - - try { - // give it a try! load 'er up. But not if we already have, of course. - if (enginesObject[engineDiscovery.name]) { - throw new Error("already loaded, skipping."); - } - enginesObject[engineDiscovery.name] = require(engineDiscovery.modulePath); - } catch (err) { - errorMessage = err.message; - } finally { - // report on the status of the engine, one way or another! - console.log(` ${engineDiscovery.name}:`, errorMessage ? chalk.red(errorMessage) : successMessage); - } - }); - console.log(''); - }); - - // Complain if for some reason we haven't loaded any engines. - if (Object.keys(enginesObject).length === 0) { - throw new Error('No engines loaded! Something is seriously wrong.'); - } - console.log(chalk.bold('Done loading engines.\n')); -} - - -// produce a mapping between file extension and engine name for each of the -// loaded engines -function createFileExtensionToEngineNameMap(enginesObject) { - var mapping = {}; - - Object.keys(enginesObject).forEach(function (engineName) { - var extensionForEngine = enginesObject[engineName].engineFileExtension; - mapping[extensionForEngine] = engineName; - }); - - return mapping; -} - - // // PatternEngines: the main export of this module // @@ -117,13 +60,84 @@ function createFileExtensionToEngineNameMap(enginesObject) { // only the engine names so we can easily iterate over them; all the handy // methods and properites below should therefore be on its prototype. -PatternEngines = Object.create({ +const PatternEngines = Object.create({ + + loadAllEngines: function (patternLabConfig) { + var self = this; + + // Try to load engines! We scan for engines at each path specified above. This + // function is kind of a big deal. + enginesDirectories.forEach(function (engineDirectory) { + const enginesInThisDir = findEngineModulesInDirectory(engineDirectory.path); + if (patternLabConfig.debug) { + console.log(chalk.bold(`Loading engines from ${engineDirectory.displayName}...\n`)); + } + + // find all engine-named things in this directory and try to load them, + // unless it's already been loaded. + enginesInThisDir.forEach(function (engineDiscovery) { + let errorMessage; + const successMessage = "good to go"; + if (patternLabConfig.debug) { + chalk.green(successMessage); + } + + try { + // Give it a try! load 'er up. But not if we already have, + // of course. Also pass the pattern lab config object into + // the engine's closure scope so it can know things about + // things. + if (self[engineDiscovery.name]) { + throw new Error("already loaded, skipping."); + } + self[engineDiscovery.name] = require(engineDiscovery.modulePath); + if (typeof self[engineDiscovery.name].usePatternLabConfig === 'function') { + self[engineDiscovery.name].usePatternLabConfig(patternLabConfig); + } + if (typeof self[engineDiscovery.name].spawnMeta === 'function') { + self[engineDiscovery.name].spawnMeta(patternLabConfig); + } + } catch (err) { + errorMessage = err.message; + } finally { + // report on the status of the engine, one way or another! + if (patternLabConfig.debug) { + console.log(` ${engineDiscovery.name}:`, errorMessage ? chalk.red(errorMessage) : successMessage); + } + } + }); + console.log(''); + }); + + // Complain if for some reason we haven't loaded any engines. + if (Object.keys(self).length === 0) { + throw new Error('No engines loaded! Something is seriously wrong.'); + } + if (patternLabConfig.debug) { + console.log(chalk.bold('Done loading engines.\n')); + } + }, + getEngineNameForPattern: function (pattern) { // avoid circular dependency by putting this in here. TODO: is this slow? - var of = require('./object_factory'); - + const of = require('./object_factory'); if (pattern instanceof of.Pattern && typeof pattern.fileExtension === 'string' && pattern.fileExtension) { - return engineNameForExtension[pattern.fileExtension]; + //loop through known engines and find the one that supports the pattern's fileExtension + const engineNames = Object.keys(this); + for (let i = 0; i < engineNames.length; i++) { + const engine = this[engineNames[i]]; + + if (Array.isArray(engine.engineFileExtension)) { + if (engine.engineFileExtension.includes(pattern.fileExtension)) { + return engine.engineName; + } + } else { + //this likely means the users engines are out of date. todo: tell them to upgrade + if (engine.engineFileExtension === pattern.fileExtension) { + return engine.engineName; + } + } + } } // otherwise, assume it's a plain mustache template string and act @@ -135,27 +149,29 @@ PatternEngines = Object.create({ if (pattern.isPseudoPattern) { return this.getEngineForPattern(pattern.basePattern); } else { - var engineName = this.getEngineNameForPattern(pattern); + const engineName = this.getEngineNameForPattern(pattern); return this[engineName]; } }, + // combine all found engines into a single array of supported extensions getSupportedFileExtensions: function () { - var engineNames = Object.keys(PatternEngines); - return engineNames.map(function (engineName) { + const engineNames = Object.keys(PatternEngines); + const allEnginesExtensions = engineNames.map((engineName) => { return PatternEngines[engineName].engineFileExtension; }); + return [].concat.apply([], allEnginesExtensions); }, isFileExtensionSupported: function (fileExtension) { - var supportedExtensions = PatternEngines.getSupportedFileExtensions(); + const supportedExtensions = PatternEngines.getSupportedFileExtensions(); return (supportedExtensions.lastIndexOf(fileExtension) !== -1); }, // given a filename, return a boolean: whether or not the filename indicates // that the file is pseudopattern JSON isPseudoPatternJSON: function (filename) { - var extension = path.extname(filename); + const extension = path.extname(filename); return (extension === '.json' && filename.indexOf('~') > -1); }, @@ -165,24 +181,17 @@ PatternEngines = Object.create({ // pattern files! isPatternFile: function (filename) { // skip hidden patterns/files without a second thought - var extension = path.extname(filename); + const extension = path.extname(filename); if (filename.charAt(0) === '.' || (extension === '.json' && !PatternEngines.isPseudoPatternJSON(filename))) { return false; } // not a hidden pattern, let's dig deeper - var supportedPatternFileExtensions = PatternEngines.getSupportedFileExtensions(); + const supportedPatternFileExtensions = PatternEngines.getSupportedFileExtensions(); return (supportedPatternFileExtensions.lastIndexOf(extension) !== -1 || PatternEngines.isPseudoPatternJSON(filename)); } }); - -// load up the engines we found -loadAllEngines(PatternEngines); - -// mapping of file extensions to engine names, for lookup use -engineNameForExtension = createFileExtensionToEngineNameMap(PatternEngines); - module.exports = PatternEngines; diff --git a/core/lib/pattern_exporter.js b/core/lib/pattern_exporter.js index 1b899a6a2..3d8d161c1 100644 --- a/core/lib/pattern_exporter.js +++ b/core/lib/pattern_exporter.js @@ -1,8 +1,8 @@ "use strict"; -var fs = require('fs-extra'); +const fs = require('fs-extra'); -var pattern_exporter = function () { +const pattern_exporter = function () { /** * Exports all pattern's final HTML as defined in patternlab-config.json to desired location. @@ -13,11 +13,11 @@ var pattern_exporter = function () { */ function exportPatterns(patternlab) { //read the config export options - var exportPartials = patternlab.config.patternExportPatternPartials; + const exportPartials = patternlab.config.patternExportPatternPartials; //find the chosen patterns to export - for (var i = 0; i < exportPartials.length; i++) { - for (var j = 0; j < patternlab.patterns.length; j++) { + for (let i = 0; i < exportPartials.length; i++) { + for (let j = 0; j < patternlab.patterns.length; j++) { if (exportPartials[i] === patternlab.patterns[j].patternPartial) { //write matches to the desired location fs.outputFileSync(patternlab.config.patternExportDirectory + patternlab.patterns[j].patternPartial + '.html', patternlab.patterns[j].patternPartialCode); diff --git a/core/lib/pattern_graph.js b/core/lib/pattern_graph.js index 5c28d3af1..c509ca406 100644 --- a/core/lib/pattern_graph.js +++ b/core/lib/pattern_graph.js @@ -125,9 +125,9 @@ PatternGraph.prototype = { * @throws {Error} If the pattern is unknown */ link: function (patternFrom, patternTo) { - let nameFrom = nodeName(patternFrom); - let nameTo = nodeName(patternTo); - for (let name of [nameFrom, nameTo]) { + const nameFrom = nodeName(patternFrom); + const nameTo = nodeName(patternTo); + for (const name of [nameFrom, nameTo]) { if (!this.patterns.has(name)) { throw new Error("Pattern not known: " + name); } @@ -144,8 +144,8 @@ PatternGraph.prototype = { * @return {boolean} */ hasLink: function (patternFrom, patternTo) { - let nameFrom = nodeName(patternFrom); - let nameTo = nodeName(patternTo); + const nameFrom = nodeName(patternFrom); + const nameTo = nodeName(patternTo); return this.graph.hasEdge(nameFrom, nameTo); }, @@ -170,22 +170,22 @@ PatternGraph.prototype = { * Edges are added in reverse order for topological sorting(e.g. atom -> molecule -> organism, * where "->" means "included by"). */ - let compileGraph = new Graph({ + const compileGraph = new Graph({ directed: true }); - let nodes = this.graph.nodes(); - let changedNodes = nodes.filter(n => compileStateFilter(this.patterns, n)); + const nodes = this.graph.nodes(); + const changedNodes = nodes.filter(n => compileStateFilter(this.patterns, n)); this.nodes2patterns(changedNodes).forEach(pattern => { - let patternNode = nodeName(pattern); + const patternNode = nodeName(pattern); if (!compileGraph.hasNode(patternNode)) { compileGraph.setNode(patternNode); } this.applyReverse(pattern, (from, to) => { from.compileState = CompileState.NEEDS_REBUILD; - let fromName = nodeName(from); - let toName = nodeName(to); - for (let name of [fromName, toName]) { + const fromName = nodeName(from); + const toName = nodeName(to); + for (const name of [fromName, toName]) { if (!compileGraph.hasNode(name)) { compileGraph.setNode(name); } @@ -212,7 +212,7 @@ PatternGraph.prototype = { * between patterns and node metadata. */ applyReverse: function (pattern, fn) { - for (let p of this.lineageR(pattern)) { + for (const p of this.lineageR(pattern)) { fn(p, pattern); this.applyReverse(p, fn); } diff --git a/core/lib/pattern_graph_dot.js b/core/lib/pattern_graph_dot.js index 5d87c383e..1b89060b9 100644 --- a/core/lib/pattern_graph_dot.js +++ b/core/lib/pattern_graph_dot.js @@ -88,11 +88,11 @@ const PatternGraphDot = {}; PatternGraphDot.generate = function (patternGraph) { const g = patternGraph.graph; const patterns = patternGraph.patterns; - let buckets = new Map(); + const buckets = new Map(); const colors = ["darkgreen", "firebrick", "slateblue", "darkgoldenrod", "black"]; const colorMap = new Map(); let colIdx = 0; - for (let p of patterns.partials.values()) { + for (const p of patterns.partials.values()) { if (p.isPseudoPattern || !p.patternType) { continue; } @@ -117,7 +117,7 @@ PatternGraphDot.generate = function (patternGraph) { let subGraphLines = []; - for (let key of sortedKeys) { + for (const key of sortedKeys) { const subPatterns = buckets.get(key); subGraphLines = subGraphLines.concat(subGraph(key, subPatterns)); } @@ -125,9 +125,9 @@ PatternGraphDot.generate = function (patternGraph) { res.push("edge[style=solid];"); - foo: for (let edge of g.edges()) { - let fromTo = patternGraph.nodes2patterns([edge.v, edge.w]); - for (let pattern of fromTo) { + foo: for (const edge of g.edges()) { + const fromTo = patternGraph.nodes2patterns([edge.v, edge.w]); + for (const pattern of fromTo) { if (pattern.isPseudoPattern || !pattern.patternType) { continue foo; } diff --git a/core/lib/pattern_registry.js b/core/lib/pattern_registry.js index cbd46d82d..6463607ac 100644 --- a/core/lib/pattern_registry.js +++ b/core/lib/pattern_registry.js @@ -50,16 +50,16 @@ PatternRegistry.prototype = { */ // This previously has been a for loop over an array in pattern_ - let byPartialName = this.partials.get(partialName); + const byPartialName = this.partials.get(partialName); if (this.partials.has(partialName)) { return byPartialName; } - let patterns = this.allPatterns(); + const patterns = this.allPatterns(); //else look by verbose syntax - for (let thisPattern of patterns) { + for (const thisPattern of patterns) { switch (partialName) { case thisPattern.relPath: case thisPattern.verbosePartial: @@ -68,7 +68,7 @@ PatternRegistry.prototype = { } //return the fuzzy match if all else fails - for (let thisPattern of patterns) { + for (const thisPattern of patterns) { const partialParts = partialName.split('-'), partialType = partialParts[0], partialNameEnd = partialParts.slice(1).join('-'); diff --git a/core/lib/patternlab.js b/core/lib/patternlab.js index a4f5a8131..c76651bf4 100644 --- a/core/lib/patternlab.js +++ b/core/lib/patternlab.js @@ -1,5 +1,5 @@ /* - * patternlab-node - v2.12.0 - 2017 + * patternlab-node - v3.0.0-alpha.1 - 2017 * * Brian Muenzenmeyer, Geoff Pursell, Raphael Okon, tburny and the web community. * Licensed under the MIT license. @@ -10,24 +10,36 @@ "use strict"; -var diveSync = require('diveSync'), - _ = require('lodash'), - path = require('path'), - chalk = require('chalk'), - cleanHtml = require('js-beautify').html, - inherits = require('util').inherits, - pm = require('./plugin_manager'), - fs = require('fs-extra'), - packageInfo = require('../../package.json'), - dataLoader = require('./data_loader')(), - plutils = require('./utilities'), - jsonCopy = require('./json_copy'), - ui = require('./ui_builder'), - ui_builder = new ui(), - pe = require('./pattern_exporter'), - pattern_exporter = new pe(), - PatternGraph = require('./pattern_graph').PatternGraph, - updateNotifier = require('update-notifier'); +const diveSync = require('diveSync'); +const dive = require('dive'); +const _ = require('lodash'); +const path = require('path'); +const chalk = require('chalk'); +const cleanHtml = require('js-beautify').html; +const inherits = require('util').inherits; +const pm = require('./plugin_manager'); +const packageInfo = require('../../package.json'); +const dataLoader = require('./data_loader')(); +const plutils = require('./utilities'); +const jsonCopy = require('./json_copy'); +const PatternGraph = require('./pattern_graph').PatternGraph; +const pa = require('./pattern_assembler'); +const lh = require('./lineage_hunter'); +const sm = require('./starterkit_manager'); +const pe = require('./pattern_exporter'); +const Pattern = require('./object_factory').Pattern; +const CompileState = require('./object_factory').CompileState; +const updateNotifier = require('update-notifier'); + +//these are mocked in unit tests, so let them be overridden +let fs = require('fs-extra'); // eslint-disable-line +let ui_builder = require('./ui_builder'); // eslint-disable-line +let pattern_exporter = new pe(); // eslint-disable-line +let assetCopier = require('./asset_copy'); // eslint-disable-line +let serve = require('./serve'); // eslint-disable-line + +const pattern_assembler = new pa(); +const lineage_hunter = new lh(); //register our log events plutils.log.on('error', msg => console.log(msg)); @@ -35,14 +47,8 @@ plutils.log.on('debug', msg => console.log(msg)); plutils.log.on('warning', msg => console.log(msg)); plutils.log.on('info', msg => console.log(msg)); -console.log( - chalk.bold('\n====[ Pattern Lab / Node'), - `- v${packageInfo.version}`, - chalk.bold(']====\n') -); - -var patternEngines = require('./pattern_engines'); -var EventEmitter = require('events').EventEmitter; +const patternEngines = require('./pattern_engines'); +const EventEmitter = require('events').EventEmitter; //bootstrap update notifier updateNotifier({ @@ -62,21 +68,45 @@ function buildPatternData(dataFilesPath, fsDep) { // GTP: these two diveSync pattern processors factored out so they can be reused // from unit tests to reduce code dupe! -function processAllPatternsIterative(pattern_assembler, patterns_dir, patternlab) { - diveSync( - patterns_dir, - function (err, file) { - //log any errors - if (err) { - console.log(err); - return; - } - pattern_assembler.process_pattern_iterative(path.relative(patterns_dir, file), patternlab); - } - ); +function processAllPatternsIterative(patterns_dir, patternlab) { + + const promiseAllPatternFiles = new Promise(function (resolve) { + dive( + patterns_dir, + (err, file) => { + //log any errors + if (err) { + console.log('error in processAllPatternsIterative():', err); + return; + } + + // We now have the loading and process phases spearated; this + // loads all the patterns before beginning any analysis, so we + // can load them asynchronously and be sure we know about all + // of them before we start lineage hunting, for + // example. Incidentally, this should also allow people to do + // horrifying things like include a page in a atom. But + // please, if you're reading this: don't. + + // NOTE: sync for now + pattern_assembler.load_pattern_iterative(path.relative(patterns_dir, file), patternlab); + }, + resolve + ); + }); + return promiseAllPatternFiles.then(() => { + // This is the second phase: once we've loaded all patterns, + // start analysis. + // patternlab.patterns.forEach((pattern) => { + // pattern_assembler.process_pattern_iterative(pattern, patternlab); + // }); + return Promise.all(patternlab.patterns.map((pattern) => { + return pattern_assembler.process_pattern_iterative(pattern, patternlab); + })); + }); } -function processAllPatternsRecursive(pattern_assembler, patterns_dir, patternlab) { +function processAllPatternsRecursive(patterns_dir, patternlab) { diveSync( patterns_dir, function (err, file) { @@ -92,7 +122,7 @@ function processAllPatternsRecursive(pattern_assembler, patterns_dir, patternlab function checkConfiguration(patternlab) { //default the output suffixes if not present - var outputFileSuffixes = { + const outputFileSuffixes = { rendered: '.rendered', rawTemplate: '', markupOnly: '.markup-only' @@ -101,10 +131,16 @@ function checkConfiguration(patternlab) { if (!patternlab.config.outputFileSuffixes) { plutils.warning('Configuration Object "outputFileSuffixes" not found, and defaulted to the following:'); console.log(outputFileSuffixes); - plutils.warning('Since Pattern Lab Core 2.3.0 this configuration option is required. Suggest you add it to your patternlab-config.json file.'); + plutils.warning('Since Pattern Lab Node Core 2.3.0 this configuration option is required. Suggest you add it to your patternlab-config.json file.'); console.log(); } patternlab.config.outputFileSuffixes = _.extend(outputFileSuffixes, patternlab.config.outputFileSuffixes); + + if (typeof patternlab.config.paths.source.patternlabFiles === 'string') { + plutils.warning(`Configuration key [paths.source.patternlabFiles] inside patternlab-config.json was found as the string '${patternlab.config.paths.source.patternlabFiles}'`); + plutils.warning('Since Pattern Lab Node Core 3.0.0 this key is an object. Suggest you update this key following this issue: https://github.com/pattern-lab/patternlab-node/issues/683.'); + } + } /** @@ -117,21 +153,21 @@ function initializePlugins(patternlab) { if (!patternlab.config.plugins) { return; } - var plugin_manager = new pm(patternlab.config, path.resolve(__dirname, '../../patternlab-config.json')); - var foundPlugins = plugin_manager.detect_plugins(); + const plugin_manager = new pm(patternlab.config, path.resolve(__dirname, '../../patternlab-config.json')); + const foundPlugins = plugin_manager.detect_plugins(); if (foundPlugins && foundPlugins.length > 0) { - for (var i = 0; i < foundPlugins.length; i++) { + for (let i = 0; i < foundPlugins.length; i++) { - let pluginKey = foundPlugins[i]; + const pluginKey = foundPlugins[i]; if (patternlab.config.debug) { console.log('Found plugin: ', pluginKey); console.log('Attempting to load and initialize plugin.'); } - var plugin = plugin_manager.load_plugin(pluginKey); + const plugin = plugin_manager.load_plugin(pluginKey); plugin(patternlab); } } @@ -143,9 +179,9 @@ function initializePlugins(patternlab) { */ function installPlugin(pluginName) { //get the config - var configPath = path.resolve(process.cwd(), 'patternlab-config.json'); - var config = fs.readJSONSync(path.resolve(configPath), 'utf8'); - var plugin_manager = new pm(config, configPath); + const configPath = path.resolve(process.cwd(), 'patternlab-config.json'); + const config = fs.readJSONSync(path.resolve(configPath), 'utf8'); + const plugin_manager = new pm(config, configPath); plugin_manager.install_plugin(pluginName); } @@ -155,24 +191,16 @@ function PatternLabEventEmitter() { } inherits(PatternLabEventEmitter, EventEmitter); -var patternlab_engine = function (config) { - 'use strict'; - - var pa = require('./pattern_assembler'), - lh = require('./lineage_hunter'), - sm = require('./starterkit_manager'), - Pattern = require('./object_factory').Pattern, - CompileState = require('./object_factory').CompileState, - patternlab = {}; +const patternlab_engine = function (config) { + const patternlab = {}; patternlab.engines = patternEngines; - - var pattern_assembler = new pa(), - lineage_hunter = new lh(); + patternlab.engines.loadAllEngines(config); patternlab.package = fs.readJSONSync(path.resolve(__dirname, '../../package.json')); patternlab.config = config || fs.readJSONSync(path.resolve(__dirname, '../../patternlab-config.json')); patternlab.events = new PatternLabEventEmitter(); + patternlab.watchers = {}; // Initialized when building patternlab.graph = null; @@ -182,9 +210,13 @@ var patternlab_engine = function (config) { //todo: determine if this is the best place to wire up plugins initializePlugins(patternlab); - var paths = patternlab.config.paths; + const paths = patternlab.config.paths; function getVersion() { + return patternlab.package.version; + } + + function logVersion() { console.log(patternlab.package.version); } @@ -277,12 +309,12 @@ var patternlab_engine = function (config) { } function listStarterkits() { - var starterkit_manager = new sm(patternlab.config); + const starterkit_manager = new sm(patternlab.config); return starterkit_manager.list_starterkits(); } function loadStarterKit(starterkitName, clean) { - var starterkit_manager = new sm(patternlab.config); + const starterkit_manager = new sm(patternlab.config); starterkit_manager.load_starterkit(starterkitName, clean); } @@ -291,8 +323,8 @@ var patternlab_engine = function (config) { */ function processHeadPattern() { try { - var headPath = path.resolve(paths.source.meta, '_00-head.mustache'); - var headPattern = new Pattern(headPath, null, patternlab); + const headPath = path.resolve(paths.source.meta, '_00-head.mustache'); + const headPattern = new Pattern(headPath, null, patternlab); headPattern.template = fs.readFileSync(headPath, 'utf8'); headPattern.isPattern = false; headPattern.isMetaPattern = true; @@ -311,8 +343,8 @@ var patternlab_engine = function (config) { */ function processFootPattern() { try { - var footPath = path.resolve(paths.source.meta, '_01-foot.mustache'); - var footPattern = new Pattern(footPath, null, patternlab); + const footPath = path.resolve(paths.source.meta, '_01-foot.mustache'); + const footPattern = new Pattern(footPath, null, patternlab); footPattern.template = fs.readFileSync(footPath, 'utf8'); footPattern.isPattern = false; footPattern.isMetaPattern = true; @@ -376,19 +408,19 @@ var patternlab_engine = function (config) { patternlab.events.emit('patternlab-pattern-before-data-merge', patternlab, pattern); //render the pattern, but first consolidate any data we may have - var allData; + let allData; try { allData = jsonCopy(patternlab.data, 'config.paths.source.data global data'); } catch (err) { console.log('There was an error parsing JSON for ' + pattern.relPath); console.log(err); } - allData = plutils.mergeData(allData, pattern.jsonFileData); + allData = _.merge(allData, pattern.jsonFileData); allData.cacheBuster = patternlab.cacheBuster; //re-rendering the headHTML each time allows pattern-specific data to influence the head of the pattern pattern.header = head; - var headHTML = pattern_assembler.renderPattern(pattern.header, allData); + const headHTML = pattern_assembler.renderPattern(pattern.header, allData); //render the extendedTemplate with all data pattern.patternPartialCode = pattern_assembler.renderPattern(pattern, allData); @@ -428,23 +460,23 @@ var patternlab_engine = function (config) { }); //set the pattern-specific footer by compiling the general-footer with data, and then adding it to the meta footer - var footerPartial = pattern_assembler.renderPattern(patternlab.footer, { + const footerPartial = pattern_assembler.renderPattern(patternlab.footer, { isPattern: pattern.isPattern, patternData: pattern.patternData, cacheBuster: patternlab.cacheBuster }); - var allFooterData; + let allFooterData; try { allFooterData = jsonCopy(patternlab.data, 'config.paths.source.data global data'); } catch (err) { console.log('There was an error parsing JSON for ' + pattern.relPath); console.log(err); } - allFooterData = plutils.mergeData(allFooterData, pattern.jsonFileData); + allFooterData = _.merge(allFooterData, pattern.jsonFileData); allFooterData.patternLabFoot = footerPartial; - var footerHTML = pattern_assembler.renderPattern(patternlab.userFoot, allFooterData); + const footerHTML = pattern_assembler.renderPattern(patternlab.userFoot, allFooterData); patternlab.events.emit('patternlab-pattern-write-begin', patternlab, pattern); @@ -479,28 +511,35 @@ var patternlab_engine = function (config) { function buildPatterns(deletePatternDir) { + if (patternlab.config.debug) { + console.log( + chalk.bold('\n====[ Pattern Lab / Node'), + `- v${packageInfo.version}`, + chalk.bold(']====\n') + ); + } + patternlab.events.emit('patternlab-build-pattern-start', patternlab); - let graph = patternlab.graph = loadPatternGraph(deletePatternDir); + const graph = patternlab.graph = loadPatternGraph(deletePatternDir); - let graphNeedsUpgrade = !PatternGraph.checkVersion(graph); + const graphNeedsUpgrade = !PatternGraph.checkVersion(graph); if (graphNeedsUpgrade) { plutils.log.info("Due to an upgrade, a complete rebuild is required and the public/patterns directory was deleted. " + - "Incremental build is available again on the next successful run."); + "Incremental build is available again on the next successful run."); // Ensure that the freshly built graph has the latest version again. patternlab.graph.upgradeVersion(); } // Flags - let incrementalBuildsEnabled = !(deletePatternDir || graphNeedsUpgrade); + const incrementalBuildsEnabled = !(deletePatternDir || graphNeedsUpgrade); if (incrementalBuildsEnabled) { plutils.log.info("Incremental builds enabled."); } else { // needs to be done BEFORE processing patterns - fs.removeSync(paths.public.patterns); fs.emptyDirSync(paths.public.patterns); } @@ -517,11 +556,11 @@ var patternlab_engine = function (config) { patternlab.listitems = {}; } try { - patternlab.header = fs.readFileSync(path.resolve(paths.source.patternlabFiles, 'partials', 'general-header.mustache'), 'utf8'); - patternlab.footer = fs.readFileSync(path.resolve(paths.source.patternlabFiles, 'partials', 'general-footer.mustache'), 'utf8'); - patternlab.patternSection = fs.readFileSync(path.resolve(paths.source.patternlabFiles, 'partials', 'patternSection.mustache'), 'utf8'); - patternlab.patternSectionSubType = fs.readFileSync(path.resolve(paths.source.patternlabFiles, 'partials', 'patternSectionSubtype.mustache'), 'utf8'); - patternlab.viewAll = fs.readFileSync(path.resolve(paths.source.patternlabFiles, 'viewall.mustache'), 'utf8'); + patternlab.header = fs.readFileSync(path.resolve(paths.source.patternlabFiles['general-header']), 'utf8'); + patternlab.footer = fs.readFileSync(path.resolve(paths.source.patternlabFiles['general-footer']), 'utf8'); + patternlab.patternSection = fs.readFileSync(path.resolve(paths.source.patternlabFiles.patternSection), 'utf8'); + patternlab.patternSectionSubType = fs.readFileSync(path.resolve(paths.source.patternlabFiles.patternSectionSubtype), 'utf8'); + patternlab.viewAll = fs.readFileSync(path.resolve(paths.source.patternlabFiles.viewall), 'utf8'); } catch (ex) { console.log(ex); plutils.error('\nERROR: missing an essential file from ' + paths.source.patternlabFiles + '. Pattern Lab won\'t work without this file.\n'); @@ -539,118 +578,224 @@ var patternlab_engine = function (config) { patternlab.events.emit('patternlab-build-global-data-end', patternlab); // diveSync once to perform iterative populating of patternlab object - processAllPatternsIterative(pattern_assembler, paths.source.patterns, patternlab); + return processAllPatternsIterative(paths.source.patterns, patternlab).then(() => { - patternlab.events.emit('patternlab-pattern-iteration-end', patternlab); + patternlab.events.emit('patternlab-pattern-iteration-end', patternlab); - //now that all the main patterns are known, look for any links that might be within data and expand them - //we need to do this before expanding patterns & partials into extendedTemplates, otherwise we could lose the data -> partial reference - pattern_assembler.parse_data_links(patternlab); + //now that all the main patterns are known, look for any links that might be within data and expand them + //we need to do this before expanding patterns & partials into extendedTemplates, otherwise we could lose the data -> partial reference + pattern_assembler.parse_data_links(patternlab); - //diveSync again to recursively include partials, filling out the - //extendedTemplate property of the patternlab.patterns elements - // TODO we can reduce the time needed by only processing changed patterns and their partials - processAllPatternsRecursive(pattern_assembler, paths.source.patterns, patternlab); + //diveSync again to recursively include partials, filling out the + //extendedTemplate property of the patternlab.patterns elements + // TODO we can reduce the time needed by only processing changed patterns and their partials + processAllPatternsRecursive(paths.source.patterns, patternlab); - //take the user defined head and foot and process any data and patterns that apply - processHeadPattern(); - processFootPattern(); + //take the user defined head and foot and process any data and patterns that apply + processHeadPattern(); + processFootPattern(); - //cascade any patternStates - lineage_hunter.cascade_pattern_states(patternlab); + //cascade any patternStates + lineage_hunter.cascade_pattern_states(patternlab); - //set pattern-specific header if necessary - var head; - if (patternlab.userHead) { - head = patternlab.userHead; - } else { - head = patternlab.header; - } - - //set the pattern-specific header by compiling the general-header with data, and then adding it to the meta header - patternlab.data.patternLabHead = pattern_assembler.renderPattern(patternlab.header, { - cacheBuster: patternlab.cacheBuster - }); - - // If deletePatternDir == true or graph needs to be updated - // rebuild all patterns - let patternsToBuild = null; + //set pattern-specific header if necessary + let head; + if (patternlab.userHead) { + head = patternlab.userHead; + } else { + head = patternlab.header; + } - if (incrementalBuildsEnabled) { - // When the graph was loaded from file, some patterns might have been moved/deleted between runs - // so the graph data become out of sync - patternlab.graph.sync().forEach(n => { - plutils.log.info("[Deleted/Moved] " + n); + //set the pattern-specific header by compiling the general-header with data, and then adding it to the meta header + patternlab.data.patternLabHead = pattern_assembler.renderPattern(patternlab.header, { + cacheBuster: patternlab.cacheBuster }); - // TODO Find created or deleted files - let now = new Date().getTime(); - pattern_assembler.mark_modified_patterns(now, patternlab); - patternsToBuild = patternlab.graph.compileOrder(); - } else { - // build all patterns, mark all to be rebuilt - patternsToBuild = patternlab.patterns; - for (let p of patternsToBuild) { - p.compileState = CompileState.NEEDS_REBUILD; + // If deletePatternDir == true or graph needs to be updated + // rebuild all patterns + let patternsToBuild = null; + + // If deletePatternDir == true or graph needs to be updated + // rebuild all patterns + patternsToBuild = null; + + if (incrementalBuildsEnabled) { + // When the graph was loaded from file, some patterns might have been moved/deleted between runs + // so the graph data become out of sync + patternlab.graph.sync().forEach(n => { + plutils.log.info("[Deleted/Moved] " + n); + }); + + // TODO Find created or deleted files + const now = new Date().getTime(); + pattern_assembler.mark_modified_patterns(now, patternlab); + patternsToBuild = patternlab.graph.compileOrder(); + } else { + // build all patterns, mark all to be rebuilt + patternsToBuild = patternlab.patterns; + for (const p of patternsToBuild) { + p.compileState = CompileState.NEEDS_REBUILD; + } } - } - //render all patterns last, so lineageR works - patternsToBuild.forEach(pattern => renderSinglePattern(pattern, head)); + //render all patterns last, so lineageR works + patternsToBuild.forEach(pattern => renderSinglePattern(pattern, head)); - // Saves the pattern graph when all files have been compiled - PatternGraph.storeToFile(patternlab); - if (patternlab.config.exportToGraphViz) { - PatternGraph.exportToDot(patternlab, "dependencyGraph.dot"); - plutils.log.info(`Exported pattern graph to ${path.join(config.paths.public.root, "dependencyGraph.dot")}`); - } + // Saves the pattern graph when all files have been compiled + PatternGraph.storeToFile(patternlab); + if (patternlab.config.exportToGraphViz) { + PatternGraph.exportToDot(patternlab, "dependencyGraph.dot"); + plutils.log.info(`Exported pattern graph to ${path.join(config.paths.public.root, "dependencyGraph.dot")}`); + } - //export patterns if necessary - pattern_exporter.export_patterns(patternlab); + //export patterns if necessary + pattern_exporter.export_patterns(patternlab); + }).catch((err) => { + console.log('Error in buildPatterns():', err); + }); } return { + /** + * logs current version + * + * @returns {void} current patternlab-node version as defined in package.json, as console output + */ version: function () { + return logVersion(); + }, + + /** + * return current version + * + * @returns {string} current patternlab-node version as defined in package.json, as string + */ + v: function () { return getVersion(); }, - build: function (callback, deletePatternDir) { + + /** + * build patterns, copy assets, and construct ui + * + * @param {function} callback a function invoked when build is complete + * @param {object} options an object used to control build behavior + * @returns {Promise} a promise fulfilled when build is complete + */ + build: function (callback, options) { if (patternlab && patternlab.isBusy) { console.log('Pattern Lab is busy building a previous run - returning early.'); - return; + return Promise.resolve(); } patternlab.isBusy = true; - buildPatterns(deletePatternDir); - ui_builder.buildFrontend(patternlab); - printDebug(); - patternlab.isBusy = false; - callback(); + return buildPatterns(options.cleanPublic).then(() => { + + new ui_builder().buildFrontend(patternlab); + assetCopier().copyAssets(patternlab.config.paths, patternlab, options); + + this.events.on('patternlab-pattern-change', () => { + if (!patternlab.isBusy) { + options.cleanPublic = false; + return this.build(callback, options); + } + return Promise.resolve(); + }); + + this.events.on('patternlab-global-change', () => { + if (!patternlab.isBusy) { + options.cleanPublic = true; //rebuild everything + return this.build(callback, options); + } + return Promise.resolve(); + }); + + printDebug(); + patternlab.isBusy = false; + callback(); + }); }, + + /** + * logs usage + * + * @returns {void} pattern lab API usage, as console output + */ help: function () { help(); }, - patternsonly: function (callback, deletePatternDir) { + + /** + * build patterns only, leaving existing public files intact + * + * @param {function} callback a function invoked when build is complete + * @param {object} options an object used to control build behavior + * @returns {Promise} a promise fulfilled when build is complete + */ + patternsonly: function (callback, options) { if (patternlab && patternlab.isBusy) { console.log('Pattern Lab is busy building a previous run - returning early.'); - return; + return Promise.resolve(); } patternlab.isBusy = true; - buildPatterns(deletePatternDir); - printDebug(); - patternlab.isBusy = false; - callback(); + return buildPatterns(options.cleanPublic).then(() => { + printDebug(); + patternlab.isBusy = false; + callback(); + }); }, + + /** + * fetches starterkit repos from pattern-lab github org that contain 'starterkit' in their name + * + * @returns {Promise} Returns an Array<{name,url}> for the starterkit repos + */ liststarterkits: function () { return listStarterkits(); }, + + /** + * load starterkit already available via `node_modules/` + * + * @param {string} starterkitName name of starterkit + * @param {boolean} clean whether or not to delete contents of source/ before load + * @returns {void} + */ loadstarterkit: function (starterkitName, clean) { loadStarterKit(starterkitName, clean); }, + + + /** + * install plugin already available via `node_modules/` + * + * @param {string} pluginName name of plugin + * @returns {void} + */ installplugin: function (pluginName) { installPlugin(pluginName); }, + + /** + * returns all file extensions supported by installed PatternEngines + * + * @returns {Array} all supported file extensions + */ getSupportedTemplateExtensions: function () { return getSupportedTemplateExtensions(); - } + }, + + /** + * build patterns, copy assets, and construct ui, watch source files, and serve locally + * + * @param {object} options an object used to control build, copy, and serve behavior + * @returns {Promise} TODO: validate + */ + serve: function (options) { + options.watch = true; + return this.build(() => {}, options).then(function () { + serve(patternlab); + }); + }, + events: patternlab.events }; }; diff --git a/core/lib/plugin_manager.js b/core/lib/plugin_manager.js index 3cac4fd69..e636dd4a5 100644 --- a/core/lib/plugin_manager.js +++ b/core/lib/plugin_manager.js @@ -1,9 +1,9 @@ "use strict"; -var plugin_manager = function (config, configPath) { - var path = require('path'), - fs = require('fs-extra'), - util = require('./utilities'); +const plugin_manager = function (config, configPath) { + const path = require('path'); + const fs = require('fs-extra'); + const util = require('./utilities'); /** * Loads a plugin @@ -22,7 +22,7 @@ var plugin_manager = function (config, configPath) { */ function installPlugin(pluginName) { try { - var pluginPath = path.resolve( + const pluginPath = path.resolve( path.join(process.cwd(), 'node_modules', pluginName) ); console.log('Attempting to load plugin from', pluginPath); @@ -33,10 +33,10 @@ var plugin_manager = function (config, configPath) { util.error(pluginName + ' not loaded.'); return; } - var pluginPathDirExists = pluginDirStats.isDirectory(); + const pluginPathDirExists = pluginDirStats.isDirectory(); if (pluginPathDirExists) { - var diskConfig = fs.readJSONSync(path.resolve(configPath), 'utf8'); + const diskConfig = fs.readJSONSync(path.resolve(configPath), 'utf8'); //add the plugin entry to patternlab-config.json if (!diskConfig.plugins) { @@ -79,9 +79,9 @@ var plugin_manager = function (config, configPath) { * @return {array} list of installed plugins */ function detectPlugins() { - var node_modules_path = path.join(process.cwd(), 'node_modules'); + const node_modules_path = path.join(process.cwd(), 'node_modules'); return fs.readdirSync(node_modules_path).filter(function (dir) { - var module_path = path.join(process.cwd(), 'node_modules', dir); + const module_path = path.join(process.cwd(), 'node_modules', dir); return fs.statSync(module_path).isDirectory() && dir.indexOf('plugin-node-') === 0; }); } diff --git a/core/lib/pseudopattern_hunter.js b/core/lib/pseudopattern_hunter.js index fbcca89ad..debae2d8c 100644 --- a/core/lib/pseudopattern_hunter.js +++ b/core/lib/pseudopattern_hunter.js @@ -1,94 +1,136 @@ "use strict"; -var ch = require('./changes_hunter'); - -var pseudopattern_hunter = function () { - - function findpseudopatterns(currentPattern, patternlab) { - var glob = require('glob'), - fs = require('fs-extra'), - pa = require('./pattern_assembler'), - lh = require('./lineage_hunter'), - Pattern = require('./object_factory').Pattern, - plutils = require('./utilities'), - path = require('path'); - - - var pattern_assembler = new pa(); - var lineage_hunter = new lh(); - var changes_hunter = new ch(); - var paths = patternlab.config.paths; - - //look for a pseudo pattern by checking if there is a file containing same - //name, with ~ in it, ending in .json - var needle = currentPattern.subdir + '/' + currentPattern.fileName + '~*.json'; - var pseudoPatterns = glob.sync(needle, { - cwd: paths.source.patterns, - debug: false, - nodir: true - }); - - if (pseudoPatterns.length > 0) { - for (var i = 0; i < pseudoPatterns.length; i++) { - if (patternlab.config.debug) { - console.log('found pseudoPattern variant of ' + currentPattern.patternPartial); - } - - //we want to do everything we normally would here, except instead read the pseudoPattern data - try { - var variantFileFullPath = path.resolve(paths.source.patterns, pseudoPatterns[i]); - var variantFileData = fs.readJSONSync(variantFileFullPath); - } catch (err) { - console.log('There was an error parsing pseudopattern JSON for ' + currentPattern.relPath); - console.log(err); - } - - //extend any existing data with variant data - variantFileData = plutils.mergeData(currentPattern.jsonFileData, variantFileData); - - var variantName = pseudoPatterns[i].substring(pseudoPatterns[i].indexOf('~') + 1).split('.')[0]; - var variantFilePath = path.join(currentPattern.subdir, currentPattern.fileName + '~' + variantName + '.json'); - var lm = fs.statSync(variantFileFullPath); - var patternVariant = Pattern.create(variantFilePath, variantFileData, { - //use the same template as the non-variant - template: currentPattern.template, - fileExtension: currentPattern.fileExtension, - extendedTemplate: currentPattern.extendedTemplate, - isPseudoPattern: true, - basePattern: currentPattern, - stylePartials: currentPattern.stylePartials, - parameteredPartials: currentPattern.parameteredPartials, - - // Only regular patterns are discovered during iterative walks - // Need to recompile on data change or template change - lastModified: Math.max(currentPattern.lastModified, lm.mtime), - - // use the same template engine as the non-variant - engine: currentPattern.engine - }, patternlab); - - changes_hunter.checkBuildState(patternVariant, patternlab); - patternlab.graph.add(patternVariant); - patternlab.graph.link(patternVariant, currentPattern); - - //process the companion markdown file if it exists - pattern_assembler.parse_pattern_markdown(patternVariant, patternlab); - - //find pattern lineage - lineage_hunter.find_lineage(patternVariant, patternlab); - - //add to patternlab object so we can look these up later. - pattern_assembler.addPattern(patternVariant, patternlab); +const ch = require('./changes_hunter'); +const glob = require('glob'); +const fs = require('fs-extra'); +const _ = require('lodash'); +const lh = require('./lineage_hunter'); +const Pattern = require('./object_factory').Pattern; +const path = require('path'); +const lineage_hunter = new lh(); +const changes_hunter = new ch(); + +const pseudopattern_hunter = function () {}; + +pseudopattern_hunter.prototype.find_pseudopatterns = function (currentPattern, patternlab) { + const pa = require('./pattern_assembler'); + const pattern_assembler = new pa(); + + const paths = patternlab.config.paths; + + //look for a pseudo pattern by checking if there is a file containing same + //name, with ~ in it, ending in .json + const needle = currentPattern.subdir + '/' + currentPattern.fileName + '~*.json'; + const pseudoPatterns = glob.sync(needle, { + cwd: paths.source.patterns, + debug: false, + nodir: true + }); + + if (pseudoPatterns.length > 0) { + for (let i = 0; i < pseudoPatterns.length; i++) { + if (patternlab.config.debug) { + console.log('found pseudoPattern variant of ' + currentPattern.patternPartial); + } + + //we want to do everything we normally would here, except instead read the pseudoPattern data + try { + var variantFileFullPath = path.resolve(paths.source.patterns, pseudoPatterns[i]); + var variantFileData = fs.readJSONSync(variantFileFullPath); + } catch (err) { + console.log('There was an error parsing pseudopattern JSON for ' + currentPattern.relPath); + console.log(err); } - } - } - return { - find_pseudopatterns: function (pattern, patternlab) { - findpseudopatterns(pattern, patternlab); + //extend any existing data with variant data + variantFileData = _.merge(currentPattern.jsonFileData, variantFileData); + + let variantName = pseudoPatterns[i].substring(pseudoPatterns[i].indexOf('~') + 1).split('.')[0]; + let variantFilePath = path.join(currentPattern.subdir, currentPattern.fileName + '~' + variantName + '.json'); + let lm = fs.statSync(variantFileFullPath); + let patternVariant = Pattern.create(variantFilePath, variantFileData, { + //use the same template as the non-variant + template: currentPattern.template, + fileExtension: currentPattern.fileExtension, + extendedTemplate: currentPattern.extendedTemplate, + isPseudoPattern: true, + basePattern: currentPattern, + stylePartials: currentPattern.stylePartials, + parameteredPartials: currentPattern.parameteredPartials, + + // Only regular patterns are discovered during iterative walks + // Need to recompile on data change or template change + lastModified: Math.max(currentPattern.lastModified, lm.mtime), + + // use the same template engine as the non-variant + engine: currentPattern.engine + }, patternlab); + + changes_hunter.checkBuildState(patternVariant, patternlab); + patternlab.graph.add(patternVariant); + patternlab.graph.link(patternVariant, currentPattern); + + //process the companion markdown file if it exists + pattern_assembler.parse_pattern_markdown(patternVariant, patternlab); + + //find pattern lineage + lineage_hunter.find_lineage(patternVariant, patternlab); + + //add to patternlab object so we can look these up later. + pattern_assembler.addPattern(patternVariant, patternlab); + + //we want to do everything we normally would here, except instead read the pseudoPattern data + try { + var variantFileFullPath = path.resolve(paths.source.patterns, pseudoPatterns[i]); + var variantFileData = fs.readJSONSync(variantFileFullPath); + } catch (err) { + console.log('There was an error parsing pseudopattern JSON for ' + currentPattern.relPath); + console.log(err); + } + + //extend any existing data with variant data + variantFileData = _.merge(currentPattern.jsonFileData, variantFileData); + + variantName = pseudoPatterns[i].substring(pseudoPatterns[i].indexOf('~') + 1).split('.')[0]; + variantFilePath = path.join(currentPattern.subdir, currentPattern.fileName + '~' + variantName + '.json'); + lm = fs.statSync(variantFileFullPath); + patternVariant = Pattern.create(variantFilePath, variantFileData, { + //use the same template as the non-variant + template: currentPattern.template, + fileExtension: currentPattern.fileExtension, + extendedTemplate: currentPattern.extendedTemplate, + isPseudoPattern: true, + basePattern: currentPattern, + stylePartials: currentPattern.stylePartials, + parameteredPartials: currentPattern.parameteredPartials, + + // Only regular patterns are discovered during iterative walks + // Need to recompile on data change or template change + lastModified: Math.max(currentPattern.lastModified, lm.mtime), + + // use the same template engine as the non-variant + engine: currentPattern.engine + }, patternlab); + + changes_hunter.checkBuildState(patternVariant, patternlab); + patternlab.graph.add(patternVariant); + patternlab.graph.link(patternVariant, currentPattern); + + //process the companion markdown file if it exists + pattern_assembler.parse_pattern_markdown(patternVariant, patternlab); + + //find pattern lineage + lineage_hunter.find_lineage(patternVariant, patternlab); + + //add to patternlab object so we can look these up later. + pattern_assembler.addPattern(patternVariant, patternlab); } - }; + // GTP: this is to emulate the behavior of the stale asynced + // version; when we have time, we can make all the FS calls in here + // async and see if it helps any, but it didn't when I tried it. + } + return Promise.resolve(); }; -module.exports = pseudopattern_hunter; +module.exports = new pseudopattern_hunter(); diff --git a/core/lib/serve.js b/core/lib/serve.js new file mode 100644 index 000000000..a773acde9 --- /dev/null +++ b/core/lib/serve.js @@ -0,0 +1,39 @@ +"use strict"; +const path = require('path'); +const liveServer = require('live-server'); + +const serve = (patternlab) => { + + // our default liveserver config + const defaults = { + root: patternlab.config.paths.public.root, + open: true, + ignore: path.join(path.resolve(patternlab.config.paths.public.root)), + file: 'index.html', + logLevel: 0, // errors only + wait: 1000 + }; + + // allow for overrides should they exist inside patternlab-config.json + const liveServerConfig = Object.assign({}, defaults, patternlab.config.serverOptions); + + // watch for asset changes, and reload appropriately + patternlab.events.on('patternlab-asset-change', (data) => { + if (data.file.indexOf('css') > -1) { + liveServer.refreshCSS(); + } else { + liveServer.reload(); + } + }); + + //watch for pattern changes, and reload + patternlab.events.on('patternlab-pattern-change', () => { + liveServer.reload(); + }); + + //start! + liveServer.start(liveServerConfig); + +}; + +module.exports = serve; diff --git a/core/lib/starterkit_manager.js b/core/lib/starterkit_manager.js index 77fbf91a2..2498580b9 100644 --- a/core/lib/starterkit_manager.js +++ b/core/lib/starterkit_manager.js @@ -1,11 +1,11 @@ "use strict"; -var starterkit_manager = function (config) { - var path = require('path'), - fetch = require('node-fetch'), - fs = require('fs-extra'), - util = require('./utilities'), - paths = config.paths; +const starterkit_manager = function (config) { + const path = require('path'); + const fetch = require('node-fetch'); + const fs = require('fs-extra'); + const util = require('./utilities'); + const paths = config.paths; /** * Loads npm module identified by the starterkitName parameter. @@ -15,7 +15,7 @@ var starterkit_manager = function (config) { */ function loadStarterKit(starterkitName, clean) { try { - var kitPath = path.resolve( + const kitPath = path.resolve( path.join(process.cwd(), 'node_modules', starterkitName, config.starterkitSubDir) ); console.log('Attempting to load starterkit from', kitPath); @@ -26,12 +26,12 @@ var starterkit_manager = function (config) { util.error(starterkitName + ' not loaded.'); return; } - var kitPathDirExists = kitDirStats.isDirectory(); + const kitPathDirExists = kitDirStats.isDirectory(); if (kitPathDirExists) { if (clean) { console.log('Deleting contents of', paths.source.root, 'prior to starterkit load.'); - util.emptyDirectory(paths.source.root); + fs.emptyDirSync(paths.source.root); } else { console.log('Overwriting contents of', paths.source.root, 'during starterkit load.'); } @@ -61,7 +61,7 @@ var starterkit_manager = function (config) { 'Accept': 'application/json' } }).then(function (res) { - var contentType = res.headers.get('content-type'); + const contentType = res.headers.get('content-type'); if (contentType && contentType.indexOf('application/json') === -1) { throw new TypeError("StarterkitManager->listStarterkits: Not valid JSON"); } @@ -90,9 +90,9 @@ var starterkit_manager = function (config) { * @return {array} List of starter kits installed */ function detectStarterKits() { - var node_modules_path = path.join(process.cwd(), 'node_modules'); - var npm_modules = fs.readdirSync(node_modules_path).filter(function (dir) { - var module_path = path.join(process.cwd(), 'node_modules', dir); + const node_modules_path = path.join(process.cwd(), 'node_modules'); + const npm_modules = fs.readdirSync(node_modules_path).filter(function (dir) { + const module_path = path.join(process.cwd(), 'node_modules', dir); return fs.statSync(module_path).isDirectory() && dir.indexOf('starterkit-') === 0; }); return npm_modules; diff --git a/core/lib/style_modifier_hunter.js b/core/lib/style_modifier_hunter.js index f6f9f0596..af50fb155 100644 --- a/core/lib/style_modifier_hunter.js +++ b/core/lib/style_modifier_hunter.js @@ -1,6 +1,6 @@ "use strict"; -var style_modifier_hunter = function () { +const style_modifier_hunter = function () { /** * Modifies a patterns partial with any styleModifiers found on the supplied partial @@ -11,7 +11,7 @@ var style_modifier_hunter = function () { */ function consumestylemodifier(pattern, partial, patternlab) { //extract the classname from the stylemodifier which comes in the format of :className - var styleModifier = partial.match(/:([\w\-_|])+/g) ? partial.match(/:([\w\-_|])+/g)[0].slice(1) : null; + let styleModifier = partial.match(/:([\w\-_|])+/g) ? partial.match(/:([\w\-_|])+/g)[0].slice(1) : null; if (styleModifier) { //replace the special character pipe | used to separate multiple classes with a space diff --git a/core/lib/ui_builder.js b/core/lib/ui_builder.js index 2df7218f0..6c2807467 100644 --- a/core/lib/ui_builder.js +++ b/core/lib/ui_builder.js @@ -1,17 +1,19 @@ "use strict"; -var path = require('path'); -var fs = require('fs-extra'); -var ae = require('./annotation_exporter'); -var of = require('./object_factory'); -var Pattern = of.Pattern; -var pattern_assembler = require('./pattern_assembler')(); -var plutils = require('./utilities'); -var eol = require('os').EOL; -var _ = require('lodash'); -var jsonCopy = require('./json_copy'); - -var ui_builder = function () { +const path = require('path'); +const jsonCopy = require('./json_copy'); +const ae = require('./annotation_exporter'); +const of = require('./object_factory'); +const Pattern = of.Pattern; +const plutils = require('./utilities'); +const eol = require('os').EOL; +const _ = require('lodash'); + +//these are mocked in unit tests, so let them be overridden +let fs = require('fs-extra'); //eslint-disable-line prefer-const +let pattern_assembler = require('./pattern_assembler')(); //eslint-disable-line prefer-const + +const ui_builder = function () { /** * Registers the pattern to the patternPaths object for the appropriate patternGroup and basename @@ -60,7 +62,7 @@ var ui_builder = function () { * @returns boolean - whether or not the pattern is excluded */ function isPatternExcluded(pattern, patternlab) { - var isOmitted; + let isOmitted; // skip underscore-prefixed files isOmitted = pattern.isPattern && pattern.fileName.charAt(0) === '_'; @@ -112,7 +114,7 @@ var ui_builder = function () { */ function injectDocumentationBlock(pattern, patternlab, isSubtypePattern) { //first see if pattern_assembler processed one already - var docPattern = patternlab.subtypePatterns[pattern.patternGroup + (isSubtypePattern ? '-' + pattern.patternSubGroup : '')]; + let docPattern = patternlab.subtypePatterns[pattern.patternGroup + (isSubtypePattern ? '-' + pattern.patternSubGroup : '')]; if (docPattern) { docPattern.isDocPattern = true; docPattern.order = -Number.MAX_SAFE_INTEGER; @@ -164,7 +166,7 @@ var ui_builder = function () { * @returns the found pattern type object */ function getPatternType(patternlab, pattern) { - var patternType = _.find(patternlab.patternTypes, ['patternType', pattern.patternType]); + const patternType = _.find(patternlab.patternTypes, ['patternType', pattern.patternType]); if (!patternType) { plutils.error('Could not find patternType' + pattern.patternType + '. This is a critical error.'); @@ -182,8 +184,8 @@ var ui_builder = function () { * @returns the found patternSubType object */ function getPatternSubType(patternlab, pattern) { - var patternType = getPatternType(patternlab, pattern); - var patternSubType = _.find(patternType.patternTypeItems, ['patternSubtype', pattern.patternSubType]); + const patternType = getPatternType(patternlab, pattern); + const patternSubType = _.find(patternType.patternTypeItems, ['patternSubtype', pattern.patternSubType]); if (!patternSubType) { plutils.error('Could not find patternType ' + pattern.patternType + '-' + pattern.patternType + '. This is a critical error.'); @@ -201,15 +203,15 @@ var ui_builder = function () { * @param pattern - the pattern to register */ function addPatternSubType(patternlab, pattern) { - let newSubType = { + const newSubType = { patternSubtypeLC: pattern.patternSubGroup.toLowerCase(), patternSubtypeUC: pattern.patternSubGroup.charAt(0).toUpperCase() + pattern.patternSubGroup.slice(1), patternSubtype: pattern.patternSubType, patternSubtypeDash: pattern.patternSubGroup, //todo verify patternSubtypeItems: [] }; - var patternType = getPatternType(patternlab, pattern); - let insertIndex = _.sortedIndexBy(patternType.patternTypeItems, newSubType, 'patternSubtype'); + const patternType = getPatternType(patternlab, pattern); + const insertIndex = _.sortedIndexBy(patternType.patternTypeItems, newSubType, 'patternSubtype'); patternType.patternTypeItems.splice(insertIndex, 0, newSubType); } @@ -220,7 +222,7 @@ var ui_builder = function () { * @returns {{patternPartial: string, patternName: (*|string), patternState: string, patternSrcPath: string, patternPath: string}} */ function createPatternSubTypeItem(pattern) { - var patternPath = ''; + let patternPath = ''; if (pattern.isFlatPattern) { patternPath = pattern.flatPatternPath + '-' + pattern.fileName + '/' + pattern.flatPatternPath + '-' + pattern.fileName + '.html'; } else { @@ -261,7 +263,7 @@ var ui_builder = function () { newSubTypeItem = createPatternSubTypeItem(pattern); } - let patternSubType = getPatternSubType(patternlab, pattern); + const patternSubType = getPatternSubType(patternlab, pattern); patternSubType.patternSubtypeItems.push(newSubTypeItem); patternSubType.patternSubtypeItems = _.sortBy(patternSubType.patternSubtypeItems, ['order', 'name']); } @@ -272,7 +274,7 @@ var ui_builder = function () { * @param pattern - the pattern to add */ function addPatternItem(patternlab, pattern, isViewAllVariant) { - var patternType = getPatternType(patternlab, pattern); + const patternType = getPatternType(patternlab, pattern); if (!patternType) { plutils.error('Could not find patternType' + pattern.patternType + '. This is a critical error.'); console.trace(); @@ -317,7 +319,7 @@ var ui_builder = function () { return patternsArray.sort(function (a, b) { let aOrder = parseInt(a.order, 10); - let bOrder = parseInt(b.order, 10); + const bOrder = parseInt(b.order, 10); if (aOrder === NaN) { aOrder = Number.MAX_SAFE_INTEGER; @@ -367,7 +369,7 @@ var ui_builder = function () { * @returns ptterns grouped by type -> subtype like atoms -> global -> pattern, pattern, pattern */ function groupPatterns(patternlab) { - var groupedPatterns = { + const groupedPatterns = { patternGroups: {} }; @@ -426,14 +428,14 @@ var ui_builder = function () { */ function buildFooterHTML(patternlab, patternPartial) { //first render the general footer - var footerPartial = pattern_assembler.renderPattern(patternlab.footer, { + const footerPartial = pattern_assembler.renderPattern(patternlab.footer, { patternData: JSON.stringify({ patternPartial: patternPartial, }), cacheBuster: patternlab.cacheBuster }); - var allFooterData; + let allFooterData; try { allFooterData = jsonCopy(patternlab.data, 'config.paths.source.data plus patterns data'); } catch (err) { @@ -443,7 +445,7 @@ var ui_builder = function () { allFooterData.patternLabFoot = footerPartial; //then add it to the user footer - var footerHTML = pattern_assembler.renderPattern(patternlab.userFoot, allFooterData); + const footerHTML = pattern_assembler.renderPattern(patternlab.userFoot, allFooterData); return footerHTML; } @@ -456,7 +458,7 @@ var ui_builder = function () { * @returns HTML */ function buildViewAllHTML(patternlab, patterns, patternPartial) { - var viewAllHTML = pattern_assembler.renderPattern(patternlab.viewAll, + const viewAllHTML = pattern_assembler.renderPattern(patternlab.viewAll, { partials: patterns, patternPartial: 'viewall-' + patternPartial, @@ -476,20 +478,21 @@ var ui_builder = function () { * @returns every built pattern and set of viewall patterns, so the styleguide can use it */ function buildViewAllPages(mainPageHeadHtml, patternlab, styleguidePatterns) { - var paths = patternlab.config.paths; - var patterns = []; - var writeViewAllFile = true; + const paths = patternlab.config.paths; + let patterns = []; + let writeViewAllFile = true; //loop through the grouped styleguide patterns, building at each level _.forEach(styleguidePatterns.patternGroups, function (patternTypeObj, patternType) { - var p; - var typePatterns = [], styleguideTypePatterns = []; - var styleGuideExcludes = patternlab.config.styleGuideExcludes || patternlab.config.styleguideExcludes; + let p; + let typePatterns = []; + let styleguideTypePatterns = []; + const styleGuideExcludes = patternlab.config.styleGuideExcludes || patternlab.config.styleguideExcludes; _.forOwn(patternTypeObj, function (patternSubtypes, patternSubtype) { - var patternPartial = patternType + '-' + patternSubtype; + const patternPartial = patternType + '-' + patternSubtype; //do not create a viewall page for flat patterns if (patternType === patternSubtype) { @@ -498,10 +501,10 @@ var ui_builder = function () { } //render the footer needed for the viewall template - var footerHTML = buildFooterHTML(patternlab, 'viewall-' + patternPartial); + const footerHTML = buildFooterHTML(patternlab, 'viewall-' + patternPartial); //render the viewall template by finding these smallest subtype-grouped patterns - var subtypePatterns = sortPatterns(_.values(patternSubtypes)); + const subtypePatterns = sortPatterns(_.values(patternSubtypes)); //determine if we should write at this time by checking if these are flat patterns or grouped patterns p = _.find(subtypePatterns, function (pat) { @@ -523,7 +526,7 @@ var ui_builder = function () { typePatterns = typePatterns.concat(subtypePatterns); - var viewAllHTML = buildViewAllHTML(patternlab, subtypePatterns, patternPartial); + const viewAllHTML = buildViewAllHTML(patternlab, subtypePatterns, patternPartial); fs.outputFileSync(paths.public.patterns + p.flatPatternPath + '/index.html', mainPageHeadHtml + viewAllHTML + footerHTML); }); @@ -533,22 +536,22 @@ var ui_builder = function () { } //render the footer needed for the viewall template - var footerHTML = buildFooterHTML(patternlab, 'viewall-' + patternType + '-all'); + const footerHTML = buildFooterHTML(patternlab, 'viewall-' + patternType + '-all'); //add any flat patterns //todo this isn't quite working yet //typePatterns = typePatterns.concat(getPatternItems(patternlab, patternType)); //get the appropriate patternType - var anyPatternOfType = _.find(typePatterns, function (pat) { + const anyPatternOfType = _.find(typePatterns, function (pat) { return pat.patternType && pat.patternType !== '';}); //render the viewall template for the type - var viewAllHTML = buildViewAllHTML(patternlab, typePatterns, patternType); + const viewAllHTML = buildViewAllHTML(patternlab, typePatterns, patternType); fs.outputFileSync(paths.public.patterns + anyPatternOfType.patternType + '/index.html', mainPageHeadHtml + viewAllHTML + footerHTML); //determine if we should omit this patterntype completely from the viewall page - var omitPatternType = styleGuideExcludes && styleGuideExcludes.length + const omitPatternType = styleGuideExcludes && styleGuideExcludes.length && _.some(styleGuideExcludes, function (exclude) { return exclude === patternType; }); @@ -568,11 +571,11 @@ var ui_builder = function () { * @param patternlab - global data store */ function exportData(patternlab) { - var annotation_exporter = new ae(patternlab); - var paths = patternlab.config.paths; + const annotation_exporter = new ae(patternlab); + const paths = patternlab.config.paths; //write out the data - var output = ''; + let output = ''; //config output += 'var config = ' + JSON.stringify(patternlab.config) + ';\n'; @@ -592,9 +595,6 @@ var ui_builder = function () { //plugins output += 'var plugins = ' + JSON.stringify(patternlab.plugins || []) + ';' + eol; - //theme - output += 'var theme = ' + JSON.stringify(patternlab.config.theme) + ';' + eol; - //smaller config elements output += 'var defaultShowPatternInfo = ' + (patternlab.config.defaultShowPatternInfo ? patternlab.config.defaultShowPatternInfo : 'false') + ';' + eol; output += 'var defaultPattern = "' + (patternlab.config.defaultPattern ? patternlab.config.defaultPattern : 'all') + '";' + eol; @@ -603,8 +603,8 @@ var ui_builder = function () { fs.outputFileSync(path.resolve(paths.public.data, 'patternlab-data.js'), output); //annotations - var annotationsJSON = annotation_exporter.gather(); - var annotations = 'var comments = { "comments" : ' + JSON.stringify(annotationsJSON) + '};'; + const annotationsJSON = annotation_exporter.gather(); + const annotations = 'var comments = { "comments" : ' + JSON.stringify(annotationsJSON) + '};'; fs.outputFileSync(path.resolve(paths.public.annotations, 'annotations.js'), annotations); } @@ -625,31 +625,31 @@ var ui_builder = function () { resetUIBuilderState(patternlab); - var paths = patternlab.config.paths; + const paths = patternlab.config.paths; //determine which patterns should be included in the front-end rendering - var styleguidePatterns = groupPatterns(patternlab); + const styleguidePatterns = groupPatterns(patternlab); //set the pattern-specific header by compiling the general-header with data, and then adding it to the meta header - var headerPartial = pattern_assembler.renderPattern(patternlab.header, { + const headerPartial = pattern_assembler.renderPattern(patternlab.header, { cacheBuster: patternlab.cacheBuster }); - var headFootData = patternlab.data; + const headFootData = patternlab.data; headFootData.patternLabHead = headerPartial; headFootData.cacheBuster = patternlab.cacheBuster; - var headerHTML = pattern_assembler.renderPattern(patternlab.userHead, headFootData); + const headerHTML = pattern_assembler.renderPattern(patternlab.userHead, headFootData); //set the pattern-specific footer by compiling the general-footer with data, and then adding it to the meta footer - var footerPartial = pattern_assembler.renderPattern(patternlab.footer, { + const footerPartial = pattern_assembler.renderPattern(patternlab.footer, { patternData: '{}', cacheBuster: patternlab.cacheBuster }); headFootData.patternLabFoot = footerPartial; - var footerHTML = pattern_assembler.renderPattern(patternlab.userFoot, headFootData); + const footerHTML = pattern_assembler.renderPattern(patternlab.userFoot, headFootData); //build the viewall pages - var allPatterns = buildViewAllPages(headerHTML, patternlab, styleguidePatterns); + const allPatterns = buildViewAllPages(headerHTML, patternlab, styleguidePatterns); //add the defaultPattern if we found one if (patternlab.defaultPattern) { @@ -658,7 +658,7 @@ var ui_builder = function () { } //build the main styleguide page - var styleguideHtml = pattern_assembler.renderPattern(patternlab.viewAll, + const styleguideHtml = pattern_assembler.renderPattern(patternlab.viewAll, { partials: allPatterns }, { @@ -668,7 +668,7 @@ var ui_builder = function () { fs.outputFileSync(path.resolve(paths.public.styleguide, 'html/styleguide.html'), headerHTML + styleguideHtml + footerHTML); //move the index file from its asset location into public root - var patternlabSiteHtml; + let patternlabSiteHtml; try { patternlabSiteHtml = fs.readFileSync(path.resolve(paths.source.styleguide, 'index.html'), 'utf8'); } catch (error) { diff --git a/core/lib/utilities.js b/core/lib/utilities.js index 28166a830..6c88dac90 100644 --- a/core/lib/utilities.js +++ b/core/lib/utilities.js @@ -1,7 +1,5 @@ "use strict"; -const fs = require('fs-extra'); -const path = require('path'); const chalk = require('chalk'); const EventEmitter = require('events').EventEmitter; @@ -49,105 +47,23 @@ const warning = log.warning.bind(log); */ const error = log.error.bind(log); - /** - * Shuffles an array in place. - * http://stackoverflow.com/questions/6274339/how-can-i-shuffle-an-array-in-javascript - * - * @param {Array} o - * @returns {Array} o - */ -const shuffle = function (o) { - /*eslint-disable curly*/ - for (var j, x, i = o.length; i; j = Math.floor(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x); - return o; -}; - /** - * Recursively merge properties of two objects. - * - * @param {Object} obj1 If obj1 has properties obj2 doesn't, add to obj2. - * @param {Object} obj2 This object's properties have priority over obj1. - * @returns {Object} obj2 + * Useful for reporting errors in .catch() on Promises + * @param {string} - a message to report + * @returns {function} - a callback to be passed to a Promise's .catch() */ -const mergeData = function (obj1, obj2) { - /*eslint-disable no-param-reassign, guard-for-in*/ - if (typeof obj2 === 'undefined') { - obj2 = {}; - } - for (var p in obj1) { - try { - // Only recurse if obj1[p] is an object. - if (obj1[p].constructor === Object) { - // Requires 2 objects as params; create obj2[p] if undefined. - if (typeof obj2[p] === 'undefined') { - obj2[p] = {}; - } - obj2[p] = mergeData(obj1[p], obj2[p]); - - // Pop when recursion meets a non-object. If obj1[p] is a non-object, - // only copy to undefined obj2[p]. This way, obj2 maintains priority. - } else if (typeof obj2[p] === 'undefined') { - obj2[p] = obj1[p]; - } - } catch (e) { - // Property in destination object not set; create it and set its value. - if (typeof obj2[p] === 'undefined') { - obj2[p] = obj1[p]; - } - } - } - return obj2; +const reportError = function (message) { + return function (err) { + console.log(message); + console.log(err); + }; }; -/** - * Determines whether or not an object is empty. - * - * @param {Object} obj - * @returns {Boolean} - */ -const isObjectEmpty = function (obj) { - for (var prop in obj) { - if (obj.hasOwnProperty(prop)) { return false; } - } - return true; -}; - -/** - * Recursively delete the contents of directory. - * Adapted from https://gist.github.com/tkihira/2367067 - * - * @param {string} dir - directory to empty - * @param {string} cleanDir - already empty directory - * @returns {undefined} - */ -const emptyDirectory = function (dir, cleanDir) { - var list = fs.readdirSync(dir); - for (var i = 0; i < list.length; i++) { - var filename = path.join(dir, list[i]); - var stat = fs.statSync(filename); - - if (filename === "." || filename === "..") { - // pass these files - } else if (stat.isDirectory()) { - this.emptyDirectory(filename); - } else { - // rm fiilename - fs.unlinkSync(filename); - } - } - if (cleanDir) { - fs.rmdirSync(dir); - } -}; module.exports = { debug, warning, error, log, - shuffle, - mergeData, - isObjectEmpty, - emptyDirectory + reportError }; - diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 000000000..8db5e864b --- /dev/null +++ b/package-lock.json @@ -0,0 +1,5363 @@ +{ + "name": "@pattern-lab/patternlab-node", + "version": "3.0.0-alpha.1", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "accepts": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.4.tgz", + "integrity": "sha1-hiRnWMfdbSGmR0/whKR0DsBesh8=", + "requires": { + "mime-types": "2.1.17", + "negotiator": "0.6.1" + } + }, + "any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" + }, + "anymatch": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", + "requires": { + "micromatch": "2.3.11", + "normalize-path": "2.1.1" + } + }, + "apache-crypt": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/apache-crypt/-/apache-crypt-1.2.1.tgz", + "integrity": "sha1-1vxyqm0n2ZyVqU/RiNcx7v/6Zjw=", + "requires": { + "unix-crypt-td-js": "1.0.0" + } + }, + "apache-md5": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/apache-md5/-/apache-md5-1.1.2.tgz", + "integrity": "sha1-7klza2ObTxCLbp5ibG2pkwa0FpI=" + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "requires": { + "arr-flatten": "1.1.0" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" + }, + "array-differ": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", + "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=" + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "requires": { + "array-uniq": "1.0.3" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=" + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=" + }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" + }, + "async": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/async/-/async-2.5.0.tgz", + "integrity": "sha512-e+lJAJeNWuPCNyxZKOBdaJGyLGHugXVQtrAwtuAe2vhxTYxFTKE73p8JuTmdH0qdQZtDvI4dhJwjZc5zsfIsYw==", + "requires": { + "lodash": "4.17.4" + }, + "dependencies": { + "lodash": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" + } + } + }, + "async-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", + "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=" + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "basic-auth": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.0.tgz", + "integrity": "sha1-AV2z81PgLlY3d1X5YnQuiYHnu7o=", + "requires": { + "safe-buffer": "5.1.1" + } + }, + "batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=" + }, + "bcryptjs": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", + "integrity": "sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms=" + }, + "binary-extensions": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.10.0.tgz", + "integrity": "sha1-muuabF6IY4qtFx4Wf1kAq+JINdA=" + }, + "brace-expansion": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "requires": { + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.2" + } + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "2.1.1" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + } + } + }, + "chokidar": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", + "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", + "requires": { + "anymatch": "1.3.2", + "async-each": "1.0.1", + "glob-parent": "2.0.0", + "inherits": "2.0.3", + "is-binary-path": "1.0.1", + "is-glob": "2.0.1", + "path-is-absolute": "1.0.1", + "readdirp": "2.1.0" + } + }, + "colors": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", + "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "connect": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.5.1.tgz", + "integrity": "sha1-bTDXpjx/FwhXprOqazY9lz3KWI4=", + "requires": { + "debug": "2.2.0", + "finalhandler": "0.5.1", + "parseurl": "1.3.2", + "utils-merge": "1.0.0" + } + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "cors": { + "version": "2.8.4", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.4.tgz", + "integrity": "sha1-K9OB8usgECAQXNUOpZ2mMJBpRoY=", + "requires": { + "object-assign": "4.1.1", + "vary": "1.1.2" + }, + "dependencies": { + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + } + } + }, + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "requires": { + "ms": "0.7.1" + } + }, + "del": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "requires": { + "globby": "5.0.0", + "is-path-cwd": "1.0.0", + "is-path-in-cwd": "1.0.0", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "rimraf": "2.6.2" + }, + "dependencies": { + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + } + } + }, + "depd": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", + "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "dive": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/dive/-/dive-0.5.0.tgz", + "integrity": "sha1-BtDgft0l2oSVmLrKtE1R8oCb7Ec=" + }, + "diveSync": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/diveSync/-/diveSync-0.3.0.tgz", + "integrity": "sha1-2ZgEk64zvuw29P7G8XH/IYEwzBI=", + "requires": { + "append": "0.1.1" + }, + "dependencies": { + "append": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/append/-/append-0.1.1.tgz", + "integrity": "sha1-fl3TJ3RweNh3KG+7Yksej00rOWs=" + } + } + }, + "duplexer": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", + "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=" + }, + "editorconfig": { + "version": "0.13.3", + "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.13.3.tgz", + "integrity": "sha512-WkjsUNVCu+ITKDj73QDvi0trvpdDWdkDyHybDGSXPfekLCqwmpD7CP7iPbvBgosNuLcI96XTDwNa75JyFl7tEQ==", + "requires": { + "bluebird": "3.5.1", + "commander": "2.11.0", + "lru-cache": "3.2.0", + "semver": "5.4.1", + "sigmund": "1.0.1" + }, + "dependencies": { + "bluebird": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", + "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==" + }, + "commander": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", + "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==" + }, + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==" + } + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "emitter-mixin": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/emitter-mixin/-/emitter-mixin-0.0.3.tgz", + "integrity": "sha1-WUjLKG8uSO3DslGnz8H3iDOW1lw=" + }, + "encodeurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz", + "integrity": "sha1-eePVhlU0aQn+bw9Fpd5oEDspTSA=" + }, + "errno": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.4.tgz", + "integrity": "sha1-uJbiOp5ei6M4cfyZar02NfyaHH0=", + "requires": { + "prr": "0.0.0" + } + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "eslint": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-3.5.0.tgz", + "integrity": "sha1-IvyfeA6lvKEwb6srbTM2sPpix1Q=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "concat-stream": "1.6.0", + "debug": "2.6.9", + "doctrine": "1.5.0", + "escope": "3.6.0", + "espree": "3.5.1", + "estraverse": "4.2.0", + "esutils": "2.0.2", + "file-entry-cache": "2.0.0", + "glob": "7.1.2", + "globals": "9.18.0", + "ignore": "3.3.5", + "imurmurhash": "0.1.4", + "inquirer": "0.12.0", + "is-my-json-valid": "2.16.1", + "is-resolvable": "1.0.0", + "js-yaml": "3.10.0", + "json-stable-stringify": "1.0.1", + "levn": "0.3.0", + "lodash": "4.13.1", + "mkdirp": "0.5.1", + "natural-compare": "1.4.0", + "optionator": "0.8.2", + "path-is-inside": "1.0.2", + "pluralize": "1.2.1", + "progress": "1.1.8", + "require-uncached": "1.0.3", + "shelljs": "0.6.1", + "strip-bom": "3.0.0", + "strip-json-comments": "1.0.4", + "table": "3.8.3", + "text-table": "0.2.0", + "user-home": "2.0.0" + }, + "dependencies": { + "acorn": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.1.2.tgz", + "integrity": "sha512-o96FZLJBPY1lvTuJylGA9Bk3t/GKPPJG8H0ydQQl01crzwJgspa4AEIq/pVTXigmK0PHVQhiAtn8WMBLL9D2WA==", + "dev": true + }, + "acorn-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", + "dev": true, + "requires": { + "acorn": "3.3.0" + }, + "dependencies": { + "acorn": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", + "dev": true + } + } + }, + "ajv": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "dev": true, + "requires": { + "co": "4.6.0", + "json-stable-stringify": "1.0.1" + } + }, + "ajv-keywords": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz", + "integrity": "sha1-MU3QpLM2j609/NxU7eYXG4htrzw=", + "dev": true + }, + "ansi-escapes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", + "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "1.0.3" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "caller-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", + "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", + "dev": true, + "requires": { + "callsites": "0.2.0" + } + }, + "callsites": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", + "dev": true + }, + "circular-json": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", + "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", + "dev": true + }, + "cli-cursor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", + "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", + "dev": true, + "requires": { + "restore-cursor": "1.0.1" + } + }, + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", + "dev": true + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "concat-stream": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", + "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.3", + "typedarray": "0.0.6" + } + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "d": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", + "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", + "dev": true, + "requires": { + "es5-ext": "0.10.30" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "del": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "dev": true, + "requires": { + "globby": "5.0.0", + "is-path-cwd": "1.0.0", + "is-path-in-cwd": "1.0.0", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "rimraf": "2.6.2" + } + }, + "doctrine": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "dev": true, + "requires": { + "esutils": "2.0.2", + "isarray": "1.0.0" + } + }, + "es5-ext": { + "version": "0.10.30", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.30.tgz", + "integrity": "sha1-cUGhaDZpfbq/qq7uQUlc4p9SyTk=", + "dev": true, + "requires": { + "es6-iterator": "2.0.1", + "es6-symbol": "3.1.1" + } + }, + "es6-iterator": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.1.tgz", + "integrity": "sha1-jjGcnwRTv1ddN0lAplWSDlnKVRI=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.30", + "es6-symbol": "3.1.1" + } + }, + "es6-map": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", + "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.30", + "es6-iterator": "2.0.1", + "es6-set": "0.1.5", + "es6-symbol": "3.1.1", + "event-emitter": "0.3.5" + } + }, + "es6-set": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", + "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.30", + "es6-iterator": "2.0.1", + "es6-symbol": "3.1.1", + "event-emitter": "0.3.5" + } + }, + "es6-symbol": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", + "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.30" + } + }, + "es6-weak-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", + "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.30", + "es6-iterator": "2.0.1", + "es6-symbol": "3.1.1" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "escope": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", + "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", + "dev": true, + "requires": { + "es6-map": "0.1.5", + "es6-weak-map": "2.0.2", + "esrecurse": "4.2.0", + "estraverse": "4.2.0" + } + }, + "espree": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.1.tgz", + "integrity": "sha1-DJiLirRttTEAoZVK5LqZXd0n2H4=", + "dev": true, + "requires": { + "acorn": "5.1.2", + "acorn-jsx": "3.0.1" + } + }, + "esrecurse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz", + "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=", + "dev": true, + "requires": { + "estraverse": "4.2.0", + "object-assign": "4.1.1" + } + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.30" + } + }, + "exit-hook": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", + "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true, + "requires": { + "escape-string-regexp": "1.0.5", + "object-assign": "4.1.1" + } + }, + "file-entry-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", + "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", + "dev": true, + "requires": { + "flat-cache": "1.3.0", + "object-assign": "4.1.1" + } + }, + "flat-cache": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", + "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", + "dev": true, + "requires": { + "circular-json": "0.3.3", + "del": "2.2.2", + "graceful-fs": "4.1.11", + "write": "0.2.1" + } + }, + "generate-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", + "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", + "dev": true + }, + "generate-object-property": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", + "dev": true, + "requires": { + "is-property": "1.0.2" + } + }, + "globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "dev": true + }, + "globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "dev": true, + "requires": { + "array-union": "1.0.2", + "arrify": "1.0.1", + "glob": "7.1.2", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "ignore": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.5.tgz", + "integrity": "sha512-JLH93mL8amZQhh/p6mfQgVBH3M6epNq3DfsXsTSuSrInVjwyYlFE1nv2AgfRCC8PoOhM0jwQ5v8s9LgbK7yGDw==", + "dev": true + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "inquirer": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz", + "integrity": "sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=", + "dev": true, + "requires": { + "ansi-escapes": "1.4.0", + "ansi-regex": "2.1.1", + "chalk": "1.1.3", + "cli-cursor": "1.0.2", + "cli-width": "2.2.0", + "figures": "1.7.0", + "lodash": "4.13.1", + "readline2": "1.0.1", + "run-async": "0.1.0", + "rx-lite": "3.1.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "through": "2.3.8" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-my-json-valid": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.16.1.tgz", + "integrity": "sha512-ochPsqWS1WXj8ZnMIV0vnNXooaMhp7cyL4FMSIPKTtnV0Ha/T19G2b9kkhcNsabV9bxYkze7/aLZJb/bYuFduQ==", + "dev": true, + "requires": { + "generate-function": "2.0.0", + "generate-object-property": "1.2.0", + "jsonpointer": "4.0.1", + "xtend": "4.0.1" + } + }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "dev": true + }, + "is-path-in-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", + "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", + "dev": true, + "requires": { + "is-path-inside": "1.0.0" + } + }, + "is-path-inside": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz", + "integrity": "sha1-/AbloWg/vaE95mev9xe7wQpI838=", + "dev": true, + "requires": { + "path-is-inside": "1.0.2" + } + }, + "is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", + "dev": true + }, + "is-resolvable": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.0.0.tgz", + "integrity": "sha1-jfV8YeouPFAUCNEA+wE8+NbgzGI=", + "dev": true, + "requires": { + "tryit": "1.0.3" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "dev": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true + }, + "jsonpointer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", + "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", + "dev": true + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "1.1.2", + "type-check": "0.3.2" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "mute-stream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz", + "integrity": "sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=", + "dev": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "onetime": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", + "dev": true + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true, + "requires": { + "deep-is": "0.1.3", + "fast-levenshtein": "2.0.6", + "levn": "0.3.0", + "prelude-ls": "1.1.2", + "type-check": "0.3.2", + "wordwrap": "1.0.0" + } + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "2.0.4" + } + }, + "pluralize": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-1.2.1.tgz", + "integrity": "sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU=", + "dev": true + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "progress": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", + "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", + "dev": true + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "readline2": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/readline2/-/readline2-1.0.1.tgz", + "integrity": "sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "mute-stream": "0.0.5" + } + }, + "require-uncached": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", + "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", + "dev": true, + "requires": { + "caller-path": "0.1.0", + "resolve-from": "1.0.1" + } + }, + "resolve-from": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", + "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", + "dev": true + }, + "restore-cursor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", + "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", + "dev": true, + "requires": { + "exit-hook": "1.1.1", + "onetime": "1.1.0" + } + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "dev": true, + "requires": { + "glob": "7.1.2" + } + }, + "run-async": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz", + "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=", + "dev": true, + "requires": { + "once": "1.4.0" + } + }, + "rx-lite": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz", + "integrity": "sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=", + "dev": true + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", + "dev": true + }, + "shelljs": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.6.1.tgz", + "integrity": "sha1-7GIRvtGSBEIIj+D3Cyg3Iy7SyKg=", + "dev": true + }, + "slice-ansi": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", + "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", + "dev": true + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "strip-json-comments": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz", + "integrity": "sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E=", + "dev": true + }, + "table": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/table/-/table-3.8.3.tgz", + "integrity": "sha1-K7xULw/amGGnVdOUf+/Ys/UThV8=", + "dev": true, + "requires": { + "ajv": "4.11.8", + "ajv-keywords": "1.5.1", + "chalk": "1.1.3", + "lodash": "4.13.1", + "slice-ansi": "0.0.4", + "string-width": "2.1.1" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + } + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "tryit": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tryit/-/tryit-1.0.3.tgz", + "integrity": "sha1-OTvnMKlEb9Hq1tpZoBQwjzbCics=", + "dev": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "1.1.2" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "user-home": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz", + "integrity": "sha1-nHC/2Babwdy/SGBODwS4tJzenp8=", + "dev": true, + "requires": { + "os-homedir": "1.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "write": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", + "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "dev": true, + "requires": { + "mkdirp": "0.5.1" + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + } + } + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + }, + "event-stream": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", + "requires": { + "duplexer": "0.1.1", + "from": "0.1.7", + "map-stream": "0.1.0", + "pause-stream": "0.0.11", + "split": "0.3.3", + "stream-combiner": "0.0.4", + "through": "2.3.8" + } + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "requires": { + "is-posix-bracket": "0.1.1" + } + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "requires": { + "fill-range": "2.2.3" + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "requires": { + "is-extglob": "1.0.0" + } + }, + "faye-websocket": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.1.tgz", + "integrity": "sha1-8O/hjE9W5PQK/H4Gxxn9XuYYjzg=", + "requires": { + "websocket-driver": "0.7.0" + } + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=" + }, + "fill-range": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", + "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", + "requires": { + "is-number": "2.1.0", + "isobject": "2.1.0", + "randomatic": "1.1.7", + "repeat-element": "1.1.2", + "repeat-string": "1.6.1" + } + }, + "finalhandler": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-0.5.1.tgz", + "integrity": "sha1-LEANjUUwk1vCMlScX6OF7Afeb80=", + "requires": { + "debug": "2.2.0", + "escape-html": "1.0.3", + "on-finished": "2.3.0", + "statuses": "1.3.1", + "unpipe": "1.0.0" + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" + }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "requires": { + "for-in": "1.0.2" + } + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + }, + "from": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", + "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=" + }, + "fs-extra": { + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", + "integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=", + "requires": { + "graceful-fs": "4.1.11", + "jsonfile": "2.4.0", + "klaw": "1.3.1", + "path-is-absolute": "1.0.1", + "rimraf": "2.6.2" + }, + "dependencies": { + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + }, + "jsonfile": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", + "requires": { + "graceful-fs": "4.1.11" + } + }, + "klaw": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", + "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", + "requires": { + "graceful-fs": "4.1.11" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "requires": { + "glob": "7.1.2" + } + } + } + }, + "fs-promise": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-promise/-/fs-promise-1.0.0.tgz", + "integrity": "sha1-QkakzUVJfS7Vfm5LIhZ9OGSyNnk=", + "requires": { + "any-promise": "1.3.0", + "fs-extra": "1.0.0", + "mz": "2.7.0", + "thenify-all": "1.6.0" + }, + "dependencies": { + "fs-extra": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-1.0.0.tgz", + "integrity": "sha1-zTzl9+fLYUWIP8rjGR6Yd/hYeVA=", + "requires": { + "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "jsonfile": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "klaw": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz" + } + } + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + }, + "dependencies": { + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "brace-expansion": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "1.1.8" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + } + } + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "requires": { + "glob-parent": "2.0.0", + "is-glob": "2.0.1" + } + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "requires": { + "is-glob": "2.0.1" + } + }, + "globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "requires": { + "array-union": "1.0.2", + "arrify": "1.0.1", + "glob": "7.1.2", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + }, + "dependencies": { + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + } + } + }, + "graceful-fs": { + "version": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + }, + "graphlib": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/graphlib/-/graphlib-2.1.1.tgz", + "integrity": "sha1-QjUsUrovTQNctWbrkfc5X3bryVE=", + "requires": { + "lodash": "4.13.1" + } + }, + "http-auth": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/http-auth/-/http-auth-3.1.3.tgz", + "integrity": "sha1-lFz63WZSHq+PfISRPTd9exXyTjE=", + "requires": { + "apache-crypt": "1.2.1", + "apache-md5": "1.1.2", + "bcryptjs": "2.4.3", + "uuid": "3.1.0" + } + }, + "http-errors": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", + "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", + "requires": { + "depd": "1.1.1", + "inherits": "2.0.3", + "setprototypeof": "1.0.3", + "statuses": "1.3.1" + } + }, + "http-parser-js": { + "version": "0.4.9", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.9.tgz", + "integrity": "sha1-6hoE+2St/wJC6ZdPKX3Uw8rSceE=" + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "requires": { + "binary-extensions": "1.10.0" + } + }, + "is-buffer": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz", + "integrity": "sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw=" + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=" + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "requires": { + "is-primitive": "2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=" + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "requires": { + "is-extglob": "1.0.0" + } + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "requires": { + "kind-of": "3.2.2" + } + }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=" + }, + "is-path-in-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", + "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", + "requires": { + "is-path-inside": "1.0.0" + } + }, + "is-path-inside": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz", + "integrity": "sha1-/AbloWg/vaE95mev9xe7wQpI838=", + "requires": { + "path-is-inside": "1.0.2" + } + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=" + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=" + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "requires": { + "isarray": "1.0.0" + } + }, + "js-beautify": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.7.3.tgz", + "integrity": "sha512-mT9skIu0OWfBQPXOGJ4CgpPBgo3tj9gxi7weQdeaxxmpKIADK2g0xS0qCtQml7Ny3Ick5Cno093LKGZTzDd2UQ==", + "requires": { + "config-chain": "1.1.11", + "editorconfig": "0.13.3", + "mkdirp": "0.5.1", + "nopt": "3.0.6" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "config-chain": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.11.tgz", + "integrity": "sha1-q6CXR9++TD5w52am5BWG4YWfxvI=", + "requires": { + "ini": "1.3.4", + "proto-list": "1.2.4" + } + }, + "ini": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz", + "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=" + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + } + }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "requires": { + "abbrev": "1.1.1" + } + }, + "proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=" + } + } + }, + "js-yaml": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", + "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==", + "requires": { + "argparse": "1.0.9", + "esprima": "4.0.0" + }, + "dependencies": { + "argparse": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", + "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", + "requires": { + "sprintf-js": "1.0.3" + } + }, + "esprima": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==" + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + } + } + }, + "jsonfile": { + "version": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", + "requires": { + "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz" + } + }, + "junk": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/junk/-/junk-1.0.3.tgz", + "integrity": "sha1-h75jSIZJy9ym9Tqzm+yczSNH9ZI=" + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.5" + } + }, + "klaw": { + "version": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", + "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", + "requires": { + "graceful-fs": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz" + } + }, + "live-server": { + "version": "github:pattern-lab/live-server#d46ec211455efb0ae2ad140b09e151bc2649c496", + "requires": { + "chokidar": "1.7.0", + "colors": "1.1.2", + "connect": "3.5.1", + "cors": "2.8.4", + "event-stream": "3.3.4", + "faye-websocket": "0.11.1", + "http-auth": "3.1.3", + "morgan": "1.9.0", + "object-assign": "4.1.1", + "opn": "5.1.0", + "proxy-middleware": "0.15.0", + "send": "0.16.1", + "serve-index": "1.9.1" + }, + "dependencies": { + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + } + } + }, + "lodash": { + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.13.1.tgz", + "integrity": "sha1-g+SxCRP0hJbU0W/sSlYK8u50S2g=" + }, + "lru-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-3.2.0.tgz", + "integrity": "sha1-cXibO39Tmb7IVl3aOKow0qCX7+4=", + "requires": { + "pseudomap": "1.0.2" + }, + "dependencies": { + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + } + } + }, + "map-stream": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", + "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=" + }, + "markdown-it": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-6.1.1.tgz", + "integrity": "sha1-ztA39Ec+6fUVOsQU933IPJG6knw=", + "requires": { + "argparse": "1.0.9", + "entities": "1.1.1", + "linkify-it": "1.2.4", + "mdurl": "1.0.1", + "uc.micro": "1.0.3" + }, + "dependencies": { + "argparse": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", + "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", + "requires": { + "sprintf-js": "1.0.3" + } + }, + "entities": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", + "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=" + }, + "linkify-it": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-1.2.4.tgz", + "integrity": "sha1-B3NSbDF8j9E71TTuHRgP+Iq/iBo=", + "requires": { + "uc.micro": "1.0.3" + } + }, + "mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=" + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + }, + "uc.micro": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.3.tgz", + "integrity": "sha1-ftUNXg+an7ClczeSWfKndFjVAZI=" + } + } + }, + "maximatch": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/maximatch/-/maximatch-0.1.0.tgz", + "integrity": "sha1-hs2NawTJ8wfAWmuUGZBtA2D7E6I=", + "requires": { + "array-differ": "1.0.0", + "array-union": "1.0.2", + "arrify": "1.0.1", + "minimatch": "3.0.4" + } + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "requires": { + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.4" + } + }, + "mime": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" + }, + "mime-db": { + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", + "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=" + }, + "mime-types": { + "version": "2.1.17", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", + "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", + "requires": { + "mime-db": "1.30.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "1.1.8" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + } + }, + "morgan": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.9.0.tgz", + "integrity": "sha1-0B+mxlhZt2/PMbPLU6OCGjEdgFE=", + "requires": { + "basic-auth": "2.0.0", + "debug": "2.6.9", + "depd": "1.1.1", + "on-finished": "2.3.0", + "on-headers": "1.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=" + }, + "mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "requires": { + "any-promise": "1.3.0", + "object-assign": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "thenify-all": "1.6.0" + } + }, + "negotiator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" + }, + "node-fetch": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", + "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", + "requires": { + "encoding": "0.1.12", + "is-stream": "1.1.0" + }, + "dependencies": { + "encoding": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", + "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", + "requires": { + "iconv-lite": "0.4.19" + } + }, + "iconv-lite": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + } + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "requires": { + "remove-trailing-separator": "1.1.0" + } + }, + "object-assign": { + "version": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "requires": { + "for-own": "0.1.5", + "is-extendable": "0.1.1" + } + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", + "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=" + }, + "opn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/opn/-/opn-5.1.0.tgz", + "integrity": "sha512-iPNl7SyM8L30Rm1sjGdLLheyHVw5YXVfi3SKWJzBI7efxRwHojfRFjwE/OLM6qp9xJYMgab8WicTU1cPoY+Hpg==", + "requires": { + "is-wsl": "1.1.0" + } + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "requires": { + "glob-base": "0.3.0", + "is-dotfile": "1.0.3", + "is-extglob": "1.0.0", + "is-glob": "2.0.1" + } + }, + "parseurl": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=" + }, + "pause-stream": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", + "requires": { + "through": "2.3.8" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "requires": { + "pinkie": "2.0.4" + } + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=" + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" + }, + "promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "requires": { + "asap": "2.0.6" + } + }, + "proxy-middleware": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/proxy-middleware/-/proxy-middleware-0.15.0.tgz", + "integrity": "sha1-o/3xvvtzD5UZZYcqwvYHTGFHelY=" + }, + "prr": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/prr/-/prr-0.0.0.tgz", + "integrity": "sha1-GoS4WQgyVQFBGFPQCB7j+obikmo=" + }, + "randomatic": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", + "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.5" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "requires": { + "is-buffer": "1.1.5" + } + } + } + }, + "range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "readdirp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", + "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", + "requires": { + "graceful-fs": "4.1.11", + "minimatch": "3.0.4", + "readable-stream": "2.3.3", + "set-immediate-shim": "1.0.1" + }, + "dependencies": { + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + } + } + }, + "recursive-copy": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/recursive-copy/-/recursive-copy-2.0.6.tgz", + "integrity": "sha1-1ZD5618WW5ahuAvI+cvLXG+ciek=", + "requires": { + "del": "2.2.2", + "emitter-mixin": "0.0.3", + "errno": "0.1.4", + "graceful-fs": "4.1.11", + "junk": "1.0.3", + "maximatch": "0.1.0", + "mkdirp": "0.5.1", + "pify": "2.3.0", + "promise": "7.3.1", + "slash": "1.0.0" + }, + "dependencies": { + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + } + } + }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "requires": { + "is-equal-shallow": "0.1.3" + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" + }, + "repeat-element": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=" + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" + }, + "rewire": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/rewire/-/rewire-2.5.2.tgz", + "integrity": "sha1-ZCfee3/u+n02QBUH62SlOFvFjcc=", + "dev": true + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "requires": { + "glob": "7.1.2" + } + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + }, + "send": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.16.1.tgz", + "integrity": "sha512-ElCLJdJIKPk6ux/Hocwhk7NFHpI3pVm/IZOYWqUmoxcgeyM+MpxHHKhb8QmlJDX1pU6WrgaHBkVNm73Sv7uc2A==", + "requires": { + "debug": "2.6.9", + "depd": "1.1.1", + "destroy": "1.0.4", + "encodeurl": "1.0.1", + "escape-html": "1.0.3", + "etag": "1.8.1", + "fresh": "0.5.2", + "http-errors": "1.6.2", + "mime": "1.4.1", + "ms": "2.0.0", + "on-finished": "2.3.0", + "range-parser": "1.2.0", + "statuses": "1.3.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, + "serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", + "requires": { + "accepts": "1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "1.0.3", + "http-errors": "1.6.2", + "mime-types": "2.1.17", + "parseurl": "1.3.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + }, + "set-immediate-shim": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=" + }, + "setprototypeof": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", + "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=" + }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=" + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=" + }, + "split": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", + "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", + "requires": { + "through": "2.3.8" + } + }, + "statuses": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", + "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=" + }, + "stream-combiner": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", + "requires": { + "duplexer": "0.1.1" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "requires": { + "safe-buffer": "5.1.1" + } + }, + "tap": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/tap/-/tap-7.1.2.tgz", + "integrity": "sha1-36w+zxSshUe7rSW70Wzyw3Q/Zc8=", + "dev": true, + "requires": { + "bluebird": "3.5.1", + "clean-yaml-object": "0.1.0", + "color-support": "1.1.3", + "coveralls": "2.13.3", + "deeper": "2.1.0", + "foreground-child": "1.5.6", + "glob": "7.1.2", + "isexe": "1.1.2", + "js-yaml": "3.10.0", + "nyc": "7.1.0", + "only-shallow": "1.2.0", + "opener": "1.4.3", + "os-homedir": "1.0.1", + "readable-stream": "2.3.3", + "signal-exit": "3.0.2", + "stack-utils": "0.4.0", + "tap-mocha-reporter": "2.0.1", + "tap-parser": "2.2.3", + "tmatch": "2.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "argparse": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", + "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", + "dev": true, + "requires": { + "sprintf-js": "1.0.3" + } + }, + "asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", + "dev": true + }, + "assert-plus": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", + "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "aws-sign2": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", + "dev": true + }, + "aws4": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "dev": true, + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "bluebird": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", + "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==", + "dev": true + }, + "boom": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "caseless": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", + "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=", + "dev": true + }, + "clean-yaml-object": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/clean-yaml-object/-/clean-yaml-object-0.1.0.tgz", + "integrity": "sha1-Y/sRDcLOGoTcIfbZM0h20BCui2g=", + "dev": true + }, + "color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true + }, + "combined-stream": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", + "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", + "dev": true, + "requires": { + "delayed-stream": "1.0.0" + } + }, + "commander": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", + "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "coveralls": { + "version": "2.13.3", + "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-2.13.3.tgz", + "integrity": "sha512-iiAmn+l1XqRwNLXhW8Rs5qHZRFMYp9ZIPjEOVRpC/c4so6Y/f4/lFi0FfR5B9cCqgyhkJ5cZmbvcVRfP8MHchw==", + "dev": true, + "requires": { + "js-yaml": "3.6.1", + "lcov-parse": "0.0.10", + "log-driver": "1.2.5", + "minimist": "1.2.0", + "request": "2.79.0" + }, + "dependencies": { + "js-yaml": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.6.1.tgz", + "integrity": "sha1-bl/mfYsgXOTSL60Ft3geja3MSzA=", + "dev": true, + "requires": { + "argparse": "1.0.9", + "esprima": "2.7.3" + } + } + } + }, + "cross-spawn": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.2.tgz", + "integrity": "sha1-e5JHYhwjrf3ThWAEqCPL45dCTUE=", + "dev": true, + "requires": { + "lru-cache": "4.1.1", + "which": "1.3.0" + } + }, + "cryptiles": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", + "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", + "dev": true, + "requires": { + "boom": "2.10.1" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "deeper": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/deeper/-/deeper-2.1.0.tgz", + "integrity": "sha1-vFZOX3MXT98gHgiwADDooU2nQ2g=", + "dev": true + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "diff": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-1.4.0.tgz", + "integrity": "sha1-fyjS657nsVqX79ic5j3P2qPMur8=", + "dev": true + }, + "ecc-jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "dev": true + }, + "events-to-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/events-to-array/-/events-to-array-1.1.2.tgz", + "integrity": "sha1-LUH1Y+H+QA7Uli/hpNXGp1Od9/Y=", + "dev": true + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", + "dev": true + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true + }, + "foreground-child": { + "version": "1.5.6", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-1.5.6.tgz", + "integrity": "sha1-T9ca0t/elnibmApcCilZN8svXOk=", + "dev": true, + "requires": { + "cross-spawn": "4.0.2", + "signal-exit": "3.0.2" + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "form-data": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", + "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", + "dev": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.17" + } + }, + "generate-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", + "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", + "dev": true + }, + "generate-object-property": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", + "dev": true, + "requires": { + "is-property": "1.0.2" + } + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "har-validator": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", + "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "commander": "2.11.0", + "is-my-json-valid": "2.16.1", + "pinkie-promise": "2.0.1" + } + }, + "hawk": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", + "dev": true, + "requires": { + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" + } + }, + "hoek": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", + "dev": true + }, + "http-signature": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", + "dev": true, + "requires": { + "assert-plus": "0.2.0", + "jsprim": "1.4.1", + "sshpk": "1.13.1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "is-my-json-valid": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.16.1.tgz", + "integrity": "sha512-ochPsqWS1WXj8ZnMIV0vnNXooaMhp7cyL4FMSIPKTtnV0Ha/T19G2b9kkhcNsabV9bxYkze7/aLZJb/bYuFduQ==", + "dev": true, + "requires": { + "generate-function": "2.0.0", + "generate-object-property": "1.2.0", + "jsonpointer": "4.0.1", + "xtend": "4.0.1" + } + }, + "is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", + "dev": true + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isexe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-1.1.2.tgz", + "integrity": "sha1-NvPiLmB1CSD15yQaR2qMakInWtA=", + "dev": true + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true, + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "jsonpointer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", + "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", + "dev": true + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "lcov-parse": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-0.0.10.tgz", + "integrity": "sha1-GwuP+ayceIklBYK3C3ExXZ2m2aM=", + "dev": true + }, + "log-driver": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.5.tgz", + "integrity": "sha1-euTsJXMC/XkNVXyxDJcQDYV7AFY=", + "dev": true + }, + "lru-cache": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", + "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", + "dev": true, + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" + } + }, + "mime-db": { + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", + "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=", + "dev": true + }, + "mime-types": { + "version": "2.1.17", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", + "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", + "dev": true, + "requires": { + "mime-db": "1.30.0" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "nyc": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/nyc/-/nyc-7.1.0.tgz", + "integrity": "sha1-jhSXHzoV0au+x6xhDvVMuInp/7Q=", + "dev": true, + "requires": { + "arrify": "1.0.1", + "caching-transform": "1.0.1", + "convert-source-map": "1.3.0", + "default-require-extensions": "1.0.0", + "find-cache-dir": "0.1.1", + "find-up": "1.1.2", + "foreground-child": "1.5.3", + "glob": "7.0.5", + "istanbul-lib-coverage": "1.0.0-alpha.4", + "istanbul-lib-hook": "1.0.0-alpha.4", + "istanbul-lib-instrument": "1.1.0-alpha.4", + "istanbul-lib-report": "1.0.0-alpha.3", + "istanbul-lib-source-maps": "1.0.0-alpha.10", + "istanbul-reports": "1.0.0-alpha.8", + "md5-hex": "1.3.0", + "micromatch": "2.3.11", + "mkdirp": "0.5.1", + "pkg-up": "1.0.0", + "resolve-from": "2.0.0", + "rimraf": "2.5.4", + "signal-exit": "3.0.0", + "spawn-wrap": "1.2.4", + "test-exclude": "1.1.0", + "yargs": "4.8.1", + "yargs-parser": "2.4.1" + }, + "dependencies": { + "align-text": { + "version": "0.1.4", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "3.0.3", + "longest": "1.0.1", + "repeat-string": "1.5.4" + } + }, + "amdefine": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "ansi-regex": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "bundled": true, + "dev": true + }, + "append-transform": { + "version": "0.3.0", + "bundled": true, + "dev": true + }, + "arr-diff": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "requires": { + "arr-flatten": "1.0.1" + } + }, + "arr-flatten": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "array-unique": { + "version": "0.2.1", + "bundled": true, + "dev": true + }, + "arrify": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "async": { + "version": "1.5.2", + "bundled": true, + "dev": true + }, + "babel-code-frame": { + "version": "6.11.0", + "bundled": true, + "dev": true, + "requires": { + "babel-runtime": "6.9.2", + "chalk": "1.1.3", + "esutils": "2.0.2", + "js-tokens": "2.0.0" + } + }, + "babel-generator": { + "version": "6.11.4", + "bundled": true, + "dev": true, + "requires": { + "babel-messages": "6.8.0", + "babel-runtime": "6.9.2", + "babel-types": "6.11.1", + "detect-indent": "3.0.1", + "lodash": "4.13.1", + "source-map": "0.5.6" + } + }, + "babel-messages": { + "version": "6.8.0", + "bundled": true, + "dev": true, + "requires": { + "babel-runtime": "6.9.2" + } + }, + "babel-runtime": { + "version": "6.9.2", + "bundled": true, + "dev": true, + "requires": { + "core-js": "2.4.1", + "regenerator-runtime": "0.9.5" + } + }, + "babel-template": { + "version": "6.9.0", + "bundled": true, + "dev": true, + "requires": { + "babel-runtime": "6.9.2", + "babel-traverse": "6.11.4", + "babel-types": "6.11.1", + "babylon": "6.8.4", + "lodash": "4.13.1" + } + }, + "babel-traverse": { + "version": "6.11.4", + "bundled": true, + "dev": true, + "requires": { + "babel-code-frame": "6.11.0", + "babel-messages": "6.8.0", + "babel-runtime": "6.9.2", + "babel-types": "6.11.1", + "babylon": "6.8.4", + "debug": "2.2.0", + "globals": "8.18.0", + "invariant": "2.2.1", + "lodash": "4.13.1" + } + }, + "babel-types": { + "version": "6.11.1", + "bundled": true, + "dev": true, + "requires": { + "babel-runtime": "6.9.2", + "babel-traverse": "6.11.4", + "esutils": "2.0.2", + "lodash": "4.13.1", + "to-fast-properties": "1.0.2" + } + }, + "babylon": { + "version": "6.8.4", + "bundled": true, + "dev": true, + "requires": { + "babel-runtime": "6.9.2" + } + }, + "balanced-match": { + "version": "0.4.2", + "bundled": true, + "dev": true + }, + "brace-expansion": { + "version": "1.1.6", + "bundled": true, + "dev": true, + "requires": { + "balanced-match": "0.4.2", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "1.8.5", + "bundled": true, + "dev": true, + "requires": { + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.2" + } + }, + "builtin-modules": { + "version": "1.1.1", + "bundled": true, + "dev": true + }, + "caching-transform": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "md5-hex": "1.3.0", + "mkdirp": "0.5.1", + "write-file-atomic": "1.1.4" + } + }, + "camelcase": { + "version": "1.2.1", + "bundled": true, + "dev": true, + "optional": true + }, + "center-align": { + "version": "0.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "align-text": "0.1.4", + "lazy-cache": "1.0.4" + } + }, + "chalk": { + "version": "1.1.3", + "bundled": true, + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "cliui": { + "version": "2.1.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "center-align": "0.1.3", + "right-align": "0.1.3", + "wordwrap": "0.0.2" + }, + "dependencies": { + "wordwrap": { + "version": "0.0.2", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "code-point-at": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "1.0.0" + } + }, + "commondir": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true + }, + "convert-source-map": { + "version": "1.3.0", + "bundled": true, + "dev": true + }, + "core-js": { + "version": "2.4.1", + "bundled": true, + "dev": true + }, + "cross-spawn": { + "version": "4.0.0", + "bundled": true, + "dev": true, + "requires": { + "lru-cache": "4.0.1", + "which": "1.2.10" + } + }, + "debug": { + "version": "2.2.0", + "bundled": true, + "dev": true, + "requires": { + "ms": "0.7.1" + } + }, + "decamelize": { + "version": "1.2.0", + "bundled": true, + "dev": true + }, + "default-require-extensions": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "strip-bom": "2.0.0" + } + }, + "detect-indent": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "get-stdin": "4.0.1", + "minimist": "1.2.0", + "repeating": "1.1.3" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true + } + } + }, + "error-ex": { + "version": "1.3.0", + "bundled": true, + "dev": true, + "requires": { + "is-arrayish": "0.2.1" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "bundled": true, + "dev": true + }, + "esutils": { + "version": "2.0.2", + "bundled": true, + "dev": true + }, + "expand-brackets": { + "version": "0.1.5", + "bundled": true, + "dev": true, + "requires": { + "is-posix-bracket": "0.1.1" + } + }, + "expand-range": { + "version": "1.8.2", + "bundled": true, + "dev": true, + "requires": { + "fill-range": "2.2.3" + } + }, + "extglob": { + "version": "0.3.2", + "bundled": true, + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "filename-regex": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "fill-range": { + "version": "2.2.3", + "bundled": true, + "dev": true, + "requires": { + "is-number": "2.1.0", + "isobject": "2.1.0", + "randomatic": "1.1.5", + "repeat-element": "1.1.2", + "repeat-string": "1.5.4" + } + }, + "find-cache-dir": { + "version": "0.1.1", + "bundled": true, + "dev": true, + "requires": { + "commondir": "1.0.1", + "mkdirp": "0.5.1", + "pkg-dir": "1.0.0" + } + }, + "find-up": { + "version": "1.1.2", + "bundled": true, + "dev": true, + "requires": { + "path-exists": "2.1.0", + "pinkie-promise": "2.0.1" + } + }, + "for-in": { + "version": "0.1.5", + "bundled": true, + "dev": true + }, + "for-own": { + "version": "0.1.4", + "bundled": true, + "dev": true, + "requires": { + "for-in": "0.1.5" + } + }, + "foreground-child": { + "version": "1.5.3", + "bundled": true, + "dev": true, + "requires": { + "cross-spawn": "4.0.0", + "signal-exit": "3.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "get-caller-file": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "get-stdin": { + "version": "4.0.1", + "bundled": true, + "dev": true + }, + "glob": { + "version": "7.0.5", + "bundled": true, + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.5", + "inherits": "2.0.1", + "minimatch": "3.0.2", + "once": "1.3.3", + "path-is-absolute": "1.0.0" + } + }, + "glob-base": { + "version": "0.3.0", + "bundled": true, + "dev": true, + "requires": { + "glob-parent": "2.0.0", + "is-glob": "2.0.1" + } + }, + "glob-parent": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "requires": { + "is-glob": "2.0.1" + } + }, + "globals": { + "version": "8.18.0", + "bundled": true, + "dev": true + }, + "graceful-fs": { + "version": "4.1.4", + "bundled": true, + "dev": true + }, + "handlebars": { + "version": "4.0.5", + "bundled": true, + "dev": true, + "requires": { + "async": "1.5.2", + "optimist": "0.6.1", + "source-map": "0.4.4", + "uglify-js": "2.7.0" + }, + "dependencies": { + "source-map": { + "version": "0.4.4", + "bundled": true, + "dev": true, + "requires": { + "amdefine": "1.0.0" + } + } + } + }, + "has-ansi": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "2.0.0" + } + }, + "has-flag": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "hosted-git-info": { + "version": "2.1.5", + "bundled": true, + "dev": true + }, + "imurmurhash": { + "version": "0.1.4", + "bundled": true, + "dev": true + }, + "inflight": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "requires": { + "once": "1.3.3", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.1", + "bundled": true, + "dev": true + }, + "invariant": { + "version": "2.2.1", + "bundled": true, + "dev": true, + "requires": { + "loose-envify": "1.2.0" + } + }, + "invert-kv": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "is-arrayish": { + "version": "0.2.1", + "bundled": true, + "dev": true + }, + "is-buffer": { + "version": "1.1.3", + "bundled": true, + "dev": true + }, + "is-builtin-module": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "builtin-modules": "1.1.1" + } + }, + "is-dotfile": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "bundled": true, + "dev": true, + "requires": { + "is-primitive": "2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "bundled": true, + "dev": true + }, + "is-extglob": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "is-finite": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "1.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "1.0.0" + } + }, + "is-glob": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "is-number": { + "version": "2.1.0", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "3.0.3" + } + }, + "is-posix-bracket": { + "version": "0.1.1", + "bundled": true, + "dev": true + }, + "is-primitive": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "is-utf8": { + "version": "0.2.1", + "bundled": true, + "dev": true + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "isexe": { + "version": "1.1.2", + "bundled": true, + "dev": true + }, + "isobject": { + "version": "2.1.0", + "bundled": true, + "dev": true, + "requires": { + "isarray": "1.0.0" + } + }, + "istanbul-lib-coverage": { + "version": "1.0.0-alpha.4", + "bundled": true, + "dev": true + }, + "istanbul-lib-hook": { + "version": "1.0.0-alpha.4", + "bundled": true, + "dev": true, + "requires": { + "append-transform": "0.3.0" + } + }, + "istanbul-lib-instrument": { + "version": "1.1.0-alpha.4", + "bundled": true, + "dev": true, + "requires": { + "babel-generator": "6.11.4", + "babel-template": "6.9.0", + "babel-traverse": "6.11.4", + "babel-types": "6.11.1", + "babylon": "6.8.4", + "istanbul-lib-coverage": "1.0.0-alpha.4" + } + }, + "istanbul-lib-report": { + "version": "1.0.0-alpha.3", + "bundled": true, + "dev": true, + "requires": { + "async": "1.5.2", + "istanbul-lib-coverage": "1.0.0-alpha.4", + "mkdirp": "0.5.1", + "path-parse": "1.0.5", + "rimraf": "2.5.4", + "supports-color": "3.1.2" + }, + "dependencies": { + "supports-color": { + "version": "3.1.2", + "bundled": true, + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "istanbul-lib-source-maps": { + "version": "1.0.0-alpha.10", + "bundled": true, + "dev": true, + "requires": { + "istanbul-lib-coverage": "1.0.0-alpha.4", + "mkdirp": "0.5.1", + "rimraf": "2.5.4", + "source-map": "0.5.6" + } + }, + "istanbul-reports": { + "version": "1.0.0-alpha.8", + "bundled": true, + "dev": true, + "requires": { + "handlebars": "4.0.5" + } + }, + "js-tokens": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "kind-of": { + "version": "3.0.3", + "bundled": true, + "dev": true, + "requires": { + "is-buffer": "1.1.3" + } + }, + "lazy-cache": { + "version": "1.0.4", + "bundled": true, + "dev": true, + "optional": true + }, + "lcid": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "invert-kv": "1.0.0" + } + }, + "load-json-file": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "requires": { + "graceful-fs": "4.1.4", + "parse-json": "2.2.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0" + } + }, + "lodash": { + "version": "4.13.1", + "bundled": true, + "dev": true + }, + "lodash.assign": { + "version": "4.0.9", + "bundled": true, + "dev": true, + "requires": { + "lodash.keys": "4.0.7", + "lodash.rest": "4.0.3" + } + }, + "lodash.keys": { + "version": "4.0.7", + "bundled": true, + "dev": true + }, + "lodash.rest": { + "version": "4.0.3", + "bundled": true, + "dev": true + }, + "longest": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "loose-envify": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "requires": { + "js-tokens": "1.0.3" + }, + "dependencies": { + "js-tokens": { + "version": "1.0.3", + "bundled": true, + "dev": true + } + } + }, + "lru-cache": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.0.0" + } + }, + "md5-hex": { + "version": "1.3.0", + "bundled": true, + "dev": true, + "requires": { + "md5-o-matic": "0.1.1" + } + }, + "md5-o-matic": { + "version": "0.1.1", + "bundled": true, + "dev": true + }, + "micromatch": { + "version": "2.3.11", + "bundled": true, + "dev": true, + "requires": { + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.0", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.0.3", + "normalize-path": "2.0.1", + "object.omit": "2.0.0", + "parse-glob": "3.0.4", + "regex-cache": "0.4.3" + } + }, + "minimatch": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "requires": { + "brace-expansion": "1.1.6" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "0.7.1", + "bundled": true, + "dev": true + }, + "normalize-package-data": { + "version": "2.3.5", + "bundled": true, + "dev": true, + "requires": { + "hosted-git-info": "2.1.5", + "is-builtin-module": "1.0.0", + "semver": "5.3.0", + "validate-npm-package-license": "3.0.1" + } + }, + "normalize-path": { + "version": "2.0.1", + "bundled": true, + "dev": true + }, + "number-is-nan": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "object.omit": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "requires": { + "for-own": "0.1.4", + "is-extendable": "0.1.1" + } + }, + "once": { + "version": "1.3.3", + "bundled": true, + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "optimist": { + "version": "0.6.1", + "bundled": true, + "dev": true, + "requires": { + "minimist": "0.0.8", + "wordwrap": "0.0.3" + } + }, + "os-homedir": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "os-locale": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "requires": { + "lcid": "1.0.0" + } + }, + "parse-glob": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "glob-base": "0.3.0", + "is-dotfile": "1.0.2", + "is-extglob": "1.0.0", + "is-glob": "2.0.1" + } + }, + "parse-json": { + "version": "2.2.0", + "bundled": true, + "dev": true, + "requires": { + "error-ex": "1.3.0" + } + }, + "path-exists": { + "version": "2.1.0", + "bundled": true, + "dev": true, + "requires": { + "pinkie-promise": "2.0.1" + } + }, + "path-is-absolute": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "path-parse": { + "version": "1.0.5", + "bundled": true, + "dev": true + }, + "path-type": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "requires": { + "graceful-fs": "4.1.4", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "pify": { + "version": "2.3.0", + "bundled": true, + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "bundled": true, + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "requires": { + "pinkie": "2.0.4" + } + }, + "pkg-dir": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "find-up": "1.1.2" + } + }, + "pkg-up": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "find-up": "1.1.2" + } + }, + "preserve": { + "version": "0.2.0", + "bundled": true, + "dev": true + }, + "pseudomap": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "randomatic": { + "version": "1.1.5", + "bundled": true, + "dev": true, + "requires": { + "is-number": "2.1.0", + "kind-of": "3.0.3" + } + }, + "read-pkg": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "requires": { + "load-json-file": "1.1.0", + "normalize-package-data": "2.3.5", + "path-type": "1.1.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "find-up": "1.1.2", + "read-pkg": "1.1.0" + } + }, + "regenerator-runtime": { + "version": "0.9.5", + "bundled": true, + "dev": true + }, + "regex-cache": { + "version": "0.4.3", + "bundled": true, + "dev": true, + "requires": { + "is-equal-shallow": "0.1.3", + "is-primitive": "2.0.0" + } + }, + "repeat-element": { + "version": "1.1.2", + "bundled": true, + "dev": true + }, + "repeat-string": { + "version": "1.5.4", + "bundled": true, + "dev": true + }, + "repeating": { + "version": "1.1.3", + "bundled": true, + "dev": true, + "requires": { + "is-finite": "1.0.1" + } + }, + "require-directory": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "require-main-filename": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "resolve-from": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "right-align": { + "version": "0.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "align-text": "0.1.4" + } + }, + "rimraf": { + "version": "2.5.4", + "bundled": true, + "dev": true, + "requires": { + "glob": "7.0.5" + } + }, + "semver": { + "version": "5.3.0", + "bundled": true, + "dev": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "signal-exit": { + "version": "3.0.0", + "bundled": true, + "dev": true + }, + "slide": { + "version": "1.1.6", + "bundled": true, + "dev": true + }, + "source-map": { + "version": "0.5.6", + "bundled": true, + "dev": true + }, + "spawn-wrap": { + "version": "1.2.4", + "bundled": true, + "dev": true, + "requires": { + "foreground-child": "1.5.3", + "mkdirp": "0.5.1", + "os-homedir": "1.0.1", + "rimraf": "2.5.4", + "signal-exit": "2.1.2", + "which": "1.2.10" + }, + "dependencies": { + "signal-exit": { + "version": "2.1.2", + "bundled": true, + "dev": true + } + } + }, + "spdx-correct": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "spdx-license-ids": "1.2.1" + } + }, + "spdx-exceptions": { + "version": "1.0.5", + "bundled": true, + "dev": true + }, + "spdx-expression-parse": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "spdx-exceptions": "1.0.5", + "spdx-license-ids": "1.2.1" + } + }, + "spdx-license-ids": { + "version": "1.2.1", + "bundled": true, + "dev": true + }, + "string-width": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "code-point-at": "1.0.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "2.0.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "requires": { + "is-utf8": "0.2.1" + } + }, + "supports-color": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "test-exclude": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "requires": { + "arrify": "1.0.1", + "lodash.assign": "4.0.9", + "micromatch": "2.3.11", + "read-pkg-up": "1.0.1", + "require-main-filename": "1.0.1" + } + }, + "to-fast-properties": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "uglify-js": { + "version": "2.7.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "async": "0.2.10", + "source-map": "0.5.6", + "uglify-to-browserify": "1.0.2", + "yargs": "3.10.0" + }, + "dependencies": { + "async": { + "version": "0.2.10", + "bundled": true, + "dev": true, + "optional": true + }, + "yargs": { + "version": "3.10.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "camelcase": "1.2.1", + "cliui": "2.1.0", + "decamelize": "1.2.0", + "window-size": "0.1.0" + } + } + } + }, + "uglify-to-browserify": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "validate-npm-package-license": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "spdx-correct": "1.0.2", + "spdx-expression-parse": "1.0.2" + } + }, + "which": { + "version": "1.2.10", + "bundled": true, + "dev": true, + "requires": { + "isexe": "1.1.2" + } + }, + "which-module": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "window-size": { + "version": "0.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "wordwrap": { + "version": "0.0.3", + "bundled": true, + "dev": true + }, + "wrap-ansi": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "requires": { + "string-width": "1.0.1" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "write-file-atomic": { + "version": "1.1.4", + "bundled": true, + "dev": true, + "requires": { + "graceful-fs": "4.1.4", + "imurmurhash": "0.1.4", + "slide": "1.1.6" + } + }, + "y18n": { + "version": "3.2.1", + "bundled": true, + "dev": true + }, + "yallist": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "yargs": { + "version": "4.8.1", + "bundled": true, + "dev": true, + "requires": { + "cliui": "3.2.0", + "decamelize": "1.2.0", + "get-caller-file": "1.0.1", + "lodash.assign": "4.0.9", + "os-locale": "1.4.0", + "read-pkg-up": "1.0.1", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "1.0.1", + "which-module": "1.0.0", + "window-size": "0.2.0", + "y18n": "3.2.1", + "yargs-parser": "2.4.1" + }, + "dependencies": { + "cliui": { + "version": "3.2.0", + "bundled": true, + "dev": true, + "requires": { + "string-width": "1.0.1", + "strip-ansi": "3.0.1", + "wrap-ansi": "2.0.0" + } + }, + "window-size": { + "version": "0.2.0", + "bundled": true, + "dev": true + } + } + }, + "yargs-parser": { + "version": "2.4.1", + "bundled": true, + "dev": true, + "requires": { + "camelcase": "3.0.0", + "lodash.assign": "4.0.9" + }, + "dependencies": { + "camelcase": { + "version": "3.0.0", + "bundled": true, + "dev": true + } + } + } + } + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", + "dev": true + }, + "only-shallow": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/only-shallow/-/only-shallow-1.2.0.tgz", + "integrity": "sha1-cc7O26kyS8BRiu8Q7AgNMkncJGU=", + "dev": true + }, + "opener": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.4.3.tgz", + "integrity": "sha1-XG2ixdflgx6P+jlklQ+NZnSskLg=", + "dev": true + }, + "os-homedir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.1.tgz", + "integrity": "sha1-DWK99EuRb9O73PLKsZGUj7CU8Ac=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "2.0.4" + } + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "qs": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.3.2.tgz", + "integrity": "sha1-51vV9uJoEioqDgvaYwslUMFmUCw=", + "dev": true + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "request": { + "version": "2.79.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.79.0.tgz", + "integrity": "sha1-Tf5b9r6LjNw3/Pk+BLZVd3InEN4=", + "dev": true, + "requires": { + "aws-sign2": "0.6.0", + "aws4": "1.6.0", + "caseless": "0.11.0", + "combined-stream": "1.0.5", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.1.4", + "har-validator": "2.0.6", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.17", + "oauth-sign": "0.8.2", + "qs": "6.3.2", + "stringstream": "0.0.5", + "tough-cookie": "2.3.3", + "tunnel-agent": "0.4.3", + "uuid": "3.1.0" + } + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "sntp": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", + "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "sshpk": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", + "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", + "dev": true, + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "stack-utils": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-0.4.0.tgz", + "integrity": "sha1-lAy4L8z6hOj/Lz/fKT/ngBa+zNE=", + "dev": true + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "stringstream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "tap-mocha-reporter": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/tap-mocha-reporter/-/tap-mocha-reporter-2.0.1.tgz", + "integrity": "sha1-xwMWFz1uOhbFjhupLV1s2N5YoS4=", + "dev": true, + "requires": { + "color-support": "1.1.3", + "debug": "2.6.9", + "diff": "1.4.0", + "escape-string-regexp": "1.0.5", + "glob": "7.1.2", + "js-yaml": "3.10.0", + "readable-stream": "2.3.3", + "tap-parser": "2.2.3", + "unicode-length": "1.0.3" + } + }, + "tap-parser": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/tap-parser/-/tap-parser-2.2.3.tgz", + "integrity": "sha1-rebpbje/04zg8WLaBn80A08GiwE=", + "dev": true, + "requires": { + "events-to-array": "1.1.2", + "js-yaml": "3.10.0", + "readable-stream": "2.3.3" + } + }, + "tmatch": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/tmatch/-/tmatch-2.0.1.tgz", + "integrity": "sha1-DFYkbzPzDaG409colauvFmYPOM8=", + "dev": true + }, + "tough-cookie": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", + "integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=", + "dev": true, + "requires": { + "punycode": "1.4.1" + } + }, + "tunnel-agent": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", + "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", + "dev": true + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true, + "optional": true + }, + "unicode-length": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/unicode-length/-/unicode-length-1.0.3.tgz", + "integrity": "sha1-Wtp6f+1RhBpBijKM8UlHisg1irs=", + "dev": true, + "requires": { + "punycode": "1.4.1", + "strip-ansi": "3.0.1" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "uuid": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", + "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==", + "dev": true + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "1.3.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "which": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", + "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", + "dev": true, + "requires": { + "isexe": "2.0.0" + }, + "dependencies": { + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + } + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + } + } + }, + "thenify": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.0.tgz", + "integrity": "sha1-5p44obq+lpsBCCB5eLn2K4hgSDk=", + "requires": { + "any-promise": "1.3.0" + } + }, + "thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY=", + "requires": { + "thenify": "3.3.0" + } + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "unix-crypt-td-js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unix-crypt-td-js/-/unix-crypt-td-js-1.0.0.tgz", + "integrity": "sha1-HAgkFQSBvHoB1J6Y8exmjYJBLzs=" + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "update-notifier": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-2.2.0.tgz", + "integrity": "sha1-G1g3z5DAc22IYncytmHBOPht5y8=", + "requires": { + "boxen": "1.2.1", + "chalk": "1.1.3", + "configstore": "3.1.1", + "import-lazy": "2.1.0", + "is-npm": "1.0.0", + "latest-version": "3.1.0", + "semver-diff": "2.1.0", + "xdg-basedir": "3.0.0" + }, + "dependencies": { + "ansi-align": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz", + "integrity": "sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=", + "requires": { + "string-width": "2.1.1" + } + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "requires": { + "color-convert": "1.9.0" + } + }, + "boxen": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.2.1.tgz", + "integrity": "sha1-DxHn/jRO25OXl3/BPt5/ZNlWSB0=", + "requires": { + "ansi-align": "2.0.0", + "camelcase": "4.1.0", + "chalk": "2.1.0", + "cli-boxes": "1.0.0", + "string-width": "2.1.1", + "term-size": "1.2.0", + "widest-line": "1.0.0" + }, + "dependencies": { + "chalk": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.1.0.tgz", + "integrity": "sha512-LUHGS/dge4ujbXMJrnihYMcL4AoOweGnw9Tp3kQuqy1Kx5c1qKjqvMJZ6nVJPMWJtKCTN72ZogH3oeSO9g9rXQ==", + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.4.0" + } + } + } + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" + }, + "capture-stack-trace": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz", + "integrity": "sha1-Sm+gc5nCa7pH8LJJa00PtAjFVQ0=" + }, + "cli-boxes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz", + "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM=" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "color-convert": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.0.tgz", + "integrity": "sha1-Gsz5fdc5uYO/mU1W/sj5WFNkG3o=", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "configstore": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.1.tgz", + "integrity": "sha512-5oNkD/L++l0O6xGXxb1EWS7SivtjfGQlRyxJsYgE0Z495/L81e2h4/d3r969hoPXuFItzNOKMtsXgYG4c7dYvw==", + "requires": { + "dot-prop": "4.2.0", + "graceful-fs": "4.1.11", + "make-dir": "1.0.0", + "unique-string": "1.0.0", + "write-file-atomic": "2.3.0", + "xdg-basedir": "3.0.0" + } + }, + "create-error-class": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", + "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=", + "requires": { + "capture-stack-trace": "1.0.0" + } + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "requires": { + "lru-cache": "4.1.1", + "shebang-command": "1.2.0", + "which": "1.3.0" + } + }, + "crypto-random-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", + "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=" + }, + "deep-extend": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", + "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=" + }, + "dot-prop": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", + "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", + "requires": { + "is-obj": "1.0.1" + } + }, + "duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "requires": { + "cross-spawn": "5.1.0", + "get-stream": "3.0.0", + "is-stream": "1.1.0", + "npm-run-path": "2.0.2", + "p-finally": "1.0.0", + "signal-exit": "3.0.2", + "strip-eof": "1.0.0" + } + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" + }, + "got": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz", + "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=", + "requires": { + "create-error-class": "3.0.2", + "duplexer3": "0.1.4", + "get-stream": "3.0.0", + "is-redirect": "1.0.0", + "is-retry-allowed": "1.1.0", + "is-stream": "1.1.0", + "lowercase-keys": "1.0.0", + "safe-buffer": "5.1.1", + "timed-out": "4.0.1", + "unzip-response": "2.0.1", + "url-parse-lax": "1.0.0" + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" + }, + "import-lazy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", + "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=" + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" + }, + "ini": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz", + "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=" + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "is-npm": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz", + "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ=" + }, + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=" + }, + "is-redirect": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz", + "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=" + }, + "is-retry-allowed": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", + "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=" + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "latest-version": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-3.1.0.tgz", + "integrity": "sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU=", + "requires": { + "package-json": "4.0.1" + } + }, + "lowercase-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", + "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=" + }, + "lru-cache": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", + "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" + } + }, + "make-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.0.0.tgz", + "integrity": "sha1-l6ARdR6R3YfPre9Ygy67BJNt6Xg=", + "requires": { + "pify": "2.3.0" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "requires": { + "path-key": "2.0.1" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" + }, + "package-json": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-4.0.1.tgz", + "integrity": "sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0=", + "requires": { + "got": "6.7.1", + "registry-auth-token": "3.3.1", + "registry-url": "3.1.0", + "semver": "5.4.1" + } + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + }, + "prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=" + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + }, + "rc": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.1.tgz", + "integrity": "sha1-LgPo5C7kULjLPc5lvhv4l04d/ZU=", + "requires": { + "deep-extend": "0.4.2", + "ini": "1.3.4", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + } + }, + "registry-auth-token": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.3.1.tgz", + "integrity": "sha1-+w0yie4Nmtosu1KvXf5mywcNMAY=", + "requires": { + "rc": "1.2.1", + "safe-buffer": "5.1.1" + } + }, + "registry-url": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", + "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=", + "requires": { + "rc": "1.2.1" + } + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + }, + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==" + }, + "semver-diff": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz", + "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=", + "requires": { + "semver": "5.4.1" + } + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "requires": { + "shebang-regex": "1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "3.0.0" + } + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "supports-color": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", + "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", + "requires": { + "has-flag": "2.0.0" + } + }, + "term-size": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz", + "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=", + "requires": { + "execa": "0.7.0" + } + }, + "timed-out": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", + "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=" + }, + "unique-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", + "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=", + "requires": { + "crypto-random-string": "1.0.0" + } + }, + "unzip-response": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-2.0.1.tgz", + "integrity": "sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=" + }, + "url-parse-lax": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", + "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", + "requires": { + "prepend-http": "1.0.4" + } + }, + "which": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", + "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", + "requires": { + "isexe": "2.0.0" + } + }, + "widest-line": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-1.0.0.tgz", + "integrity": "sha1-DAnIXCqUaD0Nfq+O4JfVZL8OEFw=", + "requires": { + "string-width": "1.0.2" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "1.0.1" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "2.1.1" + } + } + } + }, + "write-file-atomic": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.3.0.tgz", + "integrity": "sha512-xuPeK4OdjWqtfi59ylvVL0Yn35SF3zgcAcv7rBPFHVaEapaDr4GdGgm3j7ckTwH9wHL7fGmgfAnb0+THrHb8tA==", + "requires": { + "graceful-fs": "4.1.11", + "imurmurhash": "0.1.4", + "signal-exit": "3.0.2" + } + }, + "xdg-basedir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz", + "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=" + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + } + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "utils-merge": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", + "integrity": "sha1-ApT7kiu5N1FTVBxPcJYjHyh8ivg=" + }, + "uuid": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", + "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==" + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + }, + "websocket-driver": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz", + "integrity": "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=", + "requires": { + "http-parser-js": "0.4.9", + "websocket-extensions": "0.1.2" + } + }, + "websocket-extensions": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.2.tgz", + "integrity": "sha1-Dhh4HeYpoYMIzhSBZQ9n/6JpOl0=" + } + } +} diff --git a/package.json b/package.json index 36871314c..d9aab8d89 100644 --- a/package.json +++ b/package.json @@ -1,26 +1,31 @@ { - "name": "patternlab-node", + "name": "@pattern-lab/patternlab-node", "description": "Pattern Lab is a collection of tools to help you create atomic design systems. This is the node command line interface (CLI).", - "version": "2.12.0", + "version": "3.0.0-alpha.1", "main": "./core/lib/patternlab.js", "dependencies": { + "async": "^2.1.2", "chalk": "^1.1.3", + "chokidar": "^1.7.0", + "dive": "^0.5.0", "diveSync": "^0.3.0", "fs-extra": "^0.30.0", + "fs-promise": "^1.0.0", "glob": "^7.0.0", "graphlib": "^2.1.1", "js-beautify": "^1.6.3", "js-yaml": "^3.6.1", + "live-server": "github:pattern-lab/live-server#d46ec21", "lodash": "~4.13.1", "markdown-it": "^6.0.1", "node-fetch": "^1.6.0", - "patternengine-node-mustache": "^1.0.0", + "recursive-copy": "^2.0.6", "update-notifier": "^2.2.0" }, "devDependencies": { - "eslint": "^3.5.0", - "rewire": "^2.5.2", - "tap": "^7.1.2" + "eslint": "3.5.0", + "rewire": "2.5.2", + "tap": "7.1.2" }, "keywords": [ "Pattern Lab", @@ -51,10 +56,11 @@ ], "license": "MIT", "scripts": { - "test": "eslint core/**/*.js && tap test/*_tests.js --reporter spec", - "lint": "eslint core/**/*.js" + "lint": "eslint core/**/*.js", + "pretest": "npm run lint", + "test": "tap test/*_tests.js --reporter spec --coverage" }, "engines": { - "node": ">=4.0" + "node": ">=6.0" } } diff --git a/pattern_exports/test-paramParent.html b/pattern_exports/test-paramParent.html new file mode 100644 index 000000000..2c75ed8b1 --- /dev/null +++ b/pattern_exports/test-paramParent.html @@ -0,0 +1,4 @@ +
+Cool Dude +
+ diff --git a/patternlab-config.json b/patternlab-config.json index 70ff944c7..dc3021cc6 100644 --- a/patternlab-config.json +++ b/patternlab-config.json @@ -47,11 +47,12 @@ "tools-all": false, "tools-docs": false }, - "ishMinimum": "240", - "ishMaximum": "2600", - "patternStateCascade": ["inprogress", "inreview", "complete"], - "patternStates": { + "ishViewportRange": { + "s": [240, 500], + "m": [500, 800], + "l": [800, 2600] }, + "patternStateCascade": ["inprogress", "inreview", "complete"], "patternExportPatternPartials": [], "patternExportDirectory": "./pattern_exports/", "cacheBust": true, @@ -61,5 +62,10 @@ "markupOnly": ".markup-only" }, "cleanOutputHtml": true, - "exportToGraphViz": false + "exportToGraphViz": false, + "theme": { + "color": "dark", + "density": "compact", + "layout": "horizontal" + } } diff --git a/test/asset_copy_tests.js b/test/asset_copy_tests.js new file mode 100644 index 000000000..9d2346912 --- /dev/null +++ b/test/asset_copy_tests.js @@ -0,0 +1,66 @@ +"use strict"; + +var tap = require('tap'); +var rewire = require("rewire"); +var _ = require('lodash'); +var eol = require('os').EOL; +var Pattern = require('../core/lib/object_factory').Pattern; +var extend = require('util')._extend; +var ac = rewire('../core/lib/asset_copy'); +var path = require('path'); +var config = require('./util/patternlab-config.json'); + +var engineLoader = require('../core/lib/pattern_engines'); +engineLoader.loadAllEngines(config); + +//set up a global mocks - we don't want to be writing/rendering any files right now +// var chokidarMock = { +// watch: function (path, data, cb) { } +// }; + +// ac.__set__({ +// 'chokidar': chokidarMock, +// }); + +const assetCopier = ac(); + +function createFakePatternLab(customProps) { + var pl = { + config: { + paths: { + source: { + img: './test/img', + css: './test/css' + }, + public: { + img: './test/output/img', + css: './test/output/css' + } + }, + styleGuideExcludes: [ ], + debug: false, + outputFileSuffixes: { + rendered: '.rendered', + rawTemplate: '', + markupOnly: '.markup-only' + } + }, + data: {} + }; + return extend(pl, customProps); +} + +tap.test('transformConfigPaths takes configuration.paths() and maps to a better key store', function (test) { + //arrange + var patternlab = createFakePatternLab({}); + + //act + var result = assetCopier.transformConfigPaths(patternlab.config.paths); + + //assert + test.equals(result.img.source, './test/img'); + test.equals(result.img.public, './test/output/img'); + test.equals(result.css.source, './test/css'); + test.equals(result.css.public, './test/output/css'); + test.end(); +}); diff --git a/test/engine_handlebars_tests.js b/test/engine_handlebars_tests.js index 58a7085f6..53a2453e5 100644 --- a/test/engine_handlebars_tests.js +++ b/test/engine_handlebars_tests.js @@ -8,14 +8,16 @@ var Pattern = require('../core/lib/object_factory').Pattern; var PatternGraph = require('../core/lib/pattern_graph').PatternGraph; var testPatternsPath = path.resolve(__dirname, 'files', '_handlebars-test-patterns'); var eol = require('os').EOL; +var config = require('./util/patternlab-config.json'); +var engineLoader = require('../core/lib/pattern_engines'); +engineLoader.loadAllEngines(config); // don't run these tests unless handlebars is installed -var engineLoader = require('../core/lib/pattern_engines'); if (!engineLoader.handlebars) { tap.test('Handlebars engine not installed, skipping tests.', function (test) { - test.end() - }) - return + test.end(); + }); + return; } // fake pattern lab constructor: @@ -81,11 +83,14 @@ tap.test('hello world handlebars pattern renders', function (test) { // do all the normal processing of the pattern var patternlab = new fakePatternLab(); var assembler = new pa(); - var helloWorldPattern = assembler.process_pattern_iterative(patternPath, patternlab); - assembler.process_pattern_recursive(patternPath, patternlab); + var helloWorldPattern = assembler.load_pattern_iterative(patternPath, patternlab); - test.equals(helloWorldPattern.render(), 'Hello world!' + eol); - test.end(); + return assembler.process_pattern_iterative(helloWorldPattern, patternlab) + .then((helloWorldPattern) => { + assembler.process_pattern_recursive(patternPath, patternlab); + + test.equals(helloWorldPattern.render(), 'Hello world!' + eol); + }); }); tap.test('hello worlds handlebars pattern can see the atoms-helloworld partial and renders it twice', function (test) { @@ -99,15 +104,20 @@ tap.test('hello worlds handlebars pattern can see the atoms-helloworld partial a var patternlab = new fakePatternLab(); // environment var assembler = new pa(); - // do all the normal processing of the pattern - assembler.process_pattern_iterative(pattern1Path, patternlab); - var helloWorldsPattern = assembler.process_pattern_iterative(pattern2Path, patternlab); - assembler.process_pattern_recursive(pattern1Path, patternlab); - assembler.process_pattern_recursive(pattern2Path, patternlab); + // do all the normal loading and processing of the pattern + const pattern1 = assembler.load_pattern_iterative(pattern1Path, patternlab); + const pattern2 = assembler.load_pattern_iterative(pattern2Path, patternlab); - // test - test.equals(helloWorldsPattern.render(), 'Hello world!' + eol + ' and Hello world!' + eol + eol); - test.end(); + return Promise.all([ + assembler.process_pattern_iterative(pattern1, patternlab), + assembler.process_pattern_iterative(pattern2, patternlab) + ]).then(() => { + assembler.process_pattern_recursive(pattern1Path, patternlab); + assembler.process_pattern_recursive(pattern2Path, patternlab); + + // test + test.equals(pattern2.render(), 'Hello world!' + eol + ' and Hello world!' + eol + eol); + }); }); tap.test('handlebars partials can render JSON values', function (test) { @@ -121,12 +131,14 @@ tap.test('handlebars partials can render JSON values', function (test) { var assembler = new pa(); // do all the normal processing of the pattern - var helloWorldWithData = assembler.process_pattern_iterative(pattern1Path, patternlab); - assembler.process_pattern_recursive(pattern1Path, patternlab); + var helloWorldWithData = assembler.load_pattern_iterative(pattern1Path, patternlab); - // test - test.equals(helloWorldWithData.render(), 'Hello world!' + eol + 'Yeah, we got the subtitle from the JSON.' + eol); - test.end(); + return assembler.process_pattern_iterative(helloWorldWithData, patternlab).then(() => { + assembler.process_pattern_recursive(pattern1Path, patternlab); + + // test + test.equals(helloWorldWithData.render(), 'Hello world!' + eol + 'Yeah, we got the subtitle from the JSON.' + eol); + }); }); tap.test('handlebars partials use the JSON environment from the calling pattern and can accept passed parameters', function (test) { @@ -141,14 +153,19 @@ tap.test('handlebars partials use the JSON environment from the calling pattern var assembler = new pa(); // do all the normal processing of the pattern - assembler.process_pattern_iterative(atomPath, patternlab); - var mol = assembler.process_pattern_iterative(molPath, patternlab); - assembler.process_pattern_recursive(atomPath, patternlab); - assembler.process_pattern_recursive(molPath, patternlab); - - // test - test.equals(mol.render(), '

Call with default JSON environment:

' + eol + 'This is Hello world!' + eol + 'from the default JSON.' + eol + eol + eol +'

Call with passed parameter:

' + eol + 'However, this is Hello world!' + eol + 'from a totally different blob.' + eol + eol); - test.end(); + const atom = assembler.load_pattern_iterative(atomPath, patternlab); + const mol = assembler.load_pattern_iterative(molPath, patternlab); + + return Promise.all([ + assembler.process_pattern_iterative(atom, patternlab), + assembler.process_pattern_iterative(mol, patternlab) + ]).then(() => { + assembler.process_pattern_recursive(atomPath, patternlab); + assembler.process_pattern_recursive(molPath, patternlab); + + // test + test.equals(mol.render(), '

Call with default JSON environment:

' + eol + 'This is Hello world!' + eol + 'from the default JSON.' + eol + eol + eol +'

Call with passed parameter:

' + eol + 'However, this is Hello world!' + eol + 'from a totally different blob.' + eol + eol); + }); }); tap.test('find_pattern_partials finds partials', function (test) { @@ -213,16 +230,21 @@ tap.test('hidden handlebars patterns can be called by their nice names', functio var pattern_assembler = new pa(); var hiddenPatternPath = path.join('00-atoms', '00-global', '_00-hidden.hbs'); - var hiddenPattern = pattern_assembler.process_pattern_iterative(hiddenPatternPath, pl); - pattern_assembler.process_pattern_recursive(hiddenPatternPath, pl); - var testPatternPath = path.join('00-molecules', '00-global', '00-hidden-pattern-tester.hbs'); - var testPattern = pattern_assembler.process_pattern_iterative(testPatternPath, pl); - pattern_assembler.process_pattern_recursive(testPatternPath, pl); - //act - test.equals(util.sanitized(testPattern.render()), util.sanitized('Here\'s the hidden atom: [I\'m the hidden atom\n]\n')); - test.end(); + var hiddenPattern = pattern_assembler.load_pattern_iterative(hiddenPatternPath, pl); + var testPattern = pattern_assembler.load_pattern_iterative(testPatternPath, pl); + + return Promise.all([ + pattern_assembler.process_pattern_iterative(hiddenPattern, pl), + pattern_assembler.process_pattern_iterative(testPattern, pl) + ]).then(() => { + pattern_assembler.process_pattern_recursive(hiddenPatternPath, pl); + pattern_assembler.process_pattern_recursive(testPatternPath, pl); + + //act + test.equals(util.sanitized(testPattern.render()), util.sanitized('Here\'s the hidden atom: [I\'m the hidden atom\n]\n')); + }); }); tap.test('@partial-block template should render without throwing (@geoffp repo issue #3)', function(test) { @@ -233,13 +255,15 @@ tap.test('@partial-block template should render without throwing (@geoffp repo i // do all the normal processing of the pattern var patternlab = new fakePatternLab(); var assembler = new pa(); - var atPartialBlockPattern = assembler.process_pattern_iterative(patternPath, patternlab); - assembler.process_pattern_recursive(patternPath, patternlab); + var atPartialBlockPattern = assembler.load_pattern_iterative(patternPath, patternlab); - var results = '{{> @partial-block }}' + eol + 'It worked!' + eol; - test.equal(atPartialBlockPattern.render(), results); - test.end(); -}) + return assembler.process_pattern_iterative(atPartialBlockPattern, patternlab).then(() => { + assembler.process_pattern_recursive(patternPath, patternlab); + + var results = '{{> @partial-block }}' + eol + 'It worked!' + eol; + test.equal(atPartialBlockPattern.render(), results); + }); +}); tap.test('A template calling a @partial-block template should render correctly', function(test) { test.plan(1); @@ -253,13 +277,19 @@ tap.test('A template calling a @partial-block template should render correctly', var assembler = new pa(); // do all the normal processing of the pattern - assembler.process_pattern_iterative(pattern1Path, patternlab); - var callAtPartialBlockPattern = assembler.process_pattern_iterative(pattern2Path, patternlab); - assembler.process_pattern_recursive(pattern1Path, patternlab); - assembler.process_pattern_recursive(pattern2Path, patternlab); - - // test - var results = 'Hello World!' + eol + 'It worked!' + eol; - test.equals(callAtPartialBlockPattern.render(), results); - test.end(); -}) + const pattern1 = assembler.load_pattern_iterative(pattern1Path, patternlab); + const callAtPartialBlockPattern = assembler.load_pattern_iterative(pattern2Path, patternlab); + + return Promise.all([ + assembler.process_pattern_iterative(pattern1, patternlab), + assembler.process_pattern_iterative(callAtPartialBlockPattern, patternlab) + ]).then(() => { + assembler.process_pattern_recursive(pattern1Path, patternlab); + assembler.process_pattern_recursive(pattern2Path, patternlab); + + // test + var results = 'Hello World!' + eol + 'It worked!' + eol; + test.equals(callAtPartialBlockPattern.render(), results); + }); + +}); diff --git a/test/engine_mustache_tests.js b/test/engine_mustache_tests.js index 30d2c3048..77330ec8a 100644 --- a/test/engine_mustache_tests.js +++ b/test/engine_mustache_tests.js @@ -7,9 +7,11 @@ var Pattern = require('../core/lib/object_factory').Pattern; var PatternGraph = require('../core/lib/pattern_graph').PatternGraph; var testPatternsPath = path.resolve(__dirname, 'files', '_patterns'); var eol = require('os').EOL; +var config = require('./util/patternlab-config.json'); // don't run these tests unless mustache is installed var engineLoader = require('../core/lib/pattern_engines'); +engineLoader.loadAllEngines(config); if (!engineLoader.mustache) { tap.test('Mustache engine not installed, skipping tests.', function (test) { test.end(); @@ -32,7 +34,7 @@ function fakePatternLab() { data: { link: {} }, - config: require('../patternlab-config.json'), + config: config, package: {} }; diff --git a/test/engine_twig_tests.js b/test/engine_twig_tests.js index d41b70901..713071462 100644 --- a/test/engine_twig_tests.js +++ b/test/engine_twig_tests.js @@ -81,11 +81,13 @@ tap.test('button twig pattern renders', function (test) { // do all the normal processing of the pattern var patternlab = new fakePatternLab(); var assembler = new pa(); - var helloWorldPattern = assembler.process_pattern_iterative(patternPath, patternlab); - assembler.process_pattern_recursive(patternPath, patternlab); + var helloWorldPattern = assembler.load_pattern_iterative(patternPath, patternlab); - test.equals(helloWorldPattern.render(), expectedValue); - test.end(); + return assembler.process_pattern_iterative(helloWorldPattern, patternlab).then(() => { + assembler.process_pattern_recursive(patternPath, patternlab); + + test.equals(helloWorldPattern.render(), expectedValue); + }); }); tap.test('media object twig pattern can see the atoms-button and atoms-image partials and renders them', function (test) { @@ -103,17 +105,23 @@ tap.test('media object twig pattern can see the atoms-button and atoms-image par var assembler = new pa(); // do all the normal processing of the pattern - assembler.process_pattern_iterative(buttonPatternPath, patternlab); - assembler.process_pattern_iterative(imagePatternPath, patternlab); - var mediaObjectPattern = assembler.process_pattern_iterative(mediaObjectPatternPath, patternlab); - assembler.process_pattern_recursive(buttonPatternPath, patternlab); - assembler.process_pattern_recursive(imagePatternPath, patternlab); - assembler.process_pattern_recursive(mediaObjectPatternPath, patternlab); - - // test - // this pattern is too long - so just remove line endings on both sides and compare output - test.equals(mediaObjectPattern.render().replace(/\r?\n|\r/gm, ""), expectedValue.replace(/\r?\n|\r/gm, "")); - test.end(); + const buttonPattern = assembler.load_pattern_iterative(buttonPatternPath, patternlab); + const imagePattern = assembler.load_pattern_iterative(imagePatternPath, patternlab); + const mediaObjectPattern = assembler.load_pattern_iterative(mediaObjectPatternPath, patternlab); + + return Promise.all([ + assembler.process_pattern_iterative(buttonPattern, patternlab), + assembler.process_pattern_iterative(imagePattern, patternlab), + assembler.process_pattern_iterative(mediaObjectPattern, patternlab) + ]).then(() => { + assembler.process_pattern_recursive(buttonPatternPath, patternlab); + assembler.process_pattern_recursive(imagePatternPath, patternlab); + assembler.process_pattern_recursive(mediaObjectPatternPath, patternlab); + + // test + // this pattern is too long - so just remove line endings on both sides and compare output + test.equals(mediaObjectPattern.render().replace(/\r?\n|\r/gm, ""), expectedValue.replace(/\r?\n|\r/gm, "")); + }); }); tap.test('twig partials can render JSON values', {skip: true}, function (test) { @@ -198,4 +206,3 @@ tap.test('find_pattern_partials finds partials with twig parameters', function ( "{% include 'organisms-sidebar' ignore missing with {'foo': 'bar'} %}" ]); }); - diff --git a/test/engine_underscore_tests.js b/test/engine_underscore_tests.js index 7e2342449..db5854c72 100644 --- a/test/engine_underscore_tests.js +++ b/test/engine_underscore_tests.js @@ -55,12 +55,13 @@ tap.test('hello world underscore pattern renders', function (test) { // do all the normal processing of the pattern var patternlab = new fakePatternLab(); var assembler = new pa(); - var helloWorldPattern = assembler.process_pattern_iterative(patternPath, patternlab); - assembler.process_pattern_recursive(patternPath, patternlab); + const helloWorldPattern = assembler.load_pattern_iterative(patternPath, patternlab); - test.equals(helloWorldPattern.render(), 'Hello world!' + eol); - test.end(); + return assembler.process_pattern_iterative(helloWorldPattern, patternlab).then(() => { + assembler.process_pattern_recursive(patternPath, patternlab); + test.equals(helloWorldPattern.render(), 'Hello world!' + eol); + }); }); tap.test('underscore partials can render JSON values', function (test) { @@ -80,13 +81,13 @@ tap.test('underscore partials can render JSON values', function (test) { var assembler = new pa(); // do all the normal processing of the pattern - var helloWorldWithData = assembler.process_pattern_iterative(pattern1Path, patternlab); - assembler.process_pattern_recursive(pattern1Path, patternlab); - - // test - test.equals(helloWorldWithData.render(), 'Hello world!' + eol + 'Yeah, we got the subtitle from the JSON.' + eol); - test.end(); + const helloWorldWithData = assembler.load_pattern_iterative(pattern1Path, patternlab); + return assembler.process_pattern_iterative(helloWorldWithData, patternlab).then(() => { + assembler.process_pattern_recursive(pattern1Path, patternlab); + // test + test.equals(helloWorldWithData.render(), 'Hello world!' + eol + 'Yeah, we got the subtitle from the JSON.' + eol); + }); }); tap.test('findPartial return the ID of the partial, given a whole partial call', function (test) { @@ -103,22 +104,28 @@ tap.test('findPartial return the ID of the partial, given a whole partial call', }); tap.test('hidden underscore patterns can be called by their nice names', function(test){ - const util = require('./util/test_utils.js'); + const util = require('./util/test_utils.js'); - //arrange - const testPatternsPath = path.resolve(__dirname, 'files', '_underscore-test-patterns'); - const pl = util.fakePatternLab(testPatternsPath); - var pattern_assembler = new pa(); + //arrange + const testPatternsPath = path.resolve(__dirname, 'files', '_underscore-test-patterns'); + const pl = util.fakePatternLab(testPatternsPath); + var pattern_assembler = new pa(); - var hiddenPatternPath = path.join('00-atoms', '00-global', '_00-hidden.html'); - var hiddenPattern = pattern_assembler.process_pattern_iterative(hiddenPatternPath, pl); - pattern_assembler.process_pattern_recursive(hiddenPatternPath, pl); + var hiddenPatternPath = path.join('00-atoms', '00-global', '_00-hidden.html'); + var testPatternPath = path.join('00-molecules', '00-global', '00-hidden-pattern-tester.html'); + + var hiddenPattern = pattern_assembler.load_pattern_iterative(hiddenPatternPath, pl); + var testPattern = pattern_assembler.load_pattern_iterative(testPatternPath, pl); - var testPatternPath = path.join('00-molecules', '00-global', '00-hidden-pattern-tester.html'); - var testPattern = pattern_assembler.process_pattern_iterative(testPatternPath, pl); + return Promise.all([ + pattern_assembler.process_pattern_iterative(hiddenPattern, pl), + pattern_assembler.process_pattern_iterative(testPattern, pl) + ]).then(() => { + pattern_assembler.process_pattern_recursive(hiddenPatternPath, pl); pattern_assembler.process_pattern_recursive(testPatternPath, pl); //act test.equals(util.sanitized(testPattern.render()), util.sanitized('Here\'s the hidden atom: [I\'m the hidden atom\n]\n')); test.end(); }); +}); diff --git a/test/files/_patterns/00-test/00-foo.md b/test/files/_patterns/00-test/00-foo.md index 4c8bbf296..b284e8103 100644 --- a/test/files/_patterns/00-test/00-foo.md +++ b/test/files/_patterns/00-test/00-foo.md @@ -1,3 +1,6 @@ +--- +state: inreview +--- ## A Simple Include This pattern contains an include of `test-bar`. It also has this markdown file, which does not have frontmatter. diff --git a/test/files/_patterns/00-test/01-bar.md b/test/files/_patterns/00-test/01-bar.md index 755aa5799..a811dacd7 100644 --- a/test/files/_patterns/00-test/01-bar.md +++ b/test/files/_patterns/00-test/01-bar.md @@ -1,5 +1,5 @@ --- -status: complete +state: complete title: An Atom Walks Into a Bar joke: bad --- diff --git a/test/files/_patterns/00-test/02-baz.md b/test/files/_patterns/00-test/02-baz.md new file mode 100644 index 000000000..f6f78b399 --- /dev/null +++ b/test/files/_patterns/00-test/02-baz.md @@ -0,0 +1 @@ +### Only baz \ No newline at end of file diff --git a/test/files/_patterns/00-test/02-baz.mustache b/test/files/_patterns/00-test/02-baz.mustache new file mode 100644 index 000000000..3f9538666 --- /dev/null +++ b/test/files/_patterns/00-test/02-baz.mustache @@ -0,0 +1 @@ +baz \ No newline at end of file diff --git a/test/files/_patterns/00-test/03-styled-atom.md b/test/files/_patterns/00-test/03-styled-atom.md index 23371c488..58c494066 100644 --- a/test/files/_patterns/00-test/03-styled-atom.md +++ b/test/files/_patterns/00-test/03-styled-atom.md @@ -1,3 +1,3 @@ --- -status: inprogress +state: inprogress --- diff --git a/test/lineage_hunter_tests.js b/test/lineage_hunter_tests.js index d1206c1e1..58d7892c6 100644 --- a/test/lineage_hunter_tests.js +++ b/test/lineage_hunter_tests.js @@ -7,6 +7,10 @@ var pa = require('../core/lib/pattern_assembler'); var of = require('../core/lib/object_factory'); var Pattern = require('../core/lib/object_factory').Pattern; var PatternGraph = require('../core/lib/pattern_graph').PatternGraph; +var config = require('./util/patternlab-config.json'); + +var engineLoader = require('../core/lib/pattern_engines'); +engineLoader.loadAllEngines(config); var fs = require('fs-extra'); var path = require('path'); @@ -31,6 +35,9 @@ function createBasePatternLabObject() { paths: { source: { patterns: patterns_dir + }, + public: { + patterns: './test/public/_patterns' } }, outputFileSuffixes: { @@ -45,6 +52,8 @@ function createBasePatternLabObject() { pl.config.debug = false; pl.patterns = []; pl.partials = {}; + pl.patternGroups = {}; + pl.subtypePatterns = {}; return pl; } @@ -263,17 +272,8 @@ tap.test('cascade_pattern_states sets the pattern state on any lineage patterns //arrange var pl = createBasePatternLabObject(); - var atomPattern = new of.Pattern('00-test/01-bar.mustache'); - atomPattern.template = fs.readFileSync(pl.config.paths.source.patterns + '00-test/01-bar.mustache', 'utf8'); - atomPattern.extendedTemplate = atomPattern.template; - atomPattern.patternState = "inreview"; - pattern_assembler.addPattern(atomPattern, pl); - - var consumerPattern = new of.Pattern('00-test/00-foo.mustache'); - consumerPattern.template = fs.readFileSync(pl.config.paths.source.patterns + '00-test/00-foo.mustache', 'utf8'); - consumerPattern.extendedTemplate = consumerPattern.template; - consumerPattern.patternState = "complete"; - pattern_assembler.addPattern(consumerPattern, pl); + var atomPattern = pattern_assembler.load_pattern_iterative('00-test/01-bar.mustache', pl); + var consumerPattern = pattern_assembler.load_pattern_iterative('00-test/00-foo.mustache', pl); lineage_hunter.find_lineage(consumerPattern, pl); diff --git a/test/list_item_hunter_tests.js b/test/list_item_hunter_tests.js index 74b21cd74..ff7dae374 100644 --- a/test/list_item_hunter_tests.js +++ b/test/list_item_hunter_tests.js @@ -8,6 +8,9 @@ var PatternGraph = require('../core/lib/pattern_graph').PatternGraph; var extend = require('util')._extend; var pa = require('../core/lib/pattern_assembler'); var pattern_assembler = new pa(); +var config = require('./util/patternlab-config.json'); +var engineLoader = require('../core/lib/pattern_engines'); +engineLoader.loadAllEngines(config); // fake pattern creators function createFakeListPattern(customProps) { @@ -421,5 +424,3 @@ tap.test('process_list_item_partials - correctly ignores already processed parti test.equals(listPattern.extendedTemplate.replace(/\s\s+/g, ' ').replace(/\n/g, ' ').trim(), expectedValue.trim()); test.end(); }); - - diff --git a/test/markdown_parser_tests.js b/test/markdown_parser_tests.js index 5931dd832..63f541ab8 100644 --- a/test/markdown_parser_tests.js +++ b/test/markdown_parser_tests.js @@ -10,14 +10,14 @@ var markdown_parser = new mp(); tap.test('parses pattern description block correctly when frontmatter not present', function(test) { //arrange - var markdownFileName = path.resolve("./test/files/_patterns/00-test/00-foo.md"); + var markdownFileName = path.resolve("./test/files/_patterns/00-test/02-baz.md"); var markdownFileContents = fs.readFileSync(markdownFileName, 'utf8'); //act var returnObject = markdown_parser.parse(markdownFileContents); //assert - test.equals(returnObject.markdown, '

A Simple Include

\n

This pattern contains an include of test-bar. It also has this markdown file, which does not have frontmatter.

\n'); + test.equals(returnObject.markdown, '

Only baz

\n'); test.end(); }); @@ -31,7 +31,7 @@ tap.test('parses pattern description block correctly when frontmatter present', //assert test.equals(returnObject.markdown, '

A Simple Bit of Markup

\n

Foo cannot get simpler than bar, amiright?

\n'); - test.equals(returnObject.status, 'complete'); + test.equals(returnObject.state, 'complete'); test.end(); }); @@ -45,6 +45,6 @@ tap.test('parses frontmatter only when no markdown present', function (test) { //assert test.equals(returnObject.markdown, ''); - test.equals(returnObject.status, 'inprogress'); + test.equals(returnObject.state, 'inprogress'); test.end(); }); diff --git a/test/object_factory_tests.js b/test/object_factory_tests.js index f20034f61..0b8512ce8 100644 --- a/test/object_factory_tests.js +++ b/test/object_factory_tests.js @@ -1,6 +1,7 @@ "use strict"; var tap = require('tap'); +var config = require('./util/patternlab-config.json'); // fake pattern lab constructor: // sets up a fake patternlab object, which is needed by the pattern processing @@ -16,7 +17,7 @@ function fakePatternLab() { data: { link: {} }, - config: require('../patternlab-config.json'), + config: config, package: {} }; @@ -27,6 +28,8 @@ var of = require('../core/lib/object_factory'); var Pattern = require('../core/lib/object_factory').Pattern; var path = require('path'); var pl = fakePatternLab(); +var engineLoader = require('../core/lib/pattern_engines'); +engineLoader.loadAllEngines(config); tap.test('test Pattern initializes correctly', function (test) { var p = new Pattern('00-atoms/00-global/00-colors.mustache', { d: 123}); diff --git a/test/parameter_hunter_tests.js b/test/parameter_hunter_tests.js index 5393c077f..05823fd30 100644 --- a/test/parameter_hunter_tests.js +++ b/test/parameter_hunter_tests.js @@ -3,14 +3,15 @@ var tap = require('tap'); var pa = require('../core/lib/pattern_assembler'); var Pattern = require('../core/lib/object_factory').Pattern; -var CompileState = require('../core/lib/object_factory').CompileState; var PatternGraph = require('../core/lib/pattern_graph').PatternGraph; var fs = require('fs-extra'); var util = require('./util/test_utils.js'); var ph = require('../core/lib/parameter_hunter'); - +var config = require('./util/patternlab-config.json'); +var engineLoader = require('../core/lib/pattern_engines'); +engineLoader.loadAllEngines(config); //setup current pattern from what we would have during execution function currentPatternClosure() { @@ -59,12 +60,14 @@ function patternlabClosure() { }, data: { description: 'Not a quote from a smart man', - link: {} + link: { + "molecules-single-comment": "01-molecules-06-components-02-single-comment/01-molecules-06-components-02-single-comment.html" + } }, partials: {}, graph: PatternGraph.empty() - } -}; + }; +} tap.test('parameter hunter finds and extends templates', function(test) { var currentPattern = currentPatternClosure(); @@ -402,3 +405,21 @@ tap.test('parameter hunter parses parameters containing html tags', function(tes test.end(); }); + +tap.test('parameter hunter expands links inside parameters', function (test) { + var currentPattern = currentPatternClosure(); + var patternlab = patternlabClosure(); + var parameter_hunter = new ph(); + + patternlab.patterns[0].template = '{{ description }}'; + patternlab.patterns[0].extendedTemplate = patternlab.patterns[0].template; + + currentPattern.template = "{{> molecules-single-comment(url: 'link.molecules-single-comment', description: 'Link to single comment') }}"; + currentPattern.extendedTemplate = currentPattern.template; + currentPattern.parameteredPartials[0] = currentPattern.template; + + parameter_hunter.find_parameters(currentPattern, patternlab); + test.equals(currentPattern.extendedTemplate, 'Link to single comment'); + + test.end(); +}); diff --git a/test/pattern_assembler_tests.js b/test/pattern_assembler_tests.js index 5d4e02a45..fe35e6fb6 100644 --- a/test/pattern_assembler_tests.js +++ b/test/pattern_assembler_tests.js @@ -7,6 +7,9 @@ var Pattern = require('../core/lib/object_factory').Pattern; var CompileState = require('../core/lib/object_factory').CompileState; var PatternGraph = require('../core/lib/pattern_graph').PatternGraph; var path = require('path'); +var config = require('./util/patternlab-config.json'); +var engineLoader = require('../core/lib/pattern_engines'); +engineLoader.loadAllEngines(config); function emptyPatternLab() { return { @@ -32,45 +35,43 @@ tap.test('process_pattern_recursive recursively includes partials', function(tes patternlab.config.paths.public = public_dir; patternlab.config.outputFileSuffixes = {rendered: ''}; - //patternlab.data = fs.readJSONSync(path.resolve(patternlab.config.paths.source.data, 'data.json')); patternlab.data = {}; - //patternlab.listitems = fs.readJSONSync(path.resolve(patternlab.config.paths.source.data, 'listitems.json')); patternlab.listitems = {}; - //patternlab.header = fs.readFileSync(path.resolve(patternlab.config.paths.source.patternlabFiles, 'templates/pattern-header-footer/header.html'), 'utf8'); patternlab.header = ''; - //patternlab.footer = fs.readFileSync(path.resolve(patternlab.config.paths.source.patternlabFiles, 'templates/pattern-header-footer/footer.html'), 'utf8'); patternlab.footer = ''; patternlab.patterns = []; patternlab.data.link = {}; patternlab.partials = {}; //diveSync once to perform iterative populating of patternlab object - plMain.process_all_patterns_iterative(pattern_assembler, patterns_dir, patternlab); - - //diveSync again to recursively include partials, filling out the - //extendedTemplate property of the patternlab.patterns elements - plMain.process_all_patterns_recursive(pattern_assembler, patterns_dir, patternlab); - - //get test output for comparison - var foo = fs.readFileSync(patterns_dir + '/00-test/00-foo.mustache', 'utf8').trim(); - var bar = fs.readFileSync(patterns_dir + '/00-test/01-bar.mustache', 'utf8').trim(); - var fooExtended; - - //get extended pattern - for (var i = 0; i < patternlab.patterns.length; i++) { - if (patternlab.patterns[i].fileName === '00-foo') { - fooExtended = patternlab.patterns[i].extendedTemplate.trim(); - break; - } - } + plMain.process_all_patterns_iterative(patterns_dir, patternlab) + .then(() => { + //diveSync again to recursively include partials, filling out the + //extendedTemplate property of the patternlab.patterns elements + plMain.process_all_patterns_recursive(patterns_dir, patternlab); + + //get test output for comparison + var foo = fs.readFileSync(patterns_dir + '/00-test/00-foo.mustache', 'utf8').trim(); + var bar = fs.readFileSync(patterns_dir + '/00-test/01-bar.mustache', 'utf8').trim(); + var fooExtended; + + //get extended pattern + for (var i = 0; i < patternlab.patterns.length; i++) { + if (patternlab.patterns[i].fileName === '00-foo') { + fooExtended = patternlab.patterns[i].extendedTemplate.trim(); + break; + } + } - //check initial values - test.equals(foo, '{{> test-bar }}', 'foo template not as expected'); - test.equals(bar, 'bar', 'bar template not as expected'); - //test that 00-foo.mustache included partial 01-bar.mustache - test.equals(fooExtended, 'bar', 'foo includes bar'); + //check initial values + test.equals(foo, '{{> test-bar }}', 'foo template not as expected'); + test.equals(bar, 'bar', 'bar template not as expected'); + //test that 00-foo.mustache included partial 01-bar.mustache + test.equals(fooExtended, 'bar', 'foo includes bar'); - test.end(); + test.end(); + }) + .catch(test.threw); }); tap.test('processPatternRecursive - correctly replaces all stylemodifiers when multiple duplicate patterns with different stylemodifiers found', function(test) { @@ -478,59 +479,21 @@ tap.test('processPatternRecursive - 685 ensure listitems data is used', function pattern_assembler.combine_listItems(pl); var listPatternPath = path.join('00-test', '685-list.mustache'); - var listPattern = pattern_assembler.process_pattern_iterative(listPatternPath, pl); + var listPattern = pattern_assembler.load_pattern_iterative(listPatternPath, pl); - //act - pattern_assembler.process_pattern_recursive(listPatternPath, pl); + return Promise.all([ + pattern_assembler.process_pattern_iterative(listPattern, pl) + ]).then((results) => { - //assert - test.true(listPattern.extendedTemplate.indexOf(1) > -1); - test.true(listPattern.extendedTemplate.indexOf(2) > -1); - test.true(listPattern.extendedTemplate.indexOf(3) > -1); - test.end(); -}); + //act + pattern_assembler.process_pattern_recursive(listPatternPath, pl); -tap.test('setState - applies any patternState matching the pattern', function(test) { - //arrange - var pa = require('../core/lib/pattern_assembler'); - var pattern_assembler = new pa(); - var patternlab = {}; - patternlab.config = {}; - patternlab.config.patternStates = {}; - patternlab.config.patternStates["pages-homepage-emergency"] = "inprogress"; - - var pattern = { - patternPartial: "pages-homepage-emergency" - }; - - //act - pattern_assembler.setPatternState(pattern, patternlab); - - //assert - test.equals(pattern.patternState, "inprogress"); - test.end(); -}); - -tap.test('setState - does not apply any patternState if nothing matches the pattern', function(test) { - //arrange - var pa = require('../core/lib/pattern_assembler'); - var pattern_assembler = new pa(); - var patternlab = {}; - patternlab.config = {}; - patternlab.config.patternStates = {}; - patternlab.config.patternStates["pages-homepage-emergency"] = "inprogress"; - - var pattern = { - key: "pages-homepage", - patternState: "" - }; - - //act - pattern_assembler.setPatternState(pattern, patternlab); - - //assert - test.equals(pattern.patternState, ""); - test.end(); + //assert + test.true(results[0].extendedTemplate.indexOf(1) > -1); + test.true(results[0].extendedTemplate.indexOf(2) > -1); + test.true(results[0].extendedTemplate.indexOf(3) > -1); + test.end(); + }).catch(test.threw); }); tap.test('parseDataLinks - replaces found link.* data for their expanded links', function(test) { @@ -550,61 +513,53 @@ tap.test('parseDataLinks - replaces found link.* data for their expanded links', patternlab.listitems = {}; patternlab.header = {}; patternlab.footer = {}; - //patternlab.data = fs.readJSONSync(path.resolve(patternlab.config.paths.source.data, 'data.json')); - //patternlab.listitems = fs.readJSONSync(path.resolve(patternlab.config.paths.source.data, 'listitems.json')); - //patternlab.header = fs.readFileSync(path.resolve(patternlab.config.paths.source.patternlabFiles, 'templates/pattern-header-footer/header.html'), 'utf8'); - //patternlab.footer = fs.readFileSync(path.resolve(patternlab.config.paths.source.patternlabFiles, 'templates/pattern-header-footer/footer.html'), 'utf8'); patternlab.patterns = [ - { - patternPartial: 'twitter-brad' - }, - { - patternPartial: 'twitter-dave' - }, - { - patternPartial: 'twitter-brian' - } + Pattern.createEmpty({ patternPartial: 'twitter-brad' }, patternlab), + Pattern.createEmpty({ patternPartial: 'twitter-dave' }, patternlab), + Pattern.createEmpty({ patternPartial: 'twitter-brian' }, patternlab) ]; patternlab.data.link = {}; patternlab.partials = {}; //diveSync once to perform iterative populating of patternlab object - plMain.process_all_patterns_iterative(pattern_assembler, patterns_dir, patternlab); - - //for the sake of the test, also imagining I have the following pages... - patternlab.data.link['twitter-brad'] = 'https://twitter.com/brad_frost'; - patternlab.data.link['twitter-dave'] = 'https://twitter.com/dmolsen'; - patternlab.data.link['twitter-brian'] = 'https://twitter.com/bmuenzenmeyer'; - - patternlab.data.brad = {url: "link.twitter-brad"}; - patternlab.data.dave = {url: "link.twitter-dave"}; - patternlab.data.brian = {url: "link.twitter-brian"}; - - - var pattern; - for (var i = 0; i < patternlab.patterns.length; i++) { - if (patternlab.patterns[i].patternPartial === 'test-nav') { - pattern = patternlab.patterns[i]; - } - } - - //assert before - test.equals(pattern.jsonFileData.brad.url, "link.twitter-brad", "brad pattern data should be found"); - test.equals(pattern.jsonFileData.dave.url, "link.twitter-dave", "dave pattern data should be found"); - test.equals(pattern.jsonFileData.brian.url, "link.twitter-brian", "brian pattern data should be found"); - - //act - pattern_assembler.parse_data_links(patternlab); - - //assert after - test.equals(pattern.jsonFileData.brad.url, "https://twitter.com/brad_frost", "brad pattern data should be replaced"); - test.equals(pattern.jsonFileData.dave.url, "https://twitter.com/dmolsen", "dave pattern data should be replaced"); - test.equals(pattern.jsonFileData.brian.url, "https://twitter.com/bmuenzenmeyer", "brian pattern data should be replaced"); + plMain.process_all_patterns_iterative( patterns_dir, patternlab) + .then(() => { + //for the sake of the test, also imagining I have the following pages... + patternlab.data.link['twitter-brad'] = 'https://twitter.com/brad_frost'; + patternlab.data.link['twitter-dave'] = 'https://twitter.com/dmolsen'; + patternlab.data.link['twitter-brian'] = 'https://twitter.com/bmuenzenmeyer'; + + patternlab.data.brad = {url: "link.twitter-brad"}; + patternlab.data.dave = {url: "link.twitter-dave"}; + patternlab.data.brian = {url: "link.twitter-brian"}; + + + var pattern; + for (var i = 0; i < patternlab.patterns.length; i++) { + if (patternlab.patterns[i].patternPartial === 'test-nav') { + pattern = patternlab.patterns[i]; + } + } - test.equals(patternlab.data.brad.url, "https://twitter.com/brad_frost", "global brad data should be replaced"); - test.equals(patternlab.data.dave.url, "https://twitter.com/dmolsen", "global dave data should be replaced"); - test.equals(patternlab.data.brian.url, "https://twitter.com/bmuenzenmeyer", "global brian data should be replaced"); - test.end(); + //assert before + test.equals(pattern.jsonFileData.brad.url, "link.twitter-brad", "brad pattern data should be found"); + test.equals(pattern.jsonFileData.dave.url, "link.twitter-dave", "dave pattern data should be found"); + test.equals(pattern.jsonFileData.brian.url, "link.twitter-brian", "brian pattern data should be found"); + + //act + pattern_assembler.parse_data_links(patternlab); + + //assert after + test.equals(pattern.jsonFileData.brad.url, "https://twitter.com/brad_frost", "brad pattern data should be replaced"); + test.equals(pattern.jsonFileData.dave.url, "https://twitter.com/dmolsen", "dave pattern data should be replaced"); + test.equals(pattern.jsonFileData.brian.url, "https://twitter.com/bmuenzenmeyer", "brian pattern data should be replaced"); + + test.equals(patternlab.data.brad.url, "https://twitter.com/brad_frost", "global brad data should be replaced"); + test.equals(patternlab.data.dave.url, "https://twitter.com/dmolsen", "global dave data should be replaced"); + test.equals(patternlab.data.brian.url, "https://twitter.com/bmuenzenmeyer", "global brian data should be replaced"); + test.end(); + }) + .catch(test.threw); }); tap.test('get_pattern_by_key - returns the fuzzy result when no others found', function(test) { @@ -791,16 +746,21 @@ tap.test('hidden patterns can be called by their nice names', function(test){ //act var hiddenPatternPath = path.join('00-test', '_00-hidden-pattern.mustache'); - var hiddenPattern = pattern_assembler.process_pattern_iterative(hiddenPatternPath, pl); - pattern_assembler.process_pattern_recursive(hiddenPatternPath, pl); - var testPatternPath = path.join('00-test', '15-hidden-pattern-tester.mustache'); - var testPattern = pattern_assembler.process_pattern_iterative(testPatternPath, pl); - pattern_assembler.process_pattern_recursive(testPatternPath, pl); - //assert - test.equals(util.sanitized(testPattern.render()), util.sanitized('Hello there! Here\'s the hidden atom: [This is the hidden atom]'), 'hidden pattern rendered output not as expected'); - test.end(); + var hiddenPattern = pattern_assembler.load_pattern_iterative(hiddenPatternPath, pl); + var testPattern = pattern_assembler.load_pattern_iterative(testPatternPath, pl); + + return Promise.all([ + pattern_assembler.process_pattern_iterative(hiddenPattern, pl), + pattern_assembler.process_pattern_iterative(testPattern, pl) + ]).then((results) => { + pattern_assembler.process_pattern_recursive(hiddenPatternPath, pl); + pattern_assembler.process_pattern_recursive(testPatternPath, pl); + + //assert + test.equals(util.sanitized(results[1].render()), util.sanitized('Hello there! Here\'s the hidden atom: [This is the hidden atom]'), 'hidden pattern rendered output not as expected'); + }).catch(test.threw); }); tap.test('parses pattern title correctly when frontmatter present', function(test){ @@ -811,14 +771,17 @@ tap.test('parses pattern title correctly when frontmatter present', function(tes var pl = util.fakePatternLab(testPatternsPath); var pattern_assembler = new pa(); - //act var testPatternPath = path.join('00-test', '01-bar.mustache'); - var testPattern = pattern_assembler.process_pattern_iterative(testPatternPath, pl); - pattern_assembler.process_pattern_recursive(testPatternPath, pl); + var testPattern = pattern_assembler.load_pattern_iterative(testPatternPath, pl); - //assert - test.equals(testPattern.patternName, 'An Atom Walks Into a Bar','patternName not overridden'); - test.end(); + //act + return Promise.all([ + pattern_assembler.process_pattern_iterative(testPattern, pl), + pattern_assembler.process_pattern_recursive(testPatternPath, pl) + ]).then((results) => { + //assert + test.equals(results[0].patternName, 'An Atom Walks Into a Bar','patternName not overridden'); + }).catch(test.threw); }); tap.test('parses pattern extra frontmatter correctly when frontmatter present', function(test){ @@ -829,12 +792,16 @@ tap.test('parses pattern extra frontmatter correctly when frontmatter present', var pl = util.fakePatternLab(testPatternsPath); var pattern_assembler = new pa(); - //act var testPatternPath = path.join('00-test', '01-bar.mustache'); - var testPattern = pattern_assembler.process_pattern_iterative(testPatternPath, pl); - pattern_assembler.process_pattern_recursive(testPatternPath, pl); + var testPattern = pattern_assembler.load_pattern_iterative(testPatternPath, pl); - //assert - test.equals(testPattern.allMarkdown.joke, 'bad','extra key not added'); - test.end(); + //act + return Promise.all([ + pattern_assembler.process_pattern_iterative(testPattern, pl), + pattern_assembler.process_pattern_recursive(testPatternPath, pl) + ]).then((results) => { + //assert + test.equals(results[0].allMarkdown.joke, 'bad','extra key not added'); + + }).catch(test.threw); }); diff --git a/test/pattern_engines_tests.js b/test/pattern_engines_tests.js index dc55b6cf0..0d20e73ad 100644 --- a/test/pattern_engines_tests.js +++ b/test/pattern_engines_tests.js @@ -4,6 +4,9 @@ var tap = require('tap'); var patternEngines = require('../core/lib/pattern_engines'); var Pattern = require('../core/lib/object_factory').Pattern; +var config = require('./util/patternlab-config.json'); + +patternEngines.loadAllEngines(config); // the mustache test pattern, stolen from object_factory unit tests var mustacheTestPattern = new Pattern('source/_patterns/00-atoms/00-global/00-colors-alt.mustache', {d: 123}); @@ -122,7 +125,7 @@ function testProps(object, propTests, test) { }); test.ok(object.hasOwnProperty(propName), '"' + propName + '" prop should be present'); - test.ok(isOneOfTheseTypes, '"' + propName + '" prop should be one of types ' + possibleTypes); + test.ok(isOneOfTheseTypes, '"' + propName + '" prop should be one of types ' + possibleTypes + ' but was instead ' + typeof propName); } // go over each property test and run it @@ -151,7 +154,7 @@ engineNames.forEach(function (engineName) { var propertyTests = { 'engine': ['object', 'function'], 'engineName': 'string', - 'engineFileExtension': 'string', + 'engineFileExtension': ['string', 'object'], 'renderPattern': 'function', 'findPartials': 'function' }; @@ -162,3 +165,23 @@ engineNames.forEach(function (engineName) { }); }); +tap.test('patternEngines getSupportedFileExtensions flattens known engine extensions into a single array', function (test) { + + //arrange + patternEngines.fooEngine = { + engineFileExtension : ['.foo1', '.foo2'] + }; + patternEngines.barEngine = { + engineFileExtension : '.bar' + }; + + const exts = patternEngines.getSupportedFileExtensions(); + test.ok(exts.includes('.foo1')); + test.ok(exts.includes('.foo2')); + test.ok(exts.includes('.bar')); + + delete patternEngines.fooEngine; + delete patternEngines.barEngine; + + test.end(); +}); diff --git a/test/pattern_graph_tests.js b/test/pattern_graph_tests.js index 78980422b..b09a2c4b2 100644 --- a/test/pattern_graph_tests.js +++ b/test/pattern_graph_tests.js @@ -7,6 +7,9 @@ var Pattern = require('../core/lib/object_factory').Pattern; var CompileState = require('../core/lib/object_factory').CompileState; var tap = require('tap'); const posixPath = require('./util/test_utils.js').posixPath; +var config = require('./util/patternlab-config.json'); +var engineLoader = require('../core/lib/pattern_engines'); +engineLoader.loadAllEngines(config); var patternlab = { config: { diff --git a/test/patternlab_tests.js b/test/patternlab_tests.js index 52456e187..c680058ba 100644 --- a/test/patternlab_tests.js +++ b/test/patternlab_tests.js @@ -9,8 +9,10 @@ var config = require('./util/patternlab-config.json'); var plEngineModule = rewire('../core/lib/patternlab'); //set up a global mocks - we don't want to be writing/rendering any files right now -const uiBuilderMock = { - buildFrontend: function (patternlab) { } +const uiBuilderMock = function(){ + return { + buildFrontend: function () { } + }; }; const fsMock = { diff --git a/test/pseudopattern_hunter_tests.js b/test/pseudopattern_hunter_tests.js index 007138475..57becf357 100644 --- a/test/pseudopattern_hunter_tests.js +++ b/test/pseudopattern_hunter_tests.js @@ -3,14 +3,18 @@ var tap = require('tap'); var path = require('path'); -var pha = require('../core/lib/pseudopattern_hunter'); +var pph = require('../core/lib/pseudopattern_hunter'); + var pa = require('../core/lib/pattern_assembler'); var Pattern = require('../core/lib/object_factory').Pattern; var PatternGraph = require('../core/lib/pattern_graph').PatternGraph; +var config = require('./util/patternlab-config.json'); +var engineLoader = require('../core/lib/pattern_engines'); +engineLoader.loadAllEngines(config); + var fs = require('fs-extra'); var pattern_assembler = new pa(); -var pseudopattern_hunter = new pha(); var patterns_dir = './test/files/_patterns/'; var public_patterns_dir = './test/public/patterns'; @@ -51,16 +55,14 @@ tap.test('pseudpattern found and added as a pattern', function (test) { //act var patternCountBefore = pl.patterns.length; - pseudopattern_hunter.find_pseudopatterns(atomPattern, pl); - - //assert - test.equals(patternCountBefore + 1, pl.patterns.length); - test.equals(pl.patterns[1].patternPartial, 'test-styled-atom-alt'); - test.equals(pl.patterns[1].extendedTemplate.replace(/\s\s+/g, ' ').replace(/\n/g, ' ').trim(), ' {{message}} '); - test.equals(JSON.stringify(pl.patterns[1].jsonFileData), JSON.stringify({"message": "alternateMessage"})); - test.equals(pl.patterns[1].patternLink, '00-test-03-styled-atom-alt' + path.sep + '00-test-03-styled-atom-alt.html'); - - test.end(); + return pph.find_pseudopatterns(atomPattern, pl).then(() => { + //assert + test.equals(patternCountBefore + 1, pl.patterns.length); + test.equals(pl.patterns[1].patternPartial, 'test-styled-atom-alt'); + test.equals(pl.patterns[1].extendedTemplate.replace(/\s\s+/g, ' ').replace(/\n/g, ' ').trim(), ' {{message}} '); + test.equals(JSON.stringify(pl.patterns[1].jsonFileData), JSON.stringify({"message": "alternateMessage"})); + test.equals(pl.patterns[1].patternLink, '00-test-03-styled-atom-alt' + path.sep + '00-test-03-styled-atom-alt.html'); + }); }); tap.test('pseudpattern variant includes stylePartials and parameteredPartials', function (test) { @@ -83,12 +85,10 @@ tap.test('pseudpattern variant includes stylePartials and parameteredPartials', pattern_assembler.addPattern(pseudoPattern, pl); //act - pseudopattern_hunter.find_pseudopatterns(pseudoPattern, pl); - - //assert - test.equals(pl.patterns[2].patternPartial, 'test-pseudomodifier-test'); - test.equals(pl.patterns[2].stylePartials, pseudoPattern.stylePartials); - test.equals(pl.patterns[2].parameteredPartials, pseudoPattern.parameteredPartials); - - test.end(); + return pph.find_pseudopatterns(pseudoPattern, pl).then(() => { + //assert + test.equals(pl.patterns[2].patternPartial, 'test-pseudomodifier-test'); + test.equals(pl.patterns[2].stylePartials, pseudoPattern.stylePartials); + test.equals(pl.patterns[2].parameteredPartials, pseudoPattern.parameteredPartials); + }); }); diff --git a/test/ui_builder_tests.js b/test/ui_builder_tests.js index 5bf8af416..6dc5bf308 100644 --- a/test/ui_builder_tests.js +++ b/test/ui_builder_tests.js @@ -8,6 +8,10 @@ var Pattern = require('../core/lib/object_factory').Pattern; var extend = require('util')._extend; var uiModule = rewire('../core/lib/ui_builder'); var path = require('path'); +var config = require('./util/patternlab-config.json'); + +var engineLoader = require('../core/lib/pattern_engines'); +engineLoader.loadAllEngines(config); //set up a global mocks - we don't want to be writing/rendering any files right now var fsMock = { diff --git a/test/util/patternlab-config.json b/test/util/patternlab-config.json index d13f33508..720975302 100644 --- a/test/util/patternlab-config.json +++ b/test/util/patternlab-config.json @@ -6,7 +6,13 @@ "data" : "./test/files/_data/", "meta": "./test/files/_meta/", "styleguide" : "./test/files/styleguide/", - "patternlabFiles" : "./test/files/", + "patternlabFiles" : { + "general-header": "./test/files/partials/general-header.mustache", + "general-footer": "./test/files/partials/general-footer.mustache", + "patternSection": "./test/files/partials/patternSection.mustache", + "patternSectionSubtype": "./test/files/partials/patternSectionSubtype.mustache", + "viewall": "./test/files/viewall.mustache" + }, "js" : "./test/files/js", "images" : "./test/files/images", "fonts" : "./test/files/fonts", @@ -63,5 +69,10 @@ }, "cleanOutputHtml": true, "exportToGraphViz": false, - "cleanPublic": true + "cleanPublic": true, + "theme": { + "color": "dark", + "density": "compact", + "layout": "horizontal" + } }