diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..a0448a8 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,3 @@ +# Ignore built files except build/index.js +/.vscode +node_modules diff --git a/.eslintrc-full.js b/.eslintrc-full.js new file mode 100644 index 0000000..8e27d10 --- /dev/null +++ b/.eslintrc-full.js @@ -0,0 +1,19 @@ +module.exports = { + parserOptions: { + ecmaVersion: 2018, + }, + env: { + node: true, + es6: true, + mocha: true, + }, + extends: [ + "eslint-config-postcss", + ], + rules: { + "max-len": [1, 100], + "semi": [2, "always"], + + "prefer-let/prefer-let": 0, + }, +} diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..f84dcc2 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,19 @@ +module.exports = { + parserOptions: { + ecmaVersion: 2018, + }, + env: { + node: true, + es6: true, + mocha: true, + }, + extends: [ + "eslint-config-postcss", + ], + rules: { + "max-len": [1, 100], + "semi": [1, "always"], + + "prefer-let/prefer-let": 0, + }, +} diff --git a/.gitignore b/.gitignore index 9043f24..124b545 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ yarn-error.log *.css postcss.config.js test/test.js +styles/ diff --git a/index.js b/index.js index 254203f..6f8bc46 100644 --- a/index.js +++ b/index.js @@ -1,36 +1,51 @@ -const postcss = require('postcss') -const valueParser = require('postcss-values-parser') -const convert = require('color-convert') +const postcss = require('postcss'); +const valueParser = require('postcss-values-parser'); +const convert = require('color-convert'); -const regexpHEX = /#([a-f\d]{3}|[a-f\d]{6})/i +const regexpHEX = /#([a-f\d]{3}|[a-f\d]{6})$/i; +const regexpHEXAlpha = /#([a-f\d]{4}|[a-f\d]{8})$/i; +const regexpRGB = /rgb\(/; +const regexpHSL = /hsl\(/; const defaultOptions = { syntax: '', outputColorFormat: '' -} +}; module.exports = postcss.plugin('postcss-color-converter', (opts = {}) => { let currentOptions = { ...defaultOptions, ...opts - } + }; return style => { style.walkDecls(decl => { - let value = decl.value + let value = decl.value; if (value) { - let newColor = valueParser.parse(value) + let newValue = valueParser.parse(value); if (regexpHEX.test(value) && currentOptions.outputColorFormat === 'rgb') { - newColor.walk(node => { - if (node.type === 'word') { - node.value = `rgb(${ convert.hex.rgb(node.value).join(', ') })` + newValue.walk(node => { + if (node.type === 'word' && node.isColor && node.isHex) { + node.value = `rgb(${ convert.hex.rgb(node.value).join(', ') })`; } - }) + }); } - decl.value = newColor.toString() + + if (regexpRGB.test(value) && currentOptions.outputColorFormat === 'hex') { + newValue.walk(node => { + if (node.type === 'func' && node.isColor) { + const newNode = node.clone({ type: 'word' }); + newNode.value = `#${ convert.rgb.hex(node.nodes[0], node.nodes[2], node.nodes[4]) }`; + node.replaceWith(newNode); + // console.log(newNode) + } + }); + } + + decl.value = newValue.toString(); } - }) - } -}) + }); + }; +}); diff --git a/package.json b/package.json index ba008ae..c4da8cd 100644 --- a/package.json +++ b/package.json @@ -10,8 +10,9 @@ "converter" ], "scripts": { - "test": "mocha ./test/index.test.js", - "postcss": "postcss test.css --config ./postcss.config.js -r" + "test": "mocha ./test/*.test.js", + "lint": "eslint --config ./.eslintrc-full.js **/*.js --fix", + "postcss": "postcss ./styles/test.{css,scss} --config ./postcss.config.js -r" }, "author": "EdMSL ", "license": "MIT", diff --git a/test/hex.test.js b/test/hex.test.js new file mode 100644 index 0000000..56b2421 --- /dev/null +++ b/test/hex.test.js @@ -0,0 +1,50 @@ +const postcss = require('postcss'); +const { assert } = require('chai'); + +const plugin = require('../index'); + +/* eslint-disable prefer-arrow-callback, func-names */ + +describe('postcss-color-converter', function () { + function transform (source, opts) { + return postcss([plugin(opts)]).process(source).css; + } + + it('Input color should not be converted', function () { + assert.equal(transform( + 'body { color: #ffffff; }', + {} + ), 'body { color: #ffffff; }'); + assert.equal(transform( + 'body { color: #ffffff; }', + { outputColorFormat: 'hex' } + ), 'body { color: #ffffff; }'); + }); + + it('Input color must be converted to rgb', function () { + assert.equal(transform( + 'body { color: #ffffff; }', + { outputColorFormat: 'rgb' } + ), 'body { color: rgb(255, 255, 255); }'); + assert.equal(transform( + `ul { + background: linear-gradient( + to bottom, + #456789 0%, + #fff555 100%, + ); + }`, + { outputColorFormat: 'rgb' } + ), `ul { + background: linear-gradient( + to bottom, + rgb(69, 103, 137) 0%, + rgb(255, 245, 85) 100%, + ); + }`); + assert.equal(transform( + 'body { color: #555; }', + { outputColorFormat: 'rgb' } + ), 'body { color: rgb(85, 85, 85); }'); + }); +}); diff --git a/test/index.test.js b/test/index.test.js deleted file mode 100644 index 34d1d43..0000000 --- a/test/index.test.js +++ /dev/null @@ -1,26 +0,0 @@ -const postcss = require('postcss') -const { assert } = require('chai') - -const plugin = require('../index') - -/* eslint-disable prefer-arrow-callback */ - -describe('postcss-color-converter', function () { - function transform (source, opts) { - return postcss([plugin(opts)]).process(source).css - } - - it('Input color should not be converted', function () { - assert.equal(transform( - 'body: { color: #ffffff; }', - {} - ), 'body: { color: #ffffff; }') - }) - - it('Input color must be converted to rgb', function () { - assert.equal(transform( - 'body: { color: #ffffff; }', - { outputColorFormat: 'rgb' } - ), 'body: { color: rgb(255, 255, 255); }') - }) -}) diff --git a/test/rgb.test.js b/test/rgb.test.js new file mode 100644 index 0000000..8324586 --- /dev/null +++ b/test/rgb.test.js @@ -0,0 +1,46 @@ +const postcss = require('postcss'); +const { assert } = require('chai'); + +const plugin = require('../index'); + +/* eslint-disable prefer-arrow-callback, func-names */ + +describe('postcss-color-converter', function () { + function transform (source, opts) { + return postcss([plugin(opts)]).process(source).css; + } + + it('Input color should not be converted', function () { + assert.equal(transform( + 'body { color: rgb(255, 255, 255); }', + { outputColorFormat: 'rgb' } + ), 'body { color: rgb(255, 255, 255); }'); + assert.equal(transform( + 'body { color: rgb(255, 255, 255); }', + {} + ), 'body { color: rgb(255, 255, 255); }'); + }); + + it('Input color must be converted to hex', function () { + assert.equal(transform( + 'body { color: rgb(255, 255, 255); }', + { outputColorFormat: 'hex' } + ), 'body { color: #ffffff; }'); + assert.equal(transform( + `ul { + background: linear-gradient( + to bottom, + rgb(69, 103, 137) 0%, + rgb(255, 245, 85) 100%, + ); + }`, + { outputColorFormat: 'hex' } + ), `ul { + background: linear-gradient( + to bottom, + #456789 0%, + #fff555 100%, + ); + }`); + }); +});