From 16d02a40ca2877cc965cde5d0513712516a201d7 Mon Sep 17 00:00:00 2001 From: Jacob Parker Date: Sun, 4 Feb 2018 18:18:58 +0000 Subject: [PATCH 1/3] Improve tokenstream performance, implement prettier --- .eslintrc.js | 2 +- package.json | 6 +- src/TokenStream.js | 68 +-- src/index.js | 53 +- src/index.test.js | 1070 +++++++++++++++++----------------- src/tokenTypes.js | 42 +- src/transforms/boxShadow.js | 23 +- src/transforms/flex.js | 18 +- src/transforms/font.js | 10 +- src/transforms/fontFamily.js | 4 +- src/transforms/index.js | 54 +- src/transforms/transform.js | 23 +- src/transforms/util.js | 29 +- yarn.lock | 14 + 14 files changed, 737 insertions(+), 679 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 1b6a646..45390b0 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,3 +1,3 @@ module.exports = { - extends: 'airbnb-base', + extends: ["airbnb-base", "prettier"] }; diff --git a/package.json b/package.json index eb71ea7..2fee4c0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "css-to-react-native", - "version": "2.1.0", + "version": "2.1.1", "description": "Convert CSS text to a React Native stylesheet object", "main": "dist/index.js", "scripts": { @@ -35,8 +35,10 @@ "babel-preset-es2015": "^6.18.0", "eslint": "^3.9.1", "eslint-config-airbnb-base": "^10.0.1", + "eslint-config-prettier": "^2.9.0", "eslint-plugin-import": "^2.2.0", - "jest": "^17.0.0" + "jest": "^17.0.0", + "prettier": "^1.10.2" }, "dependencies": { "css-color-keywords": "^1.0.0", diff --git a/src/TokenStream.js b/src/TokenStream.js index b827360..bcbbfa0 100644 --- a/src/TokenStream.js +++ b/src/TokenStream.js @@ -1,77 +1,57 @@ -const SYMBOL_BASE_MATCH = 'SYMBOL_BASE_MATCH'; -const SYMBOL_MATCH = 'SYMBOL_MATCH'; +const SYMBOL_MATCH = "SYMBOL_MATCH"; module.exports = class TokenStream { constructor(nodes, parent) { + this.index = 0; this.nodes = nodes; - this.parent = parent; - this.lastFunction = null; + this.functionName = parent != null ? parent.value : null; this.lastValue = null; - } - - get node() { - return this.nodes[0]; + this.rewindIndex = -1; } hasTokens() { - return this.nodes.length > 0; - } - - lookAhead() { - return new TokenStream(this.nodes.slice(1), this.parent); + return this.index <= this.nodes.length - 1; } - [SYMBOL_BASE_MATCH](...tokenDescriptors) { - const node = this.node; + [SYMBOL_MATCH](...tokenDescriptors) { + if (!this.hasTokens()) return null; - if (!node) return null; + const node = this.nodes[this.index]; for (let i = 0; i < tokenDescriptors.length; i += 1) { const tokenDescriptor = tokenDescriptors[i]; const value = tokenDescriptor(node); - if (value !== null) return value; + if (value !== null) { + this.index += 1; + this.lastValue = value; + return value; + } } return null; } - [SYMBOL_MATCH](...tokenDescriptors) { - const value = this[SYMBOL_BASE_MATCH](...tokenDescriptors); - if (value === null) return null; - this.nodes = this.nodes.slice(1); - this.lastFunction = null; - this.lastValue = value; - return value; - } - - test(...tokenDescriptors) { - return this[SYMBOL_BASE_MATCH](...tokenDescriptors) !== null; - } - matches(...tokenDescriptors) { return this[SYMBOL_MATCH](...tokenDescriptors) !== null; } expect(...tokenDescriptors) { const value = this[SYMBOL_MATCH](...tokenDescriptors); - if (value !== null) return value; - return this.throw(); + return value !== null ? value : this.throw(); } matchesFunction() { - const node = this.node; - if (node.type !== 'function') return null; + const node = this.nodes[this.index]; + if (node.type !== "function") return null; const value = new TokenStream(node.nodes, node); - this.nodes = this.nodes.slice(1); - this.lastFunction = value; + this.index += 1; this.lastValue = null; return value; } expectFunction() { const value = this.matchesFunction(); - if (value !== null) return value; - return this.throw(); + return value !== null ? value : this.throw(); } expectEmpty() { @@ -79,6 +59,16 @@ module.exports = class TokenStream { } throw() { - throw new Error(`Unexpected token type: ${this.node.type}`); + throw new Error(`Unexpected token type: ${this.nodes[this.index].type}`); + } + + saveRewindPoint() { + this.rewindIndex = this.index; + } + + rewind() { + if (this.rewindIndex === -1) throw new Error("Internal error"); + this.index = this.rewindIndex; + this.lastValue = null; } }; diff --git a/src/index.js b/src/index.js index f42816e..8fa30fe 100644 --- a/src/index.js +++ b/src/index.js @@ -1,8 +1,8 @@ /* eslint-disable no-param-reassign */ -const parse = require('postcss-value-parser'); -const camelizeStyleName = require('fbjs/lib/camelizeStyleName'); -const transforms = require('./transforms'); -const TokenStream = require('./TokenStream'); +const parse = require("postcss-value-parser"); +const camelizeStyleName = require("fbjs/lib/camelizeStyleName"); +const transforms = require("./transforms"); +const TokenStream = require("./TokenStream"); // Note if this is wrong, you'll need to change tokenTypes.js too const numberOrLengthRe = /^([+-]?(?:\d*\.)?\d+(?:[Ee][+-]?\d+)?)(?:px)?$/i; @@ -11,14 +11,14 @@ const nullRe = /^null$/i; const undefinedRe = /^undefined$/i; // Undocumented export -export const transformRawValue = (input) => { +export const transformRawValue = input => { const value = input.trim(); const numberMatch = value.match(numberOrLengthRe); if (numberMatch !== null) return Number(numberMatch[1]); const boolMatch = input.match(boolRe); - if (boolMatch !== null) return boolMatch[0].toLowerCase() === 'true'; + if (boolMatch !== null) return boolMatch[0].toLowerCase() === "true"; const nullMatch = input.match(nullRe); if (nullMatch !== null) return null; @@ -35,32 +35,39 @@ const baseTransformShorthandValue = (propName, inputValue) => { return transforms[propName](tokenStream); }; -const transformShorthandValue = (process.env.NODE_ENV === 'production') - ? baseTransformShorthandValue - : (propName, inputValue) => { - try { - return baseTransformShorthandValue(propName, inputValue); - } catch (e) { - throw new Error(`Failed to parse declaration "${propName}: ${inputValue}"`); - } - }; +const transformShorthandValue = + process.env.NODE_ENV === "production" + ? baseTransformShorthandValue + : (propName, inputValue) => { + try { + return baseTransformShorthandValue(propName, inputValue); + } catch (e) { + throw new Error( + `Failed to parse declaration "${propName}: ${inputValue}"` + ); + } + }; export const getStylesForProperty = (propName, inputValue, allowShorthand) => { - const isRawValue = (allowShorthand === false) || !(propName in transforms); + const isRawValue = allowShorthand === false || !(propName in transforms); const propValue = isRawValue ? transformRawValue(inputValue) : transformShorthandValue(propName, inputValue.trim()); - return (propValue && propValue.$merge) + return propValue && propValue.$merge ? propValue.$merge : { [propName]: propValue }; }; export const getPropertyName = camelizeStyleName; -export default (rules, shorthandBlacklist = []) => rules.reduce((accum, rule) => { - const propertyName = getPropertyName(rule[0]); - const value = rule[1]; - const allowShorthand = shorthandBlacklist.indexOf(propertyName) === -1; - return Object.assign(accum, getStylesForProperty(propertyName, value, allowShorthand)); -}, {}); +export default (rules, shorthandBlacklist = []) => + rules.reduce((accum, rule) => { + const propertyName = getPropertyName(rule[0]); + const value = rule[1]; + const allowShorthand = shorthandBlacklist.indexOf(propertyName) === -1; + return Object.assign( + accum, + getStylesForProperty(propertyName, value, allowShorthand) + ); + }, {}); diff --git a/src/index.test.js b/src/index.test.js index 0783d94..2222c61 100644 --- a/src/index.test.js +++ b/src/index.test.js @@ -1,556 +1,572 @@ /* global jest it, expect */ -import transformCss, { getStylesForProperty } from '.'; +import transformCss, { getStylesForProperty } from "."; const runTest = (inputCss, expectedStyles) => { const actualStyles = transformCss(inputCss); expect(actualStyles).toEqual(expectedStyles); }; -it('transforms numbers', () => runTest([ - ['top', '0'], - ['left', '0'], - ['right', '0'], - ['bottom', '0'], -], { top: 0, left: 0, right: 0, bottom: 0 })); - -it('allows pixels in unspecialized transform', () => runTest([ - ['top', '0px'], -], { top: 0 })); - -it('allows boolean values', () => runTest([ - ['boolTrue1', 'true'], - ['boolTrue2', 'TRUE'], - ['boolFalse1', 'false'], - ['boolFalse2', 'FALSE'], -], { - boolTrue1: true, - boolTrue2: true, - boolFalse1: false, - boolFalse2: false, -})); - -it('allows null values', () => runTest([ - ['null1', 'null'], - ['null2', 'NULL'], -], { - null1: null, - null2: null, -})); - -it('allows undefined values', () => runTest([ - ['undefined1', 'undefined'], - ['undefined2', 'UNDEFINED'], -], { - undefined1: undefined, - undefined2: undefined, -})); - -it('allows percent in unspecialized transform', () => runTest([ - ['top', '0%'], -], { top: '0%' })); - -it('allows decimal values', () => { - expect(getStylesForProperty('margin', '0.5px').marginTop).toBe(0.5); - expect(getStylesForProperty('margin', '1.5px').marginTop).toBe(1.5); - expect(getStylesForProperty('margin', '10.5px').marginTop).toBe(10.5); - expect(getStylesForProperty('margin', '100.5px').marginTop).toBe(100.5); - expect(getStylesForProperty('margin', '-0.5px').marginTop).toBe(-0.5); - expect(getStylesForProperty('margin', '-1.5px').marginTop).toBe(-1.5); - expect(getStylesForProperty('margin', '-10.5px').marginTop).toBe(-10.5); - expect(getStylesForProperty('margin', '-100.5px').marginTop).toBe(-100.5); - expect(getStylesForProperty('margin', '.5px').marginTop).toBe(0.5); - expect(getStylesForProperty('margin', '-.5px').marginTop).toBe(-0.5); +it("transforms numbers", () => + runTest([["top", "0"], ["left", "0"], ["right", "0"], ["bottom", "0"]], { + top: 0, + left: 0, + right: 0, + bottom: 0 + })); + +it("allows pixels in unspecialized transform", () => + runTest([["top", "0px"]], { top: 0 })); + +it("allows boolean values", () => + runTest( + [ + ["boolTrue1", "true"], + ["boolTrue2", "TRUE"], + ["boolFalse1", "false"], + ["boolFalse2", "FALSE"] + ], + { + boolTrue1: true, + boolTrue2: true, + boolFalse1: false, + boolFalse2: false + } + )); + +it("allows null values", () => + runTest([["null1", "null"], ["null2", "NULL"]], { + null1: null, + null2: null + })); + +it("allows undefined values", () => + runTest([["undefined1", "undefined"], ["undefined2", "UNDEFINED"]], { + undefined1: undefined, + undefined2: undefined + })); + +it("allows percent in unspecialized transform", () => + runTest([["top", "0%"]], { top: "0%" })); + +it("allows decimal values", () => { + expect(getStylesForProperty("margin", "0.5px").marginTop).toBe(0.5); + expect(getStylesForProperty("margin", "1.5px").marginTop).toBe(1.5); + expect(getStylesForProperty("margin", "10.5px").marginTop).toBe(10.5); + expect(getStylesForProperty("margin", "100.5px").marginTop).toBe(100.5); + expect(getStylesForProperty("margin", "-0.5px").marginTop).toBe(-0.5); + expect(getStylesForProperty("margin", "-1.5px").marginTop).toBe(-1.5); + expect(getStylesForProperty("margin", "-10.5px").marginTop).toBe(-10.5); + expect(getStylesForProperty("margin", "-100.5px").marginTop).toBe(-100.5); + expect(getStylesForProperty("margin", ".5px").marginTop).toBe(0.5); + expect(getStylesForProperty("margin", "-.5px").marginTop).toBe(-0.5); }); -it('allows decimal values in transformed values', () => runTest([ - ['border-radius', '1.5px'], -], { - borderTopLeftRadius: 1.5, - borderTopRightRadius: 1.5, - borderBottomRightRadius: 1.5, - borderBottomLeftRadius: 1.5, -})); - -it('allows negative values in transformed values', () => runTest([ - ['border-radius', '-1.5px'], -], { - borderTopLeftRadius: -1.5, - borderTopRightRadius: -1.5, - borderBottomRightRadius: -1.5, - borderBottomLeftRadius: -1.5, -})); - -it('allows percent values in transformed values', () => runTest([ - ['margin', '10%'], -], { - marginTop: '10%', - marginRight: '10%', - marginBottom: '10%', - marginLeft: '10%', -})); - -it('allows color values in transformed border-color values', () => runTest([ - ['border-color', 'red'], -], { - borderTopColor: 'red', - borderRightColor: 'red', - borderBottomColor: 'red', - borderLeftColor: 'red', -})); - -it('allows omitting units for 0', () => runTest([ - ['margin', '10px 0'], -], { - marginTop: 10, - marginRight: 0, - marginBottom: 10, - marginLeft: 0, -})); - -it('transforms strings', () => runTest([ - ['color', 'red'], -], { color: 'red' })); - -it('transforms hex colors', () => runTest([ - ['color', '#f00'], -], { color: '#f00' })); - -it('transforms rgb colors', () => runTest([ - ['color', 'rgb(255, 0, 0)'], -], { color: 'rgb(255, 0, 0)' })); - -it('converts to camel-case', () => runTest([ - ['background-color', 'red'], -], { backgroundColor: 'red' })); - -it('transforms background to backgroundColor', () => runTest([ - ['background', '#f00'], -], { backgroundColor: '#f00' })); - -it('transforms background to backgroundColor with rgb', () => runTest([ - ['background', 'rgb(255, 0, 0)'], -], { backgroundColor: 'rgb(255, 0, 0)' })); - -it('transforms background to backgroundColor with named colour', () => runTest([ - ['background', 'red'], -], { backgroundColor: 'red' })); - -it('transforms font weights as strings', () => runTest([ - ['font-weight', ' 400'], -], { fontWeight: '400' })); - -it('transforms font variant as an array', () => runTest([ - ['font-variant', 'tabular-nums'], -], { fontVariant: ['tabular-nums'] })); - -it('transforms shadow offsets', () => runTest([ - ['shadow-offset', '10px 5px'], -], { shadowOffset: { width: 10, height: 5 } })); - -it('transforms text shadow offsets', () => runTest([ - ['text-shadow-offset', '10px 5px'], -], { textShadowOffset: { width: 10, height: 5 } })); - -it('transforms a single transform value with number', () => runTest([ - ['transform', 'scaleX(5)'], -], { transform: [{ scaleX: 5 }] })); - -it('transforms a single transform value with string', () => runTest([ - ['transform', 'rotate(5deg)'], -], { transform: [{ rotate: '5deg' }] })); - -it('transforms multiple transform values', () => runTest([ - ['transform', 'scaleX(5) skewX(1deg)'], -], { transform: [{ skewX: '1deg' }, { scaleX: 5 }] })); - -it('transforms scale(number, number) to scaleX and scaleY', () => runTest([ - ['transform', 'scale(2, 3)'], -], { transform: [{ scaleY: 3 }, { scaleX: 2 }] })); - -it('transforms scale(number) to scale', () => runTest([ - ['transform', 'scale(5)'], -], { transform: [{ scale: 5 }] })); - -it('transforms translate(length, length) to translateX and translateY', () => runTest([ - ['transform', 'translate(2px, 3px)'], -], { transform: [{ translateY: 3 }, { translateX: 2 }] })); - -it('transforms translate(length) to translateX and translateY', () => runTest([ - ['transform', 'translate(5px)'], -], { transform: [{ translateY: 0 }, { translateX: 5 }] })); - -it('transforms skew(angle, angle) to skewX and skewY', () => runTest([ - ['transform', 'skew(2deg, 3deg)'], -], { transform: [{ skewY: '3deg' }, { skewX: '2deg' }] })); - -it('transforms skew(angle) to skewX and skewY', () => runTest([ - ['transform', 'skew(5deg)'], -], { transform: [{ skewY: '0deg' }, { skewX: '5deg' }] })); - -it('transforms border shorthand', () => runTest([ - ['border', '2px dashed #f00'], -], { borderWidth: 2, borderColor: '#f00', borderStyle: 'dashed' })); - -it('transforms border shorthand in other order', () => runTest([ - ['border', '#f00 2px dashed'], -], { borderWidth: 2, borderColor: '#f00', borderStyle: 'dashed' })); - -it('transforms border shorthand missing color', () => runTest([ - ['border', '2px dashed'], -], { borderWidth: 2, borderColor: 'black', borderStyle: 'dashed' })); - -it('transforms border shorthand missing style', () => runTest([ - ['border', '2px #f00'], -], { borderWidth: 2, borderColor: '#f00', borderStyle: 'solid' })); - -it('transforms border shorthand missing width', () => runTest([ - ['border', '#f00 dashed'], -], { borderWidth: 1, borderColor: '#f00', borderStyle: 'dashed' })); - -it('transforms border shorthand missing color & width', () => runTest([ - ['border', 'dashed'], -], { borderWidth: 1, borderColor: 'black', borderStyle: 'dashed' })); - -it('transforms border shorthand missing style & width', () => runTest([ - ['border', '#f00'], -], { borderWidth: 1, borderColor: '#f00', borderStyle: 'solid' })); - -it('transforms border shorthand missing color & style', () => runTest([ - ['border', '2px'], -], { borderWidth: 2, borderColor: 'black', borderStyle: 'solid' })); - -it('transforms margin shorthands using 4 values', () => runTest([ - ['margin', '10px 20px 30px 40px'], -], { marginTop: 10, marginRight: 20, marginBottom: 30, marginLeft: 40 })); - -it('transforms margin shorthands using 3 values', () => runTest([ - ['margin', '10px 20px 30px'], -], { marginTop: 10, marginRight: 20, marginBottom: 30, marginLeft: 20 })); - -it('transforms margin shorthands using 2 values', () => runTest([ - ['margin', '10px 20px'], -], { marginTop: 10, marginRight: 20, marginBottom: 10, marginLeft: 20 })); - -it('transforms margin shorthands using 1 value', () => runTest([ - ['margin', '10px'], -], { marginTop: 10, marginRight: 10, marginBottom: 10, marginLeft: 10 })); - -it('shorthand with 1 value should override previous values', () => runTest([ - ['margin-top', '2px'], - ['margin', '1px'], -], { marginTop: 1, marginRight: 1, marginBottom: 1, marginLeft: 1 })); - -it('transforms flex shorthand with 3 values', () => runTest([ - ['flex', '1 2 3px'], -], { flexGrow: 1, flexShrink: 2, flexBasis: 3 })); - -it('transforms flex shorthand with 3 values in reverse order', () => runTest([ - ['flex', '3px 1 2'], -], { flexGrow: 1, flexShrink: 2, flexBasis: 3 })); - -it('transforms flex shorthand with 2 values of flex-grow and flex-shrink', () => runTest([ - ['flex', '1 2'], -], { flexGrow: 1, flexShrink: 2, flexBasis: 0 })); - -it('transforms flex shorthand with 2 values of flex-grow and flex-basis', () => runTest([ - ['flex', '2 2px'], -], { flexGrow: 2, flexShrink: 1, flexBasis: 2 })); - -it('transforms flex shorthand with 2 values of flex-grow and flex-basis (reversed)', () => runTest([ - ['flex', '2px 2'], -], { flexGrow: 2, flexShrink: 1, flexBasis: 2 })); - -it('transforms flex shorthand with 1 value of flex-grow', () => runTest([ - ['flex', '2'], -], { flexGrow: 2, flexShrink: 1, flexBasis: 0 })); - -it('transforms flex shorthand with 1 value of flex-basis', () => runTest([ - ['flex', '10px'], -], { flexGrow: 1, flexShrink: 1, flexBasis: 10 })); +it("allows decimal values in transformed values", () => + runTest([["border-radius", "1.5px"]], { + borderTopLeftRadius: 1.5, + borderTopRightRadius: 1.5, + borderBottomRightRadius: 1.5, + borderBottomLeftRadius: 1.5 + })); + +it("allows negative values in transformed values", () => + runTest([["border-radius", "-1.5px"]], { + borderTopLeftRadius: -1.5, + borderTopRightRadius: -1.5, + borderBottomRightRadius: -1.5, + borderBottomLeftRadius: -1.5 + })); + +it("allows percent values in transformed values", () => + runTest([["margin", "10%"]], { + marginTop: "10%", + marginRight: "10%", + marginBottom: "10%", + marginLeft: "10%" + })); + +it("allows color values in transformed border-color values", () => + runTest([["border-color", "red"]], { + borderTopColor: "red", + borderRightColor: "red", + borderBottomColor: "red", + borderLeftColor: "red" + })); + +it("allows omitting units for 0", () => + runTest([["margin", "10px 0"]], { + marginTop: 10, + marginRight: 0, + marginBottom: 10, + marginLeft: 0 + })); + +it("transforms strings", () => runTest([["color", "red"]], { color: "red" })); + +it("transforms hex colors", () => + runTest([["color", "#f00"]], { color: "#f00" })); + +it("transforms rgb colors", () => + runTest([["color", "rgb(255, 0, 0)"]], { color: "rgb(255, 0, 0)" })); + +it("converts to camel-case", () => + runTest([["background-color", "red"]], { backgroundColor: "red" })); + +it("transforms background to backgroundColor", () => + runTest([["background", "#f00"]], { backgroundColor: "#f00" })); + +it("transforms background to backgroundColor with rgb", () => + runTest([["background", "rgb(255, 0, 0)"]], { + backgroundColor: "rgb(255, 0, 0)" + })); + +it("transforms background to backgroundColor with named colour", () => + runTest([["background", "red"]], { backgroundColor: "red" })); + +it("transforms font weights as strings", () => + runTest([["font-weight", " 400"]], { fontWeight: "400" })); + +it("transforms font variant as an array", () => + runTest([["font-variant", "tabular-nums"]], { + fontVariant: ["tabular-nums"] + })); + +it("transforms shadow offsets", () => + runTest([["shadow-offset", "10px 5px"]], { + shadowOffset: { width: 10, height: 5 } + })); + +it("transforms text shadow offsets", () => + runTest([["text-shadow-offset", "10px 5px"]], { + textShadowOffset: { width: 10, height: 5 } + })); + +it("transforms a single transform value with number", () => + runTest([["transform", "scaleX(5)"]], { transform: [{ scaleX: 5 }] })); + +it("transforms a single transform value with string", () => + runTest([["transform", "rotate(5deg)"]], { + transform: [{ rotate: "5deg" }] + })); + +it("transforms multiple transform values", () => + runTest([["transform", "scaleX(5) skewX(1deg)"]], { + transform: [{ skewX: "1deg" }, { scaleX: 5 }] + })); + +it("transforms scale(number, number) to scaleX and scaleY", () => + runTest([["transform", "scale(2, 3)"]], { + transform: [{ scaleY: 3 }, { scaleX: 2 }] + })); + +it("transforms scale(number) to scale", () => + runTest([["transform", "scale(5)"]], { transform: [{ scale: 5 }] })); + +it("transforms translate(length, length) to translateX and translateY", () => + runTest([["transform", "translate(2px, 3px)"]], { + transform: [{ translateY: 3 }, { translateX: 2 }] + })); + +it("transforms translate(length) to translateX and translateY", () => + runTest([["transform", "translate(5px)"]], { + transform: [{ translateY: 0 }, { translateX: 5 }] + })); + +it("transforms skew(angle, angle) to skewX and skewY", () => + runTest([["transform", "skew(2deg, 3deg)"]], { + transform: [{ skewY: "3deg" }, { skewX: "2deg" }] + })); + +it("transforms skew(angle) to skewX and skewY", () => + runTest([["transform", "skew(5deg)"]], { + transform: [{ skewY: "0deg" }, { skewX: "5deg" }] + })); + +it("transforms border shorthand", () => + runTest([["border", "2px dashed #f00"]], { + borderWidth: 2, + borderColor: "#f00", + borderStyle: "dashed" + })); + +it("transforms border shorthand in other order", () => + runTest([["border", "#f00 2px dashed"]], { + borderWidth: 2, + borderColor: "#f00", + borderStyle: "dashed" + })); + +it("transforms border shorthand missing color", () => + runTest([["border", "2px dashed"]], { + borderWidth: 2, + borderColor: "black", + borderStyle: "dashed" + })); + +it("transforms border shorthand missing style", () => + runTest([["border", "2px #f00"]], { + borderWidth: 2, + borderColor: "#f00", + borderStyle: "solid" + })); + +it("transforms border shorthand missing width", () => + runTest([["border", "#f00 dashed"]], { + borderWidth: 1, + borderColor: "#f00", + borderStyle: "dashed" + })); + +it("transforms border shorthand missing color & width", () => + runTest([["border", "dashed"]], { + borderWidth: 1, + borderColor: "black", + borderStyle: "dashed" + })); + +it("transforms border shorthand missing style & width", () => + runTest([["border", "#f00"]], { + borderWidth: 1, + borderColor: "#f00", + borderStyle: "solid" + })); + +it("transforms border shorthand missing color & style", () => + runTest([["border", "2px"]], { + borderWidth: 2, + borderColor: "black", + borderStyle: "solid" + })); + +it("transforms margin shorthands using 4 values", () => + runTest([["margin", "10px 20px 30px 40px"]], { + marginTop: 10, + marginRight: 20, + marginBottom: 30, + marginLeft: 40 + })); + +it("transforms margin shorthands using 3 values", () => + runTest([["margin", "10px 20px 30px"]], { + marginTop: 10, + marginRight: 20, + marginBottom: 30, + marginLeft: 20 + })); + +it("transforms margin shorthands using 2 values", () => + runTest([["margin", "10px 20px"]], { + marginTop: 10, + marginRight: 20, + marginBottom: 10, + marginLeft: 20 + })); + +it("transforms margin shorthands using 1 value", () => + runTest([["margin", "10px"]], { + marginTop: 10, + marginRight: 10, + marginBottom: 10, + marginLeft: 10 + })); + +it("shorthand with 1 value should override previous values", () => + runTest([["margin-top", "2px"], ["margin", "1px"]], { + marginTop: 1, + marginRight: 1, + marginBottom: 1, + marginLeft: 1 + })); + +it("transforms flex shorthand with 3 values", () => + runTest([["flex", "1 2 3px"]], { flexGrow: 1, flexShrink: 2, flexBasis: 3 })); + +it("transforms flex shorthand with 3 values in reverse order", () => + runTest([["flex", "3px 1 2"]], { flexGrow: 1, flexShrink: 2, flexBasis: 3 })); + +it("transforms flex shorthand with 2 values of flex-grow and flex-shrink", () => + runTest([["flex", "1 2"]], { flexGrow: 1, flexShrink: 2, flexBasis: 0 })); + +it("transforms flex shorthand with 2 values of flex-grow and flex-basis", () => + runTest([["flex", "2 2px"]], { flexGrow: 2, flexShrink: 1, flexBasis: 2 })); + +it("transforms flex shorthand with 2 values of flex-grow and flex-basis (reversed)", () => + runTest([["flex", "2px 2"]], { flexGrow: 2, flexShrink: 1, flexBasis: 2 })); + +it("transforms flex shorthand with 1 value of flex-grow", () => + runTest([["flex", "2"]], { flexGrow: 2, flexShrink: 1, flexBasis: 0 })); + +it("transforms flex shorthand with 1 value of flex-basis", () => + runTest([["flex", "10px"]], { flexGrow: 1, flexShrink: 1, flexBasis: 10 })); /* A unitless zero that is not already preceded by two flex factors must be interpreted as a flex factor. To avoid misinterpretation or invalid declarations, authors must specify a zero <‘flex-basis’> component with a unit or precede it by two flex factors. */ -it('transforms flex shorthand with flex-grow/shrink taking priority over basis', () => runTest([ - ['flex', '0 1 0'], -], { flexGrow: 0, flexShrink: 1, flexBasis: 0 })); - -it('transforms flex shorthand with flex-basis set to auto', () => runTest([ - ['flex', '0 1 auto'], -], { flexGrow: 0, flexShrink: 1 })); - -it('transforms flex shorthand with flex-basis set to auto appearing first', () => runTest([ - ['flex', 'auto 0 1'], -], { flexGrow: 0, flexShrink: 1 })); - -it('transforms flex auto keyword', () => runTest([ - ['flex', 'auto'], -], { flexGrow: 1, flexShrink: 1 })); - -it('transforms flex none keyword', () => runTest([ - ['flex', 'none'], -], { flexGrow: 0, flexShrink: 0 })); - -it('transforms flexFlow shorthand with two values', () => runTest([ - ['flex-flow', 'column wrap'], -], { flexDirection: 'column', flexWrap: 'wrap' })); - -it('transforms flexFlow shorthand missing flexDirection', () => runTest([ - ['flex-flow', 'wrap'], -], { flexDirection: 'row', flexWrap: 'wrap' })); - -it('transforms flexFlow shorthand missing flexWrap', () => runTest([ - ['flex-flow', 'column'], -], { flexDirection: 'column', flexWrap: 'nowrap' })); - -it('transforms font', () => runTest([ - ['font', 'bold italic small-caps 16px/18px "Helvetica"'], -], { - fontFamily: 'Helvetica', - fontSize: 16, - fontWeight: 'bold', - fontStyle: 'italic', - fontVariant: ['small-caps'], - lineHeight: 18, -})); - -it('transforms font missing font-variant', () => runTest([ - ['font', 'bold italic 16px/18px "Helvetica"'], -], { - fontFamily: 'Helvetica', - fontSize: 16, - fontWeight: 'bold', - fontStyle: 'italic', - fontVariant: [], - lineHeight: 18, -})); - -it('transforms font missing font-style', () => runTest([ - ['font', 'bold small-caps 16px/18px "Helvetica"'], -], { - fontFamily: 'Helvetica', - fontSize: 16, - fontWeight: 'bold', - fontStyle: 'normal', - fontVariant: ['small-caps'], - lineHeight: 18, -})); - -it('transforms font missing font-weight', () => runTest([ - ['font', 'italic small-caps 16px/18px "Helvetica"'], -], { - fontFamily: 'Helvetica', - fontSize: 16, - fontWeight: 'normal', - fontStyle: 'italic', - fontVariant: ['small-caps'], - lineHeight: 18, -})); - -it('transforms font with font-weight normal', () => runTest([ - ['font', 'normal 16px/18px "Helvetica"'], -], { - fontFamily: 'Helvetica', - fontSize: 16, - fontWeight: 'normal', - fontStyle: 'normal', - fontVariant: [], - lineHeight: 18, -})); - -it('transforms font with font-weight and font-style normal', () => runTest([ - ['font', 'normal normal 16px/18px "Helvetica"'], -], { - fontFamily: 'Helvetica', - fontSize: 16, - fontWeight: 'normal', - fontStyle: 'normal', - fontVariant: [], - lineHeight: 18, -})); - -it('transforms font with no font-weight, font-style, and font-variant', () => runTest([ - ['font', '16px/18px "Helvetica"'], -], { - fontFamily: 'Helvetica', - fontSize: 16, - fontWeight: 'normal', - fontStyle: 'normal', - fontVariant: [], - lineHeight: 18, -})); - -it('omits line height if not specified', () => runTest([ - ['font', '16px "Helvetica"'], -], { - fontFamily: 'Helvetica', - fontSize: 16, - fontWeight: 'normal', - fontStyle: 'normal', - fontVariant: [], -})); - -it('allows line height as multiple', () => runTest([ - ['font', '16px/1.5 "Helvetica"'], -], { - fontFamily: 'Helvetica', - fontSize: 16, - fontWeight: 'normal', - fontStyle: 'normal', - fontVariant: [], - lineHeight: 24, -})); - -it('transforms font without quotes', () => runTest([ - ['font', 'bold italic small-caps 16px/18px Helvetica Neue'], -], { - fontFamily: 'Helvetica Neue', - fontSize: 16, - fontWeight: 'bold', - fontStyle: 'italic', - fontVariant: ['small-caps'], - lineHeight: 18, -})); - -it('transforms font-family with double quotes', () => runTest([ - ['font-family', '"Helvetica Neue"'], -], { - fontFamily: 'Helvetica Neue', -})); - -it('transforms font-family with single quotes', () => runTest([ - ['font-family', '\'Helvetica Neue\''], -], { - fontFamily: 'Helvetica Neue', -})); - -it('transforms font-family without quotes', () => runTest([ - ['font-family', 'Helvetica Neue'], -], { - fontFamily: 'Helvetica Neue', -})); - -it('transforms font-family with quotes with otherwise invalid values', () => runTest([ - ['font-family', '"Goudy Bookletter 1911"'], -], { - fontFamily: 'Goudy Bookletter 1911', -})); - -it('transforms font-family with quotes with escaped values', () => runTest([ - ['font-family', '"test\\A test"'], -], { - fontFamily: 'test\ntest', -})); - -it('transforms font-family with quotes with escaped quote', () => runTest([ - ['font-family', '"test\\"test"'], -], { - fontFamily: 'test"test', -})); - -it('does not transform invalid unquoted font-family', () => { - expect(() => transformCss([['font-family', 'Goudy Bookletter 1911']])).toThrow(); +it("transforms flex shorthand with flex-grow/shrink taking priority over basis", () => + runTest([["flex", "0 1 0"]], { flexGrow: 0, flexShrink: 1, flexBasis: 0 })); + +it("transforms flex shorthand with flex-basis set to auto", () => + runTest([["flex", "0 1 auto"]], { flexGrow: 0, flexShrink: 1 })); + +it("transforms flex shorthand with flex-basis set to auto appearing first", () => + runTest([["flex", "auto 0 1"]], { flexGrow: 0, flexShrink: 1 })); + +it("transforms flex auto keyword", () => + runTest([["flex", "auto"]], { flexGrow: 1, flexShrink: 1 })); + +it("transforms flex none keyword", () => + runTest([["flex", "none"]], { flexGrow: 0, flexShrink: 0 })); + +it("transforms flexFlow shorthand with two values", () => + runTest([["flex-flow", "column wrap"]], { + flexDirection: "column", + flexWrap: "wrap" + })); + +it("transforms flexFlow shorthand missing flexDirection", () => + runTest([["flex-flow", "wrap"]], { flexDirection: "row", flexWrap: "wrap" })); + +it("transforms flexFlow shorthand missing flexWrap", () => + runTest([["flex-flow", "column"]], { + flexDirection: "column", + flexWrap: "nowrap" + })); + +it("transforms font", () => + runTest([["font", 'bold italic small-caps 16px/18px "Helvetica"']], { + fontFamily: "Helvetica", + fontSize: 16, + fontWeight: "bold", + fontStyle: "italic", + fontVariant: ["small-caps"], + lineHeight: 18 + })); + +it("transforms font missing font-variant", () => + runTest([["font", 'bold italic 16px/18px "Helvetica"']], { + fontFamily: "Helvetica", + fontSize: 16, + fontWeight: "bold", + fontStyle: "italic", + fontVariant: [], + lineHeight: 18 + })); + +it("transforms font missing font-style", () => + runTest([["font", 'bold small-caps 16px/18px "Helvetica"']], { + fontFamily: "Helvetica", + fontSize: 16, + fontWeight: "bold", + fontStyle: "normal", + fontVariant: ["small-caps"], + lineHeight: 18 + })); + +it("transforms font missing font-weight", () => + runTest([["font", 'italic small-caps 16px/18px "Helvetica"']], { + fontFamily: "Helvetica", + fontSize: 16, + fontWeight: "normal", + fontStyle: "italic", + fontVariant: ["small-caps"], + lineHeight: 18 + })); + +it("transforms font with font-weight normal", () => + runTest([["font", 'normal 16px/18px "Helvetica"']], { + fontFamily: "Helvetica", + fontSize: 16, + fontWeight: "normal", + fontStyle: "normal", + fontVariant: [], + lineHeight: 18 + })); + +it("transforms font with font-weight and font-style normal", () => + runTest([["font", 'normal normal 16px/18px "Helvetica"']], { + fontFamily: "Helvetica", + fontSize: 16, + fontWeight: "normal", + fontStyle: "normal", + fontVariant: [], + lineHeight: 18 + })); + +it("transforms font with no font-weight, font-style, and font-variant", () => + runTest([["font", '16px/18px "Helvetica"']], { + fontFamily: "Helvetica", + fontSize: 16, + fontWeight: "normal", + fontStyle: "normal", + fontVariant: [], + lineHeight: 18 + })); + +it("omits line height if not specified", () => + runTest([["font", '16px "Helvetica"']], { + fontFamily: "Helvetica", + fontSize: 16, + fontWeight: "normal", + fontStyle: "normal", + fontVariant: [] + })); + +it("allows line height as multiple", () => + runTest([["font", '16px/1.5 "Helvetica"']], { + fontFamily: "Helvetica", + fontSize: 16, + fontWeight: "normal", + fontStyle: "normal", + fontVariant: [], + lineHeight: 24 + })); + +it("transforms font without quotes", () => + runTest([["font", "bold italic small-caps 16px/18px Helvetica Neue"]], { + fontFamily: "Helvetica Neue", + fontSize: 16, + fontWeight: "bold", + fontStyle: "italic", + fontVariant: ["small-caps"], + lineHeight: 18 + })); + +it("transforms font-family with double quotes", () => + runTest([["font-family", '"Helvetica Neue"']], { + fontFamily: "Helvetica Neue" + })); + +it("transforms font-family with single quotes", () => + runTest([["font-family", "'Helvetica Neue'"]], { + fontFamily: "Helvetica Neue" + })); + +it("transforms font-family without quotes", () => + runTest([["font-family", "Helvetica Neue"]], { + fontFamily: "Helvetica Neue" + })); + +it("transforms font-family with quotes with otherwise invalid values", () => + runTest([["font-family", '"Goudy Bookletter 1911"']], { + fontFamily: "Goudy Bookletter 1911" + })); + +it("transforms font-family with quotes with escaped values", () => + runTest([["font-family", '"test\\A test"']], { + fontFamily: "test\ntest" + })); + +it("transforms font-family with quotes with escaped quote", () => + runTest([["font-family", '"test\\"test"']], { + fontFamily: 'test"test' + })); + +it("does not transform invalid unquoted font-family", () => { + expect(() => + transformCss([["font-family", "Goudy Bookletter 1911"]]) + ).toThrow(); }); -it('does not transform invalid flex', () => { - expect(() => transformCss([['flex', '1 2px 3']])).toThrow(); +it("does not transform invalid flex", () => { + expect(() => transformCss([["flex", "1 2px 3"]])).toThrow(); }); -it('transforms box-shadow into shadow- properties', () => runTest([ - ['box-shadow', '10px 20px 30px red'], -], { - shadowOffset: { width: 10, height: 20 }, - shadowRadius: 30, - shadowColor: 'red', - shadowOpacity: 1, -})); - -it('transforms box-shadow without blur-radius', () => runTest([ - ['box-shadow', '10px 20px red'], -], { - shadowOffset: { width: 10, height: 20 }, - shadowRadius: 0, - shadowColor: 'red', - shadowOpacity: 1, -})); - -it('transforms box-shadow without color', () => runTest([ - ['box-shadow', '10px 20px 30px'], -], { - shadowOffset: { width: 10, height: 20 }, - shadowRadius: 30, - shadowColor: 'black', - shadowOpacity: 1, -})); - -it('transforms box-shadow without blur-radius, color', () => runTest([ - ['box-shadow', '10px 20px'], -], { - shadowOffset: { width: 10, height: 20 }, - shadowRadius: 0, - shadowColor: 'black', - shadowOpacity: 1, -})); - -it('transforms box-shadow with rgb color', () => runTest([ - ['box-shadow', '10px 20px rgb(100, 100, 100)'], -], { - shadowOffset: { width: 10, height: 20 }, - shadowRadius: 0, - shadowColor: 'rgb(100, 100, 100)', - shadowOpacity: 1, -})); - -it('transforms box-shadow with rgba color', () => runTest([ - ['box-shadow', '10px 20px rgba(100, 100, 100, 0.5)'], -], { - shadowOffset: { width: 10, height: 20 }, - shadowRadius: 0, - shadowColor: 'rgba(100, 100, 100, 0.5)', - shadowOpacity: 1, -})); - -it('transforms box-shadow with hsl color', () => runTest([ - ['box-shadow', '10px 20px hsl(120, 100%, 50%)'], -], { - shadowOffset: { width: 10, height: 20 }, - shadowRadius: 0, - shadowColor: 'hsl(120, 100%, 50%)', - shadowOpacity: 1, -})); - -it('transforms box-shadow with hsla color', () => runTest([ - ['box-shadow', '10px 20px hsla(120, 100%, 50%, 0.7)'], -], { - shadowOffset: { width: 10, height: 20 }, - shadowRadius: 0, - shadowColor: 'hsla(120, 100%, 50%, 0.7)', - shadowOpacity: 1, -})); - -it('transforms box-shadow and throws if multiple colors are used', () => { - expect(() => transformCss([['box-shadow', '0 0 0 red yellow green blue']])) - .toThrow('Failed to parse declaration "boxShadow: 0 0 0 red yellow green blue"'); +it("transforms box-shadow into shadow- properties", () => + runTest([["box-shadow", "10px 20px 30px red"]], { + shadowOffset: { width: 10, height: 20 }, + shadowRadius: 30, + shadowColor: "red", + shadowOpacity: 1 + })); + +it("transforms box-shadow without blur-radius", () => + runTest([["box-shadow", "10px 20px red"]], { + shadowOffset: { width: 10, height: 20 }, + shadowRadius: 0, + shadowColor: "red", + shadowOpacity: 1 + })); + +it("transforms box-shadow without color", () => + runTest([["box-shadow", "10px 20px 30px"]], { + shadowOffset: { width: 10, height: 20 }, + shadowRadius: 30, + shadowColor: "black", + shadowOpacity: 1 + })); + +it("transforms box-shadow without blur-radius, color", () => + runTest([["box-shadow", "10px 20px"]], { + shadowOffset: { width: 10, height: 20 }, + shadowRadius: 0, + shadowColor: "black", + shadowOpacity: 1 + })); + +it("transforms box-shadow with rgb color", () => + runTest([["box-shadow", "10px 20px rgb(100, 100, 100)"]], { + shadowOffset: { width: 10, height: 20 }, + shadowRadius: 0, + shadowColor: "rgb(100, 100, 100)", + shadowOpacity: 1 + })); + +it("transforms box-shadow with rgba color", () => + runTest([["box-shadow", "10px 20px rgba(100, 100, 100, 0.5)"]], { + shadowOffset: { width: 10, height: 20 }, + shadowRadius: 0, + shadowColor: "rgba(100, 100, 100, 0.5)", + shadowOpacity: 1 + })); + +it("transforms box-shadow with hsl color", () => + runTest([["box-shadow", "10px 20px hsl(120, 100%, 50%)"]], { + shadowOffset: { width: 10, height: 20 }, + shadowRadius: 0, + shadowColor: "hsl(120, 100%, 50%)", + shadowOpacity: 1 + })); + +it("transforms box-shadow with hsla color", () => + runTest([["box-shadow", "10px 20px hsla(120, 100%, 50%, 0.7)"]], { + shadowOffset: { width: 10, height: 20 }, + shadowRadius: 0, + shadowColor: "hsla(120, 100%, 50%, 0.7)", + shadowOpacity: 1 + })); + +it("transforms box-shadow and throws if multiple colors are used", () => { + expect(() => + transformCss([["box-shadow", "0 0 0 red yellow green blue"]]) + ).toThrow( + 'Failed to parse declaration "boxShadow: 0 0 0 red yellow green blue"' + ); }); -it('transforms box-shadow enforces offset to be present', () => { - expect(() => transformCss([['box-shadow', 'red']])) - .toThrow('Failed to parse declaration "boxShadow: red"'); +it("transforms box-shadow enforces offset to be present", () => { + expect(() => transformCss([["box-shadow", "red"]])).toThrow( + 'Failed to parse declaration "boxShadow: red"' + ); }); -it('transforms box-shadow and enforces offset-y if offset-x present', () => { - expect(() => transformCss([['box-shadow', '10px']])) - .toThrow('Failed to parse declaration "boxShadow: 10px"'); +it("transforms box-shadow and enforces offset-y if offset-x present", () => { + expect(() => transformCss([["box-shadow", "10px"]])).toThrow( + 'Failed to parse declaration "boxShadow: 10px"' + ); }); -it('allows blacklisting shorthands', () => { - const actualStyles = transformCss([['border-radius', '50']], ['borderRadius']); +it("allows blacklisting shorthands", () => { + const actualStyles = transformCss( + [["border-radius", "50"]], + ["borderRadius"] + ); expect(actualStyles).toEqual({ borderRadius: 50 }); }); -it('throws useful errors', () => { - expect(() => transformCss([['margin', '10']])) - .toThrow('Failed to parse declaration "margin: 10"'); +it("throws useful errors", () => { + expect(() => transformCss([["margin", "10"]])).toThrow( + 'Failed to parse declaration "margin: 10"' + ); }); diff --git a/src/tokenTypes.js b/src/tokenTypes.js index 0d1216e..891a518 100644 --- a/src/tokenTypes.js +++ b/src/tokenTypes.js @@ -1,22 +1,25 @@ -const { stringify } = require('postcss-value-parser'); -const cssColorKeywords = require('css-color-keywords'); +const { stringify } = require("postcss-value-parser"); +const cssColorKeywords = require("css-color-keywords"); -const matchString = (node) => { - if (node.type !== 'string') return null; +const matchString = node => { + if (node.type !== "string") return null; return node.value - .replace(/\\([0-9a-f]{1,6})(?:\s|$)/gi, (match, charCode) => ( + .replace(/\\([0-9a-f]{1,6})(?:\s|$)/gi, (match, charCode) => String.fromCharCode(parseInt(charCode, 16)) - )) - .replace(/\\/g, ''); + ) + .replace(/\\/g, ""); }; const hexColorRe = /^(#(?:[0-9a-f]{3,4}){1,2})$/i; const cssFunctionNameRe = /^(rgba?|hsla?|hwb|lab|lch|gray|color)$/; -const matchColor = (node) => { - if (node.type === 'word' && (hexColorRe.test(node.value) || node.value in cssColorKeywords)) { +const matchColor = node => { + if ( + node.type === "word" && + (hexColorRe.test(node.value) || node.value in cssColorKeywords) + ) { return node.value; - } else if (node.type === 'function' && cssFunctionNameRe.test(node.value)) { + } else if (node.type === "function" && cssFunctionNameRe.test(node.value)) { return stringify(node); } return null; @@ -32,12 +35,13 @@ const lengthRe = /^(0$|(?:[+-]?(?:\d*\.)?\d+(?:[Ee][+-]?\d+)?)(?=px$))/; const angleRe = /^([+-]?(?:\d*\.)?\d+(?:[Ee][+-]?\d+)?(?:deg|rad))$/; const percentRe = /^([+-]?(?:\d*\.)?\d+(?:[Ee][+-]?\d+)?%)$/; -const noopToken = predicate => node => (predicate(node) ? '' : null); +const noopToken = predicate => node => (predicate(node) ? "" : null); -const valueForTypeToken = type => node => (node.type === type ? node.value : null); +const valueForTypeToken = type => node => + node.type === type ? node.value : null; -const regExpToken = (regExp, transform = String) => (node) => { - if (node.type !== 'word') return null; +const regExpToken = (regExp, transform = String) => node => { + if (node.type !== "word") return null; const match = node.value.match(regExp); if (match === null) return null; @@ -50,10 +54,10 @@ const regExpToken = (regExp, transform = String) => (node) => { module.exports.regExpToken = regExpToken; module.exports.tokens = { - SPACE: noopToken(node => node.type === 'space'), - SLASH: noopToken(node => node.type === 'div' && node.value === '/'), - COMMA: noopToken(node => node.type === 'div' && node.value === ','), - WORD: valueForTypeToken('word'), + SPACE: noopToken(node => node.type === "space"), + SLASH: noopToken(node => node.type === "div" && node.value === "/"), + COMMA: noopToken(node => node.type === "div" && node.value === ","), + WORD: valueForTypeToken("word"), NONE: regExpToken(noneRe), AUTO: regExpToken(autoRe), NUMBER: regExpToken(numberRe, Number), @@ -62,5 +66,5 @@ module.exports.tokens = { PERCENT: regExpToken(percentRe), IDENT: regExpToken(identRe), STRING: matchString, - COLOR: matchColor, + COLOR: matchColor }; diff --git a/src/transforms/boxShadow.js b/src/transforms/boxShadow.js index f0198e2..f687991 100644 --- a/src/transforms/boxShadow.js +++ b/src/transforms/boxShadow.js @@ -1,8 +1,8 @@ -const { tokens } = require('../tokenTypes'); +const { tokens } = require("../tokenTypes"); const { NONE, SPACE, COLOR, LENGTH } = tokens; -module.exports = (tokenStream) => { +module.exports = tokenStream => { let offsetX; let offsetY; let blurRadius; @@ -11,7 +11,12 @@ module.exports = (tokenStream) => { if (tokenStream.matches(NONE)) { tokenStream.expectEmpty(); return { - $merge: { shadowOffset: { width: 0, height: 0 }, shadowRadius: 0, shadowColor: 'black', shadowOpacity: 1 }, + $merge: { + shadowOffset: { width: 0, height: 0 }, + shadowRadius: 0, + shadowColor: "black", + shadowOpacity: 1 + } }; } @@ -24,9 +29,11 @@ module.exports = (tokenStream) => { tokenStream.expect(SPACE); offsetY = tokenStream.expect(LENGTH); - if (tokenStream.lookAhead().matches(LENGTH)) { - tokenStream.expect(SPACE); - blurRadius = tokenStream.expect(LENGTH); + tokenStream.saveRewindPoint(); + if (tokenStream.matches(SPACE) && tokenStream.matches(LENGTH)) { + blurRadius = tokenStream.lastValue; + } else { + tokenStream.rewind(); } } else if (color === undefined && tokenStream.matches(COLOR)) { color = tokenStream.lastValue; @@ -42,8 +49,8 @@ module.exports = (tokenStream) => { const $merge = { shadowOffset: { width: offsetX, height: offsetY }, shadowRadius: blurRadius !== undefined ? blurRadius : 0, - shadowColor: color !== undefined ? color : 'black', - shadowOpacity: 1, + shadowColor: color !== undefined ? color : "black", + shadowOpacity: 1 }; return { $merge }; }; diff --git a/src/transforms/flex.js b/src/transforms/flex.js index b76fdf8..e819560 100644 --- a/src/transforms/flex.js +++ b/src/transforms/flex.js @@ -1,4 +1,4 @@ -const { tokens } = require('../tokenTypes'); +const { tokens } = require("../tokenTypes"); const { NONE, AUTO, NUMBER, LENGTH, SPACE } = tokens; @@ -8,7 +8,7 @@ const defaultFlexBasis = 0; const FLEX_BASIS_AUTO = {}; // Used for reference equality -module.exports = (tokenStream) => { +module.exports = tokenStream => { let flexGrow; let flexShrink; let flexBasis; @@ -16,9 +16,13 @@ module.exports = (tokenStream) => { if (tokenStream.matches(NONE)) { tokenStream.expectEmpty(); return { $merge: { flexGrow: 0, flexShrink: 0 } }; - } else if (tokenStream.test(AUTO) && !tokenStream.lookAhead().hasTokens()) { + } + + tokenStream.saveRewindPoint(); + if (tokenStream.matches(AUTO) && !tokenStream.hasTokens()) { return { $merge: { flexGrow: 1, flexShrink: 1 } }; } + tokenStream.rewind(); let partsParsed = 0; while (partsParsed < 2 && tokenStream.hasTokens()) { @@ -27,9 +31,11 @@ module.exports = (tokenStream) => { if (flexGrow === undefined && tokenStream.matches(NUMBER)) { flexGrow = tokenStream.lastValue; - if (tokenStream.lookAhead().matches(NUMBER)) { - tokenStream.expect(SPACE); - flexShrink = tokenStream.expect(NUMBER); + tokenStream.saveRewindPoint(); + if (tokenStream.matches(SPACE) && tokenStream.matches(NUMBER)) { + flexShrink = tokenStream.lastValue; + } else { + tokenStream.rewind(); } } else if (flexBasis === undefined && tokenStream.matches(LENGTH)) { flexBasis = tokenStream.lastValue; diff --git a/src/transforms/font.js b/src/transforms/font.js index c7b02e6..5f2991e 100644 --- a/src/transforms/font.js +++ b/src/transforms/font.js @@ -1,5 +1,5 @@ -const parseFontFamily = require('./fontFamily'); -const { regExpToken, tokens } = require('../tokenTypes'); +const parseFontFamily = require("./fontFamily"); +const { regExpToken, tokens } = require("../tokenTypes"); const { SPACE, LENGTH, NUMBER, SLASH } = tokens; const NORMAL = regExpToken(/^(normal)$/); @@ -7,11 +7,11 @@ const STYLE = regExpToken(/^(italic)$/); const WEIGHT = regExpToken(/^([1-9]00|bold)$/); const VARIANT = regExpToken(/^(small-caps)$/); -const defaultFontStyle = 'normal'; -const defaultFontWeight = 'normal'; +const defaultFontStyle = "normal"; +const defaultFontWeight = "normal"; const defaultFontVariant = []; -module.exports = (tokenStream) => { +module.exports = tokenStream => { let fontStyle; let fontWeight; let fontVariant; diff --git a/src/transforms/fontFamily.js b/src/transforms/fontFamily.js index 3b3f368..f3449a8 100644 --- a/src/transforms/fontFamily.js +++ b/src/transforms/fontFamily.js @@ -1,8 +1,8 @@ -const { tokens } = require('../tokenTypes'); +const { tokens } = require("../tokenTypes"); const { SPACE, IDENT, STRING } = tokens; -module.exports = (tokenStream) => { +module.exports = tokenStream => { let fontFamily; if (tokenStream.matches(STRING)) { diff --git a/src/transforms/index.js b/src/transforms/index.js index 960e229..e241d7f 100644 --- a/src/transforms/index.js +++ b/src/transforms/index.js @@ -1,50 +1,56 @@ -const { regExpToken, tokens } = require('../tokenTypes'); -const boxShadow = require('./boxShadow'); -const flex = require('./flex'); -const font = require('./font'); -const fontFamily = require('./fontFamily'); -const transform = require('./transform'); -const { directionFactory, anyOrderFactory, shadowOffsetFactory } = require('./util'); +const { regExpToken, tokens } = require("../tokenTypes"); +const boxShadow = require("./boxShadow"); +const flex = require("./flex"); +const font = require("./font"); +const fontFamily = require("./fontFamily"); +const transform = require("./transform"); +const { + directionFactory, + anyOrderFactory, + shadowOffsetFactory +} = require("./util"); const { IDENT, WORD, COLOR } = tokens; -const background = tokenStream => ({ $merge: { backgroundColor: tokenStream.expect(COLOR) } }); +const background = tokenStream => ({ + $merge: { backgroundColor: tokenStream.expect(COLOR) } +}); const border = anyOrderFactory({ borderWidth: { token: tokens.LENGTH, - default: 1, + default: 1 }, borderColor: { token: COLOR, - default: 'black', + default: "black" }, borderStyle: { token: regExpToken(/^(solid|dashed|dotted)$/), - default: 'solid', - }, + default: "solid" + } }); const borderColor = directionFactory({ types: [WORD], - prefix: 'border', - suffix: 'Color', + prefix: "border", + suffix: "Color" }); const borderRadius = directionFactory({ - directions: ['TopRight', 'BottomRight', 'BottomLeft', 'TopLeft'], - prefix: 'border', - suffix: 'Radius', + directions: ["TopRight", "BottomRight", "BottomLeft", "TopLeft"], + prefix: "border", + suffix: "Radius" }); -const borderWidth = directionFactory({ prefix: 'border', suffix: 'Width' }); -const margin = directionFactory({ prefix: 'margin' }); -const padding = directionFactory({ prefix: 'padding' }); +const borderWidth = directionFactory({ prefix: "border", suffix: "Width" }); +const margin = directionFactory({ prefix: "margin" }); +const padding = directionFactory({ prefix: "padding" }); const flexFlow = anyOrderFactory({ flexWrap: { token: regExpToken(/(nowrap|wrap|wrap-reverse)/), - default: 'nowrap', + default: "nowrap" }, flexDirection: { token: regExpToken(/(row|row-reverse|column|column-reverse)/), - default: 'row', - }, + default: "row" + } }); const fontVariant = tokenStream => [tokenStream.expect(IDENT)]; const fontWeight = tokenStream => tokenStream.expect(WORD); // Also match numbers as strings @@ -68,5 +74,5 @@ module.exports = { padding, shadowOffset, textShadowOffset, - transform, + transform }; diff --git a/src/transforms/transform.js b/src/transforms/transform.js index 5b434c7..5ba89aa 100644 --- a/src/transforms/transform.js +++ b/src/transforms/transform.js @@ -1,8 +1,8 @@ -const { tokens } = require('../tokenTypes'); +const { tokens } = require("../tokenTypes"); const { SPACE, COMMA, LENGTH, NUMBER, ANGLE } = tokens; -const oneOfType = tokenType => (functionStream) => { +const oneOfType = tokenType => functionStream => { const value = functionStream.expect(tokenType); functionStream.expectEmpty(); return value; @@ -11,7 +11,10 @@ const oneOfType = tokenType => (functionStream) => { const singleNumber = oneOfType(NUMBER); const singleLength = oneOfType(LENGTH); const singleAngle = oneOfType(ANGLE); -const xyTransformFactory = tokenType => (key, valueIfOmitted) => (functionStream) => { +const xyTransformFactory = tokenType => ( + key, + valueIfOmitted +) => functionStream => { const x = functionStream.expect(tokenType); let y; @@ -36,10 +39,10 @@ const xyAngle = xyTransformFactory(ANGLE); const partTransforms = { perspective: singleNumber, - scale: xyNumber('scale'), + scale: xyNumber("scale"), scaleX: singleNumber, scaleY: singleNumber, - translate: xyLength('translate', 0), + translate: xyLength("translate", 0), translateX: singleLength, translateY: singleLength, rotate: singleAngle, @@ -48,10 +51,10 @@ const partTransforms = { rotateZ: singleAngle, skewX: singleAngle, skewY: singleAngle, - skew: xyAngle('skew', '0deg'), + skew: xyAngle("skew", "0deg") }; -module.exports = (tokenStream) => { +module.exports = tokenStream => { let transforms = []; let didParseFirst = false; @@ -59,10 +62,10 @@ module.exports = (tokenStream) => { if (didParseFirst) tokenStream.expect(SPACE); const functionStream = tokenStream.expectFunction(); - const transformName = functionStream.parent.value; - let transformedValues = partTransforms[transformName](functionStream); + const { functionName } = functionStream; + let transformedValues = partTransforms[functionName](functionStream); if (!Array.isArray(transformedValues)) { - transformedValues = [{ [transformName]: transformedValues }]; + transformedValues = [{ [functionName]: transformedValues }]; } transforms = transformedValues.concat(transforms); diff --git a/src/transforms/util.js b/src/transforms/util.js index 03bdcf1..2a4038e 100644 --- a/src/transforms/util.js +++ b/src/transforms/util.js @@ -1,13 +1,13 @@ -const { tokens } = require('../tokenTypes'); +const { tokens } = require("../tokenTypes"); const { LENGTH, PERCENT, SPACE } = tokens; module.exports.directionFactory = ({ types = [LENGTH, PERCENT], - directions = ['Top', 'Right', 'Bottom', 'Left'], - prefix = '', - suffix = '', -}) => (tokenStream) => { + directions = ["Top", "Right", "Bottom", "Left"], + prefix = "", + suffix = "" +}) => tokenStream => { const values = []; // borderWidth doesn't currently allow a percent value, but may do in the future @@ -28,13 +28,13 @@ module.exports.directionFactory = ({ [keyFor(0)]: top, [keyFor(1)]: right, [keyFor(2)]: bottom, - [keyFor(3)]: left, + [keyFor(3)]: left }; return { $merge: output }; }; -module.exports.anyOrderFactory = (properties, delim = SPACE) => (tokenStream) => { +module.exports.anyOrderFactory = (properties, delim = SPACE) => tokenStream => { const propertyNames = Object.keys(properties); const values = propertyNames.reduce((accum, propertyName) => { accum[propertyName] === undefined; // eslint-disable-line @@ -45,9 +45,11 @@ module.exports.anyOrderFactory = (properties, delim = SPACE) => (tokenStream) => while (numParsed < propertyNames.length && tokenStream.hasTokens()) { if (numParsed) tokenStream.expect(delim); - const matchedPropertyName = propertyNames.find(propertyName => ( - values[propertyName] === undefined && tokenStream.matches(properties[propertyName].token) - )); + const matchedPropertyName = propertyNames.find( + propertyName => + values[propertyName] === undefined && + tokenStream.matches(properties[propertyName].token) + ); if (!matchedPropertyName) { tokenStream.throw(); @@ -60,14 +62,15 @@ module.exports.anyOrderFactory = (properties, delim = SPACE) => (tokenStream) => tokenStream.expectEmpty(); - propertyNames.forEach((propertyName) => { - if (values[propertyName] === undefined) values[propertyName] = properties[propertyName].default; + propertyNames.forEach(propertyName => { + if (values[propertyName] === undefined) + values[propertyName] = properties[propertyName].default; }); return { $merge: values }; }; -module.exports.shadowOffsetFactory = () => (tokenStream) => { +module.exports.shadowOffsetFactory = () => tokenStream => { const width = tokenStream.expect(LENGTH); const height = tokenStream.matches(SPACE) ? tokenStream.expect(LENGTH) diff --git a/yarn.lock b/yarn.lock index 62ec6e2..a5f7203 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1078,6 +1078,12 @@ eslint-config-airbnb-base@^10.0.1: version "10.0.1" resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-10.0.1.tgz#f17d4e52992c1d45d1b7713efbcd5ecd0e7e0506" +eslint-config-prettier@^2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-2.9.0.tgz#5ecd65174d486c22dff389fe036febf502d468a3" + dependencies: + get-stdin "^5.0.1" + eslint-import-resolver-node@^0.2.0: version "0.2.3" resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.2.3.tgz#5add8106e8c928db2cba232bcd9efa846e3da16c" @@ -1387,6 +1393,10 @@ get-caller-file@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5" +get-stdin@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-5.0.1.tgz#122e161591e21ff4c52530305693f20e6393a398" + getpass@^0.1.1: version "0.1.6" resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.6.tgz#283ffd9fc1256840875311c1b60e8c40187110e6" @@ -2556,6 +2566,10 @@ preserve@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" +prettier@^1.10.2: + version "1.10.2" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.10.2.tgz#1af8356d1842276a99a5b5529c82dd9e9ad3cc93" + pretty-format@~4.2.1: version "4.2.3" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-4.2.3.tgz#8894c2ac81419cf801629d8f66320a25380d8b05" From 4db60e4a1d93f0816f7afef661e07eda8ce4e3f8 Mon Sep 17 00:00:00 2001 From: Jacob Parker Date: Sun, 4 Feb 2018 18:28:25 +0000 Subject: [PATCH 2/3] Update prettier to match main repo --- .prettierrc | 5 + .travis.yml | 1 - src/TokenStream.js | 66 +-- src/index.js | 74 ++-- src/index.test.js | 815 +++++++++++++++++------------------ src/tokenTypes.js | 70 +-- src/transforms/boxShadow.js | 56 +-- src/transforms/flex.js | 60 +-- src/transforms/font.js | 66 +-- src/transforms/fontFamily.js | 22 +- src/transforms/index.js | 72 ++-- src/transforms/transform.js | 72 ++-- src/transforms/util.js | 74 ++-- 13 files changed, 726 insertions(+), 727 deletions(-) create mode 100644 .prettierrc diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..36301bc --- /dev/null +++ b/.prettierrc @@ -0,0 +1,5 @@ +{ + "semi": false, + "singleQuote": true, + "trailingComma": "es5" +} diff --git a/.travis.yml b/.travis.yml index 03c7111..467b86f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,3 @@ - language: node_js dist: trusty node_js: diff --git a/src/TokenStream.js b/src/TokenStream.js index bcbbfa0..4dd8a48 100644 --- a/src/TokenStream.js +++ b/src/TokenStream.js @@ -1,74 +1,74 @@ -const SYMBOL_MATCH = "SYMBOL_MATCH"; +const SYMBOL_MATCH = 'SYMBOL_MATCH' module.exports = class TokenStream { constructor(nodes, parent) { - this.index = 0; - this.nodes = nodes; - this.functionName = parent != null ? parent.value : null; - this.lastValue = null; - this.rewindIndex = -1; + this.index = 0 + this.nodes = nodes + this.functionName = parent != null ? parent.value : null + this.lastValue = null + this.rewindIndex = -1 } hasTokens() { - return this.index <= this.nodes.length - 1; + return this.index <= this.nodes.length - 1 } [SYMBOL_MATCH](...tokenDescriptors) { - if (!this.hasTokens()) return null; + if (!this.hasTokens()) return null - const node = this.nodes[this.index]; + const node = this.nodes[this.index] for (let i = 0; i < tokenDescriptors.length; i += 1) { - const tokenDescriptor = tokenDescriptors[i]; - const value = tokenDescriptor(node); + const tokenDescriptor = tokenDescriptors[i] + const value = tokenDescriptor(node) if (value !== null) { - this.index += 1; - this.lastValue = value; - return value; + this.index += 1 + this.lastValue = value + return value } } - return null; + return null } matches(...tokenDescriptors) { - return this[SYMBOL_MATCH](...tokenDescriptors) !== null; + return this[SYMBOL_MATCH](...tokenDescriptors) !== null } expect(...tokenDescriptors) { - const value = this[SYMBOL_MATCH](...tokenDescriptors); - return value !== null ? value : this.throw(); + const value = this[SYMBOL_MATCH](...tokenDescriptors) + return value !== null ? value : this.throw() } matchesFunction() { - const node = this.nodes[this.index]; - if (node.type !== "function") return null; - const value = new TokenStream(node.nodes, node); - this.index += 1; - this.lastValue = null; - return value; + const node = this.nodes[this.index] + if (node.type !== 'function') return null + const value = new TokenStream(node.nodes, node) + this.index += 1 + this.lastValue = null + return value } expectFunction() { - const value = this.matchesFunction(); - return value !== null ? value : this.throw(); + const value = this.matchesFunction() + return value !== null ? value : this.throw() } expectEmpty() { - if (this.hasTokens()) this.throw(); + if (this.hasTokens()) this.throw() } throw() { - throw new Error(`Unexpected token type: ${this.nodes[this.index].type}`); + throw new Error(`Unexpected token type: ${this.nodes[this.index].type}`) } saveRewindPoint() { - this.rewindIndex = this.index; + this.rewindIndex = this.index } rewind() { - if (this.rewindIndex === -1) throw new Error("Internal error"); - this.index = this.rewindIndex; - this.lastValue = null; + if (this.rewindIndex === -1) throw new Error('Internal error') + this.index = this.rewindIndex + this.lastValue = null } -}; +} diff --git a/src/index.js b/src/index.js index 8fa30fe..5ade741 100644 --- a/src/index.js +++ b/src/index.js @@ -1,73 +1,73 @@ /* eslint-disable no-param-reassign */ -const parse = require("postcss-value-parser"); -const camelizeStyleName = require("fbjs/lib/camelizeStyleName"); -const transforms = require("./transforms"); -const TokenStream = require("./TokenStream"); +const parse = require('postcss-value-parser') +const camelizeStyleName = require('fbjs/lib/camelizeStyleName') +const transforms = require('./transforms') +const TokenStream = require('./TokenStream') // Note if this is wrong, you'll need to change tokenTypes.js too -const numberOrLengthRe = /^([+-]?(?:\d*\.)?\d+(?:[Ee][+-]?\d+)?)(?:px)?$/i; -const boolRe = /^true|false$/i; -const nullRe = /^null$/i; -const undefinedRe = /^undefined$/i; +const numberOrLengthRe = /^([+-]?(?:\d*\.)?\d+(?:[Ee][+-]?\d+)?)(?:px)?$/i +const boolRe = /^true|false$/i +const nullRe = /^null$/i +const undefinedRe = /^undefined$/i // Undocumented export export const transformRawValue = input => { - const value = input.trim(); + const value = input.trim() - const numberMatch = value.match(numberOrLengthRe); - if (numberMatch !== null) return Number(numberMatch[1]); + const numberMatch = value.match(numberOrLengthRe) + if (numberMatch !== null) return Number(numberMatch[1]) - const boolMatch = input.match(boolRe); - if (boolMatch !== null) return boolMatch[0].toLowerCase() === "true"; + const boolMatch = input.match(boolRe) + if (boolMatch !== null) return boolMatch[0].toLowerCase() === 'true' - const nullMatch = input.match(nullRe); - if (nullMatch !== null) return null; + const nullMatch = input.match(nullRe) + if (nullMatch !== null) return null - const undefinedMatch = input.match(undefinedRe); - if (undefinedMatch !== null) return undefined; + const undefinedMatch = input.match(undefinedRe) + if (undefinedMatch !== null) return undefined - return value; -}; + return value +} const baseTransformShorthandValue = (propName, inputValue) => { - const ast = parse(inputValue.trim()); - const tokenStream = new TokenStream(ast.nodes); - return transforms[propName](tokenStream); -}; + const ast = parse(inputValue.trim()) + const tokenStream = new TokenStream(ast.nodes) + return transforms[propName](tokenStream) +} const transformShorthandValue = - process.env.NODE_ENV === "production" + process.env.NODE_ENV === 'production' ? baseTransformShorthandValue : (propName, inputValue) => { try { - return baseTransformShorthandValue(propName, inputValue); + return baseTransformShorthandValue(propName, inputValue) } catch (e) { throw new Error( `Failed to parse declaration "${propName}: ${inputValue}"` - ); + ) } - }; + } export const getStylesForProperty = (propName, inputValue, allowShorthand) => { - const isRawValue = allowShorthand === false || !(propName in transforms); + const isRawValue = allowShorthand === false || !(propName in transforms) const propValue = isRawValue ? transformRawValue(inputValue) - : transformShorthandValue(propName, inputValue.trim()); + : transformShorthandValue(propName, inputValue.trim()) return propValue && propValue.$merge ? propValue.$merge - : { [propName]: propValue }; -}; + : { [propName]: propValue } +} -export const getPropertyName = camelizeStyleName; +export const getPropertyName = camelizeStyleName export default (rules, shorthandBlacklist = []) => rules.reduce((accum, rule) => { - const propertyName = getPropertyName(rule[0]); - const value = rule[1]; - const allowShorthand = shorthandBlacklist.indexOf(propertyName) === -1; + const propertyName = getPropertyName(rule[0]) + const value = rule[1] + const allowShorthand = shorthandBlacklist.indexOf(propertyName) === -1 return Object.assign( accum, getStylesForProperty(propertyName, value, allowShorthand) - ); - }, {}); + ) + }, {}) diff --git a/src/index.test.js b/src/index.test.js index 2222c61..3375f70 100644 --- a/src/index.test.js +++ b/src/index.test.js @@ -1,572 +1,569 @@ /* global jest it, expect */ -import transformCss, { getStylesForProperty } from "."; +import transformCss, { getStylesForProperty } from '.' const runTest = (inputCss, expectedStyles) => { - const actualStyles = transformCss(inputCss); - expect(actualStyles).toEqual(expectedStyles); -}; + const actualStyles = transformCss(inputCss) + expect(actualStyles).toEqual(expectedStyles) +} -it("transforms numbers", () => - runTest([["top", "0"], ["left", "0"], ["right", "0"], ["bottom", "0"]], { +it('transforms numbers', () => + runTest([['top', '0'], ['left', '0'], ['right', '0'], ['bottom', '0']], { top: 0, left: 0, right: 0, - bottom: 0 - })); + bottom: 0, + })) -it("allows pixels in unspecialized transform", () => - runTest([["top", "0px"]], { top: 0 })); +it('allows pixels in unspecialized transform', () => + runTest([['top', '0px']], { top: 0 })) -it("allows boolean values", () => +it('allows boolean values', () => runTest( [ - ["boolTrue1", "true"], - ["boolTrue2", "TRUE"], - ["boolFalse1", "false"], - ["boolFalse2", "FALSE"] + ['boolTrue1', 'true'], + ['boolTrue2', 'TRUE'], + ['boolFalse1', 'false'], + ['boolFalse2', 'FALSE'], ], { boolTrue1: true, boolTrue2: true, boolFalse1: false, - boolFalse2: false + boolFalse2: false, } - )); + )) -it("allows null values", () => - runTest([["null1", "null"], ["null2", "NULL"]], { +it('allows null values', () => + runTest([['null1', 'null'], ['null2', 'NULL']], { null1: null, - null2: null - })); + null2: null, + })) -it("allows undefined values", () => - runTest([["undefined1", "undefined"], ["undefined2", "UNDEFINED"]], { +it('allows undefined values', () => + runTest([['undefined1', 'undefined'], ['undefined2', 'UNDEFINED']], { undefined1: undefined, - undefined2: undefined - })); - -it("allows percent in unspecialized transform", () => - runTest([["top", "0%"]], { top: "0%" })); - -it("allows decimal values", () => { - expect(getStylesForProperty("margin", "0.5px").marginTop).toBe(0.5); - expect(getStylesForProperty("margin", "1.5px").marginTop).toBe(1.5); - expect(getStylesForProperty("margin", "10.5px").marginTop).toBe(10.5); - expect(getStylesForProperty("margin", "100.5px").marginTop).toBe(100.5); - expect(getStylesForProperty("margin", "-0.5px").marginTop).toBe(-0.5); - expect(getStylesForProperty("margin", "-1.5px").marginTop).toBe(-1.5); - expect(getStylesForProperty("margin", "-10.5px").marginTop).toBe(-10.5); - expect(getStylesForProperty("margin", "-100.5px").marginTop).toBe(-100.5); - expect(getStylesForProperty("margin", ".5px").marginTop).toBe(0.5); - expect(getStylesForProperty("margin", "-.5px").marginTop).toBe(-0.5); -}); - -it("allows decimal values in transformed values", () => - runTest([["border-radius", "1.5px"]], { + undefined2: undefined, + })) + +it('allows percent in unspecialized transform', () => + runTest([['top', '0%']], { top: '0%' })) + +it('allows decimal values', () => { + expect(getStylesForProperty('margin', '0.5px').marginTop).toBe(0.5) + expect(getStylesForProperty('margin', '1.5px').marginTop).toBe(1.5) + expect(getStylesForProperty('margin', '10.5px').marginTop).toBe(10.5) + expect(getStylesForProperty('margin', '100.5px').marginTop).toBe(100.5) + expect(getStylesForProperty('margin', '-0.5px').marginTop).toBe(-0.5) + expect(getStylesForProperty('margin', '-1.5px').marginTop).toBe(-1.5) + expect(getStylesForProperty('margin', '-10.5px').marginTop).toBe(-10.5) + expect(getStylesForProperty('margin', '-100.5px').marginTop).toBe(-100.5) + expect(getStylesForProperty('margin', '.5px').marginTop).toBe(0.5) + expect(getStylesForProperty('margin', '-.5px').marginTop).toBe(-0.5) +}) + +it('allows decimal values in transformed values', () => + runTest([['border-radius', '1.5px']], { borderTopLeftRadius: 1.5, borderTopRightRadius: 1.5, borderBottomRightRadius: 1.5, - borderBottomLeftRadius: 1.5 - })); + borderBottomLeftRadius: 1.5, + })) -it("allows negative values in transformed values", () => - runTest([["border-radius", "-1.5px"]], { +it('allows negative values in transformed values', () => + runTest([['border-radius', '-1.5px']], { borderTopLeftRadius: -1.5, borderTopRightRadius: -1.5, borderBottomRightRadius: -1.5, - borderBottomLeftRadius: -1.5 - })); - -it("allows percent values in transformed values", () => - runTest([["margin", "10%"]], { - marginTop: "10%", - marginRight: "10%", - marginBottom: "10%", - marginLeft: "10%" - })); - -it("allows color values in transformed border-color values", () => - runTest([["border-color", "red"]], { - borderTopColor: "red", - borderRightColor: "red", - borderBottomColor: "red", - borderLeftColor: "red" - })); - -it("allows omitting units for 0", () => - runTest([["margin", "10px 0"]], { + borderBottomLeftRadius: -1.5, + })) + +it('allows percent values in transformed values', () => + runTest([['margin', '10%']], { + marginTop: '10%', + marginRight: '10%', + marginBottom: '10%', + marginLeft: '10%', + })) + +it('allows color values in transformed border-color values', () => + runTest([['border-color', 'red']], { + borderTopColor: 'red', + borderRightColor: 'red', + borderBottomColor: 'red', + borderLeftColor: 'red', + })) + +it('allows omitting units for 0', () => + runTest([['margin', '10px 0']], { marginTop: 10, marginRight: 0, marginBottom: 10, - marginLeft: 0 - })); + marginLeft: 0, + })) -it("transforms strings", () => runTest([["color", "red"]], { color: "red" })); +it('transforms strings', () => runTest([['color', 'red']], { color: 'red' })) -it("transforms hex colors", () => - runTest([["color", "#f00"]], { color: "#f00" })); +it('transforms hex colors', () => + runTest([['color', '#f00']], { color: '#f00' })) -it("transforms rgb colors", () => - runTest([["color", "rgb(255, 0, 0)"]], { color: "rgb(255, 0, 0)" })); +it('transforms rgb colors', () => + runTest([['color', 'rgb(255, 0, 0)']], { color: 'rgb(255, 0, 0)' })) -it("converts to camel-case", () => - runTest([["background-color", "red"]], { backgroundColor: "red" })); +it('converts to camel-case', () => + runTest([['background-color', 'red']], { backgroundColor: 'red' })) -it("transforms background to backgroundColor", () => - runTest([["background", "#f00"]], { backgroundColor: "#f00" })); +it('transforms background to backgroundColor', () => + runTest([['background', '#f00']], { backgroundColor: '#f00' })) -it("transforms background to backgroundColor with rgb", () => - runTest([["background", "rgb(255, 0, 0)"]], { - backgroundColor: "rgb(255, 0, 0)" - })); +it('transforms background to backgroundColor with rgb', () => + runTest([['background', 'rgb(255, 0, 0)']], { + backgroundColor: 'rgb(255, 0, 0)', + })) -it("transforms background to backgroundColor with named colour", () => - runTest([["background", "red"]], { backgroundColor: "red" })); +it('transforms background to backgroundColor with named colour', () => + runTest([['background', 'red']], { backgroundColor: 'red' })) -it("transforms font weights as strings", () => - runTest([["font-weight", " 400"]], { fontWeight: "400" })); +it('transforms font weights as strings', () => + runTest([['font-weight', ' 400']], { fontWeight: '400' })) -it("transforms font variant as an array", () => - runTest([["font-variant", "tabular-nums"]], { - fontVariant: ["tabular-nums"] - })); +it('transforms font variant as an array', () => + runTest([['font-variant', 'tabular-nums']], { + fontVariant: ['tabular-nums'], + })) -it("transforms shadow offsets", () => - runTest([["shadow-offset", "10px 5px"]], { - shadowOffset: { width: 10, height: 5 } - })); +it('transforms shadow offsets', () => + runTest([['shadow-offset', '10px 5px']], { + shadowOffset: { width: 10, height: 5 }, + })) -it("transforms text shadow offsets", () => - runTest([["text-shadow-offset", "10px 5px"]], { - textShadowOffset: { width: 10, height: 5 } - })); +it('transforms text shadow offsets', () => + runTest([['text-shadow-offset', '10px 5px']], { + textShadowOffset: { width: 10, height: 5 }, + })) -it("transforms a single transform value with number", () => - runTest([["transform", "scaleX(5)"]], { transform: [{ scaleX: 5 }] })); +it('transforms a single transform value with number', () => + runTest([['transform', 'scaleX(5)']], { transform: [{ scaleX: 5 }] })) -it("transforms a single transform value with string", () => - runTest([["transform", "rotate(5deg)"]], { - transform: [{ rotate: "5deg" }] - })); +it('transforms a single transform value with string', () => + runTest([['transform', 'rotate(5deg)']], { + transform: [{ rotate: '5deg' }], + })) -it("transforms multiple transform values", () => - runTest([["transform", "scaleX(5) skewX(1deg)"]], { - transform: [{ skewX: "1deg" }, { scaleX: 5 }] - })); +it('transforms multiple transform values', () => + runTest([['transform', 'scaleX(5) skewX(1deg)']], { + transform: [{ skewX: '1deg' }, { scaleX: 5 }], + })) -it("transforms scale(number, number) to scaleX and scaleY", () => - runTest([["transform", "scale(2, 3)"]], { - transform: [{ scaleY: 3 }, { scaleX: 2 }] - })); +it('transforms scale(number, number) to scaleX and scaleY', () => + runTest([['transform', 'scale(2, 3)']], { + transform: [{ scaleY: 3 }, { scaleX: 2 }], + })) -it("transforms scale(number) to scale", () => - runTest([["transform", "scale(5)"]], { transform: [{ scale: 5 }] })); +it('transforms scale(number) to scale', () => + runTest([['transform', 'scale(5)']], { transform: [{ scale: 5 }] })) -it("transforms translate(length, length) to translateX and translateY", () => - runTest([["transform", "translate(2px, 3px)"]], { - transform: [{ translateY: 3 }, { translateX: 2 }] - })); +it('transforms translate(length, length) to translateX and translateY', () => + runTest([['transform', 'translate(2px, 3px)']], { + transform: [{ translateY: 3 }, { translateX: 2 }], + })) -it("transforms translate(length) to translateX and translateY", () => - runTest([["transform", "translate(5px)"]], { - transform: [{ translateY: 0 }, { translateX: 5 }] - })); +it('transforms translate(length) to translateX and translateY', () => + runTest([['transform', 'translate(5px)']], { + transform: [{ translateY: 0 }, { translateX: 5 }], + })) -it("transforms skew(angle, angle) to skewX and skewY", () => - runTest([["transform", "skew(2deg, 3deg)"]], { - transform: [{ skewY: "3deg" }, { skewX: "2deg" }] - })); +it('transforms skew(angle, angle) to skewX and skewY', () => + runTest([['transform', 'skew(2deg, 3deg)']], { + transform: [{ skewY: '3deg' }, { skewX: '2deg' }], + })) -it("transforms skew(angle) to skewX and skewY", () => - runTest([["transform", "skew(5deg)"]], { - transform: [{ skewY: "0deg" }, { skewX: "5deg" }] - })); +it('transforms skew(angle) to skewX and skewY', () => + runTest([['transform', 'skew(5deg)']], { + transform: [{ skewY: '0deg' }, { skewX: '5deg' }], + })) -it("transforms border shorthand", () => - runTest([["border", "2px dashed #f00"]], { +it('transforms border shorthand', () => + runTest([['border', '2px dashed #f00']], { borderWidth: 2, - borderColor: "#f00", - borderStyle: "dashed" - })); + borderColor: '#f00', + borderStyle: 'dashed', + })) -it("transforms border shorthand in other order", () => - runTest([["border", "#f00 2px dashed"]], { +it('transforms border shorthand in other order', () => + runTest([['border', '#f00 2px dashed']], { borderWidth: 2, - borderColor: "#f00", - borderStyle: "dashed" - })); + borderColor: '#f00', + borderStyle: 'dashed', + })) -it("transforms border shorthand missing color", () => - runTest([["border", "2px dashed"]], { +it('transforms border shorthand missing color', () => + runTest([['border', '2px dashed']], { borderWidth: 2, - borderColor: "black", - borderStyle: "dashed" - })); + borderColor: 'black', + borderStyle: 'dashed', + })) -it("transforms border shorthand missing style", () => - runTest([["border", "2px #f00"]], { +it('transforms border shorthand missing style', () => + runTest([['border', '2px #f00']], { borderWidth: 2, - borderColor: "#f00", - borderStyle: "solid" - })); + borderColor: '#f00', + borderStyle: 'solid', + })) -it("transforms border shorthand missing width", () => - runTest([["border", "#f00 dashed"]], { +it('transforms border shorthand missing width', () => + runTest([['border', '#f00 dashed']], { borderWidth: 1, - borderColor: "#f00", - borderStyle: "dashed" - })); + borderColor: '#f00', + borderStyle: 'dashed', + })) -it("transforms border shorthand missing color & width", () => - runTest([["border", "dashed"]], { +it('transforms border shorthand missing color & width', () => + runTest([['border', 'dashed']], { borderWidth: 1, - borderColor: "black", - borderStyle: "dashed" - })); + borderColor: 'black', + borderStyle: 'dashed', + })) -it("transforms border shorthand missing style & width", () => - runTest([["border", "#f00"]], { +it('transforms border shorthand missing style & width', () => + runTest([['border', '#f00']], { borderWidth: 1, - borderColor: "#f00", - borderStyle: "solid" - })); + borderColor: '#f00', + borderStyle: 'solid', + })) -it("transforms border shorthand missing color & style", () => - runTest([["border", "2px"]], { +it('transforms border shorthand missing color & style', () => + runTest([['border', '2px']], { borderWidth: 2, - borderColor: "black", - borderStyle: "solid" - })); + borderColor: 'black', + borderStyle: 'solid', + })) -it("transforms margin shorthands using 4 values", () => - runTest([["margin", "10px 20px 30px 40px"]], { +it('transforms margin shorthands using 4 values', () => + runTest([['margin', '10px 20px 30px 40px']], { marginTop: 10, marginRight: 20, marginBottom: 30, - marginLeft: 40 - })); + marginLeft: 40, + })) -it("transforms margin shorthands using 3 values", () => - runTest([["margin", "10px 20px 30px"]], { +it('transforms margin shorthands using 3 values', () => + runTest([['margin', '10px 20px 30px']], { marginTop: 10, marginRight: 20, marginBottom: 30, - marginLeft: 20 - })); + marginLeft: 20, + })) -it("transforms margin shorthands using 2 values", () => - runTest([["margin", "10px 20px"]], { +it('transforms margin shorthands using 2 values', () => + runTest([['margin', '10px 20px']], { marginTop: 10, marginRight: 20, marginBottom: 10, - marginLeft: 20 - })); + marginLeft: 20, + })) -it("transforms margin shorthands using 1 value", () => - runTest([["margin", "10px"]], { +it('transforms margin shorthands using 1 value', () => + runTest([['margin', '10px']], { marginTop: 10, marginRight: 10, marginBottom: 10, - marginLeft: 10 - })); + marginLeft: 10, + })) -it("shorthand with 1 value should override previous values", () => - runTest([["margin-top", "2px"], ["margin", "1px"]], { +it('shorthand with 1 value should override previous values', () => + runTest([['margin-top', '2px'], ['margin', '1px']], { marginTop: 1, marginRight: 1, marginBottom: 1, - marginLeft: 1 - })); + marginLeft: 1, + })) -it("transforms flex shorthand with 3 values", () => - runTest([["flex", "1 2 3px"]], { flexGrow: 1, flexShrink: 2, flexBasis: 3 })); +it('transforms flex shorthand with 3 values', () => + runTest([['flex', '1 2 3px']], { flexGrow: 1, flexShrink: 2, flexBasis: 3 })) -it("transforms flex shorthand with 3 values in reverse order", () => - runTest([["flex", "3px 1 2"]], { flexGrow: 1, flexShrink: 2, flexBasis: 3 })); +it('transforms flex shorthand with 3 values in reverse order', () => + runTest([['flex', '3px 1 2']], { flexGrow: 1, flexShrink: 2, flexBasis: 3 })) -it("transforms flex shorthand with 2 values of flex-grow and flex-shrink", () => - runTest([["flex", "1 2"]], { flexGrow: 1, flexShrink: 2, flexBasis: 0 })); +it('transforms flex shorthand with 2 values of flex-grow and flex-shrink', () => + runTest([['flex', '1 2']], { flexGrow: 1, flexShrink: 2, flexBasis: 0 })) -it("transforms flex shorthand with 2 values of flex-grow and flex-basis", () => - runTest([["flex", "2 2px"]], { flexGrow: 2, flexShrink: 1, flexBasis: 2 })); +it('transforms flex shorthand with 2 values of flex-grow and flex-basis', () => + runTest([['flex', '2 2px']], { flexGrow: 2, flexShrink: 1, flexBasis: 2 })) -it("transforms flex shorthand with 2 values of flex-grow and flex-basis (reversed)", () => - runTest([["flex", "2px 2"]], { flexGrow: 2, flexShrink: 1, flexBasis: 2 })); +it('transforms flex shorthand with 2 values of flex-grow and flex-basis (reversed)', () => + runTest([['flex', '2px 2']], { flexGrow: 2, flexShrink: 1, flexBasis: 2 })) -it("transforms flex shorthand with 1 value of flex-grow", () => - runTest([["flex", "2"]], { flexGrow: 2, flexShrink: 1, flexBasis: 0 })); +it('transforms flex shorthand with 1 value of flex-grow', () => + runTest([['flex', '2']], { flexGrow: 2, flexShrink: 1, flexBasis: 0 })) -it("transforms flex shorthand with 1 value of flex-basis", () => - runTest([["flex", "10px"]], { flexGrow: 1, flexShrink: 1, flexBasis: 10 })); +it('transforms flex shorthand with 1 value of flex-basis', () => + runTest([['flex', '10px']], { flexGrow: 1, flexShrink: 1, flexBasis: 10 })) /* A unitless zero that is not already preceded by two flex factors must be interpreted as a flex factor. To avoid misinterpretation or invalid declarations, authors must specify a zero <‘flex-basis’> component with a unit or precede it by two flex factors. */ -it("transforms flex shorthand with flex-grow/shrink taking priority over basis", () => - runTest([["flex", "0 1 0"]], { flexGrow: 0, flexShrink: 1, flexBasis: 0 })); +it('transforms flex shorthand with flex-grow/shrink taking priority over basis', () => + runTest([['flex', '0 1 0']], { flexGrow: 0, flexShrink: 1, flexBasis: 0 })) -it("transforms flex shorthand with flex-basis set to auto", () => - runTest([["flex", "0 1 auto"]], { flexGrow: 0, flexShrink: 1 })); +it('transforms flex shorthand with flex-basis set to auto', () => + runTest([['flex', '0 1 auto']], { flexGrow: 0, flexShrink: 1 })) -it("transforms flex shorthand with flex-basis set to auto appearing first", () => - runTest([["flex", "auto 0 1"]], { flexGrow: 0, flexShrink: 1 })); +it('transforms flex shorthand with flex-basis set to auto appearing first', () => + runTest([['flex', 'auto 0 1']], { flexGrow: 0, flexShrink: 1 })) -it("transforms flex auto keyword", () => - runTest([["flex", "auto"]], { flexGrow: 1, flexShrink: 1 })); +it('transforms flex auto keyword', () => + runTest([['flex', 'auto']], { flexGrow: 1, flexShrink: 1 })) -it("transforms flex none keyword", () => - runTest([["flex", "none"]], { flexGrow: 0, flexShrink: 0 })); +it('transforms flex none keyword', () => + runTest([['flex', 'none']], { flexGrow: 0, flexShrink: 0 })) -it("transforms flexFlow shorthand with two values", () => - runTest([["flex-flow", "column wrap"]], { - flexDirection: "column", - flexWrap: "wrap" - })); +it('transforms flexFlow shorthand with two values', () => + runTest([['flex-flow', 'column wrap']], { + flexDirection: 'column', + flexWrap: 'wrap', + })) -it("transforms flexFlow shorthand missing flexDirection", () => - runTest([["flex-flow", "wrap"]], { flexDirection: "row", flexWrap: "wrap" })); +it('transforms flexFlow shorthand missing flexDirection', () => + runTest([['flex-flow', 'wrap']], { flexDirection: 'row', flexWrap: 'wrap' })) -it("transforms flexFlow shorthand missing flexWrap", () => - runTest([["flex-flow", "column"]], { - flexDirection: "column", - flexWrap: "nowrap" - })); +it('transforms flexFlow shorthand missing flexWrap', () => + runTest([['flex-flow', 'column']], { + flexDirection: 'column', + flexWrap: 'nowrap', + })) -it("transforms font", () => - runTest([["font", 'bold italic small-caps 16px/18px "Helvetica"']], { - fontFamily: "Helvetica", +it('transforms font', () => + runTest([['font', 'bold italic small-caps 16px/18px "Helvetica"']], { + fontFamily: 'Helvetica', fontSize: 16, - fontWeight: "bold", - fontStyle: "italic", - fontVariant: ["small-caps"], - lineHeight: 18 - })); - -it("transforms font missing font-variant", () => - runTest([["font", 'bold italic 16px/18px "Helvetica"']], { - fontFamily: "Helvetica", + fontWeight: 'bold', + fontStyle: 'italic', + fontVariant: ['small-caps'], + lineHeight: 18, + })) + +it('transforms font missing font-variant', () => + runTest([['font', 'bold italic 16px/18px "Helvetica"']], { + fontFamily: 'Helvetica', fontSize: 16, - fontWeight: "bold", - fontStyle: "italic", + fontWeight: 'bold', + fontStyle: 'italic', fontVariant: [], - lineHeight: 18 - })); + lineHeight: 18, + })) -it("transforms font missing font-style", () => - runTest([["font", 'bold small-caps 16px/18px "Helvetica"']], { - fontFamily: "Helvetica", +it('transforms font missing font-style', () => + runTest([['font', 'bold small-caps 16px/18px "Helvetica"']], { + fontFamily: 'Helvetica', fontSize: 16, - fontWeight: "bold", - fontStyle: "normal", - fontVariant: ["small-caps"], - lineHeight: 18 - })); - -it("transforms font missing font-weight", () => - runTest([["font", 'italic small-caps 16px/18px "Helvetica"']], { - fontFamily: "Helvetica", + fontWeight: 'bold', + fontStyle: 'normal', + fontVariant: ['small-caps'], + lineHeight: 18, + })) + +it('transforms font missing font-weight', () => + runTest([['font', 'italic small-caps 16px/18px "Helvetica"']], { + fontFamily: 'Helvetica', fontSize: 16, - fontWeight: "normal", - fontStyle: "italic", - fontVariant: ["small-caps"], - lineHeight: 18 - })); - -it("transforms font with font-weight normal", () => - runTest([["font", 'normal 16px/18px "Helvetica"']], { - fontFamily: "Helvetica", + fontWeight: 'normal', + fontStyle: 'italic', + fontVariant: ['small-caps'], + lineHeight: 18, + })) + +it('transforms font with font-weight normal', () => + runTest([['font', 'normal 16px/18px "Helvetica"']], { + fontFamily: 'Helvetica', fontSize: 16, - fontWeight: "normal", - fontStyle: "normal", + fontWeight: 'normal', + fontStyle: 'normal', fontVariant: [], - lineHeight: 18 - })); + lineHeight: 18, + })) -it("transforms font with font-weight and font-style normal", () => - runTest([["font", 'normal normal 16px/18px "Helvetica"']], { - fontFamily: "Helvetica", +it('transforms font with font-weight and font-style normal', () => + runTest([['font', 'normal normal 16px/18px "Helvetica"']], { + fontFamily: 'Helvetica', fontSize: 16, - fontWeight: "normal", - fontStyle: "normal", + fontWeight: 'normal', + fontStyle: 'normal', fontVariant: [], - lineHeight: 18 - })); + lineHeight: 18, + })) -it("transforms font with no font-weight, font-style, and font-variant", () => - runTest([["font", '16px/18px "Helvetica"']], { - fontFamily: "Helvetica", +it('transforms font with no font-weight, font-style, and font-variant', () => + runTest([['font', '16px/18px "Helvetica"']], { + fontFamily: 'Helvetica', fontSize: 16, - fontWeight: "normal", - fontStyle: "normal", + fontWeight: 'normal', + fontStyle: 'normal', fontVariant: [], - lineHeight: 18 - })); + lineHeight: 18, + })) -it("omits line height if not specified", () => - runTest([["font", '16px "Helvetica"']], { - fontFamily: "Helvetica", +it('omits line height if not specified', () => + runTest([['font', '16px "Helvetica"']], { + fontFamily: 'Helvetica', fontSize: 16, - fontWeight: "normal", - fontStyle: "normal", - fontVariant: [] - })); - -it("allows line height as multiple", () => - runTest([["font", '16px/1.5 "Helvetica"']], { - fontFamily: "Helvetica", + fontWeight: 'normal', + fontStyle: 'normal', + fontVariant: [], + })) + +it('allows line height as multiple', () => + runTest([['font', '16px/1.5 "Helvetica"']], { + fontFamily: 'Helvetica', fontSize: 16, - fontWeight: "normal", - fontStyle: "normal", + fontWeight: 'normal', + fontStyle: 'normal', fontVariant: [], - lineHeight: 24 - })); + lineHeight: 24, + })) -it("transforms font without quotes", () => - runTest([["font", "bold italic small-caps 16px/18px Helvetica Neue"]], { - fontFamily: "Helvetica Neue", +it('transforms font without quotes', () => + runTest([['font', 'bold italic small-caps 16px/18px Helvetica Neue']], { + fontFamily: 'Helvetica Neue', fontSize: 16, - fontWeight: "bold", - fontStyle: "italic", - fontVariant: ["small-caps"], - lineHeight: 18 - })); - -it("transforms font-family with double quotes", () => - runTest([["font-family", '"Helvetica Neue"']], { - fontFamily: "Helvetica Neue" - })); - -it("transforms font-family with single quotes", () => - runTest([["font-family", "'Helvetica Neue'"]], { - fontFamily: "Helvetica Neue" - })); - -it("transforms font-family without quotes", () => - runTest([["font-family", "Helvetica Neue"]], { - fontFamily: "Helvetica Neue" - })); - -it("transforms font-family with quotes with otherwise invalid values", () => - runTest([["font-family", '"Goudy Bookletter 1911"']], { - fontFamily: "Goudy Bookletter 1911" - })); - -it("transforms font-family with quotes with escaped values", () => - runTest([["font-family", '"test\\A test"']], { - fontFamily: "test\ntest" - })); - -it("transforms font-family with quotes with escaped quote", () => - runTest([["font-family", '"test\\"test"']], { - fontFamily: 'test"test' - })); - -it("does not transform invalid unquoted font-family", () => { + fontWeight: 'bold', + fontStyle: 'italic', + fontVariant: ['small-caps'], + lineHeight: 18, + })) + +it('transforms font-family with double quotes', () => + runTest([['font-family', '"Helvetica Neue"']], { + fontFamily: 'Helvetica Neue', + })) + +it('transforms font-family with single quotes', () => + runTest([['font-family', "'Helvetica Neue'"]], { + fontFamily: 'Helvetica Neue', + })) + +it('transforms font-family without quotes', () => + runTest([['font-family', 'Helvetica Neue']], { + fontFamily: 'Helvetica Neue', + })) + +it('transforms font-family with quotes with otherwise invalid values', () => + runTest([['font-family', '"Goudy Bookletter 1911"']], { + fontFamily: 'Goudy Bookletter 1911', + })) + +it('transforms font-family with quotes with escaped values', () => + runTest([['font-family', '"test\\A test"']], { + fontFamily: 'test\ntest', + })) + +it('transforms font-family with quotes with escaped quote', () => + runTest([['font-family', '"test\\"test"']], { + fontFamily: 'test"test', + })) + +it('does not transform invalid unquoted font-family', () => { expect(() => - transformCss([["font-family", "Goudy Bookletter 1911"]]) - ).toThrow(); -}); + transformCss([['font-family', 'Goudy Bookletter 1911']]) + ).toThrow() +}) -it("does not transform invalid flex", () => { - expect(() => transformCss([["flex", "1 2px 3"]])).toThrow(); -}); +it('does not transform invalid flex', () => { + expect(() => transformCss([['flex', '1 2px 3']])).toThrow() +}) -it("transforms box-shadow into shadow- properties", () => - runTest([["box-shadow", "10px 20px 30px red"]], { +it('transforms box-shadow into shadow- properties', () => + runTest([['box-shadow', '10px 20px 30px red']], { shadowOffset: { width: 10, height: 20 }, shadowRadius: 30, - shadowColor: "red", - shadowOpacity: 1 - })); + shadowColor: 'red', + shadowOpacity: 1, + })) -it("transforms box-shadow without blur-radius", () => - runTest([["box-shadow", "10px 20px red"]], { +it('transforms box-shadow without blur-radius', () => + runTest([['box-shadow', '10px 20px red']], { shadowOffset: { width: 10, height: 20 }, shadowRadius: 0, - shadowColor: "red", - shadowOpacity: 1 - })); + shadowColor: 'red', + shadowOpacity: 1, + })) -it("transforms box-shadow without color", () => - runTest([["box-shadow", "10px 20px 30px"]], { +it('transforms box-shadow without color', () => + runTest([['box-shadow', '10px 20px 30px']], { shadowOffset: { width: 10, height: 20 }, shadowRadius: 30, - shadowColor: "black", - shadowOpacity: 1 - })); + shadowColor: 'black', + shadowOpacity: 1, + })) -it("transforms box-shadow without blur-radius, color", () => - runTest([["box-shadow", "10px 20px"]], { +it('transforms box-shadow without blur-radius, color', () => + runTest([['box-shadow', '10px 20px']], { shadowOffset: { width: 10, height: 20 }, shadowRadius: 0, - shadowColor: "black", - shadowOpacity: 1 - })); + shadowColor: 'black', + shadowOpacity: 1, + })) -it("transforms box-shadow with rgb color", () => - runTest([["box-shadow", "10px 20px rgb(100, 100, 100)"]], { +it('transforms box-shadow with rgb color', () => + runTest([['box-shadow', '10px 20px rgb(100, 100, 100)']], { shadowOffset: { width: 10, height: 20 }, shadowRadius: 0, - shadowColor: "rgb(100, 100, 100)", - shadowOpacity: 1 - })); + shadowColor: 'rgb(100, 100, 100)', + shadowOpacity: 1, + })) -it("transforms box-shadow with rgba color", () => - runTest([["box-shadow", "10px 20px rgba(100, 100, 100, 0.5)"]], { +it('transforms box-shadow with rgba color', () => + runTest([['box-shadow', '10px 20px rgba(100, 100, 100, 0.5)']], { shadowOffset: { width: 10, height: 20 }, shadowRadius: 0, - shadowColor: "rgba(100, 100, 100, 0.5)", - shadowOpacity: 1 - })); + shadowColor: 'rgba(100, 100, 100, 0.5)', + shadowOpacity: 1, + })) -it("transforms box-shadow with hsl color", () => - runTest([["box-shadow", "10px 20px hsl(120, 100%, 50%)"]], { +it('transforms box-shadow with hsl color', () => + runTest([['box-shadow', '10px 20px hsl(120, 100%, 50%)']], { shadowOffset: { width: 10, height: 20 }, shadowRadius: 0, - shadowColor: "hsl(120, 100%, 50%)", - shadowOpacity: 1 - })); + shadowColor: 'hsl(120, 100%, 50%)', + shadowOpacity: 1, + })) -it("transforms box-shadow with hsla color", () => - runTest([["box-shadow", "10px 20px hsla(120, 100%, 50%, 0.7)"]], { +it('transforms box-shadow with hsla color', () => + runTest([['box-shadow', '10px 20px hsla(120, 100%, 50%, 0.7)']], { shadowOffset: { width: 10, height: 20 }, shadowRadius: 0, - shadowColor: "hsla(120, 100%, 50%, 0.7)", - shadowOpacity: 1 - })); + shadowColor: 'hsla(120, 100%, 50%, 0.7)', + shadowOpacity: 1, + })) -it("transforms box-shadow and throws if multiple colors are used", () => { +it('transforms box-shadow and throws if multiple colors are used', () => { expect(() => - transformCss([["box-shadow", "0 0 0 red yellow green blue"]]) + transformCss([['box-shadow', '0 0 0 red yellow green blue']]) ).toThrow( 'Failed to parse declaration "boxShadow: 0 0 0 red yellow green blue"' - ); -}); + ) +}) -it("transforms box-shadow enforces offset to be present", () => { - expect(() => transformCss([["box-shadow", "red"]])).toThrow( +it('transforms box-shadow enforces offset to be present', () => { + expect(() => transformCss([['box-shadow', 'red']])).toThrow( 'Failed to parse declaration "boxShadow: red"' - ); -}); + ) +}) -it("transforms box-shadow and enforces offset-y if offset-x present", () => { - expect(() => transformCss([["box-shadow", "10px"]])).toThrow( +it('transforms box-shadow and enforces offset-y if offset-x present', () => { + expect(() => transformCss([['box-shadow', '10px']])).toThrow( 'Failed to parse declaration "boxShadow: 10px"' - ); -}); - -it("allows blacklisting shorthands", () => { - const actualStyles = transformCss( - [["border-radius", "50"]], - ["borderRadius"] - ); - expect(actualStyles).toEqual({ borderRadius: 50 }); -}); - -it("throws useful errors", () => { - expect(() => transformCss([["margin", "10"]])).toThrow( + ) +}) + +it('allows blacklisting shorthands', () => { + const actualStyles = transformCss([['border-radius', '50']], ['borderRadius']) + expect(actualStyles).toEqual({ borderRadius: 50 }) +}) + +it('throws useful errors', () => { + expect(() => transformCss([['margin', '10']])).toThrow( 'Failed to parse declaration "margin: 10"' - ); -}); + ) +}) diff --git a/src/tokenTypes.js b/src/tokenTypes.js index 891a518..483df24 100644 --- a/src/tokenTypes.js +++ b/src/tokenTypes.js @@ -1,63 +1,63 @@ -const { stringify } = require("postcss-value-parser"); -const cssColorKeywords = require("css-color-keywords"); +const { stringify } = require('postcss-value-parser') +const cssColorKeywords = require('css-color-keywords') const matchString = node => { - if (node.type !== "string") return null; + if (node.type !== 'string') return null return node.value .replace(/\\([0-9a-f]{1,6})(?:\s|$)/gi, (match, charCode) => String.fromCharCode(parseInt(charCode, 16)) ) - .replace(/\\/g, ""); -}; + .replace(/\\/g, '') +} -const hexColorRe = /^(#(?:[0-9a-f]{3,4}){1,2})$/i; -const cssFunctionNameRe = /^(rgba?|hsla?|hwb|lab|lch|gray|color)$/; +const hexColorRe = /^(#(?:[0-9a-f]{3,4}){1,2})$/i +const cssFunctionNameRe = /^(rgba?|hsla?|hwb|lab|lch|gray|color)$/ const matchColor = node => { if ( - node.type === "word" && + node.type === 'word' && (hexColorRe.test(node.value) || node.value in cssColorKeywords) ) { - return node.value; - } else if (node.type === "function" && cssFunctionNameRe.test(node.value)) { - return stringify(node); + return node.value + } else if (node.type === 'function' && cssFunctionNameRe.test(node.value)) { + return stringify(node) } - return null; -}; + return null +} -const noneRe = /^(none)$/i; -const autoRe = /^(auto)$/i; -const identRe = /(^-?[_a-z][_a-z0-9-]*$)/i; +const noneRe = /^(none)$/i +const autoRe = /^(auto)$/i +const identRe = /(^-?[_a-z][_a-z0-9-]*$)/i // Note if these are wrong, you'll need to change index.js too -const numberRe = /^([+-]?(?:\d*\.)?\d+(?:[Ee][+-]?\d+)?)$/; +const numberRe = /^([+-]?(?:\d*\.)?\d+(?:[Ee][+-]?\d+)?)$/ // Note lengthRe is sneaky: you can omit units for 0 -const lengthRe = /^(0$|(?:[+-]?(?:\d*\.)?\d+(?:[Ee][+-]?\d+)?)(?=px$))/; -const angleRe = /^([+-]?(?:\d*\.)?\d+(?:[Ee][+-]?\d+)?(?:deg|rad))$/; -const percentRe = /^([+-]?(?:\d*\.)?\d+(?:[Ee][+-]?\d+)?%)$/; +const lengthRe = /^(0$|(?:[+-]?(?:\d*\.)?\d+(?:[Ee][+-]?\d+)?)(?=px$))/ +const angleRe = /^([+-]?(?:\d*\.)?\d+(?:[Ee][+-]?\d+)?(?:deg|rad))$/ +const percentRe = /^([+-]?(?:\d*\.)?\d+(?:[Ee][+-]?\d+)?%)$/ -const noopToken = predicate => node => (predicate(node) ? "" : null); +const noopToken = predicate => node => (predicate(node) ? '' : null) const valueForTypeToken = type => node => - node.type === type ? node.value : null; + node.type === type ? node.value : null const regExpToken = (regExp, transform = String) => node => { - if (node.type !== "word") return null; + if (node.type !== 'word') return null - const match = node.value.match(regExp); - if (match === null) return null; + const match = node.value.match(regExp) + if (match === null) return null - const value = transform(match[1]); + const value = transform(match[1]) - return value; -}; + return value +} -module.exports.regExpToken = regExpToken; +module.exports.regExpToken = regExpToken module.exports.tokens = { - SPACE: noopToken(node => node.type === "space"), - SLASH: noopToken(node => node.type === "div" && node.value === "/"), - COMMA: noopToken(node => node.type === "div" && node.value === ","), - WORD: valueForTypeToken("word"), + SPACE: noopToken(node => node.type === 'space'), + SLASH: noopToken(node => node.type === 'div' && node.value === '/'), + COMMA: noopToken(node => node.type === 'div' && node.value === ','), + WORD: valueForTypeToken('word'), NONE: regExpToken(noneRe), AUTO: regExpToken(autoRe), NUMBER: regExpToken(numberRe, Number), @@ -66,5 +66,5 @@ module.exports.tokens = { PERCENT: regExpToken(percentRe), IDENT: regExpToken(identRe), STRING: matchString, - COLOR: matchColor -}; + COLOR: matchColor, +} diff --git a/src/transforms/boxShadow.js b/src/transforms/boxShadow.js index f687991..b3b942a 100644 --- a/src/transforms/boxShadow.js +++ b/src/transforms/boxShadow.js @@ -1,56 +1,56 @@ -const { tokens } = require("../tokenTypes"); +const { tokens } = require('../tokenTypes') -const { NONE, SPACE, COLOR, LENGTH } = tokens; +const { NONE, SPACE, COLOR, LENGTH } = tokens module.exports = tokenStream => { - let offsetX; - let offsetY; - let blurRadius; - let color; + let offsetX + let offsetY + let blurRadius + let color if (tokenStream.matches(NONE)) { - tokenStream.expectEmpty(); + tokenStream.expectEmpty() return { $merge: { shadowOffset: { width: 0, height: 0 }, shadowRadius: 0, - shadowColor: "black", - shadowOpacity: 1 - } - }; + shadowColor: 'black', + shadowOpacity: 1, + }, + } } - let didParseFirst = false; + let didParseFirst = false while (tokenStream.hasTokens()) { - if (didParseFirst) tokenStream.expect(SPACE); + if (didParseFirst) tokenStream.expect(SPACE) if (offsetX === undefined && tokenStream.matches(LENGTH)) { - offsetX = tokenStream.lastValue; - tokenStream.expect(SPACE); - offsetY = tokenStream.expect(LENGTH); + offsetX = tokenStream.lastValue + tokenStream.expect(SPACE) + offsetY = tokenStream.expect(LENGTH) - tokenStream.saveRewindPoint(); + tokenStream.saveRewindPoint() if (tokenStream.matches(SPACE) && tokenStream.matches(LENGTH)) { - blurRadius = tokenStream.lastValue; + blurRadius = tokenStream.lastValue } else { - tokenStream.rewind(); + tokenStream.rewind() } } else if (color === undefined && tokenStream.matches(COLOR)) { - color = tokenStream.lastValue; + color = tokenStream.lastValue } else { - tokenStream.throw(); + tokenStream.throw() } - didParseFirst = true; + didParseFirst = true } - if (offsetX === undefined) tokenStream.throw(); + if (offsetX === undefined) tokenStream.throw() const $merge = { shadowOffset: { width: offsetX, height: offsetY }, shadowRadius: blurRadius !== undefined ? blurRadius : 0, - shadowColor: color !== undefined ? color : "black", - shadowOpacity: 1 - }; - return { $merge }; -}; + shadowColor: color !== undefined ? color : 'black', + shadowOpacity: 1, + } + return { $merge } +} diff --git a/src/transforms/flex.js b/src/transforms/flex.js index e819560..44314b3 100644 --- a/src/transforms/flex.js +++ b/src/transforms/flex.js @@ -1,60 +1,60 @@ -const { tokens } = require("../tokenTypes"); +const { tokens } = require('../tokenTypes') -const { NONE, AUTO, NUMBER, LENGTH, SPACE } = tokens; +const { NONE, AUTO, NUMBER, LENGTH, SPACE } = tokens -const defaultFlexGrow = 1; -const defaultFlexShrink = 1; -const defaultFlexBasis = 0; +const defaultFlexGrow = 1 +const defaultFlexShrink = 1 +const defaultFlexBasis = 0 -const FLEX_BASIS_AUTO = {}; // Used for reference equality +const FLEX_BASIS_AUTO = {} // Used for reference equality module.exports = tokenStream => { - let flexGrow; - let flexShrink; - let flexBasis; + let flexGrow + let flexShrink + let flexBasis if (tokenStream.matches(NONE)) { - tokenStream.expectEmpty(); - return { $merge: { flexGrow: 0, flexShrink: 0 } }; + tokenStream.expectEmpty() + return { $merge: { flexGrow: 0, flexShrink: 0 } } } - tokenStream.saveRewindPoint(); + tokenStream.saveRewindPoint() if (tokenStream.matches(AUTO) && !tokenStream.hasTokens()) { - return { $merge: { flexGrow: 1, flexShrink: 1 } }; + return { $merge: { flexGrow: 1, flexShrink: 1 } } } - tokenStream.rewind(); + tokenStream.rewind() - let partsParsed = 0; + let partsParsed = 0 while (partsParsed < 2 && tokenStream.hasTokens()) { - if (partsParsed !== 0) tokenStream.expect(SPACE); + if (partsParsed !== 0) tokenStream.expect(SPACE) if (flexGrow === undefined && tokenStream.matches(NUMBER)) { - flexGrow = tokenStream.lastValue; + flexGrow = tokenStream.lastValue - tokenStream.saveRewindPoint(); + tokenStream.saveRewindPoint() if (tokenStream.matches(SPACE) && tokenStream.matches(NUMBER)) { - flexShrink = tokenStream.lastValue; + flexShrink = tokenStream.lastValue } else { - tokenStream.rewind(); + tokenStream.rewind() } } else if (flexBasis === undefined && tokenStream.matches(LENGTH)) { - flexBasis = tokenStream.lastValue; + flexBasis = tokenStream.lastValue } else if (flexBasis === undefined && tokenStream.matches(AUTO)) { - flexBasis = FLEX_BASIS_AUTO; + flexBasis = FLEX_BASIS_AUTO } else { - tokenStream.throw(); + tokenStream.throw() } - partsParsed += 1; + partsParsed += 1 } - tokenStream.expectEmpty(); + tokenStream.expectEmpty() - if (flexGrow === undefined) flexGrow = defaultFlexGrow; - if (flexShrink === undefined) flexShrink = defaultFlexShrink; - if (flexBasis === undefined) flexBasis = defaultFlexBasis; + if (flexGrow === undefined) flexGrow = defaultFlexGrow + if (flexShrink === undefined) flexShrink = defaultFlexShrink + if (flexBasis === undefined) flexBasis = defaultFlexBasis return flexBasis !== FLEX_BASIS_AUTO ? { $merge: { flexGrow, flexShrink, flexBasis } } - : { $merge: { flexGrow, flexShrink } }; -}; + : { $merge: { flexGrow, flexShrink } } +} diff --git a/src/transforms/font.js b/src/transforms/font.js index 5f2991e..2d44b23 100644 --- a/src/transforms/font.js +++ b/src/transforms/font.js @@ -1,62 +1,62 @@ -const parseFontFamily = require("./fontFamily"); -const { regExpToken, tokens } = require("../tokenTypes"); +const parseFontFamily = require('./fontFamily') +const { regExpToken, tokens } = require('../tokenTypes') -const { SPACE, LENGTH, NUMBER, SLASH } = tokens; -const NORMAL = regExpToken(/^(normal)$/); -const STYLE = regExpToken(/^(italic)$/); -const WEIGHT = regExpToken(/^([1-9]00|bold)$/); -const VARIANT = regExpToken(/^(small-caps)$/); +const { SPACE, LENGTH, NUMBER, SLASH } = tokens +const NORMAL = regExpToken(/^(normal)$/) +const STYLE = regExpToken(/^(italic)$/) +const WEIGHT = regExpToken(/^([1-9]00|bold)$/) +const VARIANT = regExpToken(/^(small-caps)$/) -const defaultFontStyle = "normal"; -const defaultFontWeight = "normal"; -const defaultFontVariant = []; +const defaultFontStyle = 'normal' +const defaultFontWeight = 'normal' +const defaultFontVariant = [] module.exports = tokenStream => { - let fontStyle; - let fontWeight; - let fontVariant; + let fontStyle + let fontWeight + let fontVariant // let fontSize; - let lineHeight; + let lineHeight // let fontFamily; - let numStyleWeightVariantMatched = 0; + let numStyleWeightVariantMatched = 0 while (numStyleWeightVariantMatched < 3 && tokenStream.hasTokens()) { if (tokenStream.matches(NORMAL)) { /* pass */ } else if (fontStyle === undefined && tokenStream.matches(STYLE)) { - fontStyle = tokenStream.lastValue; + fontStyle = tokenStream.lastValue } else if (fontWeight === undefined && tokenStream.matches(WEIGHT)) { - fontWeight = tokenStream.lastValue; + fontWeight = tokenStream.lastValue } else if (fontVariant === undefined && tokenStream.matches(VARIANT)) { - fontVariant = [tokenStream.lastValue]; + fontVariant = [tokenStream.lastValue] } else { - break; + break } - tokenStream.expect(SPACE); - numStyleWeightVariantMatched += 1; + tokenStream.expect(SPACE) + numStyleWeightVariantMatched += 1 } - const fontSize = tokenStream.expect(LENGTH); + const fontSize = tokenStream.expect(LENGTH) if (tokenStream.matches(SLASH)) { if (tokenStream.matches(NUMBER)) { - lineHeight = fontSize * tokenStream.lastValue; + lineHeight = fontSize * tokenStream.lastValue } else { - lineHeight = tokenStream.expect(LENGTH); + lineHeight = tokenStream.expect(LENGTH) } } - tokenStream.expect(SPACE); + tokenStream.expect(SPACE) - const fontFamily = parseFontFamily(tokenStream); + const fontFamily = parseFontFamily(tokenStream) - if (fontStyle === undefined) fontStyle = defaultFontStyle; - if (fontWeight === undefined) fontWeight = defaultFontWeight; - if (fontVariant === undefined) fontVariant = defaultFontVariant; + if (fontStyle === undefined) fontStyle = defaultFontStyle + if (fontWeight === undefined) fontWeight = defaultFontWeight + if (fontVariant === undefined) fontVariant = defaultFontVariant - const out = { fontStyle, fontWeight, fontVariant, fontSize, fontFamily }; - if (lineHeight !== undefined) out.lineHeight = lineHeight; + const out = { fontStyle, fontWeight, fontVariant, fontSize, fontFamily } + if (lineHeight !== undefined) out.lineHeight = lineHeight - return { $merge: out }; -}; + return { $merge: out } +} diff --git a/src/transforms/fontFamily.js b/src/transforms/fontFamily.js index f3449a8..f363b38 100644 --- a/src/transforms/fontFamily.js +++ b/src/transforms/fontFamily.js @@ -1,22 +1,22 @@ -const { tokens } = require("../tokenTypes"); +const { tokens } = require('../tokenTypes') -const { SPACE, IDENT, STRING } = tokens; +const { SPACE, IDENT, STRING } = tokens module.exports = tokenStream => { - let fontFamily; + let fontFamily if (tokenStream.matches(STRING)) { - fontFamily = tokenStream.lastValue; + fontFamily = tokenStream.lastValue } else { - fontFamily = tokenStream.expect(IDENT); + fontFamily = tokenStream.expect(IDENT) while (tokenStream.hasTokens()) { - tokenStream.expect(SPACE); - const nextIdent = tokenStream.expect(IDENT); - fontFamily += ` ${nextIdent}`; + tokenStream.expect(SPACE) + const nextIdent = tokenStream.expect(IDENT) + fontFamily += ` ${nextIdent}` } } - tokenStream.expectEmpty(); + tokenStream.expectEmpty() - return fontFamily; -}; + return fontFamily +} diff --git a/src/transforms/index.js b/src/transforms/index.js index e241d7f..22e9978 100644 --- a/src/transforms/index.js +++ b/src/transforms/index.js @@ -1,61 +1,61 @@ -const { regExpToken, tokens } = require("../tokenTypes"); -const boxShadow = require("./boxShadow"); -const flex = require("./flex"); -const font = require("./font"); -const fontFamily = require("./fontFamily"); -const transform = require("./transform"); +const { regExpToken, tokens } = require('../tokenTypes') +const boxShadow = require('./boxShadow') +const flex = require('./flex') +const font = require('./font') +const fontFamily = require('./fontFamily') +const transform = require('./transform') const { directionFactory, anyOrderFactory, - shadowOffsetFactory -} = require("./util"); + shadowOffsetFactory, +} = require('./util') -const { IDENT, WORD, COLOR } = tokens; +const { IDENT, WORD, COLOR } = tokens const background = tokenStream => ({ - $merge: { backgroundColor: tokenStream.expect(COLOR) } -}); + $merge: { backgroundColor: tokenStream.expect(COLOR) }, +}) const border = anyOrderFactory({ borderWidth: { token: tokens.LENGTH, - default: 1 + default: 1, }, borderColor: { token: COLOR, - default: "black" + default: 'black', }, borderStyle: { token: regExpToken(/^(solid|dashed|dotted)$/), - default: "solid" - } -}); + default: 'solid', + }, +}) const borderColor = directionFactory({ types: [WORD], - prefix: "border", - suffix: "Color" -}); + prefix: 'border', + suffix: 'Color', +}) const borderRadius = directionFactory({ - directions: ["TopRight", "BottomRight", "BottomLeft", "TopLeft"], - prefix: "border", - suffix: "Radius" -}); -const borderWidth = directionFactory({ prefix: "border", suffix: "Width" }); -const margin = directionFactory({ prefix: "margin" }); -const padding = directionFactory({ prefix: "padding" }); + directions: ['TopRight', 'BottomRight', 'BottomLeft', 'TopLeft'], + prefix: 'border', + suffix: 'Radius', +}) +const borderWidth = directionFactory({ prefix: 'border', suffix: 'Width' }) +const margin = directionFactory({ prefix: 'margin' }) +const padding = directionFactory({ prefix: 'padding' }) const flexFlow = anyOrderFactory({ flexWrap: { token: regExpToken(/(nowrap|wrap|wrap-reverse)/), - default: "nowrap" + default: 'nowrap', }, flexDirection: { token: regExpToken(/(row|row-reverse|column|column-reverse)/), - default: "row" - } -}); -const fontVariant = tokenStream => [tokenStream.expect(IDENT)]; -const fontWeight = tokenStream => tokenStream.expect(WORD); // Also match numbers as strings -const shadowOffset = shadowOffsetFactory(); -const textShadowOffset = shadowOffsetFactory(); + default: 'row', + }, +}) +const fontVariant = tokenStream => [tokenStream.expect(IDENT)] +const fontWeight = tokenStream => tokenStream.expect(WORD) // Also match numbers as strings +const shadowOffset = shadowOffsetFactory() +const textShadowOffset = shadowOffsetFactory() module.exports = { background, @@ -74,5 +74,5 @@ module.exports = { padding, shadowOffset, textShadowOffset, - transform -}; + transform, +} diff --git a/src/transforms/transform.js b/src/transforms/transform.js index 5ba89aa..ecbb710 100644 --- a/src/transforms/transform.js +++ b/src/transforms/transform.js @@ -1,48 +1,48 @@ -const { tokens } = require("../tokenTypes"); +const { tokens } = require('../tokenTypes') -const { SPACE, COMMA, LENGTH, NUMBER, ANGLE } = tokens; +const { SPACE, COMMA, LENGTH, NUMBER, ANGLE } = tokens const oneOfType = tokenType => functionStream => { - const value = functionStream.expect(tokenType); - functionStream.expectEmpty(); - return value; -}; + const value = functionStream.expect(tokenType) + functionStream.expectEmpty() + return value +} -const singleNumber = oneOfType(NUMBER); -const singleLength = oneOfType(LENGTH); -const singleAngle = oneOfType(ANGLE); +const singleNumber = oneOfType(NUMBER) +const singleLength = oneOfType(LENGTH) +const singleAngle = oneOfType(ANGLE) const xyTransformFactory = tokenType => ( key, valueIfOmitted ) => functionStream => { - const x = functionStream.expect(tokenType); + const x = functionStream.expect(tokenType) - let y; + let y if (functionStream.hasTokens()) { - functionStream.expect(COMMA); - y = functionStream.expect(tokenType); + functionStream.expect(COMMA) + y = functionStream.expect(tokenType) } else if (valueIfOmitted !== undefined) { - y = valueIfOmitted; + y = valueIfOmitted } else { // Assumption, if x === y, then we can omit XY // I.e. scale(5) => [{ scale: 5 }] rather than [{ scaleX: 5 }, { scaleY: 5 }] - return x; + return x } - functionStream.expectEmpty(); + functionStream.expectEmpty() - return [{ [`${key}Y`]: y }, { [`${key}X`]: x }]; -}; -const xyNumber = xyTransformFactory(NUMBER); -const xyLength = xyTransformFactory(LENGTH); -const xyAngle = xyTransformFactory(ANGLE); + return [{ [`${key}Y`]: y }, { [`${key}X`]: x }] +} +const xyNumber = xyTransformFactory(NUMBER) +const xyLength = xyTransformFactory(LENGTH) +const xyAngle = xyTransformFactory(ANGLE) const partTransforms = { perspective: singleNumber, - scale: xyNumber("scale"), + scale: xyNumber('scale'), scaleX: singleNumber, scaleY: singleNumber, - translate: xyLength("translate", 0), + translate: xyLength('translate', 0), translateX: singleLength, translateY: singleLength, rotate: singleAngle, @@ -51,26 +51,26 @@ const partTransforms = { rotateZ: singleAngle, skewX: singleAngle, skewY: singleAngle, - skew: xyAngle("skew", "0deg") -}; + skew: xyAngle('skew', '0deg'), +} module.exports = tokenStream => { - let transforms = []; + let transforms = [] - let didParseFirst = false; + let didParseFirst = false while (tokenStream.hasTokens()) { - if (didParseFirst) tokenStream.expect(SPACE); + if (didParseFirst) tokenStream.expect(SPACE) - const functionStream = tokenStream.expectFunction(); - const { functionName } = functionStream; - let transformedValues = partTransforms[functionName](functionStream); + const functionStream = tokenStream.expectFunction() + const { functionName } = functionStream + let transformedValues = partTransforms[functionName](functionStream) if (!Array.isArray(transformedValues)) { - transformedValues = [{ [functionName]: transformedValues }]; + transformedValues = [{ [functionName]: transformedValues }] } - transforms = transformedValues.concat(transforms); + transforms = transformedValues.concat(transforms) - didParseFirst = true; + didParseFirst = true } - return transforms; -}; + return transforms +} diff --git a/src/transforms/util.js b/src/transforms/util.js index 2a4038e..1eaf722 100644 --- a/src/transforms/util.js +++ b/src/transforms/util.js @@ -1,80 +1,78 @@ -const { tokens } = require("../tokenTypes"); +const { tokens } = require('../tokenTypes') -const { LENGTH, PERCENT, SPACE } = tokens; +const { LENGTH, PERCENT, SPACE } = tokens module.exports.directionFactory = ({ types = [LENGTH, PERCENT], - directions = ["Top", "Right", "Bottom", "Left"], - prefix = "", - suffix = "" + directions = ['Top', 'Right', 'Bottom', 'Left'], + prefix = '', + suffix = '', }) => tokenStream => { - const values = []; + const values = [] // borderWidth doesn't currently allow a percent value, but may do in the future - values.push(tokenStream.expect(...types)); + values.push(tokenStream.expect(...types)) while (values.length < 4 && tokenStream.hasTokens()) { - tokenStream.expect(SPACE); - values.push(tokenStream.expect(...types)); + tokenStream.expect(SPACE) + values.push(tokenStream.expect(...types)) } - tokenStream.expectEmpty(); + tokenStream.expectEmpty() - const [top, right = top, bottom = top, left = right] = values; + const [top, right = top, bottom = top, left = right] = values - const keyFor = n => `${prefix}${directions[n]}${suffix}`; + const keyFor = n => `${prefix}${directions[n]}${suffix}` const output = { [keyFor(0)]: top, [keyFor(1)]: right, [keyFor(2)]: bottom, - [keyFor(3)]: left - }; + [keyFor(3)]: left, + } - return { $merge: output }; -}; + return { $merge: output } +} module.exports.anyOrderFactory = (properties, delim = SPACE) => tokenStream => { - const propertyNames = Object.keys(properties); + const propertyNames = Object.keys(properties) const values = propertyNames.reduce((accum, propertyName) => { - accum[propertyName] === undefined; // eslint-disable-line - return accum; - }, {}); + accum[propertyName] === undefined // eslint-disable-line + return accum + }, {}) - let numParsed = 0; + let numParsed = 0 while (numParsed < propertyNames.length && tokenStream.hasTokens()) { - if (numParsed) tokenStream.expect(delim); + if (numParsed) tokenStream.expect(delim) const matchedPropertyName = propertyNames.find( propertyName => values[propertyName] === undefined && tokenStream.matches(properties[propertyName].token) - ); + ) if (!matchedPropertyName) { - tokenStream.throw(); + tokenStream.throw() } else { - values[matchedPropertyName] = tokenStream.lastValue; + values[matchedPropertyName] = tokenStream.lastValue } - numParsed += 1; + numParsed += 1 } - tokenStream.expectEmpty(); + tokenStream.expectEmpty() propertyNames.forEach(propertyName => { if (values[propertyName] === undefined) - values[propertyName] = properties[propertyName].default; - }); + values[propertyName] = properties[propertyName].default + }) - return { $merge: values }; -}; + return { $merge: values } +} module.exports.shadowOffsetFactory = () => tokenStream => { - const width = tokenStream.expect(LENGTH); - const height = tokenStream.matches(SPACE) - ? tokenStream.expect(LENGTH) - : width; - tokenStream.expectEmpty(); - return { width, height }; -}; + const width = tokenStream.expect(LENGTH) + const height = tokenStream.matches(SPACE) ? tokenStream.expect(LENGTH) : width + tokenStream.expectEmpty() + return { width, height } +} From 2352b49be60c612ae7c5590503933314d3de4d40 Mon Sep 17 00:00:00 2001 From: Jacob Parker Date: Sun, 4 Feb 2018 18:36:15 +0000 Subject: [PATCH 3/3] Add linting to CI, precommit --- .eslintrc.js | 8 +- .travis.yml | 1 + package.json | 13 +- yarn.lock | 459 ++++++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 473 insertions(+), 8 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 45390b0..b24299d 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,3 +1,7 @@ module.exports = { - extends: ["airbnb-base", "prettier"] -}; + extends: ['airbnb-base', 'prettier'], + plugins: ['prettier'], + rules: { + 'prettier/prettier': 2, + }, +} diff --git a/.travis.yml b/.travis.yml index 467b86f..b95ea8d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,6 +7,7 @@ script: - node --version - yarn --version - yarn run test + - yarn run lint notifications: email: on_failure: change diff --git a/package.json b/package.json index 2fee4c0..2597ac0 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,10 @@ "build": "babel src --ignore test.js --out-dir dist", "test": "jest", "test:watch": "jest --watch", - "prepublish": "npm run build" + "lint": "eslint src", + "prepublish": "npm run build", + "precommit": "lint-staged", + "lint-staged": "lint-staged" }, "files": [ "dist", @@ -37,12 +40,20 @@ "eslint-config-airbnb-base": "^10.0.1", "eslint-config-prettier": "^2.9.0", "eslint-plugin-import": "^2.2.0", + "eslint-plugin-prettier": "^2.6.0", "jest": "^17.0.0", + "lint-staged": "^6.1.0", "prettier": "^1.10.2" }, "dependencies": { "css-color-keywords": "^1.0.0", "fbjs": "^0.8.5", "postcss-value-parser": "^3.3.0" + }, + "lint-staged": { + "*.js": [ + "eslint --fix", + "git add" + ] } } diff --git a/yarn.lock b/yarn.lock index a5f7203..072c87f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -57,7 +57,7 @@ amdefine@>=0.0.4: version "1.0.1" resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" -ansi-escapes@^1.1.0, ansi-escapes@^1.4.0: +ansi-escapes@^1.0.0, ansi-escapes@^1.1.0, ansi-escapes@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" @@ -65,14 +65,28 @@ ansi-regex@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" +ansi-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" +ansi-styles@^3.1.0, ansi-styles@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.0.tgz#c159b8d5be0f9e5a6f346dab94f16ce022161b88" + dependencies: + color-convert "^1.9.0" + ansicolors@~0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/ansicolors/-/ansicolors-0.2.1.tgz#be089599097b74a5c9c4a84a0cdbcdb62bd87aef" +any-observable@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/any-observable/-/any-observable-0.2.0.tgz#c67870058003579009083f54ac0abafb5c33d242" + anymatch@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.0.tgz#a3e52fa39168c825ff57b0248126ce5a8ff95507" @@ -80,6 +94,10 @@ anymatch@^1.3.0: arrify "^1.0.0" micromatch "^2.1.5" +app-root-path@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/app-root-path/-/app-root-path-2.0.1.tgz#cd62dcf8e4fd5a417efc664d2e5b10653c651b46" + append-transform@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-0.4.0.tgz#d76ebf8ca94d276e247a36bad44a4b74ab611991" @@ -749,6 +767,14 @@ chalk@^1.0.0, chalk@^1.1.0, chalk@^1.1.1, chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" +chalk@^2.0.1, chalk@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.0.tgz#b5ea48efc9c1793dccc9b4767c93914d3f2d52ba" + dependencies: + ansi-styles "^3.1.0" + escape-string-regexp "^1.0.5" + supports-color "^4.0.0" + chokidar@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.6.1.tgz#2f4447ab5e96e50fb3d789fd90d4c72e0e4c70c2" @@ -772,18 +798,29 @@ circular-json@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.1.tgz#be8b36aefccde8b3ca7aa2d6afc07a37242c0d2d" -cli-cursor@^1.0.1: +cli-cursor@^1.0.1, cli-cursor@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987" dependencies: restore-cursor "^1.0.1" +cli-spinners@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-0.1.2.tgz#bb764d88e185fb9e1e6a2a1f19772318f605e31c" + cli-table@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/cli-table/-/cli-table-0.3.1.tgz#f53b05266a8b1a0b934b3d0821e6e2dc5914ae23" dependencies: colors "1.0.3" +cli-truncate@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-0.2.1.tgz#9f15cfbb0705005369216c626ac7d05ab90dd574" + dependencies: + slice-ansi "0.0.4" + string-width "^1.0.1" + cli-usage@^0.1.1: version "0.1.4" resolved "https://registry.yarnpkg.com/cli-usage/-/cli-usage-0.1.4.tgz#7c01e0dc706c234b39c933838c8e20b2175776e2" @@ -819,6 +856,16 @@ code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" +color-convert@^1.9.0: + version "1.9.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.1.tgz#c1261107aeb2f294ebffec9ed9ecad529a6097ed" + dependencies: + color-name "^1.1.1" + +color-name@^1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + colors@1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b" @@ -829,6 +876,10 @@ combined-stream@^1.0.5, combined-stream@~1.0.5: dependencies: delayed-stream "~1.0.0" +commander@^2.11.0: + version "2.13.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.13.0.tgz#6964bca67685df7c1f1430c584f07d7597885b9c" + commander@^2.8.1, commander@^2.9.0: version "2.9.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" @@ -875,6 +926,23 @@ core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" +cosmiconfig@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-4.0.0.tgz#760391549580bbd2df1e562bc177b13c290972dc" + dependencies: + is-directory "^0.3.1" + js-yaml "^3.9.0" + parse-json "^4.0.0" + require-from-string "^2.0.1" + +cross-spawn@^5.0.1: + version "5.1.0" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" + dependencies: + lru-cache "^4.0.1" + shebang-command "^1.2.0" + which "^1.2.9" + cryptiles@2.x.x: version "2.0.5" resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8" @@ -907,6 +975,10 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" +date-fns@^1.27.2: + version "1.29.0" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.29.0.tgz#12e609cdcb935127311d04d33334e2960a2a54e6" + debug@2.2.0, debug@~2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da" @@ -919,10 +991,20 @@ debug@^2.1.1, debug@^2.2.0: dependencies: ms "0.7.2" +debug@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" + dependencies: + ms "2.0.0" + decamelize@^1.0.0, decamelize@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" +dedent@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" + deep-extend@~0.4.0: version "0.4.1" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.1.tgz#efe4113d08085f4e6f9687759810f807469e2253" @@ -980,6 +1062,10 @@ ecc-jsbn@~0.1.1: dependencies: jsbn "~0.1.0" +elegant-spinner@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/elegant-spinner/-/elegant-spinner-1.0.1.tgz#db043521c95d7e303fd8f345bedc3349cfb0729e" + encoding@^0.1.11: version "0.1.12" resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb" @@ -998,6 +1084,12 @@ error-ex@^1.2.0: dependencies: is-arrayish "^0.2.1" +error-ex@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.1.tgz#f855a86ce61adc4e8621c3cda21e7a7612c3a8dc" + dependencies: + is-arrayish "^0.2.1" + es5-ext@^0.10.7, es5-ext@^0.10.8, es5-ext@~0.10.11, es5-ext@~0.10.2, es5-ext@~0.10.7: version "0.10.12" resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.12.tgz#aa84641d4db76b62abba5e45fd805ecbab140047" @@ -1114,6 +1206,13 @@ eslint-plugin-import@^2.2.0: minimatch "^3.0.3" pkg-up "^1.0.0" +eslint-plugin-prettier@^2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-2.6.0.tgz#33e4e228bdb06142d03c560ce04ec23f6c767dd7" + dependencies: + fast-diff "^1.1.1" + jest-docblock "^21.0.0" + eslint@^3.9.1: version "3.14.0" resolved "https://registry.yarnpkg.com/eslint/-/eslint-3.14.0.tgz#2c617e5f782fda5cbee5bc8be7ef5053af8e63a3" @@ -1164,6 +1263,10 @@ esprima@2.7.x, esprima@^2.6.0, esprima@^2.7.1: version "2.7.3" resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" +esprima@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.0.tgz#4499eddcd1110e0b218bacf2fa7f7f59f55ca804" + esprima@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.0.0.tgz#53cf247acda77313e551c3aa2e73342d3fb4f7d9" @@ -1204,6 +1307,18 @@ exec-sh@^0.2.0: dependencies: merge "^1.1.3" +execa@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-0.8.0.tgz#d8d76bbc1b55217ed190fd6dd49d3c774ecfc8da" + dependencies: + cross-spawn "^5.0.1" + get-stream "^3.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + exit-hook@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8" @@ -1234,6 +1349,10 @@ extsprintf@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.0.2.tgz#e1080e0658e300b06294990cc70e1502235fd550" +fast-diff@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.1.2.tgz#4b62c42b8e03de3f848460b639079920695d0154" + fast-levenshtein@~2.0.4: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" @@ -1256,7 +1375,7 @@ fbjs@^0.8.5: setimmediate "^1.0.5" ua-parser-js "^0.7.9" -figures@^1.3.5: +figures@^1.3.5, figures@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" dependencies: @@ -1291,6 +1410,10 @@ fill-range@^2.1.0: repeat-element "^1.1.2" repeat-string "^1.5.2" +find-parent-dir@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/find-parent-dir/-/find-parent-dir-0.3.0.tgz#33c44b429ab2b2f0646299c5f9f718f376ff8d54" + find-up@^1.0.0, find-up@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" @@ -1393,10 +1516,18 @@ get-caller-file@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5" +get-own-enumerable-property-symbols@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-2.0.1.tgz#5c4ad87f2834c4b9b4e84549dc1e0650fb38c24b" + get-stdin@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-5.0.1.tgz#122e161591e21ff4c52530305693f20e6393a398" +get-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" + getpass@^0.1.1: version "0.1.6" resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.6.tgz#283ffd9fc1256840875311c1b60e8c40187110e6" @@ -1493,6 +1624,10 @@ has-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" +has-flag@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" + has-unicode@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" @@ -1557,6 +1692,16 @@ imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" +indent-string@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80" + dependencies: + repeating "^2.0.0" + +indent-string@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289" + inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" @@ -1630,6 +1775,10 @@ is-ci@^1.0.9: dependencies: ci-info "^1.0.0" +is-directory@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" + is-dotfile@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.2.tgz#2c132383f39199f8edc268ca01b9b007d205cc4d" @@ -1648,6 +1797,10 @@ is-extglob@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + is-finite@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" @@ -1670,6 +1823,12 @@ is-glob@^2.0.0, is-glob@^2.0.1: dependencies: is-extglob "^1.0.0" +is-glob@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.0.tgz#9521c76845cc2610a85203ddf080a958c2ffabc0" + dependencies: + is-extglob "^2.1.1" + is-my-json-valid@^2.10.0, is-my-json-valid@^2.12.4: version "2.15.0" resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.15.0.tgz#936edda3ca3c211fd98f3b2d3e08da43f7b2915b" @@ -1685,6 +1844,16 @@ is-number@^2.0.2, is-number@^2.1.0: dependencies: kind-of "^3.0.2" +is-obj@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" + +is-observable@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/is-observable/-/is-observable-0.2.0.tgz#b361311d83c6e5d726cabf5e250b0237106f5ae2" + dependencies: + symbol-observable "^0.2.2" + is-path-cwd@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" @@ -1709,17 +1878,25 @@ is-primitive@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" +is-promise@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" + is-property@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" +is-regexp@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" + is-resolvable@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.0.0.tgz#8df57c61ea2e3c501408d100fb013cf8d6e0cc62" dependencies: tryit "^1.0.1" -is-stream@^1.0.1: +is-stream@^1.0.1, is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" @@ -1739,6 +1916,10 @@ isexe@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/isexe/-/isexe-1.1.2.tgz#36f3e22e60750920f5e7241a476a8c6a42275ad0" +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + isobject@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" @@ -1899,6 +2080,10 @@ jest-diff@^17.0.3: jest-matcher-utils "^17.0.3" pretty-format "~4.2.1" +jest-docblock@^21.0.0: + version "21.2.0" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-21.2.0.tgz#51529c3b30d5fd159da60c27ceedc195faf8d414" + jest-environment-jsdom@^17.0.2: version "17.0.2" resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-17.0.2.tgz#a3098dc29806d40802c52b62b848ab6aa00fdba0" @@ -1918,6 +2103,10 @@ jest-file-exists@^17.0.0: version "17.0.0" resolved "https://registry.yarnpkg.com/jest-file-exists/-/jest-file-exists-17.0.0.tgz#7f63eb73a1c43a13f461be261768b45af2cdd169" +jest-get-type@^21.2.0: + version "21.2.0" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-21.2.0.tgz#f6376ab9db4b60d81e39f30749c6c466f40d4a23" + jest-haste-map@^17.0.3: version "17.0.3" resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-17.0.3.tgz#5232783e70577217b6b17d2a1c1766637a1d2fbd" @@ -2014,6 +2203,15 @@ jest-util@^17.0.2: jest-mock "^17.0.2" mkdirp "^0.5.1" +jest-validate@^21.1.0: + version "21.2.1" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-21.2.1.tgz#cc0cbca653cd54937ba4f2a111796774530dd3c7" + dependencies: + chalk "^2.0.1" + jest-get-type "^21.2.0" + leven "^2.1.0" + pretty-format "^21.2.1" + jest@^17.0.0: version "17.0.3" resolved "https://registry.yarnpkg.com/jest/-/jest-17.0.3.tgz#89c43b30b0aaad42462e9ea701352dacbad4a354" @@ -2037,6 +2235,13 @@ js-yaml@3.x, js-yaml@^3.5.1, js-yaml@^3.7.0: argparse "^1.0.7" esprima "^2.6.0" +js-yaml@^3.9.0: + version "3.10.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.10.0.tgz#2e78441646bd4682e963f22b6e92823c309c62dc" + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + jsbn@~0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.0.tgz#650987da0dd74f4ebf5a11377a2aa2d273e97dfd" @@ -2074,6 +2279,10 @@ jsesc@~0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" +json-parse-better-errors@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.1.tgz#50183cd1b2d25275de069e9e71b467ac9eab973a" + json-schema@0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" @@ -2124,6 +2333,10 @@ lcid@^1.0.0: dependencies: invert-kv "^1.0.0" +leven@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/leven/-/leven-2.1.0.tgz#c2e7a9f772094dee9d34202ae8acce4687875580" + levn@^0.3.0, levn@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" @@ -2131,6 +2344,79 @@ levn@^0.3.0, levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" +lint-staged@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-6.1.0.tgz#28f600c10a6cbd249ceb003118a1552e53544a93" + dependencies: + app-root-path "^2.0.0" + chalk "^2.1.0" + commander "^2.11.0" + cosmiconfig "^4.0.0" + debug "^3.1.0" + dedent "^0.7.0" + execa "^0.8.0" + find-parent-dir "^0.3.0" + is-glob "^4.0.0" + jest-validate "^21.1.0" + listr "^0.13.0" + lodash "^4.17.4" + log-symbols "^2.0.0" + minimatch "^3.0.0" + npm-which "^3.0.1" + p-map "^1.1.1" + path-is-inside "^1.0.2" + pify "^3.0.0" + staged-git-files "0.0.4" + stringify-object "^3.2.0" + +listr-silent-renderer@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz#924b5a3757153770bf1a8e3fbf74b8bbf3f9242e" + +listr-update-renderer@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/listr-update-renderer/-/listr-update-renderer-0.4.0.tgz#344d980da2ca2e8b145ba305908f32ae3f4cc8a7" + dependencies: + chalk "^1.1.3" + cli-truncate "^0.2.1" + elegant-spinner "^1.0.1" + figures "^1.7.0" + indent-string "^3.0.0" + log-symbols "^1.0.2" + log-update "^1.0.2" + strip-ansi "^3.0.1" + +listr-verbose-renderer@^0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/listr-verbose-renderer/-/listr-verbose-renderer-0.4.1.tgz#8206f4cf6d52ddc5827e5fd14989e0e965933a35" + dependencies: + chalk "^1.1.3" + cli-cursor "^1.0.2" + date-fns "^1.27.2" + figures "^1.7.0" + +listr@^0.13.0: + version "0.13.0" + resolved "https://registry.yarnpkg.com/listr/-/listr-0.13.0.tgz#20bb0ba30bae660ee84cc0503df4be3d5623887d" + dependencies: + chalk "^1.1.3" + cli-truncate "^0.2.1" + figures "^1.7.0" + indent-string "^2.1.0" + is-observable "^0.2.0" + is-promise "^2.1.0" + is-stream "^1.1.0" + listr-silent-renderer "^1.1.1" + listr-update-renderer "^0.4.0" + listr-verbose-renderer "^0.4.0" + log-symbols "^1.0.2" + log-update "^1.0.2" + ora "^0.2.3" + p-map "^1.1.1" + rxjs "^5.4.2" + stream-to-observable "^0.2.0" + strip-ansi "^3.0.1" + load-json-file@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" @@ -2218,6 +2504,29 @@ lodash@^4.0.0, lodash@^4.14.0, lodash@^4.2.0, lodash@^4.3.0: version "4.17.4" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" +lodash@^4.17.4: + version "4.17.5" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.5.tgz#99a92d65c0272debe8c96b6057bc8fbfa3bed511" + +log-symbols@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-1.0.2.tgz#376ff7b58ea3086a0f09facc74617eca501e1a18" + dependencies: + chalk "^1.0.0" + +log-symbols@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" + dependencies: + chalk "^2.0.1" + +log-update@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/log-update/-/log-update-1.0.2.tgz#19929f64c4093d2d2e7075a1dad8af59c296b8d1" + dependencies: + ansi-escapes "^1.0.0" + cli-cursor "^1.0.2" + longest@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" @@ -2228,6 +2537,13 @@ loose-envify@^1.0.0: dependencies: js-tokens "^3.0.0" +lru-cache@^4.0.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.1.tgz#622e32e82488b49279114a4f9ecf45e7cd6bba55" + dependencies: + pseudomap "^1.0.2" + yallist "^2.1.2" + makeerror@1.0.x: version "1.0.11" resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.11.tgz#e01a5c9109f2af79660e4e8b9587790184f5a96c" @@ -2308,6 +2624,10 @@ ms@0.7.2: version "0.7.2" resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.2.tgz#ae25cf2512b3885a1d95d7f037868d8431124765" +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + multimatch@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-2.1.0.tgz#9c7906a22fb4c02919e2f5f75161b4cdbd4b2a2b" @@ -2391,6 +2711,26 @@ normalize-path@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.0.1.tgz#47886ac1662760d4261b7d979d241709d3ce3f7a" +npm-path@^2.0.2: + version "2.0.4" + resolved "https://registry.yarnpkg.com/npm-path/-/npm-path-2.0.4.tgz#c641347a5ff9d6a09e4d9bce5580c4f505278e64" + dependencies: + which "^1.2.10" + +npm-run-path@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" + dependencies: + path-key "^2.0.0" + +npm-which@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/npm-which/-/npm-which-3.0.1.tgz#9225f26ec3a285c209cae67c3b11a6b4ab7140aa" + dependencies: + commander "^2.9.0" + npm-path "^2.0.2" + which "^1.2.10" + npmlog@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.0.2.tgz#d03950e0e78ce1527ba26d2a7592e9348ac3e75f" @@ -2457,6 +2797,15 @@ optionator@^0.8.1, optionator@^0.8.2: type-check "~0.3.2" wordwrap "~1.0.0" +ora@^0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/ora/-/ora-0.2.3.tgz#37527d220adcd53c39b73571d754156d5db657a4" + dependencies: + chalk "^1.1.1" + cli-cursor "^1.0.2" + cli-spinners "^0.1.2" + object-assign "^4.0.1" + os-homedir@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" @@ -2479,6 +2828,14 @@ output-file-sync@^1.1.0: mkdirp "^0.5.1" object-assign "^4.1.0" +p-finally@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" + +p-map@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-1.2.0.tgz#e4e94f311eabbc8633a1e79908165fca26241b6b" + parse-glob@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" @@ -2494,6 +2851,13 @@ parse-json@^2.2.0: dependencies: error-ex "^1.2.0" +parse-json@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" + dependencies: + error-ex "^1.3.1" + json-parse-better-errors "^1.0.1" + parse5@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/parse5/-/parse5-1.5.1.tgz#9b7f3b0de32be78dc2401b17573ccaf0f6f59d94" @@ -2508,10 +2872,14 @@ path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" -path-is-inside@^1.0.1: +path-is-inside@^1.0.1, path-is-inside@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" +path-key@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + path-parse@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" @@ -2528,6 +2896,10 @@ pify@^2.0.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" +pify@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" + pinkie-promise@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" @@ -2570,6 +2942,13 @@ prettier@^1.10.2: version "1.10.2" resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.10.2.tgz#1af8356d1842276a99a5b5529c82dd9e9ad3cc93" +pretty-format@^21.2.1: + version "21.2.1" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-21.2.1.tgz#ae5407f3cf21066cd011aa1ba5fce7b6a2eddb36" + dependencies: + ansi-regex "^3.0.0" + ansi-styles "^3.2.0" + pretty-format@~4.2.1: version "4.2.3" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-4.2.3.tgz#8894c2ac81419cf801629d8f66320a25380d8b05" @@ -2596,6 +2975,10 @@ prr@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/prr/-/prr-0.0.0.tgz#1a84b85908325501411853d0081ee3fa86e2926a" +pseudomap@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" + punycode@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" @@ -2772,6 +3155,10 @@ require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" +require-from-string@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.1.tgz#c545233e9d7da6616e9d59adfb39fc9f588676ff" + require-main-filename@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" @@ -2824,6 +3211,12 @@ rx-lite@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102" +rxjs@^5.4.2: + version "5.5.6" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-5.5.6.tgz#e31fb96d6fd2ff1fd84bcea8ae9c02d007179c02" + dependencies: + symbol-observable "1.0.1" + sane@~1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/sane/-/sane-1.4.1.tgz#88f763d74040f5f0c256b6163db399bf110ac715" @@ -2855,6 +3248,16 @@ setimmediate@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + dependencies: + shebang-regex "^1.0.0" + +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + shelljs@^0.7.5: version "0.7.6" resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.6.tgz#379cccfb56b91c8601e4793356eb5382924de9ad" @@ -2940,6 +3343,16 @@ sshpk@^1.7.0: jsbn "~0.1.0" tweetnacl "~0.14.0" +staged-git-files@0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/staged-git-files/-/staged-git-files-0.0.4.tgz#d797e1b551ca7a639dec0237dc6eb4bb9be17d35" + +stream-to-observable@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/stream-to-observable/-/stream-to-observable-0.2.0.tgz#59d6ea393d87c2c0ddac10aa0d561bc6ba6f0e10" + dependencies: + any-observable "^0.2.0" + string-width@^1.0.1, string-width@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" @@ -2963,6 +3376,14 @@ string_decoder@~0.10.x: version "0.10.31" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" +stringify-object@^3.2.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/stringify-object/-/stringify-object-3.2.1.tgz#2720c2eff940854c819f6ee252aaeb581f30624d" + dependencies: + get-own-enumerable-property-symbols "^2.0.1" + is-obj "^1.0.1" + is-regexp "^1.0.0" + stringstream@~0.0.4: version "0.0.5" resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878" @@ -2983,6 +3404,10 @@ strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" +strip-eof@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" + strip-json-comments@~1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-1.0.4.tgz#1e15fbcac97d3ee99bf2d73b4c656b082bbafb91" @@ -3005,6 +3430,20 @@ supports-color@^3.1.0, supports-color@^3.1.2: dependencies: has-flag "^1.0.0" +supports-color@^4.0.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.5.0.tgz#be7a0de484dec5c5cddf8b3d59125044912f635b" + dependencies: + has-flag "^2.0.0" + +symbol-observable@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.1.tgz#8340fc4702c3122df5d22288f88283f513d3fdd4" + +symbol-observable@^0.2.2: + version "0.2.4" + resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-0.2.4.tgz#95a83db26186d6af7e7a18dbd9760a2f86d08f40" + "symbol-tree@>= 3.1.0 < 4.0.0": version "3.2.1" resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.1.tgz#8549dd1d01fa9f893c18cc9ab0b106b4d9b168cb" @@ -3202,6 +3641,12 @@ which@^1.0.5, which@^1.1.1: dependencies: isexe "^1.1.1" +which@^1.2.10, which@^1.2.9: + version "1.3.0" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.0.tgz#ff04bdfc010ee547d780bec38e1ac1c2777d253a" + dependencies: + isexe "^2.0.0" + wide-align@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.0.tgz#40edde802a71fea1f070da3e62dcda2e7add96ad" @@ -3260,6 +3705,10 @@ y18n@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" +yallist@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" + yargs-parser@^4.2.0: version "4.2.1" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-4.2.1.tgz#29cceac0dc4f03c6c87b4a9f217dd18c9f74871c"