diff --git a/.eslintrc b/.eslintrc index d0b4de2..a1da907 100644 --- a/.eslintrc +++ b/.eslintrc @@ -4,7 +4,7 @@ "env": { "browser": false, "node": true, - "mocha": true + "jest": true }, "ecmaFeatures": { "jsx": false, diff --git a/package.json b/package.json index bb19d4e..75bb287 100644 --- a/package.json +++ b/package.json @@ -49,12 +49,14 @@ "postcss-js": "^0.3.0", "postcss-load-config": "^1.2.0", "postcss-safe-parser": "^2.0.0", + "postcss-scss": "^0.4.1", "postcss-simple-vars": "^3.0.0" }, "devDependencies": { "babel": "^6.23.0", "babel-cli": "^6.23.0", "babel-core": "^6.23.1", + "babel-eslint": "^7.2.3", "babel-jest": "^19.0.0", "babel-plugin-transform-flow-strip-types": "^6.22.0", "babel-plugin-transform-runtime": "^6.23.0", diff --git a/src/async/parser.js b/src/async/parser.js index cceafe8..bd32135 100644 --- a/src/async/parser.js +++ b/src/async/parser.js @@ -1,41 +1,9 @@ /** * @see https://gist.github.com/muratgozel/e3ca2c08f74c9cb6eb7314e3088edb77#gistcomment-1802108 */ -import postcss from 'postcss' -import safeParse from 'postcss-safe-parser' import postcssJs from 'postcss-js' -import postcssrc from 'postcss-load-config' -let config -let processor - -/** - * 1. Initiate config, options and processor variables in module scope, - * if they are not initiated yet - * - * 2. Process parsing with initiated options - * - * @param {String} rawStyles - * @param {Object} processOptions - * @returns {Object} JSS Object - */ -const processParsing = async (rawStyles, processOptions = {}) => { - const { config: customConfig } = processOptions - if (!config && customConfig) { - config = customConfig - } else if (!config) { - config = await postcssrc() - } - - const { plugins = [], options = {} } = config - const finalOptions = { parser: safeParse, ...options } - - if (!processor) { - processor = postcss(plugins) - } - - return processor.process(rawStyles, finalOptions) -} +import processParsing from '../common/process-parsing' /** * Parse specified Tagged Template Strings with CSS and expressions @@ -48,6 +16,3 @@ export default async (rawStyles, processOptions) => { const processed = await processParsing(rawStyles, processOptions) return postcssJs.objectify(processed.root) } - - - diff --git a/src/common/default-config.js b/src/common/default-config.js new file mode 100644 index 0000000..9b587f5 --- /dev/null +++ b/src/common/default-config.js @@ -0,0 +1,3 @@ +const syntax = require('postcss-scss') + +export default { options: { syntax } } diff --git a/src/common/process-parsing.js b/src/common/process-parsing.js new file mode 100644 index 0000000..1993a9e --- /dev/null +++ b/src/common/process-parsing.js @@ -0,0 +1,42 @@ +import postcss from 'postcss' +import postcssrc from 'postcss-load-config' +import safeParse from 'postcss-safe-parser' + +import defaultConfig from './default-config' + +let config +let processor + +/** + * 1. Initiate config, options and processor variables in module scope, + * if they are not initiated yet + * + * 2. Process parsing with initiated options + * + * @param {String} rawStyles + * @param {Object} processOptions + * @returns {Object} JSS Object + */ +const processParsing = async (rawStyles, processOptions = {}) => { + const { config: customConfig } = processOptions + if (!config && customConfig) { + config = customConfig + } else if (!config) { + try { + config = await postcssrc() + } catch (e) { + config = defaultConfig + } + } + + const { plugins = [], options = {} } = config + const finalOptions = { parser: safeParse, ...options } + + if (!processor) { + processor = postcss(plugins) + } + + return processor.process(rawStyles, finalOptions) +} + +export default processParsing diff --git a/src/sync/parser.js b/src/sync/parser.js index 1cd4529..1dca88b 100644 --- a/src/sync/parser.js +++ b/src/sync/parser.js @@ -8,42 +8,10 @@ * * @todo Find a way to do not use deasync */ -import postcss from 'postcss' -import safeParse from 'postcss-safe-parser' import postcssJs from 'postcss-js' -import postcssrc from 'postcss-load-config' import deasync from 'deasync' -let config -let processor - -/** - * 1. Initiate config, options and processor variables in module scope, - * if they are not initiated yet - * - * 2. Process parsing with initiated options - * - * @param {String} rawStyles - * @param {Object} processOptions - * @returns {Object} JSS Object - */ -const processParsing = async (rawStyles, processOptions = {}) => { - const { config: customConfig } = processOptions - if (!config && customConfig) { - config = customConfig - } else if (!config) { - config = await postcssrc() - } - - const { plugins = [], options = {} } = config - const finalOptions = { parser: safeParse, ...options } - - if (!processor) { - processor = postcss(plugins) - } - - return processor.process(rawStyles, finalOptions) -} +import processParsing from '../common/process-parsing' /** * Parse specified Tagged Template Strings with CSS and expressions @@ -58,6 +26,3 @@ export default deasync((rawStyles, processOptions = {}, cb) => { .then(result => cb(null, result)) .catch(error => cb(error)) }) - - - diff --git a/tests/default-config/index.test.js b/tests/default-config/index.test.js new file mode 100644 index 0000000..9ff8756 --- /dev/null +++ b/tests/default-config/index.test.js @@ -0,0 +1,34 @@ +import { asyncParser } from '../../src' + +const rawCSS = ` + button { + color: #ffffff; + width: 100px; + height: 70px; + + &.primary { + color: red; + } + } +` + +const expectedJSS = { + button: { + color: '#ffffff', + width: '100px', + height: '70px', + '&.primary': { + color: 'red', + }, + }, +} + +beforeAll(() => { + process.chdir(__dirname) +}) + +it('should handle default config', async () => { + const result = await asyncParser(rawCSS) + + expect(result).toEqual(expectedJSS) +}) diff --git a/tests/parser.test.js b/tests/parser.test.js index 60cd511..d0b0992 100644 --- a/tests/parser.test.js +++ b/tests/parser.test.js @@ -1,6 +1,6 @@ import { syncParser, asyncParser } from '../src' -const css = ` +const rawCSS = ` button { color: #ffffff; width: 100px; @@ -8,7 +8,7 @@ const css = ` } ` -const objectCss = { +const expectedJSS = { button: { color: '#ffffff', width: '100px', @@ -23,13 +23,13 @@ const options = { } it('sync parse from plain css to object', () => { - const result = syncParser(css, options) + const result = syncParser(rawCSS, options) - expect(result).toEqual(objectCss) + expect(result).toEqual(expectedJSS) }) it('async parse from plain css to object', async () => { - const result = await asyncParser(css, options) + const result = await asyncParser(rawCSS, options) - expect(result).toEqual(objectCss) -}) \ No newline at end of file + expect(result).toEqual(expectedJSS) +}) diff --git a/.postcssrc b/tests/postcssrc/.postcssrc similarity index 100% rename from .postcssrc rename to tests/postcssrc/.postcssrc diff --git a/tests/postcssrc/index.test.js b/tests/postcssrc/index.test.js new file mode 100644 index 0000000..0d30ed7 --- /dev/null +++ b/tests/postcssrc/index.test.js @@ -0,0 +1,34 @@ +import { asyncParser } from '../../src' + +const rawCSS = ` + button { + color: #ffffff; + width: 100px; + height: 70px; + + &.primary { + color: red; + } + } +` + +const expectedJSS = { + button: { + color: '#ffffff', + width: '100px', + height: '70px', + }, + 'button.primary': { + color: 'red', + }, +} + +beforeAll(() => { + process.chdir(__dirname) +}) + +it('should handle postcssrc config', async () => { + const result = await asyncParser(rawCSS) + + expect(result).toEqual(expectedJSS) +})