From fe5c16a63f42d9c7210d9a1ea92a04187d5f180f Mon Sep 17 00:00:00 2001 From: xzyfer Date: Tue, 24 Jul 2018 19:55:58 +1000 Subject: [PATCH] Handle Sass values Currently we coerce all values into quoted Sass Strings. This PR coerces the JSON value into the appropriate Sass value type. If the value type cannot be determined we fallback to a quoted Sass String to avoid errors. This differs from [prior work][1] in that no attempt is made to mangle JSON arrays and maps into a JSON string value. [1]: https://github.com/Updater/node-sass-json-importer/pull/5 Fixes #3 --- index.js | 24 ++++++++++++++++-- package.json | 3 +++ tests/__snapshots__/index.test.js.snap | 16 ++++++++++-- tests/fixtures/values.json | 34 ++++++++++++++++++++++++++ tests/index.test.js | 4 +++ 5 files changed, 77 insertions(+), 4 deletions(-) create mode 100644 tests/fixtures/values.json diff --git a/index.js b/index.js index f89584b..b73533b 100644 --- a/index.js +++ b/index.js @@ -1,5 +1,6 @@ const fs = require('fs'); const path = require('path'); +const csscolors = require('css-color-names'); const exists = (file) => { try { @@ -10,14 +11,33 @@ const exists = (file) => { } } +const reValue = new RegExp([ + // ---- hex colors + '^#[0-9a-z]{3}$', // #def + '^#[0-9a-z]{4}$', // #def0 + '^#[0-9a-z]{6}$', // #ddeeff + '^#[0-9a-z]{8}$', // #ddeeff00 + // ---- numbers + '^[0-9]+(?:\\.[0-9]+)?(?:%|[a-z]+)?$', // 12.34 + unit + // ---- function calls + '^[a-z][a-z0-9-_]*\\(', // foo(...) +].join('|'), 'i'); + +const looksLikeString = (value) => { + return !reValue.test(value) || csscolors[value]; +} + const buildSassValue = (value) => { if (Array.isArray(value)) { - return `(${value.reduce((prev, cur) => prev + `"${cur}",`, '')})`; + return `(${value.reduce((prev, cur) => prev + `${buildSassValue(cur)},`, '')})`; } if (typeof value === "object") { return `(${buildSassMap(value)})`; } - return `"${value}"`; + if (looksLikeString(value)) { + return `"${value}"`; + } + return value; } const buildSassMap = (json) => { diff --git a/package.json b/package.json index 18da68a..c5770f4 100644 --- a/package.json +++ b/package.json @@ -24,5 +24,8 @@ "devDependencies": { "jest": "^23.4.0", "node-sass": "^4.9.2" + }, + "dependencies": { + "css-color-names": "0.0.4" } } diff --git a/tests/__snapshots__/index.test.js.snap b/tests/__snapshots__/index.test.js.snap index 311fc5e..2d19b34 100644 --- a/tests/__snapshots__/index.test.js.snap +++ b/tests/__snapshots__/index.test.js.snap @@ -1,5 +1,11 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`json-importer async should not resolve Sass values to quoted strings 1`] = ` +"output { + contents: (\\"short-hex-color\\": #def, \\"short-hex-color-with-alpha\\": #def0, \\"long-hex-color\\": #ddeeff, \\"long-hex-color-with-alpha\\": #ddeeff00, \\"named-color\\": \\"red\\", \\"number\\": 16, \\"number-with-percentage\\": 16%, \\"number-with-word-unit\\": 16rem, \\"decimal\\": 12.34, \\"decimal-with-percentage\\": 12.34%, \\"decimal-with-word-unit\\": 12.34rem, \\"function-call\\": black, \\"string\\": \\"foo\\", \\"string-with-spaces\\": \\"who are you\\", \\"array\\": (16, 16px, 16%, 12.34, 12.34px, 12.34%, #def, black, \\"foo\\", \\"who are you\\"), \\"map\\": (\\"short-hex-color\\": #def, \\"short-hex-color-with-alpha\\": #def0, \\"string\\": \\"foo\\", \\"string-with-spaces\\": \\"who are you\\")); } +" +`; + exports[`json-importer async should resolve flat json strings as Sass map 1`] = ` "output { contents: (\\"color\\": \\"red\\", \\"size\\": \\"small\\"); } @@ -20,7 +26,13 @@ exports[`json-importer async should resolve json files in includePaths 1`] = ` exports[`json-importer async should resolve nested json strings as Sass map 1`] = ` "output { - contents: (\\"colors\\": (\\"red\\": \\"#f00\\", \\"blue\\": \\"#00f\\"), \\"sizes\\": (\\"small\\": \\"16px\\", \\"big\\": \\"30px\\")); } + contents: (\\"colors\\": (\\"red\\": #f00, \\"blue\\": #00f), \\"sizes\\": (\\"small\\": 16px, \\"big\\": 30px)); } +" +`; + +exports[`json-importer sync should not resolve Sass values to quoted strings 1`] = ` +"output { + contents: (\\"short-hex-color\\": #def, \\"short-hex-color-with-alpha\\": #def0, \\"long-hex-color\\": #ddeeff, \\"long-hex-color-with-alpha\\": #ddeeff00, \\"named-color\\": \\"red\\", \\"number\\": 16, \\"number-with-percentage\\": 16%, \\"number-with-word-unit\\": 16rem, \\"decimal\\": 12.34, \\"decimal-with-percentage\\": 12.34%, \\"decimal-with-word-unit\\": 12.34rem, \\"function-call\\": black, \\"string\\": \\"foo\\", \\"string-with-spaces\\": \\"who are you\\", \\"array\\": (16, 16px, 16%, 12.34, 12.34px, 12.34%, #def, black, \\"foo\\", \\"who are you\\"), \\"map\\": (\\"short-hex-color\\": #def, \\"short-hex-color-with-alpha\\": #def0, \\"string\\": \\"foo\\", \\"string-with-spaces\\": \\"who are you\\")); } " `; @@ -44,6 +56,6 @@ exports[`json-importer sync should resolve json files in includePaths 1`] = ` exports[`json-importer sync should resolve nested json strings as Sass map 1`] = ` "output { - contents: (\\"colors\\": (\\"red\\": \\"#f00\\", \\"blue\\": \\"#00f\\"), \\"sizes\\": (\\"small\\": \\"16px\\", \\"big\\": \\"30px\\")); } + contents: (\\"colors\\": (\\"red\\": #f00, \\"blue\\": #00f), \\"sizes\\": (\\"small\\": 16px, \\"big\\": 30px)); } " `; diff --git a/tests/fixtures/values.json b/tests/fixtures/values.json new file mode 100644 index 0000000..8fac3fa --- /dev/null +++ b/tests/fixtures/values.json @@ -0,0 +1,34 @@ +{ + "short-hex-color": "#def", + "short-hex-color-with-alpha": "#def0", + "long-hex-color": "#ddeeff", + "long-hex-color-with-alpha": "#ddeeff00", + "named-color": "red", + "number": "16", + "number-with-percentage": "16%", + "number-with-word-unit": "16rem", + "decimal": "12.34", + "decimal-with-percentage": "12.34%", + "decimal-with-word-unit": "12.34rem", + "function-call": "hsl(0,0,0)", + "string": "foo", + "string-with-spaces": "who are you", + "array": [ + 16, + "16px", + "16%", + 12.34, + "12.34px", + "12.34%", + "#def", + "hsl(0,0,0)", + "foo", + "who are you" + ], + "map": { + "short-hex-color": "#def", + "short-hex-color-with-alpha": "#def0", + "string": "foo", + "string-with-spaces": "who are you" + } +} diff --git a/tests/index.test.js b/tests/index.test.js index 6c454c5..4b180be 100644 --- a/tests/index.test.js +++ b/tests/index.test.js @@ -42,6 +42,10 @@ describe('json-importer', () => { func(generate('tests/fixtures/list.json')) .then(result => expect(result).toMatchSnapshot()) )); + it('should not resolve Sass values to quoted strings', () => ( + func(generate('tests/fixtures/values.json')) + .then(result => expect(result).toMatchSnapshot()) + )); it('should resolve json files in includePaths', () => ( func(generate('fixtures/flat.json'), { includePaths: ['tests']}) .then(result => expect(result).toMatchSnapshot())