From eab5c60e609fbab377a6d451adffa7e5cecffb0b Mon Sep 17 00:00:00 2001 From: Bogdan Chadkin Date: Sun, 11 Jun 2017 23:58:47 +0300 Subject: [PATCH 1/7] Remove keyframes process --- src/index.js | 31 ------------------- test/test-cases/export-difficult/expected.css | 23 -------------- test/test-cases/export-difficult/source.css | 17 ---------- test/test-cases/export-keyframes/expected.css | 23 -------------- test/test-cases/export-keyframes/source.css | 18 ----------- 5 files changed, 112 deletions(-) delete mode 100644 test/test-cases/export-difficult/expected.css delete mode 100644 test/test-cases/export-difficult/source.css delete mode 100644 test/test-cases/export-keyframes/expected.css delete mode 100644 test/test-cases/export-keyframes/source.css diff --git a/src/index.js b/src/index.js index 8341a07..05803ac 100644 --- a/src/index.js +++ b/src/index.js @@ -158,37 +158,6 @@ module.exports = postcss.plugin( }) decl.remove() }) - - rule.walkDecls(decl => { - var tokens = decl.value.split(/(,|'[^']*'|"[^"]*")/) - tokens = tokens.map((token, idx) => { - if (idx === 0 || tokens[idx - 1] === ',') { - let localMatch = /^(\s*):local\s*\((.+?)\)/.exec(token) - if (localMatch) { - return ( - localMatch[1] + - exportScopedName(localMatch[2]) + - token.substr(localMatch[0].length) - ) - } else { - return token - } - } else { - return token - } - }) - decl.value = tokens.join('') - }) - }) - - // Find any :local keyframes - css.walkAtRules(atrule => { - if (/keyframes$/.test(atrule.name)) { - var localMatch = /^\s*:local\s*\((.+?)\)\s*$/.exec(atrule.params) - if (localMatch) { - atrule.params = exportScopedName(localMatch[1]) - } - } }) // If we found any :locals, insert an :export rule diff --git a/test/test-cases/export-difficult/expected.css b/test/test-cases/export-difficult/expected.css deleted file mode 100644 index aa7cae1..0000000 --- a/test/test-cases/export-difficult/expected.css +++ /dev/null @@ -1,23 +0,0 @@ -@keyframes _input__fade-in { - from { - opacity: 0; - } -} - -@-webkit-keyframes _input__fade-out { - to { - opacity: 0; - } -} - -._input__fadeIn { - animation: _input__fade-in 5s, - _input__fade-out 1s :local(wrong); - content: _input__fade-in, wrong, "difficult, :local(wrong)" :local(wrong); -} - -:export { - fadeIn: _input__fadeIn; - fade-in: _input__fade-in; - fade-out: _input__fade-out; -} diff --git a/test/test-cases/export-difficult/source.css b/test/test-cases/export-difficult/source.css deleted file mode 100644 index 8819c47..0000000 --- a/test/test-cases/export-difficult/source.css +++ /dev/null @@ -1,17 +0,0 @@ -@keyframes :local(fade-in) { - from { - opacity: 0; - } -} - -@-webkit-keyframes :local(fade-out) { - to { - opacity: 0; - } -} - -:local(.fadeIn) { - animation: _colon_local(fade-in) 5s,/* some, :local(comment) */ - _colon_local(fade-out) 1s _colon_local(wrong); - content: _colon_local(fade-in), wrong, "difficult, :local(wrong)" _colon_local(wrong); -} diff --git a/test/test-cases/export-keyframes/expected.css b/test/test-cases/export-keyframes/expected.css deleted file mode 100644 index 546a3fb..0000000 --- a/test/test-cases/export-keyframes/expected.css +++ /dev/null @@ -1,23 +0,0 @@ -@keyframes _input__fade-in { - from { - opacity: 0; - } - 100% { - opacity: 1; - } -} - -@keyframes fade { - from { - opacity: 0.5; - } -} - -._input__fadeIn { - animation-name: _input__fade-in; -} - -:export { - fadeIn: _input__fadeIn; - fade-in: _input__fade-in; -} diff --git a/test/test-cases/export-keyframes/source.css b/test/test-cases/export-keyframes/source.css deleted file mode 100644 index f07f7c9..0000000 --- a/test/test-cases/export-keyframes/source.css +++ /dev/null @@ -1,18 +0,0 @@ -@keyframes :local(fade-in) { - from { - opacity: 0; - } - 100% { - opacity: 1; - } -} - -@keyframes fade { - from { - opacity: 0.5; - } -} - -:local(.fadeIn) { - animation-name: _colon_local(fade-in); -} From f163ee415c7b367c72914cec0e3e86ea311fa961 Mon Sep 17 00:00:00 2001 From: Bogdan Chadkin Date: Mon, 12 Jun 2017 21:40:57 +0300 Subject: [PATCH 2/7] Remove scoping functionality and add scoping contract --- .travis.yml | 5 - package.json | 19 +- src/index.js | 264 +++---- .../error-comma-in-local/expected.error.txt | 1 - .../error-comma-in-local/source.css | 3 - .../expected.error.txt | 1 - .../source.css | 3 - .../expected.error.txt | 1 - .../source.css | 3 - .../expected.error.txt | 1 - .../source.css | 3 - .../expected.error.txt | 1 - .../source.css | 3 - .../expected.error.txt | 1 - .../source.css | 3 - .../expected.error.txt | 1 - .../error-not-allowed-in-local/source.css | 3 - .../export-child-class/expected.css | 11 - test/test-cases/export-child-class/source.css | 7 - test/test-cases/export-class-path/config.json | 3 - .../test-cases/export-class-path/expected.css | 6 - test/test-cases/export-class-path/source.css | 3 - test/test-cases/export-class/expected.css | 23 - test/test-cases/export-class/source.css | 18 - .../export-multiple-classes/expected.css | 12 - .../export-multiple-classes/source.css | 7 - .../export-nested-class/expected.css | 13 - .../test-cases/export-nested-class/source.css | 7 - .../config.json | 3 - .../expected.css | 9 - .../source.css | 7 - .../export-with-composes/config.json | 3 - .../export-with-composes/expected.css | 4 - .../export-with-composes/source.css | 1 - .../export-with-global-composes/config.json | 3 - .../export-with-global-composes/expected.css | 7 - .../export-with-global-composes/source.css | 4 - .../export-with-multiple-composes/config.json | 3 - .../expected.css | 10 - .../export-with-multiple-composes/source.css | 4 - .../config.json | 3 - .../expected.css | 14 - .../source.css | 11 - test/test-cases/nothing/expected.css | 13 - test/test-cases/nothing/source.css | 13 - .../options-generateScopedName/expected.css | 11 - .../options-generateScopedName/options.js | 5 - .../options-generateScopedName/source.css | 7 - test/test.js | 362 +++++++-- yarn.lock | 691 +++++++++++------- 50 files changed, 832 insertions(+), 782 deletions(-) delete mode 100644 test/test-cases/error-comma-in-local/expected.error.txt delete mode 100644 test/test-cases/error-comma-in-local/source.css delete mode 100644 test/test-cases/error-composes-not-allowed-in-local-id/expected.error.txt delete mode 100644 test/test-cases/error-composes-not-allowed-in-local-id/source.css delete mode 100644 test/test-cases/error-composes-not-allowed-in-multiple/expected.error.txt delete mode 100644 test/test-cases/error-composes-not-allowed-in-multiple/source.css delete mode 100644 test/test-cases/error-composes-not-allowed-in-simple/expected.error.txt delete mode 100644 test/test-cases/error-composes-not-allowed-in-simple/source.css delete mode 100644 test/test-cases/error-composes-not-allowed-in-wrong-local/expected.error.txt delete mode 100644 test/test-cases/error-composes-not-allowed-in-wrong-local/source.css delete mode 100644 test/test-cases/error-composes-not-defined-class/expected.error.txt delete mode 100644 test/test-cases/error-composes-not-defined-class/source.css delete mode 100644 test/test-cases/error-not-allowed-in-local/expected.error.txt delete mode 100644 test/test-cases/error-not-allowed-in-local/source.css delete mode 100644 test/test-cases/export-child-class/expected.css delete mode 100644 test/test-cases/export-child-class/source.css delete mode 100644 test/test-cases/export-class-path/config.json delete mode 100644 test/test-cases/export-class-path/expected.css delete mode 100644 test/test-cases/export-class-path/source.css delete mode 100644 test/test-cases/export-class/expected.css delete mode 100644 test/test-cases/export-class/source.css delete mode 100644 test/test-cases/export-multiple-classes/expected.css delete mode 100644 test/test-cases/export-multiple-classes/source.css delete mode 100644 test/test-cases/export-nested-class/expected.css delete mode 100644 test/test-cases/export-nested-class/source.css delete mode 100644 test/test-cases/export-with-composes-imported-class/config.json delete mode 100644 test/test-cases/export-with-composes-imported-class/expected.css delete mode 100644 test/test-cases/export-with-composes-imported-class/source.css delete mode 100644 test/test-cases/export-with-composes/config.json delete mode 100644 test/test-cases/export-with-composes/expected.css delete mode 100644 test/test-cases/export-with-composes/source.css delete mode 100644 test/test-cases/export-with-global-composes/config.json delete mode 100644 test/test-cases/export-with-global-composes/expected.css delete mode 100644 test/test-cases/export-with-global-composes/source.css delete mode 100644 test/test-cases/export-with-multiple-composes/config.json delete mode 100644 test/test-cases/export-with-multiple-composes/expected.css delete mode 100644 test/test-cases/export-with-multiple-composes/source.css delete mode 100644 test/test-cases/export-with-transitive-composes/config.json delete mode 100644 test/test-cases/export-with-transitive-composes/expected.css delete mode 100644 test/test-cases/export-with-transitive-composes/source.css delete mode 100644 test/test-cases/nothing/expected.css delete mode 100644 test/test-cases/nothing/source.css delete mode 100644 test/test-cases/options-generateScopedName/expected.css delete mode 100644 test/test-cases/options-generateScopedName/options.js delete mode 100644 test/test-cases/options-generateScopedName/source.css diff --git a/.travis.yml b/.travis.yml index e5e7ec0..a1b29d7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,8 +3,3 @@ node_js: - "4" - "6" - "node" - -after_success: - - cat ./coverage/lcov.info | node_modules/.bin/coveralls --verbose - - cat ./coverage/coverage.json | node_modules/codecov.io/bin/codecov.io.js - - rm -rf ./coverage diff --git a/package.json b/package.json index dd1e1a8..652d8c4 100644 --- a/package.json +++ b/package.json @@ -11,10 +11,21 @@ }, "lint-staged": { "*.js": [ - "prettier --single-quote --no-semi --write", + "prettier --write", + "eslint", "git add" ] }, + "eslintConfig": { + "parserOptions": { + "ecmaVersion": 6, + "sourceType": "module" + }, + "env": { + "es6": true + }, + "extends": "eslint:recommended" + }, "babel": { "presets": [ [ @@ -54,12 +65,12 @@ "babel-cli": "^6.24.1", "babel-jest": "^20.0.3", "babel-preset-env": "^1.5.1", - "codecov.io": "^0.1.2", - "coveralls": "^2.11.2", "css-selector-parser": "^1.0.4", + "eslint": "^4.0.0", "husky": "^0.13.3", "jest": "^20.0.3", "lint-staged": "^3.4.2", - "prettier": "^1.3.1" + "prettier": "^1.3.1", + "strip-indent": "^2.0.0" } } diff --git a/src/index.js b/src/index.js index 05803ac..84d4606 100644 --- a/src/index.js +++ b/src/index.js @@ -1,172 +1,120 @@ -import postcss from 'postcss' -import Tokenizer from 'css-selector-tokenizer' -import { extractICSS, createICSSRules } from 'icss-utils' +/* eslint-env node */ +import postcss from "postcss"; +import Tokenizer from "css-selector-tokenizer"; +import { extractICSS, createICSSRules } from "icss-utils"; -let hasOwnProperty = Object.prototype.hasOwnProperty +const plugin = "postcss-icss-composes"; -function getSingleLocalNamesForComposes(selectors) { - return selectors.nodes.map(node => { - if (node.type !== 'selector' || node.nodes.length !== 1) { - throw new Error( - 'composition is only allowed when selector is single :local class name not in "' + - Tokenizer.stringify(selectors) + - '"' - ) - } - node = node.nodes[0] - if ( - node.type !== 'nested-pseudo-class' || - node.name !== 'local' || - node.nodes.length !== 1 - ) { - throw new Error( - 'composition is only allowed when selector is single :local class name not in "' + - Tokenizer.stringify(selectors) + - '", "' + - Tokenizer.stringify(node) + - '" is weird' - ) - } - node = node.nodes[0] - if (node.type !== 'selector' || node.nodes.length !== 1) { - throw new Error( - 'composition is only allowed when selector is single :local class name not in "' + - Tokenizer.stringify(selectors) + - '", "' + - Tokenizer.stringify(node) + - '" is weird' - ) - } - node = node.nodes[0] - if (node.type !== 'class') { - // 'id' is not possible, because you can't compose ids - throw new Error( - 'composition is only allowed when selector is single :local class name not in "' + - Tokenizer.stringify(selectors) + - '", "' + - Tokenizer.stringify(node) + - '" is weird' - ) - } - return node.name - }) -} - -const defaultGenerateScopedName = function(exportedName, path) { - let sanitisedPath = path - .replace(/\.[^\.\/\\]+$/, '') - .replace(/[\W_]+/g, '_') - .replace(/^_|_$/g, '') - return `_${sanitisedPath}__${exportedName}` -} +const isSingular = node => node.nodes.length === 1; -module.exports = postcss.plugin( - 'postcss-modules-scope', - (options = {}) => css => { - let generateScopedName = - options.generateScopedName || defaultGenerateScopedName +const isLocal = node => + node.type === "nested-pseudo-class" && node.name === "local"; - let exports = {} +const isClass = node => node.type === "class"; - function exportScopedName(name) { - let scopedName = generateScopedName( - name, - css.source.input.from, - css.source.input.css - ) - exports[name] = exports[name] || [] - if (exports[name].indexOf(scopedName) === -1) { - exports[name].push(scopedName) - } - return scopedName +const getSelectorIdentifier = selector => { + if (!isSingular(selector)) { + return null; + } + const [node] = selector.nodes; + if (isLocal(node)) { + const local = node.nodes[0]; + if (isSingular(local) && isClass(local.nodes[0])) { + return local.nodes[0].name; } + return null; + } + if (isClass(node)) { + return node.name; + } + return null; +}; - function localizeNode(node) { - let newNode = Object.create(node) - switch (node.type) { - case 'selector': - newNode.nodes = node.nodes.map(localizeNode) - return newNode - case 'class': - case 'id': - let scopedName = exportScopedName(node.name) - newNode.name = scopedName - return newNode +const getIdentifiers = (rule, result) => { + const selectors = Tokenizer.parse(rule.selector).nodes; + return selectors + .map(selector => { + const identifier = getSelectorIdentifier(selector); + if (identifier === null) { + result.warn( + `composition is only allowed in single class selector, not in '${Tokenizer.stringify(selector)}'`, + { node: rule } + ); } - throw new Error( - `${node.type} ("${Tokenizer.stringify(node)}") is not allowed in a :local block` - ) - } + return identifier; + }) + .filter(identifier => identifier !== null); +}; - function traverseNode(node) { - switch (node.type) { - case 'nested-pseudo-class': - if (node.name === 'local') { - if (node.nodes.length !== 1) { - throw new Error('Unexpected comma (",") in :local block') - } - return localizeNode(node.nodes[0]) - } - /* falls through */ - case 'selectors': - case 'selector': - let newNode = Object.create(node) - newNode.nodes = node.nodes.map(traverseNode) - return newNode +const walkComposes = (css, callback) => + css.walkRules(rule => { + rule.each(node => { + if (node.type === "decl" && /^(composes|compose-with)$/.test(node.prop)) { + callback(rule, node); } - return node - } + }); + }); - // Find any :import and remember imported names - const { icssImports } = extractICSS(css, false) - const importedNames = Object.keys(icssImports).reduce((acc, key) => { - Object.keys(icssImports[key]).forEach(local => { - acc[local] = true - }) - return acc - }, {}) +const flatten = outer => outer.reduce((acc, inner) => [...acc, ...inner], []); - // Find any :local classes - css.walkRules(rule => { - let selector = Tokenizer.parse(rule.selector) - let newSelector = traverseNode(selector) - rule.selector = Tokenizer.stringify(newSelector) - rule.walkDecls(/composes|compose-with/, decl => { - let localNames = getSingleLocalNamesForComposes(selector) - let classes = decl.value.split(/\s+/) - classes.forEach(className => { - let global = /^global\(([^\)]+)\)$/.exec(className) - if (global) { - localNames.forEach(exportedName => { - exports[exportedName].push(global[1]) - }) - } else if (hasOwnProperty.call(importedNames, className)) { - localNames.forEach(exportedName => { - exports[exportedName].push(className) - }) - } else if (hasOwnProperty.call(exports, className)) { - localNames.forEach(exportedName => { - exports[className].forEach(item => { - exports[exportedName].push(item) - }) - }) - } else { - throw decl.error( - `referenced class name "${className}" in ${decl.prop} not found` - ) - } - }) - decl.remove() - }) - }) +const combineIntoMessages = (classes, composed) => + flatten( + classes.map(name => + composed.map(value => ({ + plugin, + type: "icss-composed", + name, + value + })) + ) + ); - // If we found any :locals, insert an :export rule - const normalizedExports = Object.keys(exports).reduce((acc, key) => { - acc[key] = exports[key].join(' ') - return acc - }, {}) - css.append(createICSSRules({}, normalizedExports)) - } -) +const convertMessagesToExports = (messages, aliases) => + messages + .map(msg => msg.name) + .reduce( + (acc, name) => (acc.indexOf(name) === -1 ? [...acc, name] : acc), + [] + ) + .reduce( + (acc, name) => + Object.assign({}, acc, { + [name]: [ + aliases[name] || name, + ...messages + .filter(msg => msg.name === name) + .map(msg => aliases[msg.value] || msg.value) + ].join(" ") + }), + {} + ); + +const getScopedClasses = messages => + messages + .filter(msg => msg.type === "icss-scoped") + .reduce( + (acc, msg) => Object.assign({}, acc, { [msg.name]: msg.value }), + {} + ); + +module.exports = postcss.plugin(plugin, () => (css, result) => { + const scopedClasses = getScopedClasses(result.messages); + const composedMessages = []; + + const { icssImports, icssExports } = extractICSS(css); + + walkComposes(css, (rule, decl) => { + const classes = getIdentifiers(rule, result); + const composed = decl.value.split(/\s+/); + composedMessages.push(...combineIntoMessages(classes, composed)); + decl.remove(); + }); -module.exports.generateScopedName = defaultGenerateScopedName + const compositionExports = convertMessagesToExports( + composedMessages, + scopedClasses + ); + const exports = Object.assign({}, icssExports, compositionExports); + css.prepend(createICSSRules(icssImports, exports)); + result.messages.push(...composedMessages); +}); diff --git a/test/test-cases/error-comma-in-local/expected.error.txt b/test/test-cases/error-comma-in-local/expected.error.txt deleted file mode 100644 index 5c6c249..0000000 --- a/test/test-cases/error-comma-in-local/expected.error.txt +++ /dev/null @@ -1 +0,0 @@ -Unexpected comma \(","\) in :local block diff --git a/test/test-cases/error-comma-in-local/source.css b/test/test-cases/error-comma-in-local/source.css deleted file mode 100644 index e4a8529..0000000 --- a/test/test-cases/error-comma-in-local/source.css +++ /dev/null @@ -1,3 +0,0 @@ -:local(.a, .b) { - composes: className; -} diff --git a/test/test-cases/error-composes-not-allowed-in-local-id/expected.error.txt b/test/test-cases/error-composes-not-allowed-in-local-id/expected.error.txt deleted file mode 100644 index 426aebf..0000000 --- a/test/test-cases/error-composes-not-allowed-in-local-id/expected.error.txt +++ /dev/null @@ -1 +0,0 @@ -composition is only allowed when selector is single :local class name not in ":local\(#idName\)", "#idName" is weird diff --git a/test/test-cases/error-composes-not-allowed-in-local-id/source.css b/test/test-cases/error-composes-not-allowed-in-local-id/source.css deleted file mode 100644 index d72771c..0000000 --- a/test/test-cases/error-composes-not-allowed-in-local-id/source.css +++ /dev/null @@ -1,3 +0,0 @@ -:local(#idName) { - composes: className; -} diff --git a/test/test-cases/error-composes-not-allowed-in-multiple/expected.error.txt b/test/test-cases/error-composes-not-allowed-in-multiple/expected.error.txt deleted file mode 100644 index 51e304a..0000000 --- a/test/test-cases/error-composes-not-allowed-in-multiple/expected.error.txt +++ /dev/null @@ -1 +0,0 @@ -composition is only allowed when selector is single :local class name not in ":local\(\.a\) :local\(\.b\)" diff --git a/test/test-cases/error-composes-not-allowed-in-multiple/source.css b/test/test-cases/error-composes-not-allowed-in-multiple/source.css deleted file mode 100644 index b989713..0000000 --- a/test/test-cases/error-composes-not-allowed-in-multiple/source.css +++ /dev/null @@ -1,3 +0,0 @@ -:local(.a) :local(.b) { - composes: className; -} diff --git a/test/test-cases/error-composes-not-allowed-in-simple/expected.error.txt b/test/test-cases/error-composes-not-allowed-in-simple/expected.error.txt deleted file mode 100644 index 84ba02b..0000000 --- a/test/test-cases/error-composes-not-allowed-in-simple/expected.error.txt +++ /dev/null @@ -1 +0,0 @@ -composition is only allowed when selector is single :local class name not in "body", "body" is weird diff --git a/test/test-cases/error-composes-not-allowed-in-simple/source.css b/test/test-cases/error-composes-not-allowed-in-simple/source.css deleted file mode 100644 index 9ac00f3..0000000 --- a/test/test-cases/error-composes-not-allowed-in-simple/source.css +++ /dev/null @@ -1,3 +0,0 @@ -body { - composes: className; -} diff --git a/test/test-cases/error-composes-not-allowed-in-wrong-local/expected.error.txt b/test/test-cases/error-composes-not-allowed-in-wrong-local/expected.error.txt deleted file mode 100644 index 6d9699c..0000000 --- a/test/test-cases/error-composes-not-allowed-in-wrong-local/expected.error.txt +++ /dev/null @@ -1 +0,0 @@ -composition is only allowed when selector is single :local class name not in ":local\(\.a\.b\)", "\.a\.b" is weird diff --git a/test/test-cases/error-composes-not-allowed-in-wrong-local/source.css b/test/test-cases/error-composes-not-allowed-in-wrong-local/source.css deleted file mode 100644 index e1a0df6..0000000 --- a/test/test-cases/error-composes-not-allowed-in-wrong-local/source.css +++ /dev/null @@ -1,3 +0,0 @@ -:local(.a.b) { - composes: className; -} diff --git a/test/test-cases/error-composes-not-defined-class/expected.error.txt b/test/test-cases/error-composes-not-defined-class/expected.error.txt deleted file mode 100644 index 86abb09..0000000 --- a/test/test-cases/error-composes-not-defined-class/expected.error.txt +++ /dev/null @@ -1 +0,0 @@ -referenced class name "otherClassName" in compose-with not found diff --git a/test/test-cases/error-composes-not-defined-class/source.css b/test/test-cases/error-composes-not-defined-class/source.css deleted file mode 100644 index f4e8881..0000000 --- a/test/test-cases/error-composes-not-defined-class/source.css +++ /dev/null @@ -1,3 +0,0 @@ -:local(.className) { - compose-with: otherClassName; -} diff --git a/test/test-cases/error-not-allowed-in-local/expected.error.txt b/test/test-cases/error-not-allowed-in-local/expected.error.txt deleted file mode 100644 index e5432ab..0000000 --- a/test/test-cases/error-not-allowed-in-local/expected.error.txt +++ /dev/null @@ -1 +0,0 @@ -element \("body"\) is not allowed in a :local block diff --git a/test/test-cases/error-not-allowed-in-local/source.css b/test/test-cases/error-not-allowed-in-local/source.css deleted file mode 100644 index eea125d..0000000 --- a/test/test-cases/error-not-allowed-in-local/source.css +++ /dev/null @@ -1,3 +0,0 @@ -:local(body) { - color: red; -} diff --git a/test/test-cases/export-child-class/expected.css b/test/test-cases/export-child-class/expected.css deleted file mode 100644 index 97f544d..0000000 --- a/test/test-cases/export-child-class/expected.css +++ /dev/null @@ -1,11 +0,0 @@ -._input__simple { - color: red; -} - -._input__simple h1 { - color: blue; -} - -:export { - simple: _input__simple; -} diff --git a/test/test-cases/export-child-class/source.css b/test/test-cases/export-child-class/source.css deleted file mode 100644 index 9c9da42..0000000 --- a/test/test-cases/export-child-class/source.css +++ /dev/null @@ -1,7 +0,0 @@ -:local(.simple) { - color: red; -} - -:local(.simple) h1 { - color: blue; -} \ No newline at end of file diff --git a/test/test-cases/export-class-path/config.json b/test/test-cases/export-class-path/config.json deleted file mode 100644 index 4683dd6..0000000 --- a/test/test-cases/export-class-path/config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "from": "/lib/components/button.css" -} \ No newline at end of file diff --git a/test/test-cases/export-class-path/expected.css b/test/test-cases/export-class-path/expected.css deleted file mode 100644 index cb17dc5..0000000 --- a/test/test-cases/export-class-path/expected.css +++ /dev/null @@ -1,6 +0,0 @@ -._lib_components_button__exportName { - color: green; -} -:export { - exportName: _lib_components_button__exportName; -} diff --git a/test/test-cases/export-class-path/source.css b/test/test-cases/export-class-path/source.css deleted file mode 100644 index df17cc4..0000000 --- a/test/test-cases/export-class-path/source.css +++ /dev/null @@ -1,3 +0,0 @@ -:local(.exportName) { - color: green; -} diff --git a/test/test-cases/export-class/expected.css b/test/test-cases/export-class/expected.css deleted file mode 100644 index 9370948..0000000 --- a/test/test-cases/export-class/expected.css +++ /dev/null @@ -1,23 +0,0 @@ -._input__exportName { - color: green; -} - -._input__exportName:hover { - color: red; -} - -@media (max-width: 520px) { - /* selector doubled to increase specificity */ - ._input__exportName._input__exportName { - color: darkgreen; - } - - ._input__newExport { - color: blue; - } -} - -:export { - exportName: _input__exportName; - newExport: _input__newExport; -} diff --git a/test/test-cases/export-class/source.css b/test/test-cases/export-class/source.css deleted file mode 100644 index e34d30c..0000000 --- a/test/test-cases/export-class/source.css +++ /dev/null @@ -1,18 +0,0 @@ -:local(.exportName) { - color: green; -} - -:local(.exportName):hover { - color: red; -} - -@media (max-width: 520px) { - /* selector doubled to increase specificity */ - :local(.exportName):local(.exportName) { - color: darkgreen; - } - - :local(.newExport) { - color: blue; - } -} diff --git a/test/test-cases/export-multiple-classes/expected.css b/test/test-cases/export-multiple-classes/expected.css deleted file mode 100644 index b3401f1..0000000 --- a/test/test-cases/export-multiple-classes/expected.css +++ /dev/null @@ -1,12 +0,0 @@ -._input__exportName ._input__otherExport { - color: green; -} - -._input__exportName._input__otherExport { - color: red; -} - -:export { - exportName: _input__exportName; - otherExport: _input__otherExport; -} diff --git a/test/test-cases/export-multiple-classes/source.css b/test/test-cases/export-multiple-classes/source.css deleted file mode 100644 index 63205f1..0000000 --- a/test/test-cases/export-multiple-classes/source.css +++ /dev/null @@ -1,7 +0,0 @@ -:local(.exportName) :local(.otherExport) { - color: green; -} - -:local(.exportName):local(.otherExport) { - color: red; -} diff --git a/test/test-cases/export-nested-class/expected.css b/test/test-cases/export-nested-class/expected.css deleted file mode 100644 index 10811a5..0000000 --- a/test/test-cases/export-nested-class/expected.css +++ /dev/null @@ -1,13 +0,0 @@ -._input__exportName:not(._input__otherExportName.global) { - color: green; -} - -._input__exportName:has(._input__otherExportName, ._input__otherExportName2) { - color: red; -} - -:export { - exportName: _input__exportName; - otherExportName: _input__otherExportName; - otherExportName2: _input__otherExportName2; -} diff --git a/test/test-cases/export-nested-class/source.css b/test/test-cases/export-nested-class/source.css deleted file mode 100644 index b1c79d4..0000000 --- a/test/test-cases/export-nested-class/source.css +++ /dev/null @@ -1,7 +0,0 @@ -:local(.exportName):not(:local(.otherExportName).global) { - color: green; -} - -:local(.exportName):has(:local(.otherExportName), :local(.otherExportName2)) { - color: red; -} diff --git a/test/test-cases/export-with-composes-imported-class/config.json b/test/test-cases/export-with-composes-imported-class/config.json deleted file mode 100644 index 57a5f96..0000000 --- a/test/test-cases/export-with-composes-imported-class/config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "from": "/lib/extender.css" -} \ No newline at end of file diff --git a/test/test-cases/export-with-composes-imported-class/expected.css b/test/test-cases/export-with-composes-imported-class/expected.css deleted file mode 100644 index 439f792..0000000 --- a/test/test-cases/export-with-composes-imported-class/expected.css +++ /dev/null @@ -1,9 +0,0 @@ -:import("./file.css") { - imported_otherClass: otherClass; -} -._lib_extender__exportName { - color: green; -} -:export { - exportName: _lib_extender__exportName imported_otherClass; -} diff --git a/test/test-cases/export-with-composes-imported-class/source.css b/test/test-cases/export-with-composes-imported-class/source.css deleted file mode 100644 index 524f37b..0000000 --- a/test/test-cases/export-with-composes-imported-class/source.css +++ /dev/null @@ -1,7 +0,0 @@ -:import("./file.css") { - imported_otherClass: otherClass; -} -:local(.exportName) { - composes: imported_otherClass; - color: green; -} diff --git a/test/test-cases/export-with-composes/config.json b/test/test-cases/export-with-composes/config.json deleted file mode 100644 index 57a5f96..0000000 --- a/test/test-cases/export-with-composes/config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "from": "/lib/extender.css" -} \ No newline at end of file diff --git a/test/test-cases/export-with-composes/expected.css b/test/test-cases/export-with-composes/expected.css deleted file mode 100644 index e371d9d..0000000 --- a/test/test-cases/export-with-composes/expected.css +++ /dev/null @@ -1,4 +0,0 @@ -._lib_extender__otherClass { background: red; } ._lib_extender__exportName { color: green; } :export { - otherClass: _lib_extender__otherClass; - exportName: _lib_extender__exportName _lib_extender__otherClass; -} diff --git a/test/test-cases/export-with-composes/source.css b/test/test-cases/export-with-composes/source.css deleted file mode 100644 index 179505e..0000000 --- a/test/test-cases/export-with-composes/source.css +++ /dev/null @@ -1 +0,0 @@ -:local(.otherClass) { background: red; } :local(.exportName) { compose-with: otherClass; color: green; } diff --git a/test/test-cases/export-with-global-composes/config.json b/test/test-cases/export-with-global-composes/config.json deleted file mode 100644 index 57a5f96..0000000 --- a/test/test-cases/export-with-global-composes/config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "from": "/lib/extender.css" -} \ No newline at end of file diff --git a/test/test-cases/export-with-global-composes/expected.css b/test/test-cases/export-with-global-composes/expected.css deleted file mode 100644 index 6b82f46..0000000 --- a/test/test-cases/export-with-global-composes/expected.css +++ /dev/null @@ -1,7 +0,0 @@ -.otherClass { background: red; } -.andAgain { font-size: 2em; } -.aThirdClass { color: red; } -._lib_extender__exportName { color: green; } -:export { - exportName: _lib_extender__exportName otherClass andAgain aThirdClass; -} diff --git a/test/test-cases/export-with-global-composes/source.css b/test/test-cases/export-with-global-composes/source.css deleted file mode 100644 index eb9f78b..0000000 --- a/test/test-cases/export-with-global-composes/source.css +++ /dev/null @@ -1,4 +0,0 @@ -.otherClass { background: red; } -.andAgain { font-size: 2em; } -.aThirdClass { color: red; } -:local(.exportName) { compose-with: global(otherClass) global(andAgain); compose-with: global(aThirdClass); color: green; } diff --git a/test/test-cases/export-with-multiple-composes/config.json b/test/test-cases/export-with-multiple-composes/config.json deleted file mode 100644 index 57a5f96..0000000 --- a/test/test-cases/export-with-multiple-composes/config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "from": "/lib/extender.css" -} \ No newline at end of file diff --git a/test/test-cases/export-with-multiple-composes/expected.css b/test/test-cases/export-with-multiple-composes/expected.css deleted file mode 100644 index aac8ae3..0000000 --- a/test/test-cases/export-with-multiple-composes/expected.css +++ /dev/null @@ -1,10 +0,0 @@ -._lib_extender__otherClass { background: red; } -._lib_extender__andAgain { font-size: 2em; } -._lib_extender__aThirdClass { color: red; } -._lib_extender__exportName { color: green; } -:export { - otherClass: _lib_extender__otherClass; - andAgain: _lib_extender__andAgain; - aThirdClass: _lib_extender__aThirdClass; - exportName: _lib_extender__exportName _lib_extender__otherClass _lib_extender__andAgain _lib_extender__aThirdClass; -} diff --git a/test/test-cases/export-with-multiple-composes/source.css b/test/test-cases/export-with-multiple-composes/source.css deleted file mode 100644 index 9797146..0000000 --- a/test/test-cases/export-with-multiple-composes/source.css +++ /dev/null @@ -1,4 +0,0 @@ -:local(.otherClass) { background: red; } -:local(.andAgain) { font-size: 2em; } -:local(.aThirdClass) { color: red; } -:local(.exportName) { compose-with: otherClass andAgain; compose-with: aThirdClass; color: green; } diff --git a/test/test-cases/export-with-transitive-composes/config.json b/test/test-cases/export-with-transitive-composes/config.json deleted file mode 100644 index 57a5f96..0000000 --- a/test/test-cases/export-with-transitive-composes/config.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "from": "/lib/extender.css" -} \ No newline at end of file diff --git a/test/test-cases/export-with-transitive-composes/expected.css b/test/test-cases/export-with-transitive-composes/expected.css deleted file mode 100644 index 7420993..0000000 --- a/test/test-cases/export-with-transitive-composes/expected.css +++ /dev/null @@ -1,14 +0,0 @@ -._lib_extender__aThirdClass { - font-size: 2em; -} -._lib_extender__otherClass { - background: red; -} -._lib_extender__exportName { - color: green; -} -:export { - aThirdClass: _lib_extender__aThirdClass; - otherClass: _lib_extender__otherClass _lib_extender__aThirdClass; - exportName: _lib_extender__exportName _lib_extender__otherClass _lib_extender__aThirdClass; -} diff --git a/test/test-cases/export-with-transitive-composes/source.css b/test/test-cases/export-with-transitive-composes/source.css deleted file mode 100644 index aee0b2a..0000000 --- a/test/test-cases/export-with-transitive-composes/source.css +++ /dev/null @@ -1,11 +0,0 @@ -:local(.aThirdClass) { - font-size: 2em; -} -:local(.otherClass) { - composes: aThirdClass; - background: red; -} -:local(.exportName) { - composes: otherClass; - color: green; -} diff --git a/test/test-cases/nothing/expected.css b/test/test-cases/nothing/expected.css deleted file mode 100644 index 9588005..0000000 --- a/test/test-cases/nothing/expected.css +++ /dev/null @@ -1,13 +0,0 @@ -.exportName { - color: green; -} - -.exportName:hover { - color: red; -} - -@media screen { - body { - background: red; - } -} diff --git a/test/test-cases/nothing/source.css b/test/test-cases/nothing/source.css deleted file mode 100644 index 9588005..0000000 --- a/test/test-cases/nothing/source.css +++ /dev/null @@ -1,13 +0,0 @@ -.exportName { - color: green; -} - -.exportName:hover { - color: red; -} - -@media screen { - body { - background: red; - } -} diff --git a/test/test-cases/options-generateScopedName/expected.css b/test/test-cases/options-generateScopedName/expected.css deleted file mode 100644 index 1da4177..0000000 --- a/test/test-cases/options-generateScopedName/expected.css +++ /dev/null @@ -1,11 +0,0 @@ -._exportName_ { - color: green; -} - -._exportName_:hover { - color: red; -} - -:export { - exportName: _exportName_; -} diff --git a/test/test-cases/options-generateScopedName/options.js b/test/test-cases/options-generateScopedName/options.js deleted file mode 100644 index 73fe8f4..0000000 --- a/test/test-cases/options-generateScopedName/options.js +++ /dev/null @@ -1,5 +0,0 @@ -module.exports = { - generateScopedName: function(name, path) { - return "_" + name + "_"; - } -}; diff --git a/test/test-cases/options-generateScopedName/source.css b/test/test-cases/options-generateScopedName/source.css deleted file mode 100644 index 7b0e089..0000000 --- a/test/test-cases/options-generateScopedName/source.css +++ /dev/null @@ -1,7 +0,0 @@ -:local(.exportName) { - color: green; -} - -:local(.exportName):hover { - color: red; -} diff --git a/test/test.js b/test/test.js index 0738376..f55df42 100644 --- a/test/test.js +++ b/test/test.js @@ -1,62 +1,300 @@ -const fs = require('fs') -const path = require('path') -const postcss = require('postcss') -const processor = require('../src') -const { generateScopedName } = processor - -function generateInvalidCSS(css) { - css.walkDecls(function(decl) { - decl.value = decl.value.replace(/_colon_/g, ':') // because using a : in the tests would make it invalid CSS. - }) -} - -function normalize(str) { - return str.replace(/\r\n?/g, '\n').replace(/\n$/, '') -} - -var testDir = path.join(__dirname, 'test-cases') -fs.readdirSync(testDir).forEach(function(testCase) { - if (fs.existsSync(path.join(testDir, testCase, 'source.css'))) { - it('should ' + testCase.replace(/-/g, ' '), function() { - var input = normalize( - fs.readFileSync(path.join(testDir, testCase, 'source.css'), 'utf-8') - ) - var expected, expectedError - if (fs.existsSync(path.join(testDir, testCase, 'expected.error.txt'))) { - expectedError = normalize( - fs.readFileSync( - path.join(testDir, testCase, 'expected.error.txt'), - 'utf-8' - ) - ).split('\n')[0] - } else { - expected = normalize( - fs.readFileSync(path.join(testDir, testCase, 'expected.css'), 'utf-8') - ) - } - var config = { from: '/input' } - var options = { - generateScopedName: function(exportedName, inputPath) { - var normalizedPath = inputPath.replace(/^[A-Z]:/, '') - return generateScopedName(exportedName, normalizedPath) - } - } - if (fs.existsSync(path.join(testDir, testCase, 'config.json'))) { - config = JSON.parse( - fs.readFileSync(path.join(testDir, testCase, 'config.json'), 'utf-8') - ) - } - if (fs.existsSync(path.join(testDir, testCase, 'options.js'))) { - options = require(path.join(testDir, testCase, 'options.js')) - } - var pipeline = postcss([generateInvalidCSS, processor(options)]) - if (expectedError) { - expect(() => { - var result = pipeline.process(input, config).css - }).toThrowError(RegExp(expectedError)) - } else { - expect(pipeline.process(input, config).css).toEqual(expected) - } - }) - } -}) +/* eslint-env jest */ +import postcss from "postcss"; +import stripIndent from "strip-indent"; +import plugin from "../src"; + +const messagesPlugin = messages => (css, result) => + result.messages.push(...messages); + +const compile = (fixture, messages) => + postcss([messagesPlugin(messages), plugin]).process(fixture); + +const strip = input => stripIndent(input).trim(); + +const getWarnings = result => result.warnings().map(warning => warning.text); + +const getMessages = result => + result.messages.filter(msg => msg.type !== "warning"); + +const run = ({ + fixture, + messages = [], + expected, + outputMessages = [], + warnings = [] +}) => + compile(strip(fixture), messages).then(result => { + expect(getWarnings(result)).toEqual(warnings); + expect(getMessages(result)).toEqual(outputMessages); + expect(result.css.trim()).toEqual(strip(expected)); + }); + +test("skip rules without composes property", () => { + return run({ + fixture: ` + .className1 .className2 {} + `, + expected: ` + .className1 .className2 {} + ` + }); +}); + +test("warn on composes in local id", () => { + return run({ + fixture: ` + #idName { + composes: className; + } + :local(#idName) { + composes: className; + } + `, + expected: ` + #idName { + } + :local(#idName) { + } + `, + warnings: [ + "composition is only allowed in single class selector, not in '#idName'", + "composition is only allowed in single class selector, not in ':local(#idName)'" + ] + }); +}); + +test("warn on composes in multiple classes", () => { + return run({ + fixture: ` + .a .b { + composes: className; + } + .a.b { + composes: className; + } + :local(.a .b) { + composes: className; + } + :local(.a.b) { + composes: className; + } + `, + expected: ` + .a .b { + } + .a.b { + } + :local(.a .b) { + } + :local(.a.b) { + } + `, + warnings: [ + "composition is only allowed in single class selector, not in '.a .b'", + "composition is only allowed in single class selector, not in '.a.b'", + "composition is only allowed in single class selector, not in ':local(.a .b)'", + "composition is only allowed in single class selector, not in ':local(.a.b)'" + ] + }); +}); + +test("warn on composes in tag", () => { + return run({ + fixture: ` + body { + composes: className; + } + .class body { + composes: className; + } + :local(body) { + composes: className; + } + :local(.class body) { + composes: className; + } + `, + expected: ` + body { + } + .class body { + } + :local(body) { + } + :local(.class body) { + } + `, + warnings: [ + "composition is only allowed in single class selector, not in 'body'", + "composition is only allowed in single class selector, not in '.class body'", + "composition is only allowed in single class selector, not in ':local(body)'", + "composition is only allowed in single class selector, not in ':local(.class body)'" + ] + }); +}); + +test("compose class", () => { + return run({ + fixture: ` + .className1 { + composes: otherClassName; + } + :local(.className2) { + composes: otherClassName; + } + `, + expected: ` + :export { + className1: className1 otherClassName; + className2: className2 otherClassName + } + .className1 { + } + :local(.className2) { + } + `, + outputMessages: [ + { + plugin: "postcss-icss-composes", + type: "icss-composed", + name: "className1", + value: "otherClassName" + }, + { + plugin: "postcss-icss-composes", + type: "icss-composed", + name: "className2", + value: "otherClassName" + } + ] + }); +}); + +test("allow compose-with property", () => { + return run({ + fixture: ` + .className { + compose-with: otherClassName; + } + `, + expected: ` + :export { + className: className otherClassName + } + .className { + } + `, + outputMessages: [ + { + plugin: "postcss-icss-composes", + type: "icss-composed", + name: "className", + value: "otherClassName" + } + ] + }); +}); + +test("compose multiple classes", () => { + return run({ + fixture: ` + .className { + composes: otherClassName1 otherClassName2 + } + `, + expected: ` + :export { + className: className otherClassName1 otherClassName2 + } + .className { + } + `, + outputMessages: [ + { + plugin: "postcss-icss-composes", + type: "icss-composed", + name: "className", + value: "otherClassName1" + }, + { + plugin: "postcss-icss-composes", + type: "icss-composed", + name: "className", + value: "otherClassName2" + } + ] + }); +}); + +test("compose multiple properties", () => { + return run({ + fixture: ` + .className { + composes: otherClassName1; + composes: otherClassName2; + } + `, + expected: ` + :export { + className: className otherClassName1 otherClassName2 + } + .className { + } + `, + outputMessages: [ + { + plugin: "postcss-icss-composes", + type: "icss-composed", + name: "className", + value: "otherClassName1" + }, + { + plugin: "postcss-icss-composes", + type: "icss-composed", + name: "className", + value: "otherClassName2" + } + ] + }); +}); + +test("icss-scoped contract", () => { + const messages = [ + { + plugin: "previous-plugin", + type: "icss-scoped", + name: "className", + value: "__scope__className" + }, + { + plugin: "previous-plugin", + type: "icss-scoped", + name: "otherClassName", + value: "__scope__otherClassName" + } + ]; + return run({ + fixture: ` + .className { + composes: otherClassName; + } + `, + messages, + expected: ` + :export { + className: __scope__className __scope__otherClassName + } + .className { + } + `, + outputMessages: [ + ...messages, + { + plugin: "postcss-icss-composes", + type: "icss-composed", + name: "className", + value: "otherClassName" + } + ] + }); +}); diff --git a/yarn.lock b/yarn.lock index 1aef0db..1713ede 100644 --- a/yarn.lock +++ b/yarn.lock @@ -16,11 +16,29 @@ acorn-globals@^3.1.0: dependencies: acorn "^4.0.4" +acorn-jsx@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b" + dependencies: + acorn "^3.0.4" + +acorn@^3.0.4: + version "3.3.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" + acorn@^4.0.4: version "4.0.11" resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.11.tgz#edcda3bd937e7556410d42ed5860f67399c794c0" -ajv@^4.9.1: +acorn@^5.0.1: + version "5.0.3" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.0.3.tgz#c460df08491463f028ccb82eab3730bf01087b3d" + +ajv-keywords@^1.0.0: + version "1.5.1" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c" + +ajv@^4.7.0, ajv@^4.9.1: version "4.11.8" resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536" dependencies: @@ -43,6 +61,10 @@ ansi-escapes@^1.0.0, ansi-escapes@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" +ansi-escapes@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-2.0.0.tgz#5bae52be424878dd9783e8910e3fc2922e83c81b" + ansi-regex@^2.0.0, ansi-regex@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" @@ -105,6 +127,16 @@ array-equal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93" +array-union@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" + dependencies: + array-uniq "^1.0.1" + +array-uniq@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" + array-unique@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" @@ -113,10 +145,6 @@ arrify@^1.0.0, arrify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" -asn1@0.1.11: - version "0.1.11" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.1.11.tgz#559be18376d08a4ec4dbe80877d27818639b2df7" - asn1@~0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" @@ -125,10 +153,6 @@ assert-plus@1.0.0, assert-plus@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" -assert-plus@^0.1.5: - version "0.1.5" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.1.5.tgz#ee74009413002d84cec7219c6ac811812e723160" - assert-plus@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234" @@ -151,18 +175,10 @@ async@^2.1.4: dependencies: lodash "^4.14.0" -async@~0.9.0: - version "0.9.2" - resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d" - asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" -aws-sign2@~0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.5.0.tgz#c57103f7a17fc037f02d7c2e64b602ea223f7d63" - aws-sign2@~0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f" @@ -702,24 +718,12 @@ binary-extensions@^1.0.0: version "1.8.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.8.0.tgz#48ec8d16df4377eae5fa5884682480af4d95c774" -bl@~0.9.0: - version "0.9.5" - resolved "https://registry.yarnpkg.com/bl/-/bl-0.9.5.tgz#c06b797af085ea00bc527afc8efcf11de2232054" - dependencies: - readable-stream "~1.0.26" - block-stream@*: version "0.0.9" resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" dependencies: inherits "~2.0.0" -boom@0.4.x: - version "0.4.2" - resolved "https://registry.yarnpkg.com/boom/-/boom-0.4.2.tgz#7a636e9ded4efcefb19cef4947a3c67dfaee911b" - dependencies: - hoek "0.9.x" - boom@2.x.x: version "2.10.1" resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f" @@ -774,6 +778,16 @@ builtin-modules@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" +caller-path@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f" + dependencies: + callsites "^0.2.0" + +callsites@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" + callsites@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" @@ -790,18 +804,10 @@ caniuse-lite@^1.0.30000670: version "1.0.30000670" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000670.tgz#c94f7dbf0b68eaadc46d3d203f46e82e7801135e" -caseless@~0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.11.0.tgz#715b96ea9841593cc33067923f5ec60ebda4f7d7" - caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" -caseless@~0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.6.0.tgz#8167c1ab8397fb5bb95f96d28e5a81c50f247ac4" - center-align@^0.1.1: version "0.1.3" resolved "https://registry.yarnpkg.com/center-align/-/center-align-0.1.3.tgz#aa0d32629b6ee972200411cbd4461c907bc2b7ad" @@ -838,12 +844,22 @@ ci-info@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.0.0.tgz#dc5285f2b4e251821683681c381c3388f46ec534" +circular-json@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.1.tgz#be8b36aefccde8b3ca7aa2d6afc07a37242c0d2d" + cli-cursor@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987" dependencies: restore-cursor "^1.0.1" +cli-cursor@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" + dependencies: + restore-cursor "^2.0.0" + cli-spinners@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-0.1.2.tgz#bb764d88e185fb9e1e6a2a1f19772318f605e31c" @@ -855,6 +871,10 @@ cli-truncate@^0.2.1: slice-ansi "0.0.4" string-width "^1.0.1" +cli-width@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.1.0.tgz#b234ca209b29ef66fc518d9b98d5847b00edf00a" + cliui@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1" @@ -879,13 +899,6 @@ code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" -codecov.io@^0.1.2: - version "0.1.6" - resolved "https://registry.yarnpkg.com/codecov.io/-/codecov.io-0.1.6.tgz#59dfd02da1ff31c2fb2b952ad8ad16fd3781b728" - dependencies: - request "2.42.0" - urlgrey "0.4.0" - color-convert@^1.0.0: version "1.9.0" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.0.tgz#1accf97dd739b983bf994d56fec8f95853641b7a" @@ -902,12 +915,6 @@ combined-stream@^1.0.5, combined-stream@~1.0.5: dependencies: delayed-stream "~1.0.0" -combined-stream@~0.0.4: - version "0.0.7" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-0.0.7.tgz#0137e657baa5a7541c57ac37ac5fc07d73b4dc1f" - dependencies: - delayed-stream "0.0.5" - commander@^2.8.1, commander@^2.9.0: version "2.9.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" @@ -918,6 +925,14 @@ concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" +concat-stream@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7" + dependencies: + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + console-control-strings@^1.0.0, console-control-strings@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" @@ -951,16 +966,6 @@ cosmiconfig@^1.1.0: pinkie-promise "^2.0.0" require-from-string "^1.1.0" -coveralls@^2.11.2: - version "2.13.1" - resolved "https://registry.yarnpkg.com/coveralls/-/coveralls-2.13.1.tgz#d70bb9acc1835ec4f063ff9dac5423c17b11f178" - dependencies: - js-yaml "3.6.1" - lcov-parse "0.0.10" - log-driver "1.2.5" - minimist "1.2.0" - request "2.79.0" - cross-spawn@^5.0.1: version "5.1.0" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" @@ -969,12 +974,6 @@ cross-spawn@^5.0.1: shebang-command "^1.2.0" which "^1.2.9" -cryptiles@0.2.x: - version "0.2.2" - resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-0.2.2.tgz#ed91ff1f17ad13d3748288594f8a48a0d26f325c" - dependencies: - boom "0.4.x" - cryptiles@2.x.x: version "2.0.5" resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8" @@ -1007,10 +1006,6 @@ cssom@0.3.x, "cssom@>= 0.3.2 < 0.4.0": dependencies: cssom "0.3.x" -ctype@0.5.3: - version "0.5.3" - resolved "https://registry.yarnpkg.com/ctype/-/ctype-0.5.3.tgz#82c18c2461f74114ef16c135224ad0b9144ca12f" - dashdash@^1.12.0: version "1.14.1" resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" @@ -1021,7 +1016,7 @@ date-fns@^1.27.2: version "1.28.5" resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.28.5.tgz#257cfc45d322df45ef5658665967ee841cd73faf" -debug@^2.1.1, debug@^2.2.0, debug@^2.6.3: +debug@^2.1.1, debug@^2.2.0, debug@^2.6.3, debug@^2.6.8: version "2.6.8" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc" dependencies: @@ -1031,15 +1026,11 @@ decamelize@^1.0.0, decamelize@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" -deep-equal@~0.1.0: - version "0.1.2" - resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-0.1.2.tgz#b246c2b80a570a47c11be1d9bd1070ec878b87ce" - deep-extend@~0.4.0: version "0.4.2" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.2.tgz#48b699c27e334bf89f10892be432f6e4c7d34a7f" -deep-is@~0.1.2: +deep-is@~0.1.2, deep-is@~0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" @@ -1049,13 +1040,17 @@ default-require-extensions@^1.0.0: dependencies: strip-bom "^2.0.0" -defined@~0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/defined/-/defined-0.0.0.tgz#f35eea7d705e933baf13b2f03b3f83d921403b3e" - -delayed-stream@0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-0.0.5.tgz#d4b1f43a93e8296dfe02694f4680bc37a313c73f" +del@^2.0.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8" + dependencies: + globby "^5.0.0" + is-path-cwd "^1.0.0" + is-path-in-cwd "^1.0.0" + object-assign "^4.0.1" + pify "^2.0.0" + pinkie-promise "^2.0.0" + rimraf "^2.2.8" delayed-stream@~1.0.0: version "1.0.0" @@ -1075,9 +1070,12 @@ diff@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9" -duplexer@~0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1" +doctrine@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.0.0.tgz#c73d8d2909d22291e1a007a395804da8b665fe63" + dependencies: + esutils "^2.0.2" + isarray "^1.0.0" ecc-jsbn@~0.1.1: version "0.1.1" @@ -1120,6 +1118,57 @@ escodegen@^1.6.1: optionalDependencies: source-map "~0.2.0" +eslint-scope@^3.7.1: + version "3.7.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-3.7.1.tgz#3d63c3edfda02e06e01a452ad88caacc7cdcb6e8" + dependencies: + esrecurse "^4.1.0" + estraverse "^4.1.1" + +eslint@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.0.0.tgz#7277c01437fdf41dccd168d5aa0e49b75ca1f260" + dependencies: + babel-code-frame "^6.22.0" + chalk "^1.1.3" + concat-stream "^1.6.0" + debug "^2.6.8" + doctrine "^2.0.0" + eslint-scope "^3.7.1" + espree "^3.4.3" + esquery "^1.0.0" + estraverse "^4.2.0" + esutils "^2.0.2" + file-entry-cache "^2.0.0" + glob "^7.1.2" + globals "^9.17.0" + ignore "^3.3.3" + imurmurhash "^0.1.4" + inquirer "^3.0.6" + is-my-json-valid "^2.16.0" + is-resolvable "^1.0.0" + js-yaml "^3.8.4" + json-stable-stringify "^1.0.1" + levn "^0.3.0" + lodash "^4.17.4" + mkdirp "^0.5.1" + natural-compare "^1.4.0" + optionator "^0.8.2" + path-is-inside "^1.0.2" + pluralize "^4.0.0" + progress "^2.0.0" + require-uncached "^1.0.3" + strip-json-comments "~2.0.1" + table "^4.0.1" + text-table "~0.2.0" + +espree@^3.4.3: + version "3.4.3" + resolved "https://registry.yarnpkg.com/espree/-/espree-3.4.3.tgz#2910b5ccd49ce893c2ffffaab4fd8b3a31b82374" + dependencies: + acorn "^5.0.1" + acorn-jsx "^3.0.0" + esprima@^1.2.2: version "1.2.5" resolved "https://registry.yarnpkg.com/esprima/-/esprima-1.2.5.tgz#0993502feaf668138325756f30f9a51feeec11e9" @@ -1132,10 +1181,31 @@ esprima@^3.1.1: version "3.1.3" resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" +esquery@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.0.tgz#cfba8b57d7fba93f17298a8a006a04cda13d80fa" + dependencies: + estraverse "^4.0.0" + +esrecurse@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.1.0.tgz#4713b6536adf7f2ac4f327d559e7756bff648220" + dependencies: + estraverse "~4.1.0" + object-assign "^4.0.1" + estraverse@^1.9.1: version "1.9.3" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44" +estraverse@^4.0.0, estraverse@^4.1.1, estraverse@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" + +estraverse@~4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.1.1.tgz#f6caca728933a850ef90661d0e17982ba47111a2" + esutils@2.0.2, esutils@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" @@ -1178,6 +1248,14 @@ extend@~3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" +external-editor@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.0.4.tgz#1ed9199da9cbfe2ef2f7a31b2fde8b0d12368972" + dependencies: + iconv-lite "^0.4.17" + jschardet "^1.4.2" + tmp "^0.0.31" + extglob@^0.3.1: version "0.3.2" resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" @@ -1192,6 +1270,10 @@ fast-levenshtein@~1.0.0: version "1.0.7" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-1.0.7.tgz#0178dcdee023b92905193af0959e8a7639cfdcb9" +fast-levenshtein@~2.0.4: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + fastparse@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/fastparse/-/fastparse-1.1.1.tgz#d1e2643b38a94d7583b479060e6c4affc94071f8" @@ -1215,6 +1297,19 @@ figures@^1.7.0: escape-string-regexp "^1.0.5" object-assign "^4.1.0" +figures@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" + dependencies: + escape-string-regexp "^1.0.5" + +file-entry-cache@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361" + dependencies: + flat-cache "^1.2.1" + object-assign "^4.0.1" + filename-regex@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" @@ -1253,6 +1348,15 @@ find-up@^2.1.0: dependencies: locate-path "^2.0.0" +flat-cache@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.2.2.tgz#fa86714e72c21db88601761ecf2f555d1abc6b96" + dependencies: + circular-json "^0.3.1" + del "^2.0.2" + graceful-fs "^4.1.2" + write "^0.2.1" + flow-parser@0.45.0: version "0.45.0" resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.45.0.tgz#aa29d4ae27f06aa02817772bba0fcbefef7e62f0" @@ -1267,22 +1371,10 @@ for-own@^0.1.4: dependencies: for-in "^1.0.1" -forever-agent@~0.5.0: - version "0.5.2" - resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.5.2.tgz#6d0e09c4921f94a27f63d3b49c5feff1ea4c5130" - forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" -form-data@~0.1.0: - version "0.1.4" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-0.1.4.tgz#91abd788aba9702b1aabfa8bc01031a2ac9e3b12" - dependencies: - async "~0.9.0" - combined-stream "~0.0.4" - mime "~1.2.11" - form-data@~2.1.1: version "2.1.4" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.4.tgz#33c183acf193276ecaa98143a69e94bfee1750d1" @@ -1388,10 +1480,32 @@ glob@7.1.1, glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1: once "^1.3.0" path-is-absolute "^1.0.0" -globals@^9.0.0: +glob@^7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +globals@^9.0.0, globals@^9.17.0: version "9.17.0" resolved "https://registry.yarnpkg.com/globals/-/globals-9.17.0.tgz#0c0ca696d9b9bb694d2e5470bd37777caad50286" +globby@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d" + dependencies: + array-union "^1.0.1" + arrify "^1.0.0" + glob "^7.0.3" + object-assign "^4.0.1" + pify "^2.0.0" + pinkie-promise "^2.0.0" + graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.4: version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" @@ -1418,15 +1532,6 @@ har-schema@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e" -har-validator@~2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-2.0.6.tgz#cdcbc08188265ad119b6a5a7c8ab70eecfb5d27d" - dependencies: - chalk "^1.1.1" - commander "^2.9.0" - is-my-json-valid "^2.12.4" - pinkie-promise "^2.0.0" - har-validator@~4.2.1: version "4.2.1" resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-4.2.1.tgz#33481d0f1bbff600dd203d75812a6a5fba002e2a" @@ -1448,15 +1553,6 @@ has-unicode@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" -hawk@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/hawk/-/hawk-1.1.1.tgz#87cd491f9b46e4e2aeaca335416766885d2d1ed9" - dependencies: - boom "0.4.x" - cryptiles "0.2.x" - hoek "0.9.x" - sntp "0.2.x" - hawk@~3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4" @@ -1466,10 +1562,6 @@ hawk@~3.1.3: hoek "2.x.x" sntp "1.x.x" -hoek@0.9.x: - version "0.9.1" - resolved "https://registry.yarnpkg.com/hoek/-/hoek-0.9.1.tgz#3d322462badf07716ea7eb85baf88079cddce505" - hoek@2.x.x: version "2.16.3" resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" @@ -1491,14 +1583,6 @@ html-encoding-sniffer@^1.0.1: dependencies: whatwg-encoding "^1.0.1" -http-signature@~0.10.0: - version "0.10.1" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-0.10.1.tgz#4fbdac132559aa8323121e540779c0a012b27e66" - dependencies: - asn1 "0.1.11" - assert-plus "^0.1.5" - ctype "0.5.3" - http-signature@~1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf" @@ -1520,12 +1604,24 @@ iconv-lite@0.4.13: version "0.4.13" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.13.tgz#1f88aba4ab0b1508e8312acc39345f36e992e2f2" +iconv-lite@^0.4.17: + version "0.4.17" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.17.tgz#4fdaa3b38acbc2c031b045d0edcdfe1ecab18c8d" + icss-utils@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-2.1.0.tgz#83f0a0ec378bf3246178b6c2ad9136f135b1c962" dependencies: postcss "^6.0.1" +ignore@^3.3.3: + version "3.3.3" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.3.tgz#432352e57accd87ab3110e82d3fea0e47812156d" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + indent-string@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80" @@ -1543,7 +1639,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@^2.0.1, inherits@~2.0.0, inherits@~2.0.1: +inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1: version "2.0.3" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" @@ -1551,6 +1647,25 @@ ini@~1.3.0: version "1.3.4" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e" +inquirer@^3.0.6: + version "3.1.0" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.1.0.tgz#e05400d48b94937c2d3caa7038663ba9189aab01" + dependencies: + ansi-escapes "^2.0.0" + chalk "^1.0.0" + cli-cursor "^2.1.0" + cli-width "^2.0.0" + external-editor "^2.0.4" + figures "^2.0.0" + lodash "^4.3.0" + mute-stream "0.0.7" + run-async "^2.2.0" + rx-lite "^4.0.8" + rx-lite-aggregates "^4.0.8" + string-width "^2.0.0" + strip-ansi "^3.0.0" + through "^2.3.6" + invariant@^2.2.0, invariant@^2.2.2: version "2.2.2" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360" @@ -1617,13 +1732,17 @@ is-fullwidth-code-point@^1.0.0: dependencies: number-is-nan "^1.0.0" +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + is-glob@^2.0.0, is-glob@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" dependencies: is-extglob "^1.0.0" -is-my-json-valid@^2.12.4: +is-my-json-valid@^2.16.0: version "2.16.0" resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.16.0.tgz#f079dd9bfdae65ee2038aae8acbc86ab109e3693" dependencies: @@ -1638,6 +1757,22 @@ is-number@^2.0.2, is-number@^2.1.0: dependencies: kind-of "^3.0.2" +is-path-cwd@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" + +is-path-in-cwd@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz#6477582b8214d602346094567003be8a9eac04dc" + dependencies: + is-path-inside "^1.0.0" + +is-path-inside@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.0.tgz#fc06e5a1683fbda13de667aff717bbc10a48f37f" + dependencies: + path-is-inside "^1.0.1" + is-posix-bracket@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" @@ -1654,6 +1789,12 @@ is-property@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" +is-resolvable@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.0.0.tgz#8df57c61ea2e3c501408d100fb013cf8d6e0cc62" + dependencies: + tryit "^1.0.1" + is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" @@ -1666,11 +1807,7 @@ is-utf8@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" -isarray@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - -isarray@1.0.0, isarray@~1.0.0: +isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" @@ -1988,14 +2125,14 @@ js-tokens@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.1.tgz#08e9f132484a2c45a30907e9dc4d5567b7f114d7" -js-yaml@3.6.1, js-yaml@^3.4.3: +js-yaml@^3.4.3: version "3.6.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.6.1.tgz#6e5fe67d8b205ce4d22fad05b7781e8dadcc4b30" dependencies: argparse "^1.0.7" esprima "^2.6.0" -js-yaml@^3.7.0: +js-yaml@^3.7.0, js-yaml@^3.8.4: version "3.8.4" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.8.4.tgz#520b4564f86573ba96662af85a8cafa7b4b5a6f6" dependencies: @@ -2006,6 +2143,10 @@ jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" +jschardet@^1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/jschardet/-/jschardet-1.4.2.tgz#2aa107f142af4121d145659d44f50830961e699a" + jsdom@^9.12.0: version "9.12.0" resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-9.12.0.tgz#e8c546fffcb06c00d4833ca84410fed7f8a097d4" @@ -2048,7 +2189,7 @@ json-stable-stringify@^1.0.1: dependencies: jsonify "~0.0.0" -json-stringify-safe@~5.0.0, json-stringify-safe@~5.0.1: +json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" @@ -2089,14 +2230,17 @@ lcid@^1.0.0: dependencies: invert-kv "^1.0.0" -lcov-parse@0.0.10: - version "0.0.10" - resolved "https://registry.yarnpkg.com/lcov-parse/-/lcov-parse-0.0.10.tgz#1b0b8ff9ac9c7889250582b70b71315d9da6d9a3" - leven@^2.0.0, leven@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/leven/-/leven-2.1.0.tgz#c2e7a9f772094dee9d34202ae8acce4687875580" +levn@^0.3.0, levn@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + levn@~0.2.5: version "0.2.5" resolved "https://registry.yarnpkg.com/levn/-/levn-0.2.5.tgz#ba8d339d0ca4a610e3a3f145b9caf48807155054" @@ -2180,14 +2324,10 @@ locate-path@^2.0.0: p-locate "^2.0.0" path-exists "^3.0.0" -lodash@^4.14.0, lodash@^4.2.0: +lodash@^4.0.0, lodash@^4.14.0, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.3.0: version "4.17.4" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" -log-driver@1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.5.tgz#7ae4ec257302fd790d557cb10c97100d857b0056" - log-symbols@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-1.0.2.tgz#376ff7b58ea3086a0f09facc74617eca501e1a18" @@ -2256,15 +2396,11 @@ mime-types@^2.1.12, mime-types@~2.1.7: dependencies: mime-db "~1.27.0" -mime-types@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-1.0.2.tgz#995ae1392ab8affcbfcb2641dd054e943c0d5dce" - -mime@~1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.2.11.tgz#58203eed86e3a5ef17aed2b7d9ebd47f0a60dd10" +mimic-fn@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.1.0.tgz#e667783d92e89dbd342818b5230b9d62a672ad18" -minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3: +minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" dependencies: @@ -2288,6 +2424,10 @@ ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" +mute-stream@0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" + nan@^2.3.0: version "2.6.2" resolved "https://registry.yarnpkg.com/nan/-/nan-2.6.2.tgz#e4ff34e6c95fdfb5aecc08de6596f43605a7db45" @@ -2323,10 +2463,6 @@ node-pre-gyp@^0.6.29: tar "^2.2.1" tar-pack "^3.4.0" -node-uuid@~1.4.0: - version "1.4.8" - resolved "https://registry.yarnpkg.com/node-uuid/-/node-uuid-1.4.8.tgz#b040eb0923968afabf8d32fb1f17f1167fdab907" - nopt@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" @@ -2390,10 +2526,6 @@ number-is-nan@^1.0.0: version "1.4.0" resolved "https://registry.yarnpkg.com/nwmatcher/-/nwmatcher-1.4.0.tgz#b4389362170e7ef9798c3c7716d80ebc0106fccf" -oauth-sign@~0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.4.0.tgz#f22956f31ea7151a821e5f2fb32c113cad8b9f69" - oauth-sign@~0.8.1: version "0.8.2" resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" @@ -2419,6 +2551,12 @@ onetime@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789" +onetime@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" + dependencies: + mimic-fn "^1.0.0" + optimist@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" @@ -2437,6 +2575,17 @@ optionator@^0.5.0: type-check "~0.3.1" wordwrap "~0.0.2" +optionator@^0.8.2: + version "0.8.2" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" + dependencies: + deep-is "~0.1.3" + fast-levenshtein "~2.0.4" + levn "~0.3.0" + prelude-ls "~1.1.2" + type-check "~0.3.2" + wordwrap "~1.0.0" + ora@^0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/ora/-/ora-0.2.3.tgz#37527d220adcd53c39b73571d754156d5db657a4" @@ -2456,7 +2605,7 @@ os-locale@^1.4.0: dependencies: lcid "^1.0.0" -os-tmpdir@^1.0.0, os-tmpdir@^1.0.1: +os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" @@ -2526,6 +2675,10 @@ path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" +path-is-inside@^1.0.1, path-is-inside@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" + path-key@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" @@ -2560,6 +2713,10 @@ pinkie@^2.0.0: version "2.0.4" resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" +pluralize@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-4.0.0.tgz#59b708c1c0190a2f692f1c7618c446b052fd1762" + postcss@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.1.tgz#000dbd1f8eef217aa368b9a212c5fc40b2a8f3f2" @@ -2612,6 +2769,10 @@ process-nextick-args@~1.0.6: version "1.0.7" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" +progress@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.0.tgz#8a1be366bf8fc23db2bd23f10c6fe920b4389d1f" + prr@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/prr/-/prr-0.0.0.tgz#1a84b85908325501411853d0081ee3fa86e2926a" @@ -2624,14 +2785,6 @@ punycode@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" -qs@~1.2.0: - version "1.2.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-1.2.2.tgz#19b57ff24dc2a99ce1f8bdf6afcda59f8ef61f88" - -qs@~6.3.0: - version "6.3.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.3.2.tgz#e75bd5f6e268122a2a0e0bda630b2550c166502c" - qs@~6.4.0: version "6.4.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" @@ -2667,7 +2820,7 @@ read-pkg@^1.0.0: normalize-package-data "^2.3.2" path-type "^1.0.0" -readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.4: +readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.2.2: version "2.2.9" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.9.tgz#cf78ec6f4a6d1eb43d26488cac97f042e74b7fc8" dependencies: @@ -2679,15 +2832,6 @@ readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.4: string_decoder "~1.0.0" util-deprecate "~1.0.1" -readable-stream@~1.0.26: - version "1.0.34" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - readdirp@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.1.0.tgz#4ed0ad060df3073300c48440373f72d1cc642d78" @@ -2764,52 +2908,6 @@ repeating@^2.0.0: dependencies: is-finite "^1.0.0" -request@2.42.0: - version "2.42.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.42.0.tgz#572bd0148938564040ac7ab148b96423a063304a" - dependencies: - bl "~0.9.0" - caseless "~0.6.0" - forever-agent "~0.5.0" - json-stringify-safe "~5.0.0" - mime-types "~1.0.1" - node-uuid "~1.4.0" - qs "~1.2.0" - tunnel-agent "~0.4.0" - optionalDependencies: - aws-sign2 "~0.5.0" - form-data "~0.1.0" - hawk "1.1.1" - http-signature "~0.10.0" - oauth-sign "~0.4.0" - stringstream "~0.0.4" - tough-cookie ">=0.12.0" - -request@2.79.0: - version "2.79.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.79.0.tgz#4dfe5bf6be8b8cdc37fcf93e04b65577722710de" - dependencies: - aws-sign2 "~0.6.0" - aws4 "^1.2.1" - caseless "~0.11.0" - combined-stream "~1.0.5" - extend "~3.0.0" - forever-agent "~0.6.1" - form-data "~2.1.1" - har-validator "~2.0.6" - hawk "~3.1.3" - http-signature "~1.1.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.7" - oauth-sign "~0.8.1" - qs "~6.3.0" - stringstream "~0.0.4" - tough-cookie "~2.3.0" - tunnel-agent "~0.4.1" - uuid "^3.0.0" - request@^2.79.0, request@^2.81.0: version "2.81.0" resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0" @@ -2849,6 +2947,17 @@ require-main-filename@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" +require-uncached@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" + dependencies: + caller-path "^0.1.0" + resolve-from "^1.0.0" + +resolve-from@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" + resolve@1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" @@ -2866,11 +2975,12 @@ restore-cursor@^1.0.1: exit-hook "^1.0.0" onetime "^1.0.0" -resumer@~0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/resumer/-/resumer-0.0.0.tgz#f1e8f461e4064ba39e82af3cdc2a8c893d076759" +restore-cursor@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" dependencies: - through "~2.3.4" + onetime "^2.0.0" + signal-exit "^3.0.2" right-align@^0.1.1: version "0.1.3" @@ -2878,12 +2988,28 @@ right-align@^0.1.1: dependencies: align-text "^0.1.1" -rimraf@2, rimraf@^2.5.1, rimraf@^2.6.1: +rimraf@2, rimraf@^2.2.8, rimraf@^2.5.1, rimraf@^2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.1.tgz#c2338ec643df7a1b7fe5c54fa86f57428a55f33d" dependencies: glob "^7.0.5" +run-async@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" + dependencies: + is-promise "^2.1.0" + +rx-lite-aggregates@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz#753b87a89a11c95467c4ac1626c4efc4e05c67be" + dependencies: + rx-lite "*" + +rx-lite@*, rx-lite@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444" + rxjs@^5.0.0-beta.11: version "5.4.0" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-5.4.0.tgz#a7db14ab157f9d7aac6a56e655e7a3860d39bf26" @@ -2936,7 +3062,7 @@ shellwords@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.0.tgz#66afd47b6a12932d9071cbfd98a52e785cd0ba14" -signal-exit@^3.0.0: +signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" @@ -2948,12 +3074,6 @@ slice-ansi@0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" -sntp@0.2.x: - version "0.2.4" - resolved "https://registry.yarnpkg.com/sntp/-/sntp-0.2.4.tgz#fb885f18b0f3aad189f824862536bceeec750900" - dependencies: - hoek "0.9.x" - sntp@1.x.x: version "1.0.9" resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198" @@ -2996,12 +3116,6 @@ spdx-license-ids@^1.0.2: version "1.2.2" resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz#c9df7a3424594ade6bd11900d596696dc06bac57" -split@~0.2.10: - version "0.2.10" - resolved "https://registry.yarnpkg.com/split/-/split-0.2.10.tgz#67097c601d697ce1368f418f06cd201cf0521a57" - dependencies: - through "2" - sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" @@ -3025,12 +3139,6 @@ staged-git-files@0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/staged-git-files/-/staged-git-files-0.0.4.tgz#d797e1b551ca7a639dec0237dc6eb4bb9be17d35" -stream-combiner@~0.0.2: - version "0.0.4" - resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.0.4.tgz#4d5e433c185261dde623ca3f44c586bcf5c4ad14" - dependencies: - duplexer "~0.1.1" - stream-to-observable@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/stream-to-observable/-/stream-to-observable-0.1.0.tgz#45bf1d9f2d7dc09bed81f1c307c430e68b84cffe" @@ -3049,9 +3157,12 @@ string-width@^1.0.1, string-width@^1.0.2: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -string_decoder@~0.10.x: - version "0.10.31" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" +string-width@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.0.0.tgz#635c5436cc72a6e0c387ceca278d4e2eec52687e" + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^3.0.0" string_decoder@~1.0.0: version "1.0.1" @@ -3083,6 +3194,10 @@ strip-eof@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" +strip-indent@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68" + strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" @@ -3105,18 +3220,16 @@ symbol-tree@^3.2.1: version "3.2.2" resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.2.tgz#ae27db38f660a7ae2e1c3b7d1bc290819b8519e6" -tape@2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/tape/-/tape-2.3.0.tgz#0dfeec709227fbcc9170abe7f046962b271431db" +table@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/table/-/table-4.0.1.tgz#a8116c133fac2c61f4a420ab6cdf5c4d61f0e435" dependencies: - deep-equal "~0.1.0" - defined "~0.0.0" - inherits "~2.0.1" - jsonify "~0.0.0" - resumer "~0.0.0" - split "~0.2.10" - stream-combiner "~0.0.2" - through "~2.3.4" + ajv "^4.7.0" + ajv-keywords "^1.0.0" + chalk "^1.1.1" + lodash "^4.0.0" + slice-ansi "0.0.4" + string-width "^2.0.0" tar-pack@^3.4.0: version "3.4.0" @@ -3149,14 +3262,24 @@ test-exclude@^4.1.0: read-pkg-up "^1.0.1" require-main-filename "^1.0.1" +text-table@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + throat@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/throat/-/throat-3.0.0.tgz#e7c64c867cbb3845f10877642f7b60055b8ec0d6" -through@2, through@~2.3.4: +through@^2.3.6: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" +tmp@^0.0.31: + version "0.0.31" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.31.tgz#8f38ab9438e17315e5dbd8b3657e8bfb277ae4a7" + dependencies: + os-tmpdir "~1.0.1" + tmpl@1.0.x: version "1.0.4" resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1" @@ -3165,7 +3288,7 @@ to-fast-properties@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" -tough-cookie@>=0.12.0, tough-cookie@^2.3.2, tough-cookie@~2.3.0: +tough-cookie@^2.3.2, tough-cookie@~2.3.0: version "2.3.2" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.2.tgz#f081f76e4c85720e6c37a5faced737150d84072a" dependencies: @@ -3179,26 +3302,30 @@ trim-right@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" +tryit@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/tryit/-/tryit-1.0.3.tgz#393be730a9446fd1ead6da59a014308f36c289cb" + tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" dependencies: safe-buffer "^5.0.1" -tunnel-agent@~0.4.0, tunnel-agent@~0.4.1: - version "0.4.3" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.4.3.tgz#6373db76909fe570e08d73583365ed828a74eeeb" - tweetnacl@^0.14.3, tweetnacl@~0.14.0: version "0.14.5" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" -type-check@~0.3.1: +type-check@~0.3.1, type-check@~0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" dependencies: prelude-ls "~1.1.2" +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + uglify-js@^2.6: version "2.8.27" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.27.tgz#47787f912b0f242e5b984343be8e35e95f694c9c" @@ -3216,12 +3343,6 @@ uid-number@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81" -urlgrey@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/urlgrey/-/urlgrey-0.4.0.tgz#f065357040fb35c3b311d4e5dc36484d96dbea06" - dependencies: - tape "2.3.0" - user-home@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/user-home/-/user-home-1.1.1.tgz#2b5be23a32b63a7c9deb8d0f28d485724a3df190" @@ -3312,6 +3433,10 @@ wordwrap@~0.0.2: version "0.0.3" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" +wordwrap@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" + worker-farm@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.3.1.tgz#4333112bb49b17aa050b87895ca6b2cacf40e5ff" @@ -3330,6 +3455,12 @@ wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" +write@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" + dependencies: + mkdirp "^0.5.1" + xml-name-validator@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-2.0.1.tgz#4d8b8f1eccd3419aa362061becef515e1e559635" From b2839a8e6cb97f5f21120555c1446b81767b8fc8 Mon Sep 17 00:00:00 2001 From: Bogdan Chadkin Date: Mon, 12 Jun 2017 21:45:01 +0300 Subject: [PATCH 3/7] Util tweak --- src/index.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/index.js b/src/index.js index 84d4606..0e3de4f 100644 --- a/src/index.js +++ b/src/index.js @@ -5,6 +5,9 @@ import { extractICSS, createICSSRules } from "icss-utils"; const plugin = "postcss-icss-composes"; +const flatten = outer => outer.reduce((acc, inner) => [...acc, ...inner], []); +const includes = (array, value) => array.indexOf(value) !== -1; + const isSingular = node => node.nodes.length === 1; const isLocal = node => @@ -55,8 +58,6 @@ const walkComposes = (css, callback) => }); }); -const flatten = outer => outer.reduce((acc, inner) => [...acc, ...inner], []); - const combineIntoMessages = (classes, composed) => flatten( classes.map(name => @@ -72,10 +73,7 @@ const combineIntoMessages = (classes, composed) => const convertMessagesToExports = (messages, aliases) => messages .map(msg => msg.name) - .reduce( - (acc, name) => (acc.indexOf(name) === -1 ? [...acc, name] : acc), - [] - ) + .reduce((acc, name) => (includes(acc, name) ? acc : [...acc, name]), []) .reduce( (acc, name) => Object.assign({}, acc, { From a1fc11f07c88207a7c4f5dc9044e6a20cddf99e7 Mon Sep 17 00:00:00 2001 From: Bogdan Chadkin Date: Mon, 12 Jun 2017 22:20:35 +0300 Subject: [PATCH 4/7] Rename to postcss-icss-composes --- LICENSE | 20 ++++++++ README.md | 133 ++++++++++++++++++++++++++------------------------- package.json | 17 ++----- 3 files changed, 93 insertions(+), 77 deletions(-) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..52962de --- /dev/null +++ b/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright 2015 Glen Maddern + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md index 4dcb270..695f102 100644 --- a/README.md +++ b/README.md @@ -1,102 +1,105 @@ -# CSS Modules: Scope Locals & Extend +# postcss-icss-composes [![Build Status][travis-img]][travis] -[![Build Status](https://travis-ci.org/css-modules/postcss-modules-scope.svg?branch=master)](https://travis-ci.org/css-modules/postcss-modules-scope) +[PostCSS]: https://github.com/postcss/postcss +[travis-img]: https://travis-ci.org/css-modules/postcss-icss-selectors.svg +[travis]: https://travis-ci.org/css-modules/postcss-icss-selectors -Transforms: +PostCSS plugin for css modules to compose local-scope classes -```css -:local(.continueButton) { - color: green; -} -``` - -into: - -```css -:export { - continueButton: __buttons_continueButton_djd347adcxz9; -} -.__buttons_continueButton_djd347adcxz9 { - color: green; -} -``` - -so it doesn't pollute CSS global scope and can be simply used in JS like so: +## Usage ```js -import styles from './buttons.css' -elem.innerHTML = `` +postcss([require('postcss-icss-composes')]) ``` -## Composition +See [PostCSS] docs for examples for your environment. -Since we're exporting class names, there's no reason to export only one. This can give us some really useful reuse of styles: +### Local class composition + +`composes` and `compose-with` combines specified class name with rule class name. ```css -.globalButtonStyle { - background: white; - border: 1px solid; - border-radius: 0.25rem; +.buttonStyle { + background: #fff; } -.globalButtonStyle:hover { +.buttonStyle:hover { box-shadow: 0 0 4px -2px; } -:local(.continueButton) { - compose-with: globalButtonStyle; +.cellStyle { + margin: 10px; +} +.addButton { + composes: buttonStyle cellStyle; color: green; } -``` -becomes: +/* becomes */ -```css :export { - continueButton: ___buttons_continueButton_djd347adcxz9 globalButtonStyle; + buttonStyle: buttonStyle; + cellStyle: cellStyle; + addButton: addButton buttonStyle cellStyle } -.globalButtonStyle { - background: white; - border: 1px solid; - border-radius: 0.25rem; +.buttonStyle { + background: #fff; } -.globalButtonStyle:hover { +.buttonStyle:hover { box-shadow: 0 0 4px -2px; } -.___buttons_continueButton_djd347adcxz9 { +.cellStyle { + margin: 10px; +} +.addButton { color: green; } ``` -**Note:** you can also use `composes` as a shorthand for `compose-with` - -## Local-by-default & reuse across files +### Global class composition -You're looking for [CSS Modules](https://github.com/css-modules/css-modules). It uses this plugin as well as a few others, and it's amazing. +You may use any identifier for composition -## Building +```css +.addButton { + composes: globalButtonStyle; + background: #000; +} +/* becomes */ +:export { + addButton: addButton globalButtonStyle +} +.addButton { + background: #000; +} ``` -npm install -npm test -``` - -[![Build Status](https://travis-ci.org/css-modules/postcss-modules-scope.svg?branch=master)](https://travis-ci.org/css-modules/postcss-modules-scope) -* Lines: [![Coverage Status](https://coveralls.io/repos/css-modules/postcss-modules-scope/badge.svg?branch=master)](https://coveralls.io/r/css-modules/postcss-modules-scope?branch=master) -* Statements: [![codecov.io](http://codecov.io/github/css-modules/postcss-modules-scope/coverage.svg?branch=master)](http://codecov.io/github/css-modules/postcss-modules-scope?branch=master) +### Scoping class names -## Development +You may add [postcss-icss-selectors](https://github.com/css-modules/postcss-icss-selectors) plugin to local-scope classes. -- `npm autotest` will watch `src` and `test` for changes and run the tests, and transpile the ES6 to ES5 on success - -## License +```css +.buttonStyle { + background: #fff; +} +.addButton { + composes: buttonStyle; + border: 1px solid #000; +} -ISC +/* becomes */ -## With thanks +:export { + buttonStyle: __scope__buttonStyle; + addButton: __scope__addButton __scope__buttonStyle +} +.__scope__buttonStyle { + background: #fff; +} +.__scope__addButton { + border: 1px solid #000; +} +``` -- Mark Dalgleish -- Tobias Koppers -- Guy Bedford +## License ---- -Glen Maddern, 2015. +MIT © Glen Maddern and Bogdan Chadkin, 2015 diff --git a/package.json b/package.json index 652d8c4..baaac39 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { - "name": "postcss-modules-scope", + "name": "postcss-icss-composes", "version": "1.1.0", - "description": "A CSS Modules transform to extract export statements from local-scope classes", + "description": "PostCSS plugin for css modules to compose local-scope classes", "main": "lib/index.js", "scripts": { "build": "babel --out-dir lib src", @@ -38,10 +38,6 @@ ] ] }, - "repository": { - "type": "git", - "url": "https://github.com/css-modules/postcss-modules-scope.git" - }, "keywords": [ "css-modules", "postcss", @@ -50,12 +46,9 @@ "files": [ "lib" ], - "author": "Glen Maddern", - "license": "ISC", - "bugs": { - "url": "https://github.com/css-modules/postcss-modules-scope/issues" - }, - "homepage": "https://github.com/css-modules/postcss-modules-scope", + "author": "Glen Maddern and Bogdan Chadkin", + "repository": "css-modules/postcss-icss-composes", + "license": "MIT", "dependencies": { "css-selector-tokenizer": "^0.7.0", "icss-utils": "^2.1.0", From b7918593cdc20e6b771bc9225d1a10606d815e47 Mon Sep 17 00:00:00 2001 From: Bogdan Chadkin Date: Tue, 13 Jun 2017 02:23:15 +0300 Subject: [PATCH 5/7] Add external loading support --- package.json | 3 +- src/index.js | 109 +++++++++++++++++++++--- test/test.js | 231 +++++++++++++++++++++++++++++++++++++++++++++++++++ yarn.lock | 21 ++--- 4 files changed, 336 insertions(+), 28 deletions(-) diff --git a/package.json b/package.json index baaac39..c2858aa 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,8 @@ "dependencies": { "css-selector-tokenizer": "^0.7.0", "icss-utils": "^2.1.0", - "postcss": "^6.0.1" + "postcss": "^6.0.1", + "postcss-value-parser": "^3.3.0" }, "devDependencies": { "babel-cli": "^6.24.1", diff --git a/src/index.js b/src/index.js index 0e3de4f..337fda9 100644 --- a/src/index.js +++ b/src/index.js @@ -1,11 +1,13 @@ /* eslint-env node */ import postcss from "postcss"; import Tokenizer from "css-selector-tokenizer"; +import valueParser from "postcss-value-parser"; import { extractICSS, createICSSRules } from "icss-utils"; const plugin = "postcss-icss-composes"; const flatten = outer => outer.reduce((acc, inner) => [...acc, ...inner], []); + const includes = (array, value) => array.indexOf(value) !== -1; const isSingular = node => node.nodes.length === 1; @@ -49,15 +51,50 @@ const getIdentifiers = (rule, result) => { .filter(identifier => identifier !== null); }; -const walkComposes = (css, callback) => +const isComposes = node => + node.type === "decl" && + (node.prop === "composes" || node.prop === "compose-with"); + +const walkRules = (css, callback) => css.walkRules(rule => { - rule.each(node => { - if (node.type === "decl" && /^(composes|compose-with)$/.test(node.prop)) { - callback(rule, node); - } - }); + if (rule.some(node => isComposes(node))) { + callback(rule); + } + }); + +const walkDecls = (rule, callback) => + rule.each(node => { + if (isComposes(node)) { + callback(node); + } }); +const isMedia = node => + (node.type === "atrule" && node.name === "media") || + (node.parent && isMedia(node.parent)); + +const splitBy = (array, cond) => + array.reduce( + (acc, item) => + cond(item) + ? [...acc, []] + : [...acc.slice(0, -1), [...acc[acc.length - 1], item]], + [[]] + ); + +const parseComposes = value => { + const parsed = valueParser(value); + const [names, path] = splitBy( + parsed.nodes, + node => node.type === "word" && node.value === "from" + ); + return { + names: names.filter(node => node.type === "word").map(node => node.value), + path: path && + path.filter(node => node.type === "string").map(node => node.value)[0] + }; +}; + const combineIntoMessages = (classes, composed) => flatten( classes.map(name => @@ -70,6 +107,25 @@ const combineIntoMessages = (classes, composed) => ) ); +const invertObject = obj => + Object.keys(obj).reduce( + (acc, key) => Object.assign({}, acc, { [obj[key]]: key }), + {} + ); + +const combineImports = (icss, composed) => + Object.keys(composed).reduce( + (acc, path) => + Object.assign({}, acc, { + [`'${path}'`]: Object.assign( + {}, + acc[`'${path}'`], + invertObject(composed[path]) + ) + }), + Object.assign({}, icss) + ); + const convertMessagesToExports = (messages, aliases) => messages .map(msg => msg.name) @@ -98,21 +154,48 @@ const getScopedClasses = messages => module.exports = postcss.plugin(plugin, () => (css, result) => { const scopedClasses = getScopedClasses(result.messages); const composedMessages = []; + const composedImports = {}; + + let importedIndex = 0; + const getImportedName = (path, name) => { + if (!composedImports[path]) { + composedImports[path] = {}; + } + if (composedImports[path][name]) { + return composedImports[path][name]; + } + const importedName = `__composed__${name}__${importedIndex}`; + composedImports[path][name] = importedName; + importedIndex += 1; + return importedName; + }; const { icssImports, icssExports } = extractICSS(css); - walkComposes(css, (rule, decl) => { + walkRules(css, rule => { const classes = getIdentifiers(rule, result); - const composed = decl.value.split(/\s+/); - composedMessages.push(...combineIntoMessages(classes, composed)); - decl.remove(); + if (isMedia(rule)) { + result.warn( + "composition cannot be conditional and is not allowed in media queries", + { node: rule } + ); + } + walkDecls(rule, decl => { + const { names, path } = parseComposes(decl.value); + const composed = path + ? names.map(name => getImportedName(path, name)) + : names; + composedMessages.push(...combineIntoMessages(classes, composed)); + decl.remove(); + }); }); - const compositionExports = convertMessagesToExports( + const composedExports = convertMessagesToExports( composedMessages, scopedClasses ); - const exports = Object.assign({}, icssExports, compositionExports); - css.prepend(createICSSRules(icssImports, exports)); + const exports = Object.assign({}, icssExports, composedExports); + const imports = combineImports(icssImports, composedImports); + css.prepend(createICSSRules(imports, exports)); result.messages.push(...composedMessages); }); diff --git a/test/test.js b/test/test.js index f55df42..8509d70 100644 --- a/test/test.js +++ b/test/test.js @@ -133,6 +133,40 @@ test("warn on composes in tag", () => { }); }); +test("warn on composes in @media", () => { + return run({ + fixture: ` + @media print { + .className { + composes: otherClassName; + } + .empty {} + } + `, + expected: ` + :export { + className: className otherClassName + } + @media print { + .className { + } + .empty {} + } + `, + outputMessages: [ + { + plugin: "postcss-icss-composes", + type: "icss-composed", + name: "className", + value: "otherClassName" + } + ], + warnings: [ + "composition cannot be conditional and is not allowed in media queries" + ] + }); +}); + test("compose class", () => { return run({ fixture: ` @@ -298,3 +332,200 @@ test("icss-scoped contract", () => { ] }); }); + +test("compose from file", () => { + return run({ + fixture: ` + .a { + composes: b from 'path'; + composes: c from "path"; + } + `, + expected: ` + :import('path') { + __composed__b__0: b; + __composed__c__1: c + } + :export { + a: a __composed__b__0 __composed__c__1 + } + .a { + } + `, + outputMessages: [ + { + plugin: "postcss-icss-composes", + type: "icss-composed", + name: "a", + value: "__composed__b__0" + }, + { + plugin: "postcss-icss-composes", + type: "icss-composed", + name: "a", + value: "__composed__c__1" + } + ] + }); +}); + +test("compose multiple from file", () => { + return run({ + fixture: ` + .a { + composes: b c from 'path'; + } + `, + expected: ` + :import('path') { + __composed__b__0: b; + __composed__c__1: c + } + :export { + a: a __composed__b__0 __composed__c__1 + } + .a { + } + `, + outputMessages: [ + { + plugin: "postcss-icss-composes", + type: "icss-composed", + name: "a", + value: "__composed__b__0" + }, + { + plugin: "postcss-icss-composes", + type: "icss-composed", + name: "a", + value: "__composed__c__1" + } + ] + }); +}); + +test("save existing :import and :export", () => { + return run({ + fixture: ` + :import('path') { + __a: b + } + :export { + a: __a + } + .c { + composes: d from 'path'; + } + `, + expected: ` + :import('path') { + __a: b; + __composed__d__0: d + } + :export { + a: __a; + c: c __composed__d__0 + } + .c { + } + `, + outputMessages: [ + { + plugin: "postcss-icss-composes", + type: "icss-composed", + name: "c", + value: "__composed__d__0" + } + ] + }); +}); + +test("resolve external composes order", () => { + return run({ + fixture: ` + .a { + composes: c from './c.css'; + } + .b { + /* 'b' should be after 'c' */ + composes: d from './d.css'; + composes: c from './c.css'; + } + `, + expected: ` + :import('./c.css') { + __composed__c__0: c + } + :import('./d.css') { + __composed__d__1: d + } + :export { + a: a __composed__c__0; + b: b __composed__d__1 __composed__c__0 + } + .a { + } + .b { + /* 'b' should be after 'c' */ + } + `, + outputMessages: [ + { + plugin: "postcss-icss-composes", + type: "icss-composed", + name: "a", + value: "__composed__c__0" + }, + { + plugin: "postcss-icss-composes", + type: "icss-composed", + name: "b", + value: "__composed__d__1" + }, + { + plugin: "postcss-icss-composes", + type: "icss-composed", + name: "b", + value: "__composed__c__0" + } + ] + }); +}); + +test("resolve composes with the same name from different files", () => { + return run({ + fixture: ` + .a { + composes: b from './b1.css'; + composes: b from './b2.css'; + } + `, + expected: ` + :import('./b1.css') { + __composed__b__0: b + } + :import('./b2.css') { + __composed__b__1: b + } + :export { + a: a __composed__b__0 __composed__b__1 + } + .a { + } + `, + outputMessages: [ + { + plugin: "postcss-icss-composes", + type: "icss-composed", + name: "a", + value: "__composed__b__0" + }, + { + plugin: "postcss-icss-composes", + type: "icss-composed", + name: "a", + value: "__composed__b__1" + } + ] + }); +}); diff --git a/yarn.lock b/yarn.lock index 1713ede..ae2b8e1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1173,10 +1173,6 @@ esprima@^1.2.2: version "1.2.5" resolved "https://registry.yarnpkg.com/esprima/-/esprima-1.2.5.tgz#0993502feaf668138325756f30f9a51feeec11e9" -esprima@^2.6.0: - version "2.7.3" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" - esprima@^3.1.1: version "3.1.3" resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" @@ -1469,7 +1465,7 @@ glob-parent@^2.0.0: dependencies: is-glob "^2.0.0" -glob@7.1.1, glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1: +glob@7.1.1, glob@^7.0.0: version "7.1.1" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" dependencies: @@ -1480,7 +1476,7 @@ glob@7.1.1, glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.1.2: +glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2: version "7.1.2" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" dependencies: @@ -2125,14 +2121,7 @@ js-tokens@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.1.tgz#08e9f132484a2c45a30907e9dc4d5567b7f114d7" -js-yaml@^3.4.3: - version "3.6.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.6.1.tgz#6e5fe67d8b205ce4d22fad05b7781e8dadcc4b30" - dependencies: - argparse "^1.0.7" - esprima "^2.6.0" - -js-yaml@^3.7.0, js-yaml@^3.8.4: +js-yaml@^3.4.3, js-yaml@^3.7.0, js-yaml@^3.8.4: version "3.8.4" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.8.4.tgz#520b4564f86573ba96662af85a8cafa7b4b5a6f6" dependencies: @@ -2717,6 +2706,10 @@ pluralize@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-4.0.0.tgz#59b708c1c0190a2f692f1c7618c446b052fd1762" +postcss-value-parser@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz#87f38f9f18f774a4ab4c8a232f5c5ce8872a9d15" + postcss@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.1.tgz#000dbd1f8eef217aa368b9a212c5fc40b2a8f3f2" From 355890c920f30ae9ec4f1aa34855ab074fff0ca9 Mon Sep 17 00:00:00 2001 From: Bogdan Chadkin Date: Tue, 13 Jun 2017 11:27:41 +0300 Subject: [PATCH 6/7] Fix travis links --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 695f102..8414252 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # postcss-icss-composes [![Build Status][travis-img]][travis] [PostCSS]: https://github.com/postcss/postcss -[travis-img]: https://travis-ci.org/css-modules/postcss-icss-selectors.svg -[travis]: https://travis-ci.org/css-modules/postcss-icss-selectors +[travis-img]: https://travis-ci.org/css-modules/postcss-icss-composes.svg +[travis]: https://travis-ci.org/css-modules/postcss-icss-composes PostCSS plugin for css modules to compose local-scope classes From 6b1391230fd0931e34100c3b5cd55d3e66228fbd Mon Sep 17 00:00:00 2001 From: Bogdan Chadkin Date: Tue, 13 Jun 2017 11:34:43 +0300 Subject: [PATCH 7/7] Add externals and messages mention --- README.md | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8414252..6e23bbc 100644 --- a/README.md +++ b/README.md @@ -75,7 +75,7 @@ You may use any identifier for composition ### Scoping class names -You may add [postcss-icss-selectors](https://github.com/css-modules/postcss-icss-selectors) plugin to local-scope classes. +[postcss-icss-selectors](https://github.com/css-modules/postcss-icss-selectors) plugin allows to local-scope classes. ```css .buttonStyle { @@ -100,6 +100,38 @@ You may add [postcss-icss-selectors](https://github.com/css-modules/postcss-icss } ``` +### External composition + +```css +/* compositions.css */ +.button { + background: #fff; + border: 1px solid #000; +} +.cell { + margin: 10px; +} + +/* main.css */ +.addButton { + composes: button cell from './composition.css'; + font-size: 20px; +} +``` + +### Messages + +postcss-icss-composes passes result.messages for each composed class name + +```js +{ + plugin: 'postcss-icss-composes', + type: 'icss-composed', + name: string, // rule class name + value: string // composed class name +} +``` + ## License MIT © Glen Maddern and Bogdan Chadkin, 2015