documentalist
Advanced tools
Comparing version 0.0.2 to 0.0.3
10
cli.js
@@ -37,8 +37,8 @@ #!/usr/bin/env node | ||
const doc = new Documentalist(); | ||
const docs = Documentalist.create(); | ||
plugins.forEach(({ pattern, plugin }) => { | ||
doc.use(new RegExp(pattern), plugin); | ||
docs.use(new RegExp(pattern), plugin); | ||
}); | ||
const documentation = doc.documentGlobs(...argv._); | ||
console.log(JSON.stringify(documentation, null, 2)); | ||
docs.documentGlobs(...argv._) | ||
.then((data) => JSON.stringify(data, null, 2)) | ||
.then(console.log, console.error); |
@@ -7,3 +7,2 @@ /** | ||
*/ | ||
import { IInterfaceEntry } from "./plugins/typescript"; | ||
/** Represents a single `@tag <value>` line from a file. */ | ||
@@ -61,13 +60,2 @@ export interface ITag { | ||
} | ||
/** | ||
* The root type of data exported by Documentalist. | ||
* Each plugin emits its data in a separate key. | ||
*/ | ||
export interface IDocumentalistData { | ||
docs: { | ||
[key: string]: IPageData; | ||
}; | ||
ts: IInterfaceEntry[]; | ||
[plugin: string]: any; | ||
} | ||
/** One page entry in a layout tree. */ | ||
@@ -74,0 +62,0 @@ export interface ITreeEntry { |
@@ -8,2 +8,3 @@ /** | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
/** type guard to determine if a `contents` node is an `@tag` statement */ | ||
@@ -56,2 +57,1 @@ function isTag(node) { | ||
exports.createNavigableTree = createNavigableTree; | ||
//# sourceMappingURL=client.js.map |
/// <reference types="marked" /> | ||
import { IDocumentalistData, StringOrTag } from "./client"; | ||
import { IFile, IPlugin } from "./plugins"; | ||
export interface IBlock { | ||
content: string; | ||
metadata: any; | ||
renderedContent: StringOrTag[]; | ||
} | ||
export interface IApi { | ||
/** Process the given globs and emit all the data. */ | ||
documentGlobs: (...filesGlobs: string[]) => IDocumentalistData; | ||
/** Process the given list of files and emit all the data. */ | ||
documentFiles: (files: IFile[]) => IDocumentalistData; | ||
import { IFile, IMarkdownPluginData, IPlugin, ITypescriptPluginData } from "./plugins"; | ||
export interface IApi<T> { | ||
/** | ||
* Render a block of content by extracting metadata front matter and | ||
* splitting text content into rendered HTML strings and `{ tag, value }` objects. | ||
* Finds all files matching the provided variadic glob expressions and then | ||
* runs `documentFiles` with them, emitting all the documentation data. | ||
* | ||
* @see documentFiles | ||
*/ | ||
renderBlock: (blockContent: string, reservedTagWords?: string[]) => IBlock; | ||
/** Use a plugin to process the files matching the pattern. */ | ||
use: (pattern: RegExp, plugin: IPlugin<any>) => IApi; | ||
} | ||
export declare class Documentalist implements IApi { | ||
private markedOptions; | ||
private plugins; | ||
constructor(markedOptions?: MarkedOptions); | ||
use(pattern: RegExp, plugin: IPlugin<any>): this; | ||
documentGlobs(...filesGlobs: string[]): IDocumentalistData; | ||
documentFiles(files: IFile[]): IDocumentalistData; | ||
renderBlock(blockContent: string, reservedTagWords?: string[]): IBlock; | ||
/** Expand an array of globs and flatten to a single array of files. */ | ||
private expandGlobs(filesGlobs); | ||
documentGlobs: (...filesGlobs: string[]) => Promise<T>; | ||
/** | ||
* Converts the content string into an array of `ContentNode`s. If the | ||
* `contents` option is `html`, the string nodes will also be rendered with | ||
* markdown. | ||
* Iterates over all plugins, passing all matching files to each in turn. | ||
* The output of each plugin is merged to produce the resulting | ||
* documentation object. | ||
* | ||
* The return type T is a composite type has a composite type of all the | ||
* plugin data types. | ||
*/ | ||
private renderContents(content, reservedTagWords); | ||
documentFiles: (files: IFile[]) => Promise<T>; | ||
/** | ||
* Extracts optional YAML frontmatter metadata block from the beginning of a | ||
* markdown file and parses it to a JS object. | ||
* Adds the plugin to Documentalist. Returns a new instance of Documentalist | ||
* with a template type that includes the data from the plugin. This way the | ||
* `documentFiles` and `documentGlobs` methods will return an object that is | ||
* already typed to include each plugin's output. | ||
* | ||
* The plugin is applied to all files whose absolute path matches the | ||
* supplied pattern. | ||
* | ||
* @param pattern - A regexp pattern or a file extension string like "js" | ||
* @param plugin - The plugin implementation | ||
* @returns A new instance of `Documentalist` with an extended type | ||
*/ | ||
private extractMetadata(text); | ||
use: <P>(pattern: RegExp | string, plugin: IPlugin<P>) => IApi<T & P>; | ||
/** | ||
* Splits the content string when it encounters a line that begins with a | ||
* `@tag`. You may prevent this splitting by specifying an array of reserved | ||
* tag names. | ||
* Returns a new instance of Documentalist with no plugins. | ||
*/ | ||
private parseTags(content, reservedWords); | ||
clearPlugins(): IApi<{}>; | ||
} | ||
/** | ||
* Plugins are stored with the regex used to match against file paths. | ||
*/ | ||
export interface IPluginEntry<T> { | ||
pattern: RegExp; | ||
plugin: IPlugin<T>; | ||
} | ||
export declare class Documentalist<T> implements IApi<T> { | ||
private plugins; | ||
private markedOptions; | ||
static create(markedOptions?: MarkedOptions): IApi<IMarkdownPluginData & ITypescriptPluginData>; | ||
constructor(plugins?: Array<IPluginEntry<T>>, markedOptions?: MarkedOptions); | ||
use<P>(pattern: RegExp | string, plugin: IPlugin<P>): IApi<T & P>; | ||
clearPlugins(): IApi<{}>; | ||
documentGlobs(...filesGlobs: string[]): Promise<T>; | ||
documentFiles(files: IFile[]): Promise<T>; | ||
/** | ||
* Expands an array of globs and flatten to a single array of files. | ||
*/ | ||
private expandGlobs(filesGlobs); | ||
/** | ||
* Shallow-merges keys form source into destination object (modifying it in the process). | ||
*/ | ||
private mergeInto(destination, source); | ||
} |
@@ -8,57 +8,57 @@ /** | ||
"use strict"; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const fs = require("fs"); | ||
const glob = require("glob"); | ||
const yaml = require("js-yaml"); | ||
const marked = require("marked"); | ||
const path = require("path"); | ||
const compiler_1 = require("./compiler"); | ||
const plugins_1 = require("./plugins"); | ||
/** | ||
* Matches the triple-dash metadata block on the first line of markdown file. | ||
* The first capture group contains YAML content. | ||
*/ | ||
const METADATA_REGEX = /^---\n?((?:.|\n)*)\n---\n/; | ||
/** | ||
* Splits text content for lines that begin with `@tagName`. | ||
*/ | ||
const TAG_REGEX = /^@(\S+)(?:\s+([^\n]+))?$/; | ||
const TAG_SPLIT_REGEX = /^(@\S+(?:\s+[^\n]+)?)$/gm; | ||
/** | ||
* Ignored `@tag` names. Some languages already support `@tags`, so to separate | ||
* Documentalist tags, we use these default reserved words to avoid conflicts. | ||
* | ||
* Plugins may define their own reserved words when calling the `renderBlock` | ||
* method. | ||
*/ | ||
const RESERVED_WORDS = [ | ||
"import", | ||
]; | ||
class Documentalist { | ||
constructor(markedOptions = {}) { | ||
constructor(plugins = [], markedOptions = {}) { | ||
this.plugins = plugins; | ||
this.markedOptions = markedOptions; | ||
this.plugins = []; | ||
this.use(/\.md$/, new plugins_1.MarkdownPlugin()); | ||
this.use(/\.s?css$/, new plugins_1.CssPlugin()); | ||
this.use(/\.tsx?$/, new plugins_1.TypescriptPlugin()); | ||
} | ||
static create(markedOptions) { | ||
return new Documentalist([], markedOptions) | ||
.use(/\.md$/, new plugins_1.MarkdownPlugin()) | ||
.use(/\.tsx?$/, new plugins_1.TypescriptPlugin()); | ||
} | ||
use(pattern, plugin) { | ||
this.plugins.push({ pattern, plugin }); | ||
return this; | ||
if (typeof pattern === "string") { | ||
pattern = new RegExp(`${pattern}$`); | ||
} | ||
const newPlugins = [...this.plugins, { pattern, plugin }]; | ||
return new Documentalist(newPlugins, this.markedOptions); | ||
} | ||
clearPlugins() { | ||
return new Documentalist([], this.markedOptions); | ||
} | ||
documentGlobs(...filesGlobs) { | ||
const files = this.expandGlobs(filesGlobs); | ||
return this.documentFiles(files); | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const files = this.expandGlobs(filesGlobs); | ||
return this.documentFiles(files); | ||
}); | ||
} | ||
documentFiles(files) { | ||
const documentation = {}; | ||
for (const { pattern, plugin } of this.plugins) { | ||
documentation[plugin.name] = plugin.compile(this, files.filter((f) => pattern.test(f.path))); | ||
} | ||
return documentation; | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const compiler = new compiler_1.Compiler(this.markedOptions); | ||
const documentation = {}; | ||
for (const { pattern, plugin } of this.plugins) { | ||
const pluginFiles = files.filter((f) => pattern.test(f.path)); | ||
const pluginDocumentation = yield plugin.compile(pluginFiles, compiler); | ||
this.mergeInto(documentation, pluginDocumentation); | ||
} | ||
return documentation; | ||
}); | ||
} | ||
renderBlock(blockContent, reservedTagWords = RESERVED_WORDS) { | ||
const { content, metadata } = this.extractMetadata(blockContent); | ||
const renderedContent = this.renderContents(content, reservedTagWords); | ||
return { content, metadata, renderedContent }; | ||
} | ||
/** Expand an array of globs and flatten to a single array of files. */ | ||
/** | ||
* Expands an array of globs and flatten to a single array of files. | ||
*/ | ||
expandGlobs(filesGlobs) { | ||
@@ -77,45 +77,16 @@ return filesGlobs | ||
/** | ||
* Converts the content string into an array of `ContentNode`s. If the | ||
* `contents` option is `html`, the string nodes will also be rendered with | ||
* markdown. | ||
* Shallow-merges keys form source into destination object (modifying it in the process). | ||
*/ | ||
renderContents(content, reservedTagWords) { | ||
const splitContents = this.parseTags(content, reservedTagWords); | ||
return splitContents | ||
.map((node) => typeof node === "string" ? marked(node, this.markedOptions) : node) | ||
.filter((node) => node !== ""); | ||
} | ||
/** | ||
* Extracts optional YAML frontmatter metadata block from the beginning of a | ||
* markdown file and parses it to a JS object. | ||
*/ | ||
extractMetadata(text) { | ||
const match = METADATA_REGEX.exec(text); | ||
if (match === null) { | ||
return { content: text, metadata: {} }; | ||
mergeInto(destination, source) { | ||
for (const key in source) { | ||
if (source.hasOwnProperty(key)) { | ||
if (destination.hasOwnProperty(key)) { | ||
console.warn(`WARNING: Duplicate plugin key "${key}". Your plugins are overwriting each other.`); | ||
} | ||
destination[key] = source[key]; | ||
} | ||
} | ||
const content = text.substr(match[0].length); | ||
return { content, metadata: yaml.load(match[1]) || {} }; | ||
return destination; | ||
} | ||
/** | ||
* Splits the content string when it encounters a line that begins with a | ||
* `@tag`. You may prevent this splitting by specifying an array of reserved | ||
* tag names. | ||
*/ | ||
parseTags(content, reservedWords) { | ||
return content.split(TAG_SPLIT_REGEX).map((str) => { | ||
const match = TAG_REGEX.exec(str); | ||
if (match === null || reservedWords.indexOf(match[1]) >= 0) { | ||
return str; | ||
} | ||
else { | ||
return { | ||
tag: match[1], | ||
value: match[2], | ||
}; | ||
} | ||
}); | ||
} | ||
} | ||
exports.Documentalist = Documentalist; | ||
//# sourceMappingURL=documentalist.js.map |
@@ -7,3 +7,4 @@ /** | ||
*/ | ||
export * from "./client"; | ||
export * from "./documentalist"; | ||
export * from "./client"; | ||
export * from "./plugins"; |
@@ -11,4 +11,5 @@ /** | ||
} | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
__export(require("./client")); | ||
__export(require("./documentalist")); | ||
__export(require("./client")); | ||
//# sourceMappingURL=index.js.map | ||
__export(require("./plugins")); |
@@ -8,10 +8,3 @@ /** | ||
"use strict"; | ||
var __assign = (this && this.__assign) || Object.assign || function(t) { | ||
for (var s, i = 1, n = arguments.length; i < n; i++) { | ||
s = arguments[i]; | ||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) | ||
t[p] = s[p]; | ||
} | ||
return t; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const path = require("path"); | ||
@@ -22,3 +15,3 @@ const client_1 = require("./client"); | ||
const reference = getReference(props); | ||
return __assign({}, props, { reference, title }); | ||
return Object.assign({}, props, { reference, title }); | ||
} | ||
@@ -42,2 +35,1 @@ exports.makePage = makePage; | ||
} | ||
//# sourceMappingURL=page.js.map |
@@ -7,5 +7,5 @@ /** | ||
*/ | ||
export * from "./css"; | ||
export * from "./kss"; | ||
export * from "./markdown"; | ||
export * from "./plugin"; | ||
export * from "./typescript"; |
@@ -11,5 +11,5 @@ /** | ||
} | ||
__export(require("./css")); | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
__export(require("./kss")); | ||
__export(require("./markdown")); | ||
__export(require("./typescript")); | ||
//# sourceMappingURL=index.js.map |
@@ -7,10 +7,10 @@ /** | ||
*/ | ||
import { Documentalist } from ".."; | ||
import { IPageData } from "../client"; | ||
import { IFile, IPlugin } from "./plugin"; | ||
export declare type IPageMap = { | ||
[key: string]: IPageData; | ||
}; | ||
export declare class MarkdownPlugin implements IPlugin<IPageMap> { | ||
name: string; | ||
import { ICompiler, IFile, IPlugin } from "./plugin"; | ||
export interface IMarkdownPluginData { | ||
docs: { | ||
[key: string]: IPageData; | ||
}; | ||
} | ||
export declare class MarkdownPlugin implements IPlugin<IMarkdownPluginData> { | ||
/** | ||
@@ -20,5 +20,7 @@ * Reads the given set of markdown files and adds their data to the internal storage. | ||
*/ | ||
compile(documentalist: Documentalist, markdownFiles: IFile[]): { | ||
[key: string]: IPageData; | ||
compile(markdownFiles: IFile[], {renderBlock}: ICompiler): { | ||
docs: { | ||
[key: string]: IPageData; | ||
}; | ||
}; | ||
} |
@@ -8,7 +8,5 @@ /** | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const page_1 = require("../page"); | ||
class MarkdownPlugin { | ||
constructor() { | ||
this.name = "docs"; | ||
} | ||
/** | ||
@@ -18,3 +16,3 @@ * Reads the given set of markdown files and adds their data to the internal storage. | ||
*/ | ||
compile(documentalist, markdownFiles) { | ||
compile(markdownFiles, { renderBlock }) { | ||
const pageStore = new Map(); | ||
@@ -25,3 +23,3 @@ markdownFiles | ||
const fileContents = file.read(); | ||
const { content, metadata, renderedContent } = documentalist.renderBlock(fileContents); | ||
const { content, metadata, renderedContent } = renderBlock(fileContents); | ||
const page = page_1.makePage({ | ||
@@ -57,3 +55,4 @@ absolutePath, | ||
}); | ||
return mapToObject(pageStore); | ||
const docs = mapToObject(pageStore); | ||
return { docs }; | ||
} | ||
@@ -69,2 +68,1 @@ } | ||
} | ||
//# sourceMappingURL=markdown.js.map |
@@ -7,3 +7,7 @@ /** | ||
*/ | ||
import { Documentalist } from ".."; | ||
import { StringOrTag } from "../client"; | ||
export { StringOrTag }; | ||
/** | ||
* Abstract representation of a file, containing absolute path and synchronous `read` operation. | ||
*/ | ||
export interface IFile { | ||
@@ -13,5 +17,44 @@ path: string; | ||
} | ||
/** | ||
* The output of `renderBlock` which parses a long form documentation block into | ||
* metadata, rendered markdown, and tags. | ||
*/ | ||
export interface IBlock { | ||
/** | ||
* The original string content block. | ||
*/ | ||
content: string; | ||
/** | ||
* Parsed YAML front matter (if any) or {}. | ||
*/ | ||
metadata: any; | ||
/** | ||
* An array of markdown-rendered HTML or tags. | ||
*/ | ||
renderedContent: StringOrTag[]; | ||
} | ||
/** | ||
* Each plugin receives a `Compiler` instance to aid in the processing of source files. | ||
*/ | ||
export interface ICompiler { | ||
/** | ||
* Converts an array of entries into a map of key to entry, using given | ||
* callback to extract key from each item. | ||
*/ | ||
objectify: <T>(array: T[], getKey: (item: T) => string) => { | ||
[key: string]: T; | ||
}; | ||
/** | ||
* Render a block of content by extracting metadata (YAML front matter) and | ||
* splitting text content into markdown-rendered HTML strings and `{ tag, | ||
* value }` objects. | ||
* | ||
* To prevent special strings like "@include" from being parsed, a reserved | ||
* tag words array may be provided, in which case the line will be left as | ||
* is. | ||
*/ | ||
renderBlock: (blockContent: string, reservedTagWords?: string[]) => IBlock; | ||
} | ||
export interface IPlugin<T> { | ||
name: string; | ||
compile: (doc: Documentalist, files: IFile[]) => T; | ||
compile: (files: IFile[], doc: ICompiler) => T | Promise<T>; | ||
} |
@@ -8,2 +8,2 @@ /** | ||
"use strict"; | ||
//# sourceMappingURL=plugin.js.map | ||
Object.defineProperty(exports, "__esModule", { value: true }); |
@@ -8,5 +8,4 @@ /** | ||
import { IJsDocTags } from "ts-quick-docs"; | ||
import { Documentalist, IBlock } from ".."; | ||
import { IFile, IPlugin } from "./plugin"; | ||
export interface IDocEntry { | ||
import { IBlock, ICompiler, IFile, IPlugin } from "./plugin"; | ||
export interface ITsDocEntry { | ||
documentation: IBlock; | ||
@@ -18,12 +17,20 @@ fileName: string; | ||
} | ||
export interface IPropertyEntry extends IDocEntry { | ||
export interface ITsPropertyEntry extends ITsDocEntry { | ||
optional?: boolean; | ||
} | ||
export interface IInterfaceEntry extends IDocEntry { | ||
export interface ITsInterfaceEntry extends ITsDocEntry { | ||
extends?: string[]; | ||
properties: IPropertyEntry[]; | ||
properties: ITsPropertyEntry[]; | ||
} | ||
export declare class TypescriptPlugin implements IPlugin<IInterfaceEntry[]> { | ||
name: string; | ||
compile(documentalist: Documentalist, files: IFile[]): IInterfaceEntry[]; | ||
export interface ITypescriptPluginData { | ||
ts: { | ||
[name: string]: ITsInterfaceEntry; | ||
}; | ||
} | ||
export declare class TypescriptPlugin implements IPlugin<ITypescriptPluginData> { | ||
compile(files: IFile[], {renderBlock, objectify}: ICompiler): { | ||
ts: { | ||
[key: string]: ITsInterfaceEntry; | ||
}; | ||
}; | ||
} |
@@ -8,20 +8,11 @@ /** | ||
"use strict"; | ||
var __assign = (this && this.__assign) || Object.assign || function(t) { | ||
for (var s, i = 1, n = arguments.length; i < n; i++) { | ||
s = arguments[i]; | ||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) | ||
t[p] = s[p]; | ||
} | ||
return t; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const ts_quick_docs_1 = require("ts-quick-docs"); | ||
class TypescriptPlugin { | ||
constructor() { | ||
this.name = "ts"; | ||
compile(files, { renderBlock, objectify }) { | ||
const entries = ts_quick_docs_1.default.fromFiles(files.map((f) => f.path), {}).map((entry) => (Object.assign({}, entry, { documentation: renderBlock(entry.documentation), properties: entry.properties.map((prop) => (Object.assign({}, prop, { documentation: renderBlock(prop.documentation) }))) }))); | ||
const ts = objectify(entries, (e) => e.name); | ||
return { ts }; | ||
} | ||
compile(documentalist, files) { | ||
return ts_quick_docs_1.default.fromFiles(files.map((f) => f.path), {}).map((entry) => (__assign({}, entry, { documentation: documentalist.renderBlock(entry.documentation), properties: entry.properties.map((prop) => (__assign({}, prop, { documentation: documentalist.renderBlock(prop.documentation) }))) }))); | ||
} | ||
} | ||
exports.TypescriptPlugin = TypescriptPlugin; | ||
//# sourceMappingURL=typescript.js.map |
{ | ||
"name": "documentalist", | ||
"version": "0.0.2", | ||
"version": "0.0.3", | ||
"description": "documentation for the rest of us", | ||
@@ -13,5 +13,4 @@ "main": "dist/index.js", | ||
"js-yaml": "^3.7.0", | ||
"kss": "3.0.0-beta.15", | ||
"marked": "^0.3.6", | ||
"postcss": "^5.2.13", | ||
"postcss-scss": "^0.4.1", | ||
"ts-quick-docs": "^0.5.3", | ||
@@ -27,14 +26,12 @@ "yargs": "^6.6.0" | ||
"@types/node": "^6.0.52", | ||
"@types/react": "^15.0.14", | ||
"@types/yargs": "^6.6.0", | ||
"chai": "^3.5.0", | ||
"circle-github-bot": "^0.4.0", | ||
"highlights": "^1.4.1", | ||
"mocha": "^3.2.0", | ||
"npm-run-all": "^4.0.2", | ||
"pug-cli": "^1.0.0-alpha6", | ||
"react": "^15.4.2", | ||
"react-dom": "^15.4.2", | ||
"ts-node": "^1.7.2", | ||
"tslint": "^4.0.2", | ||
"typescript": "2.1.5" | ||
"ts-node": "^2.1.0", | ||
"tslint": "^4.5.1", | ||
"typescript": "^2.2.1" | ||
}, | ||
@@ -41,0 +38,0 @@ "scripts": { |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
6
16
898
39982
29
1
+ Addedkss@3.0.0-beta.15
+ Addedabbrev@1.1.1(transitive)
+ Addedbluebird@3.7.2(transitive)
+ Addedcli@0.4.4-2(transitive)
+ Addedcommander@0.6.12.0.0(transitive)
+ Addedconfig-chain@1.1.13(transitive)
+ Addeddebug@4.4.0(transitive)
+ Addeddeep-equal@0.1.2(transitive)
+ Addeddiff@1.0.7(transitive)
+ Addedforeachasync@3.0.0(transitive)
+ Addedfresh@0.1.0(transitive)
+ Addedfs-extra@0.30.0(transitive)
+ Addedglob@3.2.13.2.3(transitive)
+ Addedgraceful-fs@1.2.32.0.3(transitive)
+ Addedgrowl@1.7.0(transitive)
+ Addedhandlebars@4.7.8(transitive)
+ Addedinherits@1.0.2(transitive)
+ Addedini@1.3.8(transitive)
+ Addedjade@0.26.3(transitive)
+ Addedjs-beautify@1.4.2(transitive)
+ Addedjsonfile@2.4.0(transitive)
+ Addedklaw@1.3.1(transitive)
+ Addedkss@3.0.0-beta.15(transitive)
+ Addedlru-cache@2.7.3(transitive)
+ Addedmime@1.2.6(transitive)
+ Addedminimatch@0.2.143.0.8(transitive)
+ Addedminimist@1.2.8(transitive)
+ Addedmkdirp@0.3.00.3.5(transitive)
+ Addedmocha@1.17.0(transitive)
+ Addedms@2.1.3(transitive)
+ Addedneo-async@2.6.2(transitive)
+ Addednopt@2.1.2(transitive)
+ Addedphpjs@1.3.2(transitive)
+ Addedproto-list@1.2.4(transitive)
+ Addedrange-parser@0.0.4(transitive)
+ Addedrimraf@2.7.1(transitive)
+ Addedsend@0.1.0(transitive)
+ Addedsigmund@1.0.1(transitive)
+ Addedsource-map@0.6.1(transitive)
+ Addedtwig@0.9.5(transitive)
+ Addeduglify-js@3.19.3(transitive)
+ Addedunderscore@1.5.2(transitive)
+ Addedwalk@2.3.15(transitive)
+ Addedwordwrap@1.0.0(transitive)
- Removedpostcss@^5.2.13
- Removedpostcss-scss@^0.4.1
- Removedansi-styles@2.2.1(transitive)
- Removedchalk@1.1.3(transitive)
- Removedescape-string-regexp@1.0.5(transitive)
- Removedhas-ansi@2.0.0(transitive)
- Removedhas-flag@1.0.0(transitive)
- Removedjs-base64@2.6.4(transitive)
- Removedpostcss@5.2.18(transitive)
- Removedpostcss-scss@0.4.1(transitive)
- Removedsource-map@0.5.7(transitive)
- Removedsupports-color@2.0.03.2.3(transitive)