diff --git a/src/index.js b/src/index.js index 9ae5c35..ed05c38 100644 --- a/src/index.js +++ b/src/index.js @@ -2,11 +2,15 @@ import _ from 'lodash'; import {resolve} from 'path'; import isThere from 'is-there'; +var ESCAPE_STRINGS = false; + export default function(url, prev) { if (!isJSONfile(url)) { return null; } + ESCAPE_STRINGS = this.options.escapeStrings; + let includePaths = this.options.includePaths ? this.options.includePaths.split(':') : []; let paths = [] .concat(prev.slice(0, prev.lastIndexOf('/'))) @@ -50,6 +54,8 @@ export function parseValue(value) { return parseList(value); } else if (_.isPlainObject(value)) { return parseMap(value); + } else if (ESCAPE_STRINGS && _.isString(value)) { + return `"${value}"` } else { return value; } diff --git a/test/fixtures/escape-strings/style.scss b/test/fixtures/escape-strings/style.scss new file mode 100644 index 0000000..d5d5ff9 --- /dev/null +++ b/test/fixtures/escape-strings/style.scss @@ -0,0 +1,26 @@ +@import 'variables.json'; + +/// Map deep get +/// @author Hugo Giraudel +/// @access public +/// @param {Map} $map - Map +/// @param {Arglist} $keys - Key chain +/// @return {*} - Desired value +@function map-deep-get($map, $keys...) { + @each $key in $keys { + $map: map-get($map, $key); + } + @return $map; +} + +// Fetch nested data from JSON +$entry-name: map-get($sony, name); +$entry-selectors: map-deep-get($sony, "selectors", "entry"); + +// Generate CSS based on this data +@each $entry in $entry-selectors { + #{$entry}:before { + color: red; + content: "#{$entry-name}"; + } +} diff --git a/test/fixtures/escape-strings/variables.json b/test/fixtures/escape-strings/variables.json new file mode 100644 index 0000000..9cbe338 --- /dev/null +++ b/test/fixtures/escape-strings/variables.json @@ -0,0 +1,34 @@ +{ + "google": { + "name": "Google", + "patterns": ["*//*.google.*/*"], + "selectors": { + "entry": ["#google > div"], + "anchor": "h2 a" + } + }, + "microsoft": { + "name": "Microsoft", + "patterns": ["*//*.subdomain.microsoft.com/*", "*//microsoft.com/*"], + "selectors": { + "entry": ["#main > li"], + "anchor": "h3.title a" + } + }, + "sony": { + "name": "sony", + "patterns": ["*//www.sony.com/"], + "selectors": { + "entry": ["#results > li", "#results2 > li"], + "anchor": "h2 > a" + } + }, + "apple": { + "name": "Apple", + "patterns": ["*//apple.com/"], + "selectors": { + "entry": ["#links > .result"], + "anchor": "h2 > a" + } + } +} diff --git a/test/index.js b/test/index.js index 0050c37..62d8d0b 100644 --- a/test/index.js +++ b/test/index.js @@ -37,6 +37,37 @@ describe('Import type test', function() { expect(result.css.toString()).to.eql(EXPECTATION); }); + it('escapes strings when escapeStrings option is set', function() { + const escapeStringsExpectation = `#results > li:before { + color: red; + content: "sony"; } + +#results2 > li:before { + color: red; + content: "sony"; } +` + let result = sass.renderSync({ + file: './test/fixtures/escape-strings/style.scss', + escapeStrings: true, + importer: jsonImporter + }); + + expect(result.css.toString()).to.eql(escapeStringsExpectation); + }); + + it(`throws on complex JSON when escapeStrings option is not set`, function() { + function render() { + sass.renderSync({ + file: './test/fixtures/escape-strings/style.scss', + importer: jsonImporter + }); + } + + expect(render).to.throw( + 'Invalid CSS after "...gle,patterns: (": expected expression (e.g. 1px, bold), was "*//*.google.*/*),se"' + ); + }); + it('finds imports via includePaths', function() { let result = sass.renderSync({ file: './test/fixtures/include-paths/style.scss',