From ad4ab04ce28ee2d32270184305130b1574ada306 Mon Sep 17 00:00:00 2001 From: yosuke ota Date: Sat, 4 Apr 2020 15:10:51 +0900 Subject: [PATCH 1/5] Use eslint and prettier --- .eslintignore | 3 + .eslintrc.js | 9 + .github/workflows/nodejs.yml | 4 +- .npmignore | 4 + .prettierignore | 3 + .prettierrc.js | 23 + README.md | 2 +- camel-case.js | 21 +- extract.js | 243 ++++---- get-template.js | 6 +- index.js | 7 +- literal.js | 8 +- object-parse.js | 11 +- object-parser.js | 192 ++++--- object-stringifier.js | 123 ++-- object-stringify.js | 8 +- object-syntax.js | 7 +- object.js | 9 +- package-lock.json | 1026 +++++++++++++++++++++++++++++++++- package.json | 28 +- template-parse.js | 13 +- template-parser-helper.js | 163 ++++-- template-parser.js | 16 +- template-safe-parse.js | 13 +- template-safe-parser.js | 17 +- template-stringifier.js | 22 +- template-stringify.js | 8 +- template-tokenize.js | 28 +- test/camel-case.js | 82 +-- test/css-in-js.js | 125 +++-- test/emotion.js | 63 ++- test/glamorous.js | 36 +- test/literals.js | 171 +++--- test/non-style.js | 20 +- test/react-native.js | 44 +- test/react.js | 13 +- test/styled-components.js | 210 ++++--- test/supports.js | 73 +-- un-camel-case.js | 19 +- 39 files changed, 2106 insertions(+), 767 deletions(-) create mode 100644 .eslintignore create mode 100644 .eslintrc.js create mode 100644 .prettierignore create mode 100644 .prettierrc.js diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..c371cd1 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,3 @@ +test/fixtures/* +coverage/** +.nyc_output/** diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..69d86f3 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,9 @@ +module.exports = { + parserOptions: { + ecmaVersion: 2019, + }, + extends: ['stylelint', 'prettier'], + rules: { + 'jest/valid-expect': 'off', + }, +}; diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index ce0164a..09da851 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -4,10 +4,10 @@ on: push: branches: - master - - "dependabot/**" + - 'dependabot/**' pull_request: branches: - - "**" + - '**' env: CI: true diff --git a/.npmignore b/.npmignore index 3ad91dc..ca8d3c5 100644 --- a/.npmignore +++ b/.npmignore @@ -2,13 +2,17 @@ *.pid *.seed .editorconfig +.eslintignore .eslintrc* .git +.github .gitignore .grunt .lock-wscript .node_repl_history .nyc_output +.prettierrc.js +.prettierignore .stylelintrc* .travis.yml .vscode diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..c371cd1 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,3 @@ +test/fixtures/* +coverage/** +.nyc_output/** diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 0000000..7bf6349 --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1,23 @@ +'use strict'; + +// https://prettier.io/docs/en/options.html +module.exports = { + arrowParens: 'always', + endOfLine: 'lf', + printWidth: 100, + singleQuote: true, + trailingComma: 'es5', + useTabs: true, + overrides: [ + { + files: ['package.json', 'package-lock.json', '*.md'], + options: { + printWidth: 80, + singleQuote: false, + tabWidth: 2, + trailingComma: 'none', + useTabs: false, + }, + }, + ], +}; diff --git a/README.md b/README.md index 32a5ad1..f57705b 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ const stylelint = require("stylelint"); const syntax = require("postcss-syntax"); postcss([stylelint({ fix: true })]) .process(source, { syntax: syntax }) - .then(function(result) { + .then(function (result) { // An alias for the result.css property. Use it with syntaxes that generate non-CSS output. result.content; }); diff --git a/camel-case.js b/camel-case.js index f182de4..e5f2f89 100644 --- a/camel-case.js +++ b/camel-case.js @@ -1,18 +1,13 @@ -"use strict"; -function camelCase (str) { - return str.replace(/[\w-]+/g, (s) => ( +'use strict'; + +function camelCase(str) { + return str.replace(/[\w-]+/g, (s) => /^-?[a-z]+(?:-[a-z]+)+$/.test(s) - ? s.replace( - /^-(ms|moz|khtml|epub|(\w+-?)*webkit)(?=-)/i, - "$1" - ).replace( - /-\w/g, - s => ( - s[1].toUpperCase() - ) - ) + ? s + .replace(/^-(ms|moz|khtml|epub|(\w+-?)*webkit)(?=-)/i, '$1') + .replace(/-\w/g, (s) => s[1].toUpperCase()) : s - )); + ); } module.exports = camelCase; diff --git a/extract.js b/extract.js index f6a308c..dec7dcb 100644 --- a/extract.js +++ b/extract.js @@ -1,14 +1,10 @@ -"use strict"; -const { - parse, - types, - traverse, - loadOptions, -} = require("@babel/core"); -const getTemplate = require("./get-template"); -const loadSyntax = require("postcss-syntax/load-syntax"); - -const isStyleSheetCreate = expectAdjacentSibling(["create"]); +'use strict'; + +const getTemplate = require('./get-template'); +const loadSyntax = require('postcss-syntax/load-syntax'); +const { parse, types, traverse, loadOptions } = require('@babel/core'); + +const isStyleSheetCreate = expectAdjacentSibling(['create']); const supports = { // import styled from '@emotion/styled' // import { styled } from 'glamor/styled' @@ -42,13 +38,13 @@ const supports = { cssobj: true, // require('electron-css')({color: 'red'}) - "electron-css": true, + 'electron-css': true, // import styled from "react-emotion"; - "react-emotion": true, + 'react-emotion': true, // import styled from 'preact-emotion' - "preact-emotion": true, + 'preact-emotion': true, // https://github.com/streamich/freestyler freestyler: true, @@ -60,61 +56,60 @@ const supports = { // "i-css": (i, nameSpace) => nameSpace[i + 1] === "addStyles" && nameSpace[i + 2] === "wrapper", // https://github.com/j2css/j2c - j2c: expectAdjacentSibling(["inline", "sheet"]), + j2c: expectAdjacentSibling(['inline', 'sheet']), // var styles = StyleSheet.create({color: 'red'}) - "react-inline": isStyleSheetCreate, - "react-style": isStyleSheetCreate, + 'react-inline': isStyleSheetCreate, + 'react-style': isStyleSheetCreate, // import reactCSS from 'reactcss' reactcss: true, // const StyledButton = injectSheet(styles)(Button) - "react-jss": true, + 'react-jss': true, // import styled from 'styled-components'; - "styled-components": true, + 'styled-components': true, // import {withStyle} from "styletron-react"; - "styletron-react": expectAdjacentSibling(["withStyle"]), + 'styletron-react': expectAdjacentSibling(['withStyle']), - "styling": true, + styling: true, // const rule = superstyle({ color: 'blue' }) - "superstyle": true, + superstyle: true, // import { makeStyles } from '@material-ui/styles' - 'styles': expectAdjacentSibling(["makeStyles"]), + styles: expectAdjacentSibling(['makeStyles']), }; const plugins = [ - "jsx", - "typescript", - "objectRestSpread", - ["decorators", { "decoratorsBeforeExport": false }], - "classProperties", - "exportExtensions", - "asyncGenerators", - "functionBind", - "functionSent", - "dynamicImport", - "optionalCatchBinding", + 'jsx', + 'typescript', + 'objectRestSpread', + ['decorators', { decoratorsBeforeExport: false }], + 'classProperties', + 'exportExtensions', + 'asyncGenerators', + 'functionBind', + 'functionSent', + 'dynamicImport', + 'optionalCatchBinding', ]; -function expectAdjacentSibling (names) { - return (i, nameSpace) => ( - names.some(name => nameSpace[i + 1] === name) - ); +function expectAdjacentSibling(names) { + return (i, nameSpace) => names.some((name) => nameSpace[i + 1] === name); } -function loadBabelOpts (opts) { - const filename = opts.from && opts.from.replace(/\?.*$/, ""); +function loadBabelOpts(opts) { + const filename = opts.from && opts.from.replace(/\?.*$/, ''); + opts = { filename, parserOpts: { plugins, sourceFilename: filename, - sourceType: filename && /\.m[tj]sx?$/.test(filename) ? "module" : "unambiguous", + sourceType: filename && /\.m[tj]sx?$/.test(filename) ? 'module' : 'unambiguous', allowImportExportEverywhere: true, allowAwaitOutsideFunction: true, allowReturnOutsideFunction: true, @@ -122,33 +117,39 @@ function loadBabelOpts (opts) { }, }; let fileOpts; + try { - fileOpts = filename && loadOptions({ - filename, - }); + fileOpts = + filename && + loadOptions({ + filename, + }); } catch (ex) { // } + for (const key in fileOpts) { if (Array.isArray(fileOpts[key]) && !fileOpts[key].length) { continue; } - + opts[key] = fileOpts[key]; if (Array.isArray(fileOpts[key]) && Array.isArray(opts.parserOpts[key])) { // combine arrays for plugins opts.parserOpts[key] = opts.parserOpts[key].concat(fileOpts[key]); - } else { + } else { // because some options need to be passed to parser also opts.parserOpts[key] = fileOpts[key]; } } + return opts; } -function literalParser (source, opts, styles) { +function literalParser(source, opts, styles) { let ast; + try { ast = parse(source, loadBabelOpts(opts)); } catch (ex) { @@ -158,22 +159,24 @@ function literalParser (source, opts, styles) { const specifiers = new Map(); const variableDeclarator = new Map(); - let objLiteral = new Set(); - let tplLiteral = new Set(); + const objLiteral = new Set(); + const tplLiteral = new Set(); const tplCallee = new Set(); const jobs = []; - function addObjectJob (path) { + function addObjectJob(path) { jobs.push(() => { addObjectValue(path); }); } - function addObjectValue (path) { + function addObjectValue(path) { if (path.isIdentifier()) { const identifier = path.scope.getBindingIdentifier(path.node.name); + if (identifier) { path = variableDeclarator.get(identifier); + if (path) { variableDeclarator.delete(identifier); path.forEach(addObjectExpression); @@ -184,36 +187,42 @@ function literalParser (source, opts, styles) { } } - function addObjectExpression (path) { + function addObjectExpression(path) { if (path.isObjectExpression()) { - path.get("properties").forEach(prop => { + path.get('properties').forEach((prop) => { if (prop.isSpreadElement()) { - addObjectValue(prop.get("argument")); + addObjectValue(prop.get('argument')); } }); objLiteral.add(path.node); + return path; } } - function setSpecifier (id, nameSpace) { + function setSpecifier(id, nameSpace) { nameSpace.unshift.apply( nameSpace, - nameSpace.shift().replace(/^\W+/, "").split(/[/\\]+/g) + nameSpace + .shift() + .replace(/^\W+/, '') + .split(/[/\\]+/g) ); if (types.isIdentifier(id)) { specifiers.set(id.name, nameSpace); specifiers.set(id, nameSpace); } else if (types.isObjectPattern(id)) { - id.properties.forEach(property => { + id.properties.forEach((property) => { if (types.isObjectProperty(property)) { const key = property.key; + nameSpace = nameSpace.concat(key.name || key.value); id = property.value; } else { id = property.argument; } + setSpecifier(id, nameSpace); }); } else if (types.isArrayPattern(id)) { @@ -223,23 +232,20 @@ function literalParser (source, opts, styles) { } } - function getNameSpace (path, nameSpace) { + function getNameSpace(path, nameSpace) { let node = path.node; + if (path.isIdentifier() || path.isJSXIdentifier()) { node = path.scope.getBindingIdentifier(node.name) || node; const specifier = specifiers.get(node) || specifiers.get(node.name); + if (specifier) { nameSpace.unshift.apply(nameSpace, specifier); } else { nameSpace.unshift(node.name); } } else { - [ - "name", - "property", - "object", - "callee", - ].forEach(prop => { + ['name', 'property', 'object', 'callee'].forEach((prop) => { node[prop] && getNameSpace(path.get(prop), nameSpace); }); } @@ -247,15 +253,19 @@ function literalParser (source, opts, styles) { return nameSpace; } - function isStylePath (path) { + function isStylePath(path) { return getNameSpace(path, []).some(function (name) { - let result = name && ((supports.hasOwnProperty(name) && supports[name]) || (opts.syntax.config.hasOwnProperty(name) && opts.syntax.config[name])); + const result = + name && + ((Object.prototype.hasOwnProperty.call(supports, name) && supports[name]) || + (Object.prototype.hasOwnProperty.call(opts.syntax.config, name) && + opts.syntax.config[name])); + switch (typeof result) { - case "function": { - result = result.apply(this, Array.prototype.slice.call(arguments, 1)); + case 'function': { + return result.apply(this, Array.prototype.slice.call(arguments, 1)); } - // eslint-disable-next-line no-fallthrough - case "boolean": { + case 'boolean': { return result; } } @@ -265,27 +275,31 @@ function literalParser (source, opts, styles) { const visitor = { ImportDeclaration: (path) => { const moduleId = path.node.source.value; - path.node.specifiers.forEach(specifier => { + + path.node.specifiers.forEach((specifier) => { const nameSpace = [moduleId]; + if (specifier.imported) { nameSpace.push(specifier.imported.name); } + setSpecifier(specifier.local, nameSpace); }); }, JSXAttribute: (path) => { if (/^(?:css|style)$/.test(path.node.name.name)) { - addObjectJob(path.get("value.expression")); + addObjectJob(path.get('value.expression')); } }, VariableDeclarator: (path) => { - variableDeclarator.set(path.node.id, path.node.init ? [path.get("init")] : []); + variableDeclarator.set(path.node.id, path.node.init ? [path.get('init')] : []); }, AssignmentExpression: (path) => { if (types.isIdentifier(path.node.left) && types.isObjectExpression(path.node.right)) { const identifier = path.scope.getBindingIdentifier(path.node.left.name); const variable = variableDeclarator.get(identifier); - const valuePath = path.get("right"); + const valuePath = path.get('right'); + if (variable) { variable.push(valuePath); } else { @@ -295,38 +309,48 @@ function literalParser (source, opts, styles) { }, CallExpression: (path) => { const callee = path.node.callee; - if (types.isIdentifier(callee, { name: "require" }) && !path.scope.getBindingIdentifier(callee.name)) { - path.node.arguments.filter(types.isStringLiteral).forEach(arg => { + + if ( + types.isIdentifier(callee, { name: 'require' }) && + !path.scope.getBindingIdentifier(callee.name) + ) { + path.node.arguments.filter(types.isStringLiteral).forEach((arg) => { const moduleId = arg.value; const nameSpace = [moduleId]; let currPath = path; + do { let id = currPath.parent.id; + if (!id) { id = currPath.parent.left; + if (id) { id = path.scope.getBindingIdentifier(id.name) || id; } else { if (types.isIdentifier(currPath.parent.property)) { nameSpace.push(currPath.parent.property.name); } + currPath = currPath.parentPath; continue; } - }; + } + setSpecifier(id, nameSpace); break; } while (currPath); }); - } else if (!tplCallee.has(callee) && isStylePath(path.get("callee"))) { - path.get("arguments").forEach((arg) => { - addObjectJob(arg.isFunction() ? arg.get("body") : arg); + } else if (!tplCallee.has(callee) && isStylePath(path.get('callee'))) { + path.get('arguments').forEach((arg) => { + addObjectJob(arg.isFunction() ? arg.get('body') : arg); }); } }, TaggedTemplateExpression: (path) => { - if (isStylePath(path.get("tag"))) { + if (isStylePath(path.get('tag'))) { tplLiteral.add(path.node.quasi); + if (path.node.tag.callee) { tplCallee.add(path.node.tag.callee); } @@ -335,19 +359,23 @@ function literalParser (source, opts, styles) { }; traverse(ast, visitor); - jobs.forEach(job => job()); + jobs.forEach((job) => job()); - const objLiteralStyles = Array.from(objLiteral).map(endNode => { - const objectSyntax = require("./object-syntax"); + const objLiteralStyles = Array.from(objLiteral).map((endNode) => { + const objectSyntax = require('./object-syntax'); let startNode = endNode; + if (startNode.leadingComments && startNode.leadingComments.length) { startNode = startNode.leadingComments[0]; } + let startIndex = startNode.start; const before = source.slice(startNode.start - startNode.loc.start.column, startNode.start); + if (/^\s+$/.test(before)) { startIndex -= before.length; } + return { startIndex, endIndex: endNode.end, @@ -357,19 +385,20 @@ function literalParser (source, opts, styles) { node: endNode, }, syntax: objectSyntax, - lang: "object-literal", + lang: 'object-literal', }; }); const tplLiteralStyles = []; - Array.from(tplLiteral).forEach(node => { - if (objLiteralStyles.some(style => ( - style.startIndex <= node.end && node.start < style.endIndex - ))) { - return + + Array.from(tplLiteral).forEach((node) => { + if ( + objLiteralStyles.some((style) => style.startIndex <= node.end && node.start < style.endIndex) + ) { + return; } - const quasis = node.quasis.map(node => ({ + const quasis = node.quasis.map((node) => ({ start: node.start, end: node.end, })); @@ -378,39 +407,47 @@ function literalParser (source, opts, styles) { endIndex: quasis[quasis.length - 1].end, content: getTemplate(node, source), }; + if (node.expressions.length) { - const expressions = node.expressions.map(node => ({ + const expressions = node.expressions.map((node) => ({ start: node.start, end: node.end, })); + style.syntax = loadSyntax(opts, __dirname); - style.lang = "template-literal"; + style.lang = 'template-literal'; style.opts = { - quasis: quasis, - expressions: expressions, + quasis, + expressions, }; } else { - style.lang = "css"; + style.lang = 'css'; } let parent = null; let targetStyles = tplLiteralStyles; + while (targetStyles) { - const target = targetStyles.find(targetStyle => - targetStyle.opts && targetStyle.opts.expressions.some(expr => - expr.start <= style.startIndex && style.endIndex < expr.end - ) + const target = targetStyles.find( + (targetStyle) => + targetStyle.opts && + targetStyle.opts.expressions.some( + (expr) => expr.start <= style.startIndex && style.endIndex < expr.end + ) ); + if (target) { parent = target; targetStyles = target.opts.templateLiteralStyles; } else { - break + break; } } if (parent) { - const templateLiteralStyles = parent.opts.templateLiteralStyles || (parent.opts.templateLiteralStyles = []); + const templateLiteralStyles = + parent.opts.templateLiteralStyles || (parent.opts.templateLiteralStyles = []); + templateLiteralStyles.push(style); } else { tplLiteralStyles.push(style); @@ -418,6 +455,6 @@ function literalParser (source, opts, styles) { }); return (styles || []).concat(objLiteralStyles).concat(tplLiteralStyles); -}; +} module.exports = literalParser; diff --git a/get-template.js b/get-template.js index adf26a5..c0dbd4f 100644 --- a/get-template.js +++ b/get-template.js @@ -1,5 +1,7 @@ -"use strict"; -function getTemplate (node, source) { +'use strict'; + +function getTemplate(node, source) { return source.slice(node.quasis[0].start, node.quasis[node.quasis.length - 1].end); } + module.exports = getTemplate; diff --git a/index.js b/index.js index 071bda3..44541a2 100644 --- a/index.js +++ b/index.js @@ -1,5 +1,6 @@ -"use strict"; -const extract = require("./extract"); -const syntax = require("postcss-syntax/syntax")(extract, "jsx"); +'use strict'; + +const extract = require('./extract'); +const syntax = require('postcss-syntax/syntax')(extract, 'jsx'); module.exports = syntax; diff --git a/literal.js b/literal.js index 7237969..cb9276c 100644 --- a/literal.js +++ b/literal.js @@ -1,6 +1,6 @@ +'use strict'; -"use strict"; -const Container = require("postcss/lib/container"); +const Container = require('postcss/lib/container'); /** * Represents a JS literal @@ -14,9 +14,9 @@ const Container = require("postcss/lib/container"); * literal.toString() //=> 'a{}' */ class Literal extends Container { - constructor (defaults) { + constructor(defaults) { super(defaults); - this.type = "literal"; + this.type = 'literal'; } } diff --git a/object-parse.js b/object-parse.js index a6749e7..48a6a48 100644 --- a/object-parse.js +++ b/object-parse.js @@ -1,12 +1,15 @@ -"use strict"; +'use strict'; -const ObjectParser = require("./object-parser"); -const Input = require("postcss/lib/input"); +const Input = require('postcss/lib/input'); +const ObjectParser = require('./object-parser'); -function objectParse (source, opts) { +function objectParse(source, opts) { const input = new Input(source, opts); const parser = new ObjectParser(input); + parser.parse(opts.node); + return parser.root; } + module.exports = objectParse; diff --git a/object-parser.js b/object-parser.js index 9003b42..7841e2d 100644 --- a/object-parser.js +++ b/object-parser.js @@ -1,32 +1,29 @@ -"use strict"; -const getTemplate = require("./get-template"); -const ObjectLiteral = require("./object"); -const camelCase = require("./camel-case"); -const unCamelCase = require("./un-camel-case"); -const Literal = require("./literal"); -const postcss = require("postcss"); - -function forEach (arr, callback) { +'use strict'; + +const camelCase = require('./camel-case'); +const getTemplate = require('./get-template'); +const Literal = require('./literal'); +const ObjectLiteral = require('./object'); +const postcss = require('postcss'); +const unCamelCase = require('./un-camel-case'); + +function forEach(arr, callback) { arr && arr.forEach(callback); } -const replaceProp = (fn) => (value) => ( - value.replace(/(\(\s*)(.*?)(\s*:)/g, (s, prefix, prop, suffix) => ( - prefix + fn(prop) + suffix - )) -); +const replaceProp = (fn) => (value) => + value.replace(/(\(\s*)(.*?)(\s*:)/g, (s, prefix, prop, suffix) => prefix + fn(prop) + suffix); const camelCaseProp = replaceProp(camelCase); const unCamelCaseProp = replaceProp(unCamelCase); -function defineRaws (node, prop, prefix, suffix, props) { +function defineRaws(node, prop, prefix, suffix, props) { if (!props) { props = {}; } + const descriptor = { enumerable: true, - get: () => ( - node[prop] - ), + get: () => node[prop], set: (value) => { node[prop] = value; }, @@ -34,12 +31,10 @@ function defineRaws (node, prop, prefix, suffix, props) { if (!props.raw) { props.raw = descriptor; - } else if (props.raw === "camel") { + } else if (props.raw === 'camel') { props.raw = { enumerable: true, - get: () => ( - camelCase(node[prop]) - ), + get: () => camelCase(node[prop]), set: (value) => { node[prop] = unCamelCase(value); }, @@ -48,29 +43,34 @@ function defineRaws (node, prop, prefix, suffix, props) { props.value = descriptor; - node.raws[prop] = Object.defineProperties({ - prefix, - suffix, - }, props); + node.raws[prop] = Object.defineProperties( + { + prefix, + suffix, + }, + props + ); } class objectParser { - constructor (input) { + constructor(input) { this.input = input; } - parse (node) { + parse(node) { const root = postcss.root({ source: { input: this.input, start: node.loc.start, }, }); + root.raws.node = node; const obj = new ObjectLiteral({ raws: { node, }, }); + root.push(obj); this.process(node, obj); this.sort(root); @@ -83,11 +83,15 @@ class objectParser { line: startNode.loc.start.line, }; - let before = root.source.input.css.slice(startNode.start - startNode.loc.start.column, startNode.start); + let before = root.source.input.css.slice( + startNode.start - startNode.loc.start.column, + startNode.start + ); + if (/^\s+$/.test(before)) { start.column = 1; } else { - before = ""; + before = ''; start.column = startNode.loc.start.column; } @@ -98,80 +102,86 @@ class objectParser { this.root = root; } - process (node, parent) { - [ - "leadingComments", - "innerComments", - "trailingComments", - ].forEach(prop => { - forEach(node[prop], child => { + process(node, parent) { + ['leadingComments', 'innerComments', 'trailingComments'].forEach((prop) => { + forEach(node[prop], (child) => { this.source(child, this.comment(child, parent)); }); }); const child = (this[node.type] || this.literal).apply(this, [node, parent]); + this.source(node, child); + return child; } - source (node, parent) { + source(node, parent) { parent.source = { input: this.input, start: node.loc.start, end: node.loc.end, }; + return parent; } - raws (parent, node) { + raws(parent, node) { const source = this.input.css; + parent.nodes.forEach((child, i) => { if (i) { - child.raws.before = source.slice(parent.nodes[i - 1].raws.node.end, child.raws.node.start).replace(/^\s*,+/, ""); + child.raws.before = source + .slice(parent.nodes[i - 1].raws.node.end, child.raws.node.start) + .replace(/^\s*,+/, ''); } else if (node) { - child.raws.before = source.slice(node.start, child.raws.node.start).replace(/^\s*{+/, ""); + child.raws.before = source.slice(node.start, child.raws.node.start).replace(/^\s*{+/, ''); } }); + if (node) { let semicolon; let after; + if (parent.nodes.length) { after = source.slice(parent.last.raws.node.end, node.end).replace(/^\s*,+/, () => { semicolon = true; - return ""; + + return ''; }); } else { - after = source.slice(node.start, node.end).replace(/^\s*{/, ""); + after = source.slice(node.start, node.end).replace(/^\s*{/, ''); } - parent.raws.after = after.replace(/}+\s*$/, ""); + + parent.raws.after = after.replace(/}+\s*$/, ''); parent.raws.semicolon = semicolon || false; } } - sort (node) { - node.nodes = node.nodes.sort((a, b) => ( - a.raws.node.start - b.raws.node.start - )); + sort(node) { + node.nodes = node.nodes.sort((a, b) => a.raws.node.start - b.raws.node.start); } - getNodeValue (node, wrappedValue) { + getNodeValue(node, wrappedValue) { const source = this.input.css; let rawValue; let cookedValue; + switch (node.type) { - case "Identifier": { - const isCssFloat = node.name === "cssFloat"; + case 'Identifier': { + const isCssFloat = node.name === 'cssFloat'; + return { - prefix: "", - suffix: "", + prefix: '', + suffix: '', raw: isCssFloat && node.name, - value: isCssFloat ? "float" : node.name, + value: isCssFloat ? 'float' : node.name, }; } - case "StringLiteral": { + case 'StringLiteral': { rawValue = node.extra.raw.slice(1, -1); cookedValue = node.value; break; } - case "TemplateLiteral": { + case 'TemplateLiteral': { rawValue = getTemplate(node, source); break; } @@ -180,7 +190,9 @@ class objectParser { break; } } + const valueWrap = wrappedValue.split(rawValue); + return { prefix: valueWrap[0], suffix: valueWrap[1], @@ -188,24 +200,28 @@ class objectParser { }; } - ObjectExpression (node, parent) { - forEach(node.properties, child => { + ObjectExpression(node, parent) { + forEach(node.properties, (child) => { this.process(child, parent); }); this.sort(parent); this.raws(parent, node); + return parent; } - ObjectProperty (node, parent) { + ObjectProperty(node, parent) { const source = this.input.css; - let between = source.indexOf(":", node.key.end); + let between = source.indexOf(':', node.key.end); const rawKey = source.slice(node.start, between).trimRight(); const rawValue = source.slice(between + 1, node.end).trimLeft(); + between = source.slice(node.start + rawKey.length, node.end - rawValue.length); const key = this.getNodeValue(node.key, rawKey); - if (node.value.type === "ObjectExpression") { + + if (node.value.type === 'ObjectExpression') { let rule; + if (/^@(\S+)(\s*)(.*)$/.test(key.value)) { const name = RegExp.$1; const afterName = RegExp.$2; @@ -213,56 +229,62 @@ class objectParser { const atRule = postcss.atRule({ name: unCamelCase(name), raws: { - afterName: afterName, + afterName, }, nodes: [], }); - defineRaws(atRule, "name", key.prefix + "@", params ? "" : key.suffix, { - raw: "camel", + + defineRaws(atRule, 'name', key.prefix + '@', params ? '' : key.suffix, { + raw: 'camel', }); + if (params) { atRule.params = unCamelCaseProp(params); - defineRaws(atRule, "params", "", key.suffix, { + defineRaws(atRule, 'params', '', key.suffix, { raw: { enumerable: true, - get: () => ( - camelCaseProp(atRule.params) - ), + get: () => camelCaseProp(atRule.params), set: (value) => { atRule.params = unCamelCaseProp(value); }, }, }); } + rule = atRule; } else { // rule = this.rule(key, keyWrap, node.value, parent); rule = postcss.rule({ selector: key.value, }); - defineRaws(rule, "selector", key.prefix, key.suffix); + defineRaws(rule, 'selector', key.prefix, key.suffix); } + raw(rule); this.ObjectExpression(node.value, rule); + return rule; } const value = this.getNodeValue(node.value, rawValue); - if (key.value[0] === "@") { + if (key.value[0] === '@') { const atRule = postcss.atRule({ name: unCamelCase(key.value), params: value.value, }); - defineRaws(atRule, "name", key.prefix, key.suffix, { - raw: "camel", + + defineRaws(atRule, 'name', key.prefix, key.suffix, { + raw: 'camel', }); - defineRaws(atRule, "params", value.prefix, value.suffix); + defineRaws(atRule, 'params', value.prefix, value.suffix); raw(atRule); + return atRule; } else { let decl; + if (key.raw) { decl = postcss.decl({ prop: key.value, @@ -277,38 +299,45 @@ class objectParser { value: value.value, }); - defineRaws(decl, "prop", key.prefix, key.suffix, { - raw: "camel", + defineRaws(decl, 'prop', key.prefix, key.suffix, { + raw: 'camel', }); } - defineRaws(decl, "value", value.prefix, value.suffix); + defineRaws(decl, 'value', value.prefix, value.suffix); raw(decl); + return decl; } - function raw (postcssNode) { + function raw(postcssNode) { postcssNode.raws.between = between; postcssNode.raws.node = node; parent.push(postcssNode); } } - literal (node, parent) { + literal(node, parent) { const literal = new Literal({ text: this.input.css.slice(node.start, node.end), raws: { node, }, }); + parent.push(literal); + return literal; } - comment (node, parent) { - if (!parent.nodes || (node.start < parent.raws.node.start && parent.type !== "root" && parent.parent)) { + comment(node, parent) { + if ( + !parent.nodes || + (node.start < parent.raws.node.start && parent.type !== 'root' && parent.parent) + ) { return this.comment(node, parent.parent); } + const text = node.value.match(/^(\s*)((?:\S[\s\S]*?)?)(\s*)$/); const comment = postcss.comment({ text: text[2], @@ -316,11 +345,12 @@ class objectParser { node, left: text[1], right: text[3], - inline: node.type === "CommentLine", + inline: node.type === 'CommentLine', }, }); parent.push(comment); + return comment; } } diff --git a/object-stringifier.js b/object-stringifier.js index 99f7c72..767e564 100644 --- a/object-stringifier.js +++ b/object-stringifier.js @@ -1,124 +1,153 @@ -"use strict"; -const Stringifier = require("postcss/lib/stringifier"); -const camelCase = require("./camel-case"); +'use strict'; + +const camelCase = require('./camel-case'); +const Stringifier = require('postcss/lib/stringifier'); class ObjectStringifier extends Stringifier { - object (node, semicolon) { - this.builder("{", node, "start"); + object(node) { + this.builder('{', node, 'start'); let after; + if (node.nodes && node.nodes.length) { this.body(node); - after = this.raw(node, "after"); + after = this.raw(node, 'after'); } else { - after = this.raw(node, "after", "emptyBody"); + after = this.raw(node, 'after', 'emptyBody'); } if (after) this.builder(after); - this.builder("}", node, "end"); + + this.builder('}', node, 'end'); } - literal (node, semicolon) { - this.builder(node.text + (semicolon ? "," : ""), node); + literal(node, semicolon) { + this.builder(node.text + (semicolon ? ',' : ''), node); } - decl (node, semicolon) { - let prop = this.rawValue(node, "prop"); - if (prop === "float") { - prop = "cssFloat"; + decl(node, semicolon) { + let prop = this.rawValue(node, 'prop'); + + if (prop === 'float') { + prop = 'cssFloat'; } + let string = prop; const isObjectShorthand = node.raws.node && node.raws.node.shorthand; + if (!isObjectShorthand) { - const between = this.raw(node, "between", "colon"); - const value = this.rawValue(node, "value"); + const between = this.raw(node, 'between', 'colon'); + const value = this.rawValue(node, 'value'); + string += between + value; - } + } + + if (semicolon) string += ','; - if (semicolon) string += ","; this.builder(string, node); } - rule (node, semicolon) { - this.block(node, this.rawValue(node, "selector"), semicolon); + rule(node, semicolon) { + this.block(node, this.rawValue(node, 'selector'), semicolon); } - atrule (node, semicolon) { - const name = this.rawValue(node, "name"); - const params = this.rawValue(node, "params"); + atrule(node, semicolon) { + const name = this.rawValue(node, 'name'); + const params = this.rawValue(node, 'params'); + if (node.nodes) { let string; + if (params) { - const afterName = this.raw(node, "afterName"); + const afterName = this.raw(node, 'afterName'); + string = name + afterName + params; } else { string = name; } + this.block(node, string, semicolon); } else { - const between = this.raw(node, "between", "colon"); + const between = this.raw(node, 'between', 'colon'); let string = name + between + params; - if (semicolon) string += ","; + + if (semicolon) string += ','; + this.builder(string, node); } } - block (node, start, semicolon) { + block(node, start, semicolon) { super.block(node, start); + if (semicolon) { - this.builder(",", node); + this.builder(',', node); } } - comment (node) { - const left = this.raw(node, "left", "commentLeft"); - const right = this.raw(node, "right", "commentRight"); + comment(node) { + const left = this.raw(node, 'left', 'commentLeft'); + const right = this.raw(node, 'right', 'commentRight'); if (node.raws.inline) { const text = node.raws.text || node.text; - this.builder("//" + left + text + right, node); + + this.builder('//' + left + text + right, node); } else { - this.builder("/*" + left + node.text + right + "*/", node); + this.builder('/*' + left + node.text + right + '*/', node); } } - raw (node, own, detect) { + raw(node, own, detect) { let value = super.raw(node, own, detect); - if ((own === "between" || (own === "afterName" && node.type === "atrule" && !node.nodes)) && !/:/.test(value)) { - value = ":" + value; - } else if (own === "before" && /^(decl|rule)$/.test(node.type)) { - value = value.replace(/\S+$/, ""); + + if ( + (own === 'between' || (own === 'afterName' && node.type === 'atrule' && !node.nodes)) && + !/:/.test(value) + ) { + value = ':' + value; + } else if (own === 'before' && /^(decl|rule)$/.test(node.type)) { + value = value.replace(/\S+$/, ''); } + return value; } - rawValue (node, prop) { + rawValue(node, prop) { const raw = node.raws[prop]; + if (raw) { - const descriptor = Object.getOwnPropertyDescriptor(raw, "raw"); + const descriptor = Object.getOwnPropertyDescriptor(raw, 'raw'); + if (descriptor && descriptor.get) { return raw.prefix + raw.raw + raw.suffix; } } let value = super.rawValue(node, prop); - if (value == null) { + + if (value === null || value === undefined) { return value; } + if (/^(prop|selector)$/i.test(prop)) { value = camelCase(value); + if (node.raws.before && /(\S+)$/.test(node.raws.before)) { value = RegExp.$1 + value; } else if (value && !/\W/.test(value)) { return value; } - } else if (node.type === "atrule") { - if (prop === "name") { - value = "@" + value; + } else if (node.type === 'atrule') { + if (prop === 'name') { + value = '@' + value; } else if (node.nodes) { return; } + if (node.nodes) { - value += this.raw(node, "afterName"); - value += super.rawValue(node, "params"); + value += this.raw(node, 'afterName'); + value += super.rawValue(node, 'params'); } } + value = JSON.stringify(value); + return value; } -}; +} module.exports = ObjectStringifier; diff --git a/object-stringify.js b/object-stringify.js index a00651e..2477392 100644 --- a/object-stringify.js +++ b/object-stringify.js @@ -1,7 +1,9 @@ -"use strict"; -const ObjectStringifier = require("./object-stringifier"); +'use strict'; -module.exports = function objectStringify (node, builder) { +const ObjectStringifier = require('./object-stringifier'); + +module.exports = function objectStringify(node, builder) { const str = new ObjectStringifier(builder); + str.stringify(node); }; diff --git a/object-syntax.js b/object-syntax.js index b44fcce..f91066b 100644 --- a/object-syntax.js +++ b/object-syntax.js @@ -1,6 +1,7 @@ -"use strict"; -const stringify = require("./object-stringify"); -const parse = require("./object-parse"); +'use strict'; + +const parse = require('./object-parse'); +const stringify = require('./object-stringify'); const syntax = { parse, diff --git a/object.js b/object.js index 858b488..8d2e8e7 100644 --- a/object.js +++ b/object.js @@ -1,5 +1,6 @@ -"use strict"; -const Container = require("postcss/lib/container"); +'use strict'; + +const Container = require('postcss/lib/container'); /** * Represents a JS Object Literal @@ -13,9 +14,9 @@ const Container = require("postcss/lib/container"); * obj.toString() //=> '{}' */ class ObjectLiteral extends Container { - constructor (defaults) { + constructor(defaults) { super(defaults); - this.type = "object"; + this.type = 'object'; this.nodes = []; } } diff --git a/package-lock.json b/package-lock.json index 74e7a16..2c773a0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -335,6 +335,12 @@ "@types/node": "*" } }, + "@types/json-schema": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.4.tgz", + "integrity": "sha512-8+KAKzEvSUdeo+kmqnKrqgeE+LcA0tjYWFY7RPProVYwnqDjukzO+3b6dLD56rYX5TdWejnEOLJYOIeh4CXKuA==", + "dev": true + }, "@types/minimatch": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", @@ -365,6 +371,59 @@ "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", "dev": true }, + "@typescript-eslint/experimental-utils": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-1.13.0.tgz", + "integrity": "sha512-zmpS6SyqG4ZF64ffaJ6uah6tWWWgZ8m+c54XXgwFtUv0jNz8aJAVx8chMCvnk7yl6xwn8d+d96+tWp7fXzTuDg==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.3", + "@typescript-eslint/typescript-estree": "1.13.0", + "eslint-scope": "^4.0.0" + }, + "dependencies": { + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + } + } + }, + "@typescript-eslint/typescript-estree": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-1.13.0.tgz", + "integrity": "sha512-b5rCmd2e6DCC6tCTN9GSUAuxdYwCM/k/2wdjHGrIRGPSJotWMCe/dGpi66u42bhuh8q3QBzqM4TMA1GUUCJvdw==", + "dev": true, + "requires": { + "lodash.unescape": "4.0.1", + "semver": "5.5.0" + }, + "dependencies": { + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "dev": true + } + } + }, + "acorn": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.1.tgz", + "integrity": "sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg==", + "dev": true + }, + "acorn-jsx": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.2.0.tgz", + "integrity": "sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ==", + "dev": true + }, "agent-base": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.0.tgz", @@ -591,6 +650,12 @@ "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", "dev": true }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true + }, "async-exit-hook": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/async-exit-hook/-/async-exit-hook-2.0.1.tgz", @@ -1097,12 +1162,24 @@ "delayed-stream": "~1.0.0" } }, + "commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true + }, "commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", "dev": true }, + "compare-versions": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz", + "integrity": "sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==", + "dev": true + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -1234,6 +1311,12 @@ "mimic-response": "^1.0.0" } }, + "dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", + "dev": true + }, "deep-eql": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", @@ -1249,6 +1332,12 @@ "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "dev": true }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, "default-require-extensions": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.0.tgz", @@ -1317,6 +1406,15 @@ "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", "dev": true }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, "dot-prop": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.2.0.tgz", @@ -1425,12 +1523,303 @@ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, + "eslint": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.8.0.tgz", + "integrity": "sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "ajv": "^6.10.0", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "eslint-scope": "^5.0.0", + "eslint-utils": "^1.4.3", + "eslint-visitor-keys": "^1.1.0", + "espree": "^6.1.2", + "esquery": "^1.0.1", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.0.0", + "globals": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "inquirer": "^7.0.0", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.14", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.3", + "progress": "^2.0.0", + "regexpp": "^2.0.1", + "semver": "^6.1.2", + "strip-ansi": "^5.2.0", + "strip-json-comments": "^3.0.1", + "table": "^5.2.3", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "globals": { + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", + "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "dev": true, + "requires": { + "type-fest": "^0.8.1" + } + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "strip-json-comments": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz", + "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==", + "dev": true + } + } + }, + "eslint-config-prettier": { + "version": "6.10.1", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-6.10.1.tgz", + "integrity": "sha512-svTy6zh1ecQojvpbJSgH3aei/Rt7C6i090l5f2WQ4aB05lYHeZIR1qL4wZyyILTbtmnbHP5Yn8MrsOJMGa8RkQ==", + "dev": true, + "requires": { + "get-stdin": "^6.0.0" + } + }, + "eslint-config-stylelint": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-stylelint/-/eslint-config-stylelint-11.1.0.tgz", + "integrity": "sha512-muHh1wK0f/adiIfbUWIS/X2Vr2V8Eb/27EuMCDYA6ExyfTNmn927K96HcW7iskE1JgAOCES3ueSjtF5H0kurvQ==", + "dev": true, + "requires": { + "eslint-plugin-eslint-comments": "^3.1.2", + "eslint-plugin-jest": "^22.15.0", + "eslint-plugin-node": "^9.1.0", + "eslint-plugin-sort-requires": "^2.1.0" + } + }, + "eslint-plugin-es": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-1.4.1.tgz", + "integrity": "sha512-5fa/gR2yR3NxQf+UXkeLeP8FBBl6tSgdrAz1+cF84v1FMM4twGwQoqTnn+QxFLcPOrF4pdKEJKDB/q9GoyJrCA==", + "dev": true, + "requires": { + "eslint-utils": "^1.4.2", + "regexpp": "^2.0.1" + } + }, + "eslint-plugin-eslint-comments": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-eslint-comments/-/eslint-plugin-eslint-comments-3.1.2.tgz", + "integrity": "sha512-QexaqrNeteFfRTad96W+Vi4Zj1KFbkHHNMMaHZEYcovKav6gdomyGzaxSDSL3GoIyUOo078wRAdYlu1caiauIQ==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5", + "ignore": "^5.0.5" + }, + "dependencies": { + "ignore": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.4.tgz", + "integrity": "sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A==", + "dev": true + } + } + }, + "eslint-plugin-jest": { + "version": "22.21.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-22.21.0.tgz", + "integrity": "sha512-OaqnSS7uBgcGiqXUiEnjoqxPNKvR4JWG5mSRkzVoR6+vDwlqqp11beeql1hYs0HTbdhiwrxWLxbX0Vx7roG3Ew==", + "dev": true, + "requires": { + "@typescript-eslint/experimental-utils": "^1.13.0" + } + }, + "eslint-plugin-node": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-9.2.0.tgz", + "integrity": "sha512-2abNmzAH/JpxI4gEOwd6K8wZIodK3BmHbTxz4s79OIYwwIt2gkpEXlAouJXu4H1c9ySTnRso0tsuthSOZbUMlA==", + "dev": true, + "requires": { + "eslint-plugin-es": "^1.4.1", + "eslint-utils": "^1.4.2", + "ignore": "^5.1.1", + "minimatch": "^3.0.4", + "resolve": "^1.10.1", + "semver": "^6.1.0" + }, + "dependencies": { + "ignore": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.4.tgz", + "integrity": "sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "eslint-plugin-sort-requires": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-sort-requires/-/eslint-plugin-sort-requires-2.1.0.tgz", + "integrity": "sha1-PvrZSNyDeYIZ6An1QGfEDlVESGE=", + "dev": true + }, + "eslint-scope": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz", + "integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", + "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "eslint-visitor-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", + "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", + "dev": true + }, + "espree": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz", + "integrity": "sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==", + "dev": true, + "requires": { + "acorn": "^7.1.1", + "acorn-jsx": "^5.2.0", + "eslint-visitor-keys": "^1.1.0" + } + }, "esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true }, + "esquery": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.2.0.tgz", + "integrity": "sha512-weltsSqdeWIX9G2qQZz7KlTRJdkkOCTPgLYJUz1Hacf48R4YOwGPHO3+ORfWedqJKbq5WQmsgK90n+pFLIKt/Q==", + "dev": true, + "requires": { + "estraverse": "^5.0.0" + }, + "dependencies": { + "estraverse": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.0.0.tgz", + "integrity": "sha512-j3acdrMzqrxmJTNj5dbr1YbjacrYgAxVMeF0gK16E3j494mOe7xygM/ZLIguEQ0ETwAg2hlJCtHRGav+y0Ny5A==", + "dev": true + } + } + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "dev": true, + "requires": { + "estraverse": "^4.1.0" + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, "execa": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/execa/-/execa-4.0.0.tgz", @@ -1505,6 +1894,12 @@ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, "figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", @@ -1514,6 +1909,15 @@ "escape-string-regexp": "^1.0.5" } }, + "file-entry-cache": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", + "dev": true, + "requires": { + "flat-cache": "^2.0.1" + } + }, "fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -1543,6 +1947,15 @@ "locate-path": "^2.0.0" } }, + "find-versions": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-3.2.0.tgz", + "integrity": "sha512-P8WRou2S+oe222TOCHitLy8zj+SIsVJh52VP4lvXkaFVnOFFdoWv1H1Jjvel1aI6NCFOAaeAVm8qrI0odiLcww==", + "dev": true, + "requires": { + "semver-regex": "^2.0.0" + } + }, "flat": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", @@ -1552,6 +1965,34 @@ "is-buffer": "~2.0.3" } }, + "flat-cache": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", + "dev": true, + "requires": { + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" + }, + "dependencies": { + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "flatted": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", + "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", + "dev": true + }, "foreground-child": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", @@ -1604,6 +2045,12 @@ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, "gensync": { "version": "1.0.0-beta.1", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz", @@ -1621,6 +2068,18 @@ "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", "dev": true }, + "get-own-enumerable-property-symbols": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", + "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==", + "dev": true + }, + "get-stdin": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz", + "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==", + "dev": true + }, "get-stream": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz", @@ -1893,6 +2352,76 @@ "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", "dev": true }, + "husky": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/husky/-/husky-4.2.3.tgz", + "integrity": "sha512-VxTsSTRwYveKXN4SaH1/FefRJYCtx+wx04sSVcOpD7N2zjoHxa+cEJ07Qg5NmV3HAK+IRKOyNVpi2YBIVccIfQ==", + "dev": true, + "requires": { + "chalk": "^3.0.0", + "ci-info": "^2.0.0", + "compare-versions": "^3.5.1", + "cosmiconfig": "^6.0.0", + "find-versions": "^3.2.0", + "opencollective-postinstall": "^2.0.2", + "pkg-dir": "^4.2.0", + "please-upgrade-node": "^3.2.0", + "slash": "^3.0.0", + "which-pm-runs": "^1.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -1902,6 +2431,12 @@ "safer-buffer": ">= 2.1.2 < 3" } }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, "ignore-walk": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz", @@ -2367,6 +2902,12 @@ "has": "^1.0.3" } }, + "is-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=", + "dev": true + }, "is-scoped": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-scoped/-/is-scoped-2.1.0.tgz", @@ -2608,6 +3149,12 @@ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, "json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", @@ -2652,12 +3199,119 @@ "package-json": "^6.3.0" } }, - "lines-and-columns": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", - "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", - "dev": true - }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "lines-and-columns": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", + "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", + "dev": true + }, + "lint-staged": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-10.1.1.tgz", + "integrity": "sha512-wAeu/ePaBAOfwM2+cVbgPWDtn17B0Sxiv0NvNEqDAIvB8Yhvl60vafKFiK4grcYn87K1iK+a0zVoETvKbdT9/Q==", + "dev": true, + "requires": { + "chalk": "^3.0.0", + "commander": "^4.0.1", + "cosmiconfig": "^6.0.0", + "debug": "^4.1.1", + "dedent": "^0.7.0", + "execa": "^3.4.0", + "listr": "^0.14.3", + "log-symbols": "^3.0.0", + "micromatch": "^4.0.2", + "normalize-path": "^3.0.0", + "please-upgrade-node": "^3.2.0", + "string-argv": "0.3.1", + "stringify-object": "^3.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "execa": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-3.4.0.tgz", + "integrity": "sha512-r9vdGQk4bmCuK1yKQu1KTwcT2zwfWdbdaXfCtAh+5nU/4fSX+JAb7vZGvI5naJrQlvONrEB20jeruESI69530g==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "p-finally": "^2.0.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "p-finally": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-2.0.1.tgz", + "integrity": "sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw==", + "dev": true + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, "listr": { "version": "0.14.3", "resolved": "https://registry.npmjs.org/listr/-/listr-0.14.3.tgz", @@ -2847,6 +3501,42 @@ } } }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + }, + "dependencies": { + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + } + } + }, "load-resources": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/load-resources/-/load-resources-0.1.1.tgz", @@ -2878,6 +3568,12 @@ "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", "dev": true }, + "lodash.unescape": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.unescape/-/lodash.unescape-4.0.1.tgz", + "integrity": "sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw=", + "dev": true + }, "lodash.zip": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/lodash.zip/-/lodash.zip-4.2.0.tgz", @@ -3014,6 +3710,12 @@ "p-is-promise": "^2.0.0" } }, + "memorystream": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI=", + "dev": true + }, "meow": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/meow/-/meow-6.1.0.tgz", @@ -3051,6 +3753,16 @@ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", "dev": true }, + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" + } + }, "mime-db": { "version": "1.43.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", @@ -3229,6 +3941,12 @@ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", "dev": true }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, "new-github-release-url": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/new-github-release-url/-/new-github-release-url-1.0.0.tgz", @@ -3246,6 +3964,12 @@ } } }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, "node-environment-flags": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.6.tgz", @@ -3437,6 +4161,85 @@ "validate-npm-package-name": "^3.0.0" } }, + "npm-run-all": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", + "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "chalk": "^2.4.1", + "cross-spawn": "^6.0.5", + "memorystream": "^0.3.1", + "minimatch": "^3.0.4", + "pidtree": "^0.3.0", + "read-pkg": "^3.0.0", + "shell-quote": "^1.6.1", + "string.prototype.padend": "^3.0.0" + }, + "dependencies": { + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, + "requires": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + } + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + } + } + }, "npm-run-path": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", @@ -3747,6 +4550,26 @@ "is-wsl": "^2.1.1" } }, + "opencollective-postinstall": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.2.tgz", + "integrity": "sha512-pVOEP16TrAO2/fjej1IdOyupJY8KDUM1CvsaScRbw6oddvpQoOfGk4ywha0HKKVAD6RkW4x6Q+tNBwhf3Bgpuw==", + "dev": true + }, + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } + }, "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", @@ -3950,6 +4773,12 @@ "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", "dev": true }, + "pidtree": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz", + "integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==", + "dev": true + }, "pify": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", @@ -4040,6 +4869,15 @@ "find-up": "^2.1.0" } }, + "please-upgrade-node": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", + "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==", + "dev": true, + "requires": { + "semver-compare": "^1.0.0" + } + }, "plugin-error": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", @@ -4124,12 +4962,24 @@ "integrity": "sha512-N7h4pG+Nnu5BEIzyeaaIYWs0LI5XC40OrRh5L60z0QjFsqGWcHcbkBvpe1WYpcIS9yQ8sOi/vIPt1ejQCrMVrg==", "dev": true }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, "prepend-http": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", "dev": true }, + "prettier": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.0.2.tgz", + "integrity": "sha512-5xJQIPT8BraI7ZnaDwSbu5zLrB6vvi8hVV58yHQ+QK64qrY40dULy0HSRlQ2/2IdzeBpjhDkqdcFBnFeDEMVdg==", + "dev": true + }, "process-on-spawn": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz", @@ -4139,6 +4989,12 @@ "fromentries": "^1.2.0" } }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, "psl": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", @@ -4309,6 +5165,12 @@ "integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==", "dev": true }, + "regexpp": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", + "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", + "dev": true + }, "registry-auth-token": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.1.1.tgz", @@ -4458,6 +5320,12 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" }, + "semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", + "dev": true + }, "semver-diff": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", @@ -4475,6 +5343,12 @@ } } }, + "semver-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-2.0.0.tgz", + "integrity": "sha512-mUdIBBvdn0PLOeP3TEkMH7HHeUP3GjsXCwKarjv/kGmUFOYg1VqEemKhoQpWMu6X2I8kHeuVdGibLGkVK+/5Qw==", + "dev": true + }, "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", @@ -4496,12 +5370,24 @@ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true }, + "shell-quote": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.2.tgz", + "integrity": "sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==", + "dev": true + }, "signal-exit": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", "dev": true }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, "slice-ansi": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", @@ -4611,6 +5497,12 @@ "stubs": "^3.0.0" } }, + "string-argv": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz", + "integrity": "sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==", + "dev": true + }, "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", @@ -4621,6 +5513,16 @@ "strip-ansi": "^4.0.0" } }, + "string.prototype.padend": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.0.tgz", + "integrity": "sha512-3aIv8Ffdp8EZj8iLwREGpQaUZiPyrWrpzMBHvkiSW/bK/EGve9np07Vwy7IJ5waydpGXzQZu/F8Oze2/IWkBaA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + } + }, "string.prototype.trimend": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.0.tgz", @@ -4663,6 +5565,25 @@ "es-abstract": "^1.17.5" } }, + "stringify-object": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", + "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", + "dev": true, + "requires": { + "get-own-enumerable-property-symbols": "^3.0.0", + "is-obj": "^1.0.1", + "is-regexp": "^1.0.0" + }, + "dependencies": { + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", + "dev": true + } + } + }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", @@ -4746,6 +5667,57 @@ "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==", "dev": true }, + "table": { + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", + "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "dev": true, + "requires": { + "ajv": "^6.10.2", + "lodash": "^4.17.14", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + } + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, "teeny-request": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-6.0.1.tgz", @@ -4802,6 +5774,12 @@ } } }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -4886,6 +5864,15 @@ "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", "dev": true }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } + }, "type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", @@ -5029,6 +6016,12 @@ "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", "dev": true }, + "v8-compile-cache": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz", + "integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==", + "dev": true + }, "validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", @@ -5074,6 +6067,12 @@ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, + "which-pm-runs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz", + "integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=", + "dev": true + }, "wide-align": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", @@ -5132,6 +6131,12 @@ } } }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, "wrap-ansi": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", @@ -5177,6 +6182,15 @@ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true }, + "write": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", + "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", + "dev": true, + "requires": { + "mkdirp": "^0.5.1" + } + }, "write-file-atomic": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", diff --git a/package.json b/package.json index cf606ac..b473ea5 100644 --- a/package.json +++ b/package.json @@ -28,9 +28,17 @@ ], "all": true, "cache": true, - "check-coverage": true + "check-coverage": true, + "exclude": [ + "coverage/**", + "test{,s}/**", + "**/.{prettier,eslint,mocha}rc.{js,cjs}" + ] }, "scripts": { + "lint:formatting": "prettier . --check", + "lint:js": "eslint .", + "lint": "npm-run-all --parallel lint:*", "mocha": "mocha --no-timeouts", "test": "nyc npm run mocha", "debug": "npm run mocha -- --inspect-brk", @@ -47,16 +55,32 @@ "autoprefixer": "^9.7.5", "chai": "^4.2.0", "codecov": "^3.6.5", + "eslint": "^6.8.0", + "eslint-config-prettier": "^6.10.1", + "eslint-config-stylelint": "^11.1.0", + "husky": "^4.2.3", "json5": "^2.1.2", + "lint-staged": "^10.1.1", "mocha": "^7.1.1", "np": "^6.2.0", + "npm-run-all": "^4.1.5", "nyc": "^15.0.0", "postcss": ">=7.0.27", "postcss-parser-tests": "^6.5.0", "postcss-safe-parser": "^4.0.2", - "postcss-syntax": ">=0.36.2" + "postcss-syntax": ">=0.36.2", + "prettier": "^2.0.2" }, "publishConfig": { "access": "public" + }, + "husky": { + "hooks": { + "pre-commit": "lint-staged" + } + }, + "lint-staged": { + "*.js": "eslint --cache --fix", + "*.{js,md,yml}": "prettier --write" } } diff --git a/template-parse.js b/template-parse.js index 885537b..1bc48c8 100644 --- a/template-parse.js +++ b/template-parse.js @@ -1,16 +1,19 @@ -"use strict"; +'use strict'; -const TemplateParser = require("./template-parser"); -const Input = require("postcss/lib/input"); +const Input = require('postcss/lib/input'); +const TemplateParser = require('./template-parser'); -function templateParse (css, opts) { +function templateParse(css, opts) { const input = new Input(css, opts); + input.quasis = opts.quasis; input.templateLiteralStyles = opts.templateLiteralStyles; - input.parseOptions = opts + input.parseOptions = opts; const parser = new TemplateParser(input); + parser.parse(); return parser.root; } + module.exports = templateParse; diff --git a/template-parser-helper.js b/template-parser-helper.js index 37245eb..5f0cb42 100644 --- a/template-parser-helper.js +++ b/template-parser-helper.js @@ -1,23 +1,27 @@ -"use strict"; -const Literal = require("./literal"); -const postcssParse = require("postcss/lib/parse"); -const Input = require("postcss/lib/input"); +'use strict'; + +const Literal = require('./literal'); +const postcssParse = require('postcss/lib/parse'); const reNewLine = /(?:\r?\n|\r)/gm; -const isLiteral = token => token[0] === "word" && /^\$\{[\s\S]*\}$/.test(token[1]); -function literal (start) { +const isLiteral = (token) => token[0] === 'word' && /^\$\{[\s\S]*\}$/.test(token[1]); + +function literal(start) { if (!isLiteral(start)) { return; } + const tokens = []; let hasWord; let type; let token; + while ((token = this.tokenizer.nextToken())) { tokens.push(token); type = token[0]; + if (type.length === 1) { break; - } else if (type === "word") { + } else if (type === 'word') { hasWord = true; } } @@ -26,7 +30,7 @@ function literal (start) { this.tokenizer.back(tokens.pop()); } - if (type === "{" || (type === ":" && !hasWord)) { + if (type === '{' || (type === ':' && !hasWord)) { return; } @@ -37,23 +41,25 @@ function literal (start) { this.init(node, start[2], start[3]); const input = this.input; + if (input.templateLiteralStyles) { const offset = input.quasis[0].start; const nodeIndex = getNodeIndex(node, input); const start = offset + nodeIndex; const end = start + node.text.length; - const templateLiteralStyles = input.templateLiteralStyles.filter(style => - style.startIndex <= end && start < style.endIndex + const templateLiteralStyles = input.templateLiteralStyles.filter( + (style) => style.startIndex <= end && start < style.endIndex ); + if (templateLiteralStyles.length) { - const nodes = parseTemplateLiteralStyles( - templateLiteralStyles, - input, - [nodeIndex, nodeIndex + node.text.length] - ); + const nodes = parseTemplateLiteralStyles(templateLiteralStyles, input, [ + nodeIndex, + nodeIndex + node.text.length, + ]); + if (nodes.length) { node.nodes = nodes; - nodes.forEach(n => n.parent = node); + nodes.forEach((n) => (n.parent = node)); } } } @@ -61,19 +67,20 @@ function literal (start) { return node; } -function freeSemicolon (token) { +function freeSemicolon(token) { this.spaces += token[1]; const nodes = this.current.nodes; const prev = nodes && nodes[nodes.length - 1]; + if (prev && /^(rule|literal)$/.test(prev.type) && !prev.raws.ownSemicolon) { prev.raws.ownSemicolon = this.spaces; - this.spaces = ""; + this.spaces = ''; } } module.exports = { - freeSemicolon: freeSemicolon, - literal: literal, + freeSemicolon, + literal, }; function parseTemplateLiteralStyles(styles, input, range) { @@ -83,39 +90,49 @@ function parseTemplateLiteralStyles(styles, input, range) { const nodes = []; let index = range[0]; - styles.sort((a, b) => ( - a.startIndex - b.startIndex - )).forEach(style => { - const root = parseStyle(style); - if (!root || !root.nodes.length) { - return - } - root.raws.beforeStart = source.slice(index, style.startIndex - offset); - root.raws.afterEnd = ''; - if (style.endIndex) { - index = style.endIndex - offset; - } else { - index = style.startIndex - offset + (style.content || root.source.input.css).length; - } - nodes.push(root); - }) + + styles + .sort((a, b) => a.startIndex - b.startIndex) + .forEach((style) => { + const root = parseStyle(style); + + if (!root || !root.nodes.length) { + return; + } + + root.raws.beforeStart = source.slice(index, style.startIndex - offset); + root.raws.afterEnd = ''; + + if (style.endIndex) { + index = style.endIndex - offset; + } else { + index = style.startIndex - offset + (style.content || root.source.input.css).length; + } + + nodes.push(root); + }); + if (nodes.length) { nodes[nodes.length - 1].raws.afterEnd = source.slice(index, range[1]); } + return nodes; } class LocalFixer { - constructor (offset, lines, style, templateParse) { - const startIndex = style.startIndex - offset + constructor(offset, lines, style, templateParse) { + const startIndex = style.startIndex - offset; let line = 0; let column = startIndex; + lines.some((lineEndIndex, lineNumber) => { if (lineEndIndex >= startIndex) { line = lineNumber--; + if (lineNumber in lines) { column = startIndex - lines[lineNumber] - 1; } + return true; } }); @@ -123,50 +140,66 @@ class LocalFixer { this.line = line; this.column = column; this.style = style; - this.templateParse = templateParse + this.templateParse = templateParse; } - object (object) { + object(object) { if (object) { if (object.line === 1) { object.column += this.column; } + object.line += this.line; } } - node (node) { + node(node) { this.object(node.source.start); this.object(node.source.end); } - root (root) { + root(root) { this.node(root); - root.walk(node => { + root.walk((node) => { this.node(node); }); } - error (error) { - if (error && error.name === "CssSyntaxError") { + error(error) { + if (error && error.name === 'CssSyntaxError') { this.object(error); this.object(error.input); - error.message = error.message.replace(/:\d+:\d+:/, ":" + error.line + ":" + error.column + ":"); + error.message = error.message.replace( + /:\d+:\d+:/, + ':' + error.line + ':' + error.column + ':' + ); } + return error; } - parse (opts) { + parse(opts) { const style = this.style; const syntax = style.syntax; let root = style.root; + try { - root = this.templateParse(style.content, Object.assign({}, opts, { - map: false, - }, style.opts)); + root = this.templateParse( + style.content, + Object.assign( + {}, + opts, + { + map: false, + }, + style.opts + ) + ); } catch (error) { if (style.ignoreErrors) { return; } else if (!style.skipConvert) { this.error(error); } + throw error; } + if (!style.skipConvert) { this.root(root); } @@ -174,39 +207,47 @@ class LocalFixer { root.source.inline = Boolean(style.inline); root.source.lang = style.lang; root.source.syntax = syntax; + return root; } } -function docFixer (offset, source, opts) { +function docFixer(offset, source, opts) { let match; const lines = []; + reNewLine.lastIndex = 0; while ((match = reNewLine.exec(source))) { lines.push(match.index); } lines.push(source.length); - return function parseStyle (style) { - const parse = style.syntax ? style.syntax.parse : postcssParse + + return function parseStyle(style) { + const parse = style.syntax ? style.syntax.parse : postcssParse; + return new LocalFixer(offset, lines, style, parse).parse(opts); }; } function getNodeIndex(node, input) { - const source = input.css + const source = input.css; let match; - let line = 1 - let lastIndex = -1 + let line = 1; + let lastIndex = -1; + reNewLine.lastIndex = 0; while ((match = reNewLine.exec(source))) { if (line === node.source.start.line) { - return lastIndex + node.source.start.column + return lastIndex + node.source.start.column; } - lastIndex = match.index - line++ + + lastIndex = match.index; + line++; } + if (line === node.source.start.line) { - return lastIndex + node.source.start.column + return lastIndex + node.source.start.column; } - return source.length + + return source.length; } diff --git a/template-parser.js b/template-parser.js index d665c06..a26d131 100644 --- a/template-parser.js +++ b/template-parser.js @@ -1,17 +1,19 @@ -"use strict"; -const Parser = require("postcss/lib/parser"); -const templateTokenize = require("./template-tokenize"); -const helper = require("./template-parser-helper"); +'use strict'; + +const helper = require('./template-parser-helper'); +const Parser = require('postcss/lib/parser'); +const templateTokenize = require('./template-tokenize'); class TemplateParser extends Parser { - createTokenizer () { + createTokenizer() { this.tokenizer = templateTokenize(this.input); } - other () { + other() { const args = arguments; + return helper.literal.apply(this, args) || super.other.apply(this, args); } - freeSemicolon () { + freeSemicolon() { return helper.freeSemicolon.apply(this, arguments); } } diff --git a/template-safe-parse.js b/template-safe-parse.js index bfc005a..ec0ccd8 100644 --- a/template-safe-parse.js +++ b/template-safe-parse.js @@ -1,16 +1,19 @@ -"use strict"; +'use strict'; -const TemplateSafeParser = require("./template-safe-parser"); -const Input = require("postcss/lib/input"); +const Input = require('postcss/lib/input'); +const TemplateSafeParser = require('./template-safe-parser'); -function templateSafeParse (css, opts) { +function templateSafeParse(css, opts) { const input = new Input(css, opts); + input.quasis = opts.quasis; input.templateLiteralStyles = opts.templateLiteralStyles; - input.parseOptions = opts + input.parseOptions = opts; const parser = new TemplateSafeParser(input); + parser.parse(); return parser.root; } + module.exports = templateSafeParse; diff --git a/template-safe-parser.js b/template-safe-parser.js index 16e138b..d3b7164 100644 --- a/template-safe-parser.js +++ b/template-safe-parser.js @@ -1,17 +1,20 @@ -"use strict"; -const SafeParser = require("postcss-safe-parser/lib/safe-parser"); -const templateTokenize = require("./template-tokenize"); -const helper = require("./template-parser-helper"); +'use strict'; + +const helper = require('./template-parser-helper'); +// eslint-disable-next-line node/no-unpublished-require +const SafeParser = require('postcss-safe-parser/lib/safe-parser'); +const templateTokenize = require('./template-tokenize'); class TemplateSafeParser extends SafeParser { - createTokenizer () { + createTokenizer() { this.tokenizer = templateTokenize(this.input, { ignoreErrors: true }); } - other () { + other() { const args = arguments; + return helper.literal.apply(this, args) || super.other.apply(this, args); } - freeSemicolon () { + freeSemicolon() { return helper.freeSemicolon.apply(this, arguments); } } diff --git a/template-stringifier.js b/template-stringifier.js index 0359ba6..2a66d0e 100644 --- a/template-stringifier.js +++ b/template-stringifier.js @@ -1,21 +1,23 @@ -"use strict"; -const Stringifier = require("postcss/lib/stringifier"); +'use strict'; + +const Stringifier = require('postcss/lib/stringifier'); class TemplateStringifier extends Stringifier { - literal (node) { + literal(node) { if (node.nodes && node.nodes.length) { - node.nodes.forEach(root => { - this.builder(root.raws.beforeStart, root, "beforeStart"); - this.stringify(root) - this.builder(root.raws.afterEnd, root, "afterEnd"); - }) + node.nodes.forEach((root) => { + this.builder(root.raws.beforeStart, root, 'beforeStart'); + this.stringify(root); + this.builder(root.raws.afterEnd, root, 'afterEnd'); + }); } else { this.builder(node.text, node); } + if (node.raws.ownSemicolon) { - this.builder(node.raws.ownSemicolon, node, "end"); + this.builder(node.raws.ownSemicolon, node, 'end'); } } -}; +} module.exports = TemplateStringifier; diff --git a/template-stringify.js b/template-stringify.js index ed7bb04..291e66e 100644 --- a/template-stringify.js +++ b/template-stringify.js @@ -1,7 +1,9 @@ -"use strict"; -const TemplateStringifier = require("./template-stringifier"); +'use strict'; -module.exports = function TemplateStringify (node, builder) { +const TemplateStringifier = require('./template-stringifier'); + +module.exports = function TemplateStringify(node, builder) { const str = new TemplateStringifier(builder); + str.stringify(node); }; diff --git a/template-tokenize.js b/template-tokenize.js index 5fa5b7b..0be6414 100644 --- a/template-tokenize.js +++ b/template-tokenize.js @@ -1,27 +1,34 @@ -"use strict"; -const tokenize = require("postcss/lib/tokenize"); +'use strict'; -function templateTokenize (input) { +const tokenize = require('postcss/lib/tokenize'); + +function templateTokenize(input) { let pos = input.quasis[0].start; - const quasis = input.quasis.filter(quasi => quasi.start !== quasi.end); + const quasis = input.quasis.filter((quasi) => quasi.start !== quasi.end); const tokenizer = tokenize.apply(this, arguments); - function tokenInExpressions (token, returned) { + function tokenInExpressions(token, returned) { const start = pos; + pos += token[1].length; - if (!quasis.some(quasi => start >= quasi.start && pos <= quasi.end) || (returned.length && token[0] === returned[0][0])) { + + if ( + !quasis.some((quasi) => start >= quasi.start && pos <= quasi.end) || + (returned.length && token[0] === returned[0][0]) + ) { return true; } else if (returned.length) { back(token); } } - function back (token) { + function back(token) { pos -= token[1].length; + return tokenizer.back.apply(tokenizer, arguments); } - function nextToken () { + function nextToken() { const args = arguments; const returned = []; let token; @@ -36,18 +43,21 @@ function templateTokenize (input) { column = token[5] || token[3] || column; returned.push(token); } + if (returned.length) { token = [ returned[0][0], - returned.map(token => token[1]).join(""), + returned.map((token) => token[1]).join(''), returned[0][2], returned[0][3], line, column, ]; } + return token; } + return Object.assign({}, tokenizer, { back, nextToken, diff --git a/test/camel-case.js b/test/camel-case.js index 5e7597e..8d72f31 100644 --- a/test/camel-case.js +++ b/test/camel-case.js @@ -1,69 +1,73 @@ -"use strict"; +'use strict'; -const expect = require("chai").expect; -const camelCase = require("../camel-case"); -const unCamelCase = require("../un-camel-case"); +const camelCase = require('../camel-case'); +const expect = require('chai').expect; +const unCamelCase = require('../un-camel-case'); const data = { - borderTopLeftRadius: "border-top-left-radius", - backgroundImage: "background-image", - xwebkitAnimation: "-xwebkit-animation", - webkitAnimation: "-webkit-animation", - epubAnimation: "-epub-animation", - mozAnimation: "-moz-animation", - msAnimation: "-ms-animation", - OAnimation: "-o-animation", - XAnimation: "-x-animation", - webkitApp: "-webkit-app", - onChange: "on-change", - OnChange: "-on-change", - overflowWrap: "overflow-wrap", - overflowX: "overflow-x", - zIndex: "z-index", - "::selection": "::selection", - "::mozSelection": "::-moz-selection", - "::mozSelection,::selection": "::-moz-selection,::selection", - "--margin-top": "--margin-top", - "margin--top": "margin--top", - "height: webkitCalc(2vh-20px);": "height: -webkit-calc(2vh-20px);", - "calc(2vh-20px)": "calc(2vh-20px)", - "calc(2vh--20px)": "calc(2vh--20px)", + borderTopLeftRadius: 'border-top-left-radius', + backgroundImage: 'background-image', + xwebkitAnimation: '-xwebkit-animation', + webkitAnimation: '-webkit-animation', + epubAnimation: '-epub-animation', + mozAnimation: '-moz-animation', + msAnimation: '-ms-animation', + OAnimation: '-o-animation', + XAnimation: '-x-animation', + webkitApp: '-webkit-app', + onChange: 'on-change', + OnChange: '-on-change', + overflowWrap: 'overflow-wrap', + overflowX: 'overflow-x', + zIndex: 'z-index', + '::selection': '::selection', + '::mozSelection': '::-moz-selection', + '::mozSelection,::selection': '::-moz-selection,::selection', + '--margin-top': '--margin-top', + 'margin--top': 'margin--top', + 'height: webkitCalc(2vh-20px);': 'height: -webkit-calc(2vh-20px);', + 'calc(2vh-20px)': 'calc(2vh-20px)', + 'calc(2vh--20px)': 'calc(2vh--20px)', }; -const testCases = Object.keys(data).map(prop => { +const testCases = Object.keys(data).map((prop) => { return { camel: prop, unCamel: data[prop], }; }); -const symbols = Array.from("@*:;\n,(){} "); +const symbols = Array.from('@*:;\n,(){} '); -describe("camelCase", () => { - testCases.forEach(testCase => { +describe('camelCase', () => { + testCases.forEach((testCase) => { it(`${testCase.unCamel} => ${testCase.camel}`, () => { expect(camelCase(testCase.unCamel)).to.equal(testCase.camel); }); }); - describe("symbols", () => { - symbols.forEach(symbol => { + describe('symbols', () => { + symbols.forEach((symbol) => { it(JSON.stringify(symbol), () => { - expect(camelCase(testCases.map(testCase => testCase.unCamel).join(symbol))).to.equal(testCases.map(testCase => testCase.camel).join(symbol)); + expect(camelCase(testCases.map((testCase) => testCase.unCamel).join(symbol))).to.equal( + testCases.map((testCase) => testCase.camel).join(symbol) + ); }); }); }); }); -describe("unCamelCase", () => { - testCases.forEach(testCase => { +describe('unCamelCase', () => { + testCases.forEach((testCase) => { it(`${testCase.camel} => ${testCase.unCamel}`, () => { expect(unCamelCase(testCase.camel)).to.equal(testCase.unCamel); }); }); - describe("symbols", () => { - symbols.forEach(symbol => { + describe('symbols', () => { + symbols.forEach((symbol) => { it(JSON.stringify(symbol), () => { - expect(unCamelCase(testCases.map(testCase => testCase.camel).join(symbol))).to.equal(testCases.map(testCase => testCase.unCamel).join(symbol)); + expect(unCamelCase(testCases.map((testCase) => testCase.camel).join(symbol))).to.equal( + testCases.map((testCase) => testCase.unCamel).join(symbol) + ); }); }); }); diff --git a/test/css-in-js.js b/test/css-in-js.js index 12684bc..addca1e 100644 --- a/test/css-in-js.js +++ b/test/css-in-js.js @@ -1,21 +1,22 @@ -"use strict"; - -const expect = require("chai").expect; -const postcss = require("postcss"); -const syntax = require("../"); -const autoprefixer = require("autoprefixer"); -const cases = require("postcss-parser-tests"); -const JSON5 = require("json5"); -const objectStringify = require("../object-stringify"); - -describe("CSS in JS", () => { - it("basic js", () => { - const document = syntax.parse("x().y(z => {});", { - from: "/fixtures/basic.js", +'use strict'; + +const autoprefixer = require('autoprefixer'); +const cases = require('postcss-parser-tests'); +const expect = require('chai').expect; +const JSON5 = require('json5'); +const objectStringify = require('../object-stringify'); +const postcss = require('postcss'); +const syntax = require('../'); + +describe('CSS in JS', () => { + it('basic js', () => { + const document = syntax.parse('x().y(z => {});', { + from: '/fixtures/basic.js', }); + expect(document.nodes).to.lengthOf(0); }); - it("glamorous", () => { + it('glamorous', () => { const code = ` import glm from 'glamorous'; const Component1 = glm.a({ @@ -35,72 +36,80 @@ describe("CSS in JS", () => { }, }); `; + return postcss([ autoprefixer({ - overrideBrowserslist: ["Chrome > 10"], + overrideBrowserslist: ['Chrome > 10'], }), - ]).process( - code, - { + ]) + .process(code, { syntax, - from: "/fixtures/glamorous-prefix.jsx", - } - ).then(result => { - expect(result.content).equal(out); - }); + from: '/fixtures/glamorous-prefix.jsx', + }) + .then((result) => { + expect(result.content).equal(out); + }); }); - describe("setter for object literals", () => { - it("decl.raws.prop.raw & decl.raws.value.raw", () => { - const decl = syntax.parse(` + describe('setter for object literals', () => { + it('decl.raws.prop.raw & decl.raws.value.raw', () => { + const decl = syntax.parse( + ` import glm from 'glamorous'; const Component1 = glm.a({ borderRadius: '5px' }); - `, { - from: "/fixtures/glamorous-atRule.jsx", - }).first.first.first; - decl.raws.prop.raw = "WebkitBorderRadius"; - expect(decl.prop).to.equal("-webkit-border-radius"); - decl.raws.value.raw = "15px"; - expect(decl.value).to.equal("15px"); + `, + { + from: '/fixtures/glamorous-atRule.jsx', + } + ).first.first.first; + + decl.raws.prop.raw = 'WebkitBorderRadius'; + expect(decl.prop).to.equal('-webkit-border-radius'); + decl.raws.value.raw = '15px'; + expect(decl.value).to.equal('15px'); }); - it("atRule.raws.params.raw", () => { - const atRule = syntax.parse(` + it('atRule.raws.params.raw', () => { + const atRule = syntax.parse( + ` import glm from 'glamorous'; const Component1 = glm.a({ '@media (maxWidth: 500px)': { borderRadius: '5px' } }); - `, { - from: "/fixtures/glamorous-atRule.jsx", - }).first.first.first; + `, + { + from: '/fixtures/glamorous-atRule.jsx', + } + ).first.first.first; + atRule.raws.params.raw = "(minWidth: ' + minWidth + ')"; expect(atRule.params).to.equal("(min-width: ' + minWidth + ')"); }); }); - it("empty object literals", () => { + it('empty object literals', () => { const code = ` import glm from 'glamorous'; const Component1 = glm.a({ }); `; const root = syntax.parse(code, { - from: "/fixtures/glamorous-empty-object-literals.jsx", + from: '/fixtures/glamorous-empty-object-literals.jsx', }); expect(root.toString()).to.equal(code); - root.first.first.raws.after = ""; + root.first.first.raws.after = ''; expect(root.toString()).to.equal(` import glm from 'glamorous'; const Component1 = glm.a({}); `); }); - it("float", () => { + it('float', () => { const code = ` import glm from 'glamorous'; const Component1 = glm.a({ @@ -109,9 +118,10 @@ describe("CSS in JS", () => { `; const root = syntax.parse(code, { - from: "/fixtures/glamorous-float.jsx", + from: '/fixtures/glamorous-float.jsx', }); - expect(root.first.first.first).to.haveOwnProperty("prop", "float"); + + expect(root.first.first.first).to.haveOwnProperty('prop', 'float'); expect(root.toString()).to.equal(` import glm from 'glamorous'; @@ -122,8 +132,8 @@ describe("CSS in JS", () => { root.first.first.nodes = [ postcss.decl({ - prop: "float", - value: "right", + prop: 'float', + value: 'right', raws: { before: root.first.first.first.raws.before, }, @@ -138,33 +148,36 @@ describe("CSS in JS", () => { `); }); - describe("objectify for css", () => { + describe('objectify for css', () => { cases.each((name, css) => { - if (name === "bom.css") return; - if (name === "custom-properties.css") return; + if (name === 'bom.css') return; - it("objectStringifier " + name, () => { + if (name === 'custom-properties.css') return; + + it('objectStringifier ' + name, () => { const root = postcss.parse(css); const jsSource = root.toString(objectStringify).trim(); - const jsonSource = "{\n" + jsSource.replace(/,$/, "").replace(/[\s;]+$/gm, "") + "\n}"; + const jsonSource = '{\n' + jsSource.replace(/,$/, '').replace(/[\s;]+$/gm, '') + '\n}'; + expect(JSON5.parse(jsonSource)).be.ok; }); }); }); - it("incomplete code", () => { - const filename = "fixtures/incomplete- react-native.mjs"; + it('incomplete code', () => { + const filename = 'fixtures/incomplete- react-native.mjs'; const code = [ `StyleSheet.create({ box: { padding: 10 }, text: { fontWeight: "bold" }, });`, - "styled.div`a{display: block}`", - ].join("\n"); + 'styled.div`a{display: block}`', + ].join('\n'); const document = syntax.parse(code, { from: filename, }); + expect(document.nodes).to.have.lengthOf(2); }); }); diff --git a/test/emotion.js b/test/emotion.js index 0b6cfe4..d82e89c 100644 --- a/test/emotion.js +++ b/test/emotion.js @@ -1,11 +1,12 @@ -"use strict"; -const expect = require("chai").expect; -const syntax = require("../"); -const fs = require("fs"); - -describe("javascript tests", () => { - it("react-emotion", () => { - const filename = require.resolve("./fixtures/react-emotion.jsx"); +'use strict'; + +const expect = require('chai').expect; +const fs = require('fs'); +const syntax = require('../'); + +describe('javascript tests', () => { + it('react-emotion', () => { + const filename = require.resolve('./fixtures/react-emotion.jsx'); let code = fs.readFileSync(filename); const document = syntax.parse(code, { @@ -17,27 +18,30 @@ describe("javascript tests", () => { expect(document.toString()).to.equal(code); expect(document.nodes).to.lengthOf(4); - document.nodes.forEach(root => { - expect(root.last.toString()).to.be.a("string"); - expect(root.source).to.haveOwnProperty("input"); + document.nodes.forEach((root) => { + expect(root.last.toString()).to.be.a('string'); + expect(root.source).to.haveOwnProperty('input'); expect(code).to.includes(root.source.input.css); expect(root.source.input.css.length).lessThan(code.length); - expect(root.source).to.haveOwnProperty("start").to.haveOwnProperty("line").to.greaterThan(1); + expect(root.source).to.haveOwnProperty('start').to.haveOwnProperty('line').to.greaterThan(1); - root.walk(node => { - expect(node).to.haveOwnProperty("source"); + root.walk((node) => { + expect(node).to.haveOwnProperty('source'); - expect(node.source).to.haveOwnProperty("input").to.haveOwnProperty("css").equal(root.source.input.css); + expect(node.source) + .to.haveOwnProperty('input') + .to.haveOwnProperty('css') + .equal(root.source.input.css); - expect(node.source).to.haveOwnProperty("start").to.haveOwnProperty("line"); - expect(node.source).to.haveOwnProperty("end").to.haveOwnProperty("line"); + expect(node.source).to.haveOwnProperty('start').to.haveOwnProperty('line'); + expect(node.source).to.haveOwnProperty('end').to.haveOwnProperty('line'); }); }); }); - it("emotion-10", () => { - const filename = require.resolve("./fixtures/emotion-10.jsx"); + it('emotion-10', () => { + const filename = require.resolve('./fixtures/emotion-10.jsx'); let code = fs.readFileSync(filename); const document = syntax.parse(code, { @@ -49,21 +53,24 @@ describe("javascript tests", () => { expect(document.toString()).to.equal(code); expect(document.nodes).to.lengthOf(6); - document.nodes.forEach(root => { - expect(root.last.toString()).to.be.a("string"); - expect(root.source).to.haveOwnProperty("input"); + document.nodes.forEach((root) => { + expect(root.last.toString()).to.be.a('string'); + expect(root.source).to.haveOwnProperty('input'); expect(code).to.includes(root.source.input.css); expect(root.source.input.css.length).lessThan(code.length); - expect(root.source).to.haveOwnProperty("start").to.haveOwnProperty("line").to.greaterThan(1); + expect(root.source).to.haveOwnProperty('start').to.haveOwnProperty('line').to.greaterThan(1); - root.walk(node => { - expect(node).to.haveOwnProperty("source"); + root.walk((node) => { + expect(node).to.haveOwnProperty('source'); - expect(node.source).to.haveOwnProperty("input").to.haveOwnProperty("css").equal(root.source.input.css); + expect(node.source) + .to.haveOwnProperty('input') + .to.haveOwnProperty('css') + .equal(root.source.input.css); - expect(node.source).to.haveOwnProperty("start").to.haveOwnProperty("line"); - expect(node.source).to.haveOwnProperty("end").to.haveOwnProperty("line"); + expect(node.source).to.haveOwnProperty('start').to.haveOwnProperty('line'); + expect(node.source).to.haveOwnProperty('end').to.haveOwnProperty('line'); }); }); }); diff --git a/test/glamorous.js b/test/glamorous.js index d70115f..48159d5 100644 --- a/test/glamorous.js +++ b/test/glamorous.js @@ -1,11 +1,12 @@ -"use strict"; -const expect = require("chai").expect; -const syntax = require("../"); -const fs = require("fs"); - -describe("javascript tests", () => { - it("glamorous", () => { - const filename = require.resolve("./fixtures/glamorous.jsx"); +'use strict'; + +const expect = require('chai').expect; +const fs = require('fs'); +const syntax = require('../'); + +describe('javascript tests', () => { + it('glamorous', () => { + const filename = require.resolve('./fixtures/glamorous.jsx'); let code = fs.readFileSync(filename); const document = syntax.parse(code, { @@ -17,20 +18,23 @@ describe("javascript tests", () => { expect(document.toString(syntax)).to.equal(code); expect(document.nodes).to.lengthOf(5); - document.nodes.forEach(root => { - expect(root.source).to.haveOwnProperty("input"); + document.nodes.forEach((root) => { + expect(root.source).to.haveOwnProperty('input'); expect(code).to.includes(root.source.input.css); expect(root.source.input.css.length).lessThan(code.length); - expect(root.source).to.haveOwnProperty("start").to.haveOwnProperty("line").to.greaterThan(1); + expect(root.source).to.haveOwnProperty('start').to.haveOwnProperty('line').to.greaterThan(1); - root.walk(node => { - expect(node).to.haveOwnProperty("source"); + root.walk((node) => { + expect(node).to.haveOwnProperty('source'); - expect(node.source).to.haveOwnProperty("input").to.haveOwnProperty("css").equal(root.source.input.css); + expect(node.source) + .to.haveOwnProperty('input') + .to.haveOwnProperty('css') + .equal(root.source.input.css); - expect(node.source).to.haveOwnProperty("start").to.haveOwnProperty("line"); - expect(node.source).to.haveOwnProperty("end").to.haveOwnProperty("line"); + expect(node.source).to.haveOwnProperty('start').to.haveOwnProperty('line'); + expect(node.source).to.haveOwnProperty('end').to.haveOwnProperty('line'); }); }); }); diff --git a/test/literals.js b/test/literals.js index b75cf9e..ae7a1a9 100644 --- a/test/literals.js +++ b/test/literals.js @@ -1,11 +1,12 @@ -"use strict"; -const expect = require("chai").expect; -const syntax = require("../"); -const fs = require("fs"); - -describe("template literals", () => { - it("template literals inside template literals", () => { - const file = require.resolve("./fixtures/tpl-in-tpl.mjs"); +'use strict'; + +const expect = require('chai').expect; +const fs = require('fs'); +const syntax = require('../'); + +describe('template literals', () => { + it('template literals inside template literals', () => { + const file = require.resolve('./fixtures/tpl-in-tpl.mjs'); let code = fs.readFileSync(file); const document = syntax.parse(code, { @@ -14,20 +15,23 @@ describe("template literals", () => { code = code.toString(); expect(document.toString()).to.equal(code); - expect(document.source).to.haveOwnProperty("lang", "jsx"); + expect(document.source).to.haveOwnProperty('lang', 'jsx'); expect(document.nodes).to.have.lengthOf(1); expect(document.first.nodes).to.have.lengthOf(1); document.first.nodes.forEach((decl) => { - expect(decl).have.property("type", "decl"); - expect(decl).have.property("prop", "border-bottom"); - expect(decl).have.property("value", "${(props) => (props.border ? `1px solid ${color}` : \"0\")}"); + expect(decl).have.property('type', 'decl'); + expect(decl).have.property('prop', 'border-bottom'); + expect(decl).have.property( + 'value', + '${(props) => (props.border ? `1px solid ${color}` : "0")}' + ); }); }); - it("multiline arrow function", () => { - const file = require.resolve("./fixtures/multiline-arrow-function.mjs"); + it('multiline arrow function', () => { + const file = require.resolve('./fixtures/multiline-arrow-function.mjs'); let code = fs.readFileSync(file); const document = syntax.parse(code, { @@ -36,16 +40,17 @@ describe("template literals", () => { code = code.toString(); expect(document.toString()).to.equal(code); - expect(document.source).to.haveOwnProperty("lang", "jsx"); + expect(document.source).to.haveOwnProperty('lang', 'jsx'); expect(document.nodes).to.have.lengthOf(1); expect(document.first.nodes).to.have.lengthOf(1); document.first.nodes.forEach((decl) => { - expect(decl).have.property("type", "decl"); - expect(decl).have.property("prop", "color"); + expect(decl).have.property('type', 'decl'); + expect(decl).have.property('prop', 'color'); expect(decl).have.property( - "value", + 'value', + // prettier-ignore [ "${(props) =>", "(props.status === \"signed\" && \"red\") ||", @@ -55,8 +60,8 @@ describe("template literals", () => { }); }); - it("interpolation as the only content of a component", () => { - const file = require.resolve("./fixtures/interpolation-content.mjs"); + it('interpolation as the only content of a component', () => { + const file = require.resolve('./fixtures/interpolation-content.mjs'); let code = fs.readFileSync(file); const document = syntax.parse(code, { @@ -65,45 +70,47 @@ describe("template literals", () => { code = code.toString(); expect(document.toString()).to.equal(code); - expect(document.source).to.haveOwnProperty("lang", "jsx"); + expect(document.source).to.haveOwnProperty('lang', 'jsx'); expect(document.nodes).to.have.lengthOf(9); document.nodes.forEach((root, i) => { switch (i) { case 0: { expect(root.nodes).to.have.lengthOf(1); - root.nodes.forEach(decl => { - expect(decl).have.property("type", "decl"); - expect(decl).have.property("prop", "display"); - expect(decl).have.property("value", "inline-block"); + root.nodes.forEach((decl) => { + expect(decl).have.property('type', 'decl'); + expect(decl).have.property('prop', 'display'); + expect(decl).have.property('value', 'inline-block'); }); + return; } case 1: case 2: { expect(root.nodes).to.have.lengthOf(2); - expect(root.first).have.property("type", "literal"); - expect(root.first).have.property("text", "${buttonStyles}"); - expect(root.last).have.property("type", "decl"); - expect(root.last).have.property("prop", "color"); - expect(root.last).have.property("value", "red"); + expect(root.first).have.property('type', 'literal'); + expect(root.first).have.property('text', '${buttonStyles}'); + expect(root.last).have.property('type', 'decl'); + expect(root.last).have.property('prop', 'color'); + expect(root.last).have.property('value', 'red'); + return; } case 3: case 4: { expect(root.nodes).to.have.lengthOf(2); - expect(root.first).have.property("type", "decl"); - expect(root.first).have.property("prop", "color"); - expect(root.first).have.property("value", "red"); - expect(root.last).have.property("type", "literal"); - expect(root.last).have.property("text", "${buttonStyles}"); + expect(root.first).have.property('type', 'decl'); + expect(root.first).have.property('prop', 'color'); + expect(root.first).have.property('value', 'red'); + expect(root.last).have.property('type', 'literal'); + expect(root.last).have.property('text', '${buttonStyles}'); } } }); }); - it("selector", () => { - const file = require.resolve("./fixtures/tpl-selector.mjs"); + it('selector', () => { + const file = require.resolve('./fixtures/tpl-selector.mjs'); let code = fs.readFileSync(file); const document = syntax.parse(code, { @@ -112,45 +119,52 @@ describe("template literals", () => { code = code.toString(); expect(document.toString()).to.equal(code); - expect(document.source).to.haveOwnProperty("lang", "jsx"); + expect(document.source).to.haveOwnProperty('lang', 'jsx'); expect(document.nodes).to.have.lengthOf(1); expect(document.first.nodes).to.have.lengthOf(6); - document.first.nodes.forEach(rule => { - expect(rule).to.have.property("type", "rule"); - expect(rule).to.have.property("selector"); + document.first.nodes.forEach((rule) => { + expect(rule).to.have.property('type', 'rule'); + expect(rule).to.have.property('selector'); expect(rule.selector).to.match(/(?:^|\s)\$\{selector\}(?=,|\s|$)/); }); }); - describe("decl", () => { - const file = require.resolve("./fixtures/tpl-decl.mjs"); + describe('decl', () => { + const file = require.resolve('./fixtures/tpl-decl.mjs'); const code = fs.readFileSync(file); - syntax.parse(code, { - from: file, - }).first.nodes.forEach(rule => { - it(rule.selector, () => { - expect(rule.nodes).to.have.lengthOf(1); - const decl = rule.first; - expect(decl).to.have.property( - "prop", - /\bprop\b/.test(rule.selector) - ? `${/\bprefix\b/.test(rule.selector) ? "prefix-" : ""}\${prop}${/\bsuffix\b/.test(rule.selector) ? "-suffix" : ""}` - : "prop" - ); - expect(decl).to.have.property( - "value", - /\bvalue\b/.test(rule.selector) - ? `${/\bprefix\b/.test(rule.selector) ? "prefix-" : ""}\${value}${/\bsuffix\b/.test(rule.selector) ? "-suffix" : ""}` - : "value" - ); + syntax + .parse(code, { + from: file, + }) + .first.nodes.forEach((rule) => { + it(rule.selector, () => { + expect(rule.nodes).to.have.lengthOf(1); + const decl = rule.first; + + expect(decl).to.have.property( + 'prop', + /\bprop\b/.test(rule.selector) + ? `${/\bprefix\b/.test(rule.selector) ? 'prefix-' : ''}\${prop}${ + /\bsuffix\b/.test(rule.selector) ? '-suffix' : '' + }` + : 'prop' + ); + expect(decl).to.have.property( + 'value', + /\bvalue\b/.test(rule.selector) + ? `${/\bprefix\b/.test(rule.selector) ? 'prefix-' : ''}\${value}${ + /\bsuffix\b/.test(rule.selector) ? '-suffix' : '' + }` + : 'value' + ); + }); }); - }); }); - it("non-literals", () => { - const file = require.resolve("./fixtures/tpl-special.mjs"); + it('non-literals', () => { + const file = require.resolve('./fixtures/tpl-special.mjs'); let code = fs.readFileSync(file); const document = syntax.parse(code, { @@ -159,30 +173,31 @@ describe("template literals", () => { code = code.toString(); expect(document.toString()).to.equal(code); - expect(document.source).to.haveOwnProperty("lang", "jsx"); + expect(document.source).to.haveOwnProperty('lang', 'jsx'); - document.walk(node => { - expect(node).to.have.property("type"); - expect(node.type).to.not.equal("literal"); + document.walk((node) => { + expect(node).to.have.property('type'); + expect(node.type).to.not.equal('literal'); }); }); - describe("template-safe-parse", () => { + describe('template-safe-parse', () => { [ - "./fixtures/tpl-in-tpl.mjs", - "./fixtures/multiline-arrow-function.mjs", - "./fixtures/interpolation-content.mjs", - "./fixtures/tpl-selector.mjs", - "./fixtures/tpl-decl.mjs", - "./fixtures/tpl-special.mjs", - ].map(file => { + './fixtures/tpl-in-tpl.mjs', + './fixtures/multiline-arrow-function.mjs', + './fixtures/interpolation-content.mjs', + './fixtures/tpl-selector.mjs', + './fixtures/tpl-decl.mjs', + './fixtures/tpl-special.mjs', + ].map((file) => { it(file, () => { file = require.resolve(file); const code = fs.readFileSync(file); + syntax({ - css: "safe-parser", + css: 'safe-parser', }).parse(code, { - from: "styled-safe-parse.js", + from: 'styled-safe-parse.js', }); }); }); diff --git a/test/non-style.js b/test/non-style.js index e0d9a4e..1f21896 100644 --- a/test/non-style.js +++ b/test/non-style.js @@ -1,18 +1,20 @@ -"use strict"; -const spawnSync = require("child_process").spawnSync; -const fs = require("fs"); -const files = spawnSync("git", ["ls-files"], { encoding: "utf8" }).stdout.match(/^.+\.js$/gm); -const syntax = require("../"); -const expect = require("chai").expect; +'use strict'; -describe("not throw error for non-style js file", () => { - files.forEach(file => { +const fs = require('fs'); +const spawnSync = require('child_process').spawnSync; +const files = spawnSync('git', ['ls-files'], { encoding: 'utf8' }).stdout.match(/^.+\.js$/gm); +const expect = require('chai').expect; +const syntax = require('../'); + +describe('not throw error for non-style js file', () => { + files.forEach((file) => { it(file, () => { const code = fs.readFileSync(file); const document = syntax.parse(code, { from: file, }); - expect(document.source).to.haveOwnProperty("lang", "jsx"); + + expect(document.source).to.haveOwnProperty('lang', 'jsx'); expect(document.toString()).to.equal(code.toString()); }); }); diff --git a/test/react-native.js b/test/react-native.js index fba78ee..f18c671 100644 --- a/test/react-native.js +++ b/test/react-native.js @@ -1,11 +1,12 @@ -"use strict"; -const expect = require("chai").expect; -const syntax = require("../"); -const fs = require("fs"); - -describe("react-native", () => { - it("StyleSheet", () => { - const filename = require.resolve("./fixtures/react-native.mjs"); +'use strict'; + +const expect = require('chai').expect; +const fs = require('fs'); +const syntax = require('../'); + +describe('react-native', () => { + it('StyleSheet', () => { + const filename = require.resolve('./fixtures/react-native.mjs'); let code = fs.readFileSync(filename); const document = syntax.parse(code, { @@ -18,25 +19,28 @@ describe("react-native", () => { expect(document.nodes).to.lengthOf(1); expect(document.first.nodes).to.lengthOf(1); expect(document.first.first.nodes).to.lengthOf(2); - expect(document.first.first.first).to.haveOwnProperty("type", "rule"); - expect(document.first.first.first).to.haveOwnProperty("selector", "box"); - expect(document.first.first.last).to.haveOwnProperty("type", "rule"); - expect(document.first.first.last).to.haveOwnProperty("selector", "text"); + expect(document.first.first.first).to.haveOwnProperty('type', 'rule'); + expect(document.first.first.first).to.haveOwnProperty('selector', 'box'); + expect(document.first.first.last).to.haveOwnProperty('type', 'rule'); + expect(document.first.first.last).to.haveOwnProperty('selector', 'text'); - document.nodes.forEach(root => { - expect(root.source).to.haveOwnProperty("input"); + document.nodes.forEach((root) => { + expect(root.source).to.haveOwnProperty('input'); expect(code).to.includes(root.source.input.css); expect(root.source.input.css.length).lessThan(code.length); - expect(root.source).to.haveOwnProperty("start").to.haveOwnProperty("line").to.greaterThan(1); + expect(root.source).to.haveOwnProperty('start').to.haveOwnProperty('line').to.greaterThan(1); - root.walk(node => { - expect(node).to.haveOwnProperty("source"); + root.walk((node) => { + expect(node).to.haveOwnProperty('source'); - expect(node.source).to.haveOwnProperty("input").to.haveOwnProperty("css").equal(root.source.input.css); + expect(node.source) + .to.haveOwnProperty('input') + .to.haveOwnProperty('css') + .equal(root.source.input.css); - expect(node.source).to.haveOwnProperty("start").to.haveOwnProperty("line"); - expect(node.source).to.haveOwnProperty("end").to.haveOwnProperty("line"); + expect(node.source).to.haveOwnProperty('start').to.haveOwnProperty('line'); + expect(node.source).to.haveOwnProperty('end').to.haveOwnProperty('line'); }); }); }); diff --git a/test/react.js b/test/react.js index ccf0ae0..96a7fba 100644 --- a/test/react.js +++ b/test/react.js @@ -1,9 +1,10 @@ -"use strict"; -const expect = require("chai").expect; -const syntax = require("../"); +'use strict'; -describe("react", () => { - it("first line indentation handle", () => { +const expect = require('chai').expect; +const syntax = require('../'); + +describe('react', () => { + it('first line indentation handle', () => { const code = ` export default { - it("basic", () => { - const file = require.resolve("./fixtures/styled-components"); +'use strict'; + +const expect = require('chai').expect; +const fs = require('fs'); +const syntax = require('../'); + +describe('styled-components', () => { + it('basic', () => { + const file = require.resolve('./fixtures/styled-components'); let code = fs.readFileSync(file); const document = syntax.parse(code, { @@ -14,67 +15,75 @@ describe("styled-components", () => { code = code.toString(); expect(document.toString()).to.equal(code); - expect(document.source).to.haveOwnProperty("lang", "jsx"); + expect(document.source).to.haveOwnProperty('lang', 'jsx'); expect(document.nodes).to.have.lengthOf(1); expect(document.first.nodes).to.have.lengthOf(8); - const lines = code.match(/^.+$/gm).slice(3).map(line => (line.replace(/^\s*(.+?);?\s*$/, "$1"))); + const lines = code + .match(/^.+$/gm) + .slice(3) + .map((line) => line.replace(/^\s*(.+?);?\s*$/, '$1')); + document.first.nodes.forEach((decl, i) => { if (i) { - expect(decl).to.have.property("type", "decl"); + expect(decl).to.have.property('type', 'decl'); } else { - expect(decl).to.have.property("type", "comment"); + expect(decl).to.have.property('type', 'comment'); } + expect(decl.toString()).to.equal(lines[i]); }); }); - it("interpolation with css template literal", () => { + it('interpolation with css template literal', () => { const code = [ "import styled, { css } from 'styled-components';", - "const Message = styled.p`", - " padding: 10px;", + 'const Message = styled.p`', + ' padding: 10px;', - " ${css`", - " color: #b02d00;", - " `}", - "`;", - ].join("\n"); + ' ${css`', + ' color: #b02d00;', + ' `}', + '`;', + ].join('\n'); const document = syntax.parse(code, { from: undefined, }); + expect(document.toString()).to.equal(code); - expect(document.source).to.haveOwnProperty("lang", "jsx"); + expect(document.source).to.haveOwnProperty('lang', 'jsx'); expect(document.nodes).to.have.lengthOf(1); }); - it("interpolation with two css template literals", () => { + it('interpolation with two css template literals', () => { const code = [ "import styled, { css } from 'styled-components';", - "const Message = styled.p`", - " padding: 10px;", + 'const Message = styled.p`', + ' padding: 10px;', - " ${(props) => css`", - " color: #b02d00;", - " `}", + ' ${(props) => css`', + ' color: #b02d00;', + ' `}', - " ${(props2) => css`", - " border-color: red;", - " `}", - "`;", - ].join("\n"); + ' ${(props2) => css`', + ' border-color: red;', + ' `}', + '`;', + ].join('\n'); const document = syntax.parse(code, { from: undefined, }); + expect(document.toString()).to.equal(code); - expect(document.source).to.haveOwnProperty("lang", "jsx"); + expect(document.source).to.haveOwnProperty('lang', 'jsx'); expect(document.nodes).to.have.lengthOf(1); }); - it("empty template literal", () => { + it('empty template literal', () => { + // prettier-ignore const code = [ "function test() {", " alert`debug`", @@ -83,52 +92,58 @@ describe("styled-components", () => { "", ].join("\n"); const document = syntax.parse(code, { - from: "empty_template_literal.js", + from: 'empty_template_literal.js', }); + expect(document.toString()).to.equal(code); - expect(document.source).to.haveOwnProperty("lang", "jsx"); + expect(document.source).to.haveOwnProperty('lang', 'jsx'); expect(document.nodes).to.have.lengthOf(0); }); - it("skip javascript syntax error", () => { - const code = "\\`"; + it('skip javascript syntax error', () => { + const code = '\\`'; const document = syntax.parse(code, { - from: "syntax_error.js", + from: 'syntax_error.js', }); + expect(document.toString()).to.equal(code); - expect(document.source).to.haveOwnProperty("lang", "jsx"); + expect(document.source).to.haveOwnProperty('lang', 'jsx'); expect(document.nodes).to.have.lengthOf(0); }); - it("skip @babel/traverse error", () => { - const code = "let a;let a"; + it('skip @babel/traverse error', () => { + const code = 'let a;let a'; const document = syntax.parse(code, { - from: "traverse_error.js", + from: 'traverse_error.js', }); + expect(document.toString()).to.equal(code); - expect(document.source).to.haveOwnProperty("lang", "jsx"); + expect(document.source).to.haveOwnProperty('lang', 'jsx'); expect(document.nodes).to.have.lengthOf(0); }); - it("illegal template literal", () => { + it('illegal template literal', () => { + // prettier-ignore const code = [ "const styled = require(\"styled-components\");", "styled.div`$\n{display: block}\n${g} {}`", ].join("\n"); const document = syntax.parse(code, { - from: "illegal_template_literal.js", + from: 'illegal_template_literal.js', }); + expect(document.toString()).to.equal(code); - expect(document.source).to.haveOwnProperty("lang", "jsx"); + expect(document.source).to.haveOwnProperty('lang', 'jsx'); expect(document.nodes).to.have.lengthOf(1); expect(document.first.nodes).to.have.lengthOf(2); - expect(document.first.first).have.property("type", "rule"); - expect(document.first.first).have.property("selector", "$"); - expect(document.last.last).have.property("type", "rule"); - expect(document.last.last).have.property("selector", "${g}"); + expect(document.first.first).have.property('type', 'rule'); + expect(document.first.first).have.property('selector', '$'); + expect(document.last.last).have.property('type', 'rule'); + expect(document.last.last).have.property('selector', '${g}'); }); - it("styled.img", () => { + it('styled.img', () => { + // prettier-ignore const code = [ "const styled = require(\"styled-components\");", "const Image1 = styled.img.attrs({ src: 'url' })`", @@ -138,12 +153,14 @@ describe("styled-components", () => { "`;", ].join("\n"); const root = syntax.parse(code, { - from: "styled.img.js", + from: 'styled.img.js', }); + expect(root.toString()).to.equal(code); }); - it("throw CSS syntax error", () => { + it('throw CSS syntax error', () => { + // prettier-ignore const code = [ "const styled = require(\"styled-components\");", "styled.div`a{`;", @@ -151,107 +168,125 @@ describe("styled-components", () => { expect(() => { syntax.parse(code, { - from: "css_syntax_error.js", + from: 'css_syntax_error.js', }); - }).to.throw("css_syntax_error.js:2:12: Unclosed block"); + }).to.throw('css_syntax_error.js:2:12: Unclosed block'); }); - it("not skip empty template literal", () => { + it('not skip empty template literal', () => { + // prettier-ignore const code = [ "const styled = require(\"styled-components\");", "styled.div``;", ].join("\n"); const root = syntax.parse(code, { - from: "empty_template_literal.js", + from: 'empty_template_literal.js', }); + expect(root.toString()).to.equal(code); expect(root.nodes).to.have.lengthOf(1); }); - it("fix CSS syntax error", () => { + it('fix CSS syntax error', () => { + // prettier-ignore const code = [ "const styled = require(\"styled-components\");", "styled.div`a{`;", ].join("\n"); const document = syntax({ - css: "safe-parser", + css: 'safe-parser', }).parse(code, { - from: "postcss-safe-parser.js", + from: 'postcss-safe-parser.js', }); + + // prettier-ignore expect(document.toString()).to.equal([ "const styled = require(\"styled-components\");", "styled.div`a{}`;", ].join("\n")); - expect(document.source).to.haveOwnProperty("lang", "jsx"); + expect(document.source).to.haveOwnProperty('lang', 'jsx'); expect(document.nodes).to.have.lengthOf(1); expect(document.first.nodes).to.have.lengthOf(1); - expect(document.first.first).have.property("type", "rule"); - expect(document.first.first).have.property("selector", "a"); + expect(document.first.first).have.property('type', 'rule'); + expect(document.first.first).have.property('selector', 'a'); }); - it("fix styled syntax error", () => { + it('fix styled syntax error', () => { + // prettier-ignore const code = [ "const styled = require(\"styled-components\");", "styled.div`${ a } {`", ].join("\n"); const document = syntax({ - css: "safe-parser", + css: 'safe-parser', }).parse(code, { - from: "styled-safe-parse.js", + from: 'styled-safe-parse.js', }); + + // prettier-ignore expect(document.toString()).to.equal([ "const styled = require(\"styled-components\");", "styled.div`${ a } {}`", ].join("\n")); - expect(document.source).to.haveOwnProperty("lang", "jsx"); + expect(document.source).to.haveOwnProperty('lang', 'jsx'); expect(document.nodes).to.have.lengthOf(1); expect(document.first.nodes).to.have.lengthOf(1); - expect(document.first.first).have.property("type", "rule"); - expect(document.first.first).have.property("selector", "${ a }"); + expect(document.first.first).have.property('type', 'rule'); + expect(document.first.first).have.property('selector', '${ a }'); }); - it("template literal in prop", () => { + it('template literal in prop', () => { + // prettier-ignore const code = [ "const styled = require(\"styled-components\");", "styled.div`margin-${/* sc-custom 'left' */ rtlSwitch}: 12.5px;`", ].join("\n"); const document = syntax.parse(code, { - from: "template_literal_in_prop.js", + from: 'template_literal_in_prop.js', }); + expect(document.toString()).to.equal(code); - expect(document.source).to.haveOwnProperty("lang", "jsx"); + expect(document.source).to.haveOwnProperty('lang', 'jsx'); expect(document.nodes).to.have.lengthOf(1); - expect(document.first.first).to.haveOwnProperty("prop", "margin-${/* sc-custom 'left' */ rtlSwitch}"); + expect(document.first.first).to.haveOwnProperty( + 'prop', + "margin-${/* sc-custom 'left' */ rtlSwitch}" + ); }); - it("lazy assignment", () => { + it('lazy assignment', () => { + // prettier-ignore const code = [ "let myDiv;", "myDiv = require(\"styled-components\").div;", "myDiv`a{}`;", ].join("\n"); const document = syntax.parse(code, { - from: "lazy_assign.js", + from: 'lazy_assign.js', }); + expect(document.toString()).to.equal(code); - expect(document.source).to.haveOwnProperty("lang", "jsx"); + expect(document.source).to.haveOwnProperty('lang', 'jsx'); expect(document.nodes).to.have.lengthOf(1); }); - it("lazy assignment without init", () => { + it('lazy assignment without init', () => { + // prettier-ignore const code = [ "myDiv = require(\"styled-components\").div;", "myDiv`a{}`;", ].join("\n"); const document = syntax.parse(code, { - from: "lazy_assign_no_init.js", + from: 'lazy_assign_no_init.js', }); + expect(document.toString()).to.equal(code); - expect(document.source).to.haveOwnProperty("lang", "jsx"); + expect(document.source).to.haveOwnProperty('lang', 'jsx'); expect(document.nodes).to.have.lengthOf(1); }); - it("array destructuring assignment", () => { + it('array destructuring assignment', () => { + // prettier-ignore const code = [ "const [", "\tstyledDiv,", @@ -260,14 +295,16 @@ describe("styled-components", () => { "styledDiv`a{}`;", ].join("\n"); const document = syntax.parse(code, { - from: "arr_destructuring.js", + from: 'arr_destructuring.js', }); + expect(document.toString()).to.equal(code); - expect(document.source).to.haveOwnProperty("lang", "jsx"); + expect(document.source).to.haveOwnProperty('lang', 'jsx'); expect(document.nodes).to.have.lengthOf(1); }); - it("object destructuring assignment", () => { + it('object destructuring assignment', () => { + // prettier-ignore const code = [ "const {", "\t// commit", @@ -280,10 +317,11 @@ describe("styled-components", () => { "a`a{}`;", ].join("\n"); const document = syntax.parse(code, { - from: "obj_destructuring.js", + from: 'obj_destructuring.js', }); + expect(document.toString()).to.equal(code); - expect(document.source).to.haveOwnProperty("lang", "jsx"); + expect(document.source).to.haveOwnProperty('lang', 'jsx'); expect(document.nodes).to.have.lengthOf(3); }); }); diff --git a/test/supports.js b/test/supports.js index 6280237..daf60b4 100644 --- a/test/supports.js +++ b/test/supports.js @@ -1,15 +1,17 @@ -"use strict"; -const fs = require("fs"); -const path = require("path"); -const expect = require("chai").expect; -const syntax = require("../"); +'use strict'; -function clean (node) { +const expect = require('chai').expect; +const fs = require('fs'); +const path = require('path'); +const syntax = require('../'); + +function clean(node) { if (node.raws) { delete node.raws.node; delete node.raws.beforeStart; delete node.raws.afterEnd; } + if (node.source) { delete node.source.opts; delete node.source.input.css; @@ -18,51 +20,56 @@ function clean (node) { delete node.source.input.templateLiteralStyles; node.source.input.file = path.basename(node.source.input.file); } + delete node.indexes; delete node.lastEach; delete node.rawCache; delete node.document; + if (node.nodes) { node.nodes = node.nodes.map(clean); - }; + } + return node; } -describe("should support for each CSS in JS package", () => { +describe('should support for each CSS in JS package', () => { [ - "emotion-10.jsx", - "glamorous.jsx", - "interpolation-content.mjs", - "jsx.jsx", - "lit-css.mjs", - "react-emotion.jsx", - "react-native.mjs", - "styled-components-nesting.js", - "styled-components-nesting2.js", - "styled-components-nesting3.js", - "styled-components-nesting-nesting.js", - "styled-components-nesting-template-literal.js", - "styled-components.js", - "styled-opts.mjs", - "styled-props.jsx", - "tpl-decl.mjs", - "tpl-in-tpl.mjs", - "tpl-selector.mjs", - "tpl-special.mjs", - "material-ui.jsx", - ].forEach(file => { + 'emotion-10.jsx', + 'glamorous.jsx', + 'interpolation-content.mjs', + 'jsx.jsx', + 'lit-css.mjs', + 'react-emotion.jsx', + 'react-native.mjs', + 'styled-components-nesting.js', + 'styled-components-nesting2.js', + 'styled-components-nesting3.js', + 'styled-components-nesting-nesting.js', + 'styled-components-nesting-template-literal.js', + 'styled-components.js', + 'styled-opts.mjs', + 'styled-props.jsx', + 'tpl-decl.mjs', + 'tpl-in-tpl.mjs', + 'tpl-selector.mjs', + 'tpl-special.mjs', + 'material-ui.jsx', + ].forEach((file) => { it(file, () => { - file = require.resolve("./fixtures/" + file); + file = require.resolve('./fixtures/' + file); const code = fs.readFileSync(file); const document = syntax.parse(code, { from: file, }); - expect(document.source).to.haveOwnProperty("lang", "jsx"); + + expect(document.source).to.haveOwnProperty('lang', 'jsx'); expect(document.toString()).to.equal(code.toString()); expect(document.nodes.length).to.greaterThan(0); - const parsed = JSON.stringify(clean(document), 0, "\t"); + const parsed = JSON.stringify(clean(document), 0, '\t'); + // fs.writeFileSync(file + ".json", parsed + "\n"); - expect(parsed).to.equal(fs.readFileSync(file + ".json", "utf8").trim()); + expect(parsed).to.equal(fs.readFileSync(file + '.json', 'utf8').trim()); }); }); }); diff --git a/un-camel-case.js b/un-camel-case.js index e236031..494e49b 100644 --- a/un-camel-case.js +++ b/un-camel-case.js @@ -1,16 +1,13 @@ -"use strict"; -function unCamelCase (str) { - return str.replace(/[\w-]+/g, (s) => ( +'use strict'; + +function unCamelCase(str) { + return str.replace(/[\w-]+/g, (s) => /^[A-Z]?[a-z]*(?:[A-Z][a-z]*)+$/.test(s) - ? s.replace( - /[A-Z]/g, - s => "-" + s.toLowerCase() - ).replace( - /^(o|ms|moz|khtml|epub|(\w+-?)*webkit)(?=-)/i, - "-$1" - ) + ? s + .replace(/[A-Z]/g, (s) => '-' + s.toLowerCase()) + .replace(/^(o|ms|moz|khtml|epub|(\w+-?)*webkit)(?=-)/i, '-$1') : s - )); + ); } module.exports = unCamelCase; From 5fba90bd19736c56ea1fc62baaef639e5a0e612e Mon Sep 17 00:00:00 2001 From: yosuke ota Date: Sat, 4 Apr 2020 21:38:33 +0900 Subject: [PATCH 2/5] moved the eslint configuration to package.json. --- .eslintignore | 3 --- .eslintrc.js | 9 --------- package.json | 17 ++++++++++++++++- 3 files changed, 16 insertions(+), 13 deletions(-) delete mode 100644 .eslintignore delete mode 100644 .eslintrc.js diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index c371cd1..0000000 --- a/.eslintignore +++ /dev/null @@ -1,3 +0,0 @@ -test/fixtures/* -coverage/** -.nyc_output/** diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index 69d86f3..0000000 --- a/.eslintrc.js +++ /dev/null @@ -1,9 +0,0 @@ -module.exports = { - parserOptions: { - ecmaVersion: 2019, - }, - extends: ['stylelint', 'prettier'], - rules: { - 'jest/valid-expect': 'off', - }, -}; diff --git a/package.json b/package.json index b473ea5..ae906a2 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,7 @@ "lint:formatting": "prettier . --check", "lint:js": "eslint .", "lint": "npm-run-all --parallel lint:*", + "pretest": "npm run lint", "mocha": "mocha --no-timeouts", "test": "nyc npm run mocha", "debug": "npm run mocha -- --inspect-brk", @@ -82,5 +83,19 @@ "lint-staged": { "*.js": "eslint --cache --fix", "*.{js,md,yml}": "prettier --write" - } + }, + "eslintConfig": { + "extends": [ + "stylelint", + "prettier" + ], + "rules": { + "jest/valid-expect": "off" + } + }, + "eslintIgnore": [ + "test/fixtures/*", + "coverage/**", + ".nyc_output/**" + ] } From 3cc8e841c0b5d09c58d117296ec64e917626042e Mon Sep 17 00:00:00 2001 From: yosuke ota Date: Sat, 4 Apr 2020 22:15:34 +0900 Subject: [PATCH 3/5] Update trailingComma to "all" and add npm scripts for "format" and "watch" --- .prettierrc.js | 2 +- camel-case.js | 2 +- extract.js | 6 +++--- object-parser.js | 4 ++-- package.json | 5 +++++ template-parser-helper.js | 8 ++++---- test/camel-case.js | 4 ++-- test/css-in-js.js | 4 ++-- test/literals.js | 8 ++++---- test/styled-components.js | 2 +- un-camel-case.js | 2 +- 11 files changed, 26 insertions(+), 21 deletions(-) diff --git a/.prettierrc.js b/.prettierrc.js index 7bf6349..e363eeb 100644 --- a/.prettierrc.js +++ b/.prettierrc.js @@ -6,7 +6,7 @@ module.exports = { endOfLine: 'lf', printWidth: 100, singleQuote: true, - trailingComma: 'es5', + trailingComma: 'all', useTabs: true, overrides: [ { diff --git a/camel-case.js b/camel-case.js index e5f2f89..1015d1a 100644 --- a/camel-case.js +++ b/camel-case.js @@ -6,7 +6,7 @@ function camelCase(str) { ? s .replace(/^-(ms|moz|khtml|epub|(\w+-?)*webkit)(?=-)/i, '$1') .replace(/-\w/g, (s) => s[1].toUpperCase()) - : s + : s, ); } diff --git a/extract.js b/extract.js index dec7dcb..4a7e15b 100644 --- a/extract.js +++ b/extract.js @@ -206,7 +206,7 @@ function literalParser(source, opts, styles) { nameSpace .shift() .replace(/^\W+/, '') - .split(/[/\\]+/g) + .split(/[/\\]+/g), ); if (types.isIdentifier(id)) { @@ -432,8 +432,8 @@ function literalParser(source, opts, styles) { (targetStyle) => targetStyle.opts && targetStyle.opts.expressions.some( - (expr) => expr.start <= style.startIndex && style.endIndex < expr.end - ) + (expr) => expr.start <= style.startIndex && style.endIndex < expr.end, + ), ); if (target) { diff --git a/object-parser.js b/object-parser.js index 7841e2d..bf58f8c 100644 --- a/object-parser.js +++ b/object-parser.js @@ -48,7 +48,7 @@ function defineRaws(node, prop, prefix, suffix, props) { prefix, suffix, }, - props + props, ); } @@ -85,7 +85,7 @@ class objectParser { let before = root.source.input.css.slice( startNode.start - startNode.loc.start.column, - startNode.start + startNode.start, ); if (/^\s+$/.test(before)) { diff --git a/package.json b/package.json index ae906a2..ab7ebd0 100644 --- a/package.json +++ b/package.json @@ -36,12 +36,14 @@ ] }, "scripts": { + "format": "prettier . --write", "lint:formatting": "prettier . --check", "lint:js": "eslint .", "lint": "npm-run-all --parallel lint:*", "pretest": "npm run lint", "mocha": "mocha --no-timeouts", "test": "nyc npm run mocha", + "watch": "mocha --watch", "debug": "npm run mocha -- --inspect-brk", "release": "np" }, @@ -85,6 +87,9 @@ "*.{js,md,yml}": "prettier --write" }, "eslintConfig": { + "parserOptions": { + "ecmaVersion": 2019 + }, "extends": [ "stylelint", "prettier" diff --git a/template-parser-helper.js b/template-parser-helper.js index 5f0cb42..a9fe6f6 100644 --- a/template-parser-helper.js +++ b/template-parser-helper.js @@ -48,7 +48,7 @@ function literal(start) { const start = offset + nodeIndex; const end = start + node.text.length; const templateLiteralStyles = input.templateLiteralStyles.filter( - (style) => style.startIndex <= end && start < style.endIndex + (style) => style.startIndex <= end && start < style.endIndex, ); if (templateLiteralStyles.length) { @@ -167,7 +167,7 @@ class LocalFixer { this.object(error.input); error.message = error.message.replace( /:\d+:\d+:/, - ':' + error.line + ':' + error.column + ':' + ':' + error.line + ':' + error.column + ':', ); } @@ -187,8 +187,8 @@ class LocalFixer { { map: false, }, - style.opts - ) + style.opts, + ), ); } catch (error) { if (style.ignoreErrors) { diff --git a/test/camel-case.js b/test/camel-case.js index 8d72f31..de1e0e7 100644 --- a/test/camel-case.js +++ b/test/camel-case.js @@ -49,7 +49,7 @@ describe('camelCase', () => { symbols.forEach((symbol) => { it(JSON.stringify(symbol), () => { expect(camelCase(testCases.map((testCase) => testCase.unCamel).join(symbol))).to.equal( - testCases.map((testCase) => testCase.camel).join(symbol) + testCases.map((testCase) => testCase.camel).join(symbol), ); }); }); @@ -66,7 +66,7 @@ describe('unCamelCase', () => { symbols.forEach((symbol) => { it(JSON.stringify(symbol), () => { expect(unCamelCase(testCases.map((testCase) => testCase.camel).join(symbol))).to.equal( - testCases.map((testCase) => testCase.unCamel).join(symbol) + testCases.map((testCase) => testCase.unCamel).join(symbol), ); }); }); diff --git a/test/css-in-js.js b/test/css-in-js.js index addca1e..59bed7b 100644 --- a/test/css-in-js.js +++ b/test/css-in-js.js @@ -62,7 +62,7 @@ describe('CSS in JS', () => { `, { from: '/fixtures/glamorous-atRule.jsx', - } + }, ).first.first.first; decl.raws.prop.raw = 'WebkitBorderRadius'; @@ -82,7 +82,7 @@ describe('CSS in JS', () => { `, { from: '/fixtures/glamorous-atRule.jsx', - } + }, ).first.first.first; atRule.raws.params.raw = "(minWidth: ' + minWidth + ')"; diff --git a/test/literals.js b/test/literals.js index ae7a1a9..c71c08c 100644 --- a/test/literals.js +++ b/test/literals.js @@ -25,7 +25,7 @@ describe('template literals', () => { expect(decl).have.property('prop', 'border-bottom'); expect(decl).have.property( 'value', - '${(props) => (props.border ? `1px solid ${color}` : "0")}' + '${(props) => (props.border ? `1px solid ${color}` : "0")}', ); }); }); @@ -55,7 +55,7 @@ describe('template literals', () => { "${(props) =>", "(props.status === \"signed\" && \"red\") ||", "\"blue\"}", - ].join("\n\t\t") + ].join("\n\t\t"), ); }); }); @@ -149,7 +149,7 @@ describe('template literals', () => { ? `${/\bprefix\b/.test(rule.selector) ? 'prefix-' : ''}\${prop}${ /\bsuffix\b/.test(rule.selector) ? '-suffix' : '' }` - : 'prop' + : 'prop', ); expect(decl).to.have.property( 'value', @@ -157,7 +157,7 @@ describe('template literals', () => { ? `${/\bprefix\b/.test(rule.selector) ? 'prefix-' : ''}\${value}${ /\bsuffix\b/.test(rule.selector) ? '-suffix' : '' }` - : 'value' + : 'value', ); }); }); diff --git a/test/styled-components.js b/test/styled-components.js index d2b2021..7e84bc2 100644 --- a/test/styled-components.js +++ b/test/styled-components.js @@ -250,7 +250,7 @@ describe('styled-components', () => { expect(document.nodes).to.have.lengthOf(1); expect(document.first.first).to.haveOwnProperty( 'prop', - "margin-${/* sc-custom 'left' */ rtlSwitch}" + "margin-${/* sc-custom 'left' */ rtlSwitch}", ); }); diff --git a/un-camel-case.js b/un-camel-case.js index 494e49b..f960bb9 100644 --- a/un-camel-case.js +++ b/un-camel-case.js @@ -6,7 +6,7 @@ function unCamelCase(str) { ? s .replace(/[A-Z]/g, (s) => '-' + s.toLowerCase()) .replace(/^(o|ms|moz|khtml|epub|(\w+-?)*webkit)(?=-)/i, '-$1') - : s + : s, ); } From 7f4932a49d442415800095a174a09362f029fa00 Mon Sep 17 00:00:00 2001 From: yosuke ota Date: Sat, 4 Apr 2020 22:27:09 +0900 Subject: [PATCH 4/5] Remove trailingComma from .prettierrc.js --- .prettierrc.js | 1 - camel-case.js | 2 +- extract.js | 6 +++--- object-parser.js | 4 ++-- package.json | 3 --- template-parser-helper.js | 8 ++++---- test/camel-case.js | 4 ++-- test/css-in-js.js | 4 ++-- test/literals.js | 8 ++++---- test/styled-components.js | 2 +- un-camel-case.js | 2 +- 11 files changed, 20 insertions(+), 24 deletions(-) diff --git a/.prettierrc.js b/.prettierrc.js index e363eeb..f18f72a 100644 --- a/.prettierrc.js +++ b/.prettierrc.js @@ -6,7 +6,6 @@ module.exports = { endOfLine: 'lf', printWidth: 100, singleQuote: true, - trailingComma: 'all', useTabs: true, overrides: [ { diff --git a/camel-case.js b/camel-case.js index 1015d1a..e5f2f89 100644 --- a/camel-case.js +++ b/camel-case.js @@ -6,7 +6,7 @@ function camelCase(str) { ? s .replace(/^-(ms|moz|khtml|epub|(\w+-?)*webkit)(?=-)/i, '$1') .replace(/-\w/g, (s) => s[1].toUpperCase()) - : s, + : s ); } diff --git a/extract.js b/extract.js index 4a7e15b..dec7dcb 100644 --- a/extract.js +++ b/extract.js @@ -206,7 +206,7 @@ function literalParser(source, opts, styles) { nameSpace .shift() .replace(/^\W+/, '') - .split(/[/\\]+/g), + .split(/[/\\]+/g) ); if (types.isIdentifier(id)) { @@ -432,8 +432,8 @@ function literalParser(source, opts, styles) { (targetStyle) => targetStyle.opts && targetStyle.opts.expressions.some( - (expr) => expr.start <= style.startIndex && style.endIndex < expr.end, - ), + (expr) => expr.start <= style.startIndex && style.endIndex < expr.end + ) ); if (target) { diff --git a/object-parser.js b/object-parser.js index bf58f8c..7841e2d 100644 --- a/object-parser.js +++ b/object-parser.js @@ -48,7 +48,7 @@ function defineRaws(node, prop, prefix, suffix, props) { prefix, suffix, }, - props, + props ); } @@ -85,7 +85,7 @@ class objectParser { let before = root.source.input.css.slice( startNode.start - startNode.loc.start.column, - startNode.start, + startNode.start ); if (/^\s+$/.test(before)) { diff --git a/package.json b/package.json index ab7ebd0..4fa0456 100644 --- a/package.json +++ b/package.json @@ -87,9 +87,6 @@ "*.{js,md,yml}": "prettier --write" }, "eslintConfig": { - "parserOptions": { - "ecmaVersion": 2019 - }, "extends": [ "stylelint", "prettier" diff --git a/template-parser-helper.js b/template-parser-helper.js index a9fe6f6..5f0cb42 100644 --- a/template-parser-helper.js +++ b/template-parser-helper.js @@ -48,7 +48,7 @@ function literal(start) { const start = offset + nodeIndex; const end = start + node.text.length; const templateLiteralStyles = input.templateLiteralStyles.filter( - (style) => style.startIndex <= end && start < style.endIndex, + (style) => style.startIndex <= end && start < style.endIndex ); if (templateLiteralStyles.length) { @@ -167,7 +167,7 @@ class LocalFixer { this.object(error.input); error.message = error.message.replace( /:\d+:\d+:/, - ':' + error.line + ':' + error.column + ':', + ':' + error.line + ':' + error.column + ':' ); } @@ -187,8 +187,8 @@ class LocalFixer { { map: false, }, - style.opts, - ), + style.opts + ) ); } catch (error) { if (style.ignoreErrors) { diff --git a/test/camel-case.js b/test/camel-case.js index de1e0e7..8d72f31 100644 --- a/test/camel-case.js +++ b/test/camel-case.js @@ -49,7 +49,7 @@ describe('camelCase', () => { symbols.forEach((symbol) => { it(JSON.stringify(symbol), () => { expect(camelCase(testCases.map((testCase) => testCase.unCamel).join(symbol))).to.equal( - testCases.map((testCase) => testCase.camel).join(symbol), + testCases.map((testCase) => testCase.camel).join(symbol) ); }); }); @@ -66,7 +66,7 @@ describe('unCamelCase', () => { symbols.forEach((symbol) => { it(JSON.stringify(symbol), () => { expect(unCamelCase(testCases.map((testCase) => testCase.camel).join(symbol))).to.equal( - testCases.map((testCase) => testCase.unCamel).join(symbol), + testCases.map((testCase) => testCase.unCamel).join(symbol) ); }); }); diff --git a/test/css-in-js.js b/test/css-in-js.js index 59bed7b..addca1e 100644 --- a/test/css-in-js.js +++ b/test/css-in-js.js @@ -62,7 +62,7 @@ describe('CSS in JS', () => { `, { from: '/fixtures/glamorous-atRule.jsx', - }, + } ).first.first.first; decl.raws.prop.raw = 'WebkitBorderRadius'; @@ -82,7 +82,7 @@ describe('CSS in JS', () => { `, { from: '/fixtures/glamorous-atRule.jsx', - }, + } ).first.first.first; atRule.raws.params.raw = "(minWidth: ' + minWidth + ')"; diff --git a/test/literals.js b/test/literals.js index c71c08c..ae7a1a9 100644 --- a/test/literals.js +++ b/test/literals.js @@ -25,7 +25,7 @@ describe('template literals', () => { expect(decl).have.property('prop', 'border-bottom'); expect(decl).have.property( 'value', - '${(props) => (props.border ? `1px solid ${color}` : "0")}', + '${(props) => (props.border ? `1px solid ${color}` : "0")}' ); }); }); @@ -55,7 +55,7 @@ describe('template literals', () => { "${(props) =>", "(props.status === \"signed\" && \"red\") ||", "\"blue\"}", - ].join("\n\t\t"), + ].join("\n\t\t") ); }); }); @@ -149,7 +149,7 @@ describe('template literals', () => { ? `${/\bprefix\b/.test(rule.selector) ? 'prefix-' : ''}\${prop}${ /\bsuffix\b/.test(rule.selector) ? '-suffix' : '' }` - : 'prop', + : 'prop' ); expect(decl).to.have.property( 'value', @@ -157,7 +157,7 @@ describe('template literals', () => { ? `${/\bprefix\b/.test(rule.selector) ? 'prefix-' : ''}\${value}${ /\bsuffix\b/.test(rule.selector) ? '-suffix' : '' }` - : 'value', + : 'value' ); }); }); diff --git a/test/styled-components.js b/test/styled-components.js index 7e84bc2..d2b2021 100644 --- a/test/styled-components.js +++ b/test/styled-components.js @@ -250,7 +250,7 @@ describe('styled-components', () => { expect(document.nodes).to.have.lengthOf(1); expect(document.first.first).to.haveOwnProperty( 'prop', - "margin-${/* sc-custom 'left' */ rtlSwitch}", + "margin-${/* sc-custom 'left' */ rtlSwitch}" ); }); diff --git a/un-camel-case.js b/un-camel-case.js index f960bb9..494e49b 100644 --- a/un-camel-case.js +++ b/un-camel-case.js @@ -6,7 +6,7 @@ function unCamelCase(str) { ? s .replace(/[A-Z]/g, (s) => '-' + s.toLowerCase()) .replace(/^(o|ms|moz|khtml|epub|(\w+-?)*webkit)(?=-)/i, '-$1') - : s, + : s ); } From 5aa3b3558e6072ece54c40e12909e993d36b46fc Mon Sep 17 00:00:00 2001 From: yosuke ota Date: Sat, 4 Apr 2020 22:55:07 +0900 Subject: [PATCH 5/5] Remove 'pretest' script and add lint to CI --- .github/workflows/nodejs.yml | 27 +++++++++++++++++++++++++++ package.json | 1 - 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 09da851..fae0612 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -13,6 +13,33 @@ env: CI: true jobs: + lint: + name: Lint on Node.js ${{ matrix.node }} and ${{ matrix.os }} + + runs-on: ${{ matrix.os }} + + strategy: + matrix: + node: [12] + os: [ubuntu-latest] + + steps: + - uses: actions/checkout@v2 + + - name: Use Node.js ${{ matrix.node }} + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node }} + + - name: Install latest npm + run: npm install --global npm@latest + + - name: Install dependencies + run: npm ci + + - name: Lint + run: npm run lint + test: name: Test on Node.js ${{ matrix.node }} diff --git a/package.json b/package.json index 4fa0456..d03f5f8 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,6 @@ "lint:formatting": "prettier . --check", "lint:js": "eslint .", "lint": "npm-run-all --parallel lint:*", - "pretest": "npm run lint", "mocha": "mocha --no-timeouts", "test": "nyc npm run mocha", "watch": "mocha --watch",