From 9f59efb6d2ed4fd31f0d9367ceff042d927076d8 Mon Sep 17 00:00:00 2001 From: Krister Kari Date: Thu, 7 Jan 2016 09:38:12 +0200 Subject: [PATCH] Format properties and values to lowercase - Format CSS properties to lowercase - Format @charset to lowercase - Instead of just formatting hex colors, format all CSS colors to lowercase - Format CSS transforms to lowercase --- lib/formatAtRuleParams.js | 4 ++++ lib/formatColors.js | 22 ++++++++++++++++++ lib/formatDecls.js | 3 +++ lib/formatSassVariables.js | 13 +++++++++++ lib/formatTransforms.js | 27 ++++++++++++++++++++++ lib/formatValues.js | 8 +++---- lib/util.js | 8 ------- package.json | 2 +- test/fixtures/lowercase.css | 40 +++++++++++++++++++++++++++++++++ test/fixtures/lowercase.out.css | 39 ++++++++++++++++++++++++++++++++ test/index.js | 1 + 11 files changed, 154 insertions(+), 13 deletions(-) create mode 100644 lib/formatColors.js create mode 100644 lib/formatTransforms.js create mode 100644 test/fixtures/lowercase.css create mode 100644 test/fixtures/lowercase.out.css diff --git a/lib/formatAtRuleParams.js b/lib/formatAtRuleParams.js index e34bee5..9a0684b 100644 --- a/lib/formatAtRuleParams.js +++ b/lib/formatAtRuleParams.js @@ -30,6 +30,10 @@ function formatAtRuleParams (atrule) { params = params.replace(/\s+/g, ' ') } + if (atName === 'charset') { + params = params.toLowerCase() + } + if (atName === 'return' || atName === 'if' || atName === 'else') { // format math operators before `$` or `(`. params = params.replace(/(?!^)[+\-*/%](?=\$|\()/g, ' $& ') diff --git a/lib/formatColors.js b/lib/formatColors.js new file mode 100644 index 0000000..41b59a5 --- /dev/null +++ b/lib/formatColors.js @@ -0,0 +1,22 @@ +var cssColors = require('css-color-list') +var namedColorsRegex = new RegExp(cssColors().join('|'), 'ig') +var hslRegex = /hsla?\(\s*\d{1,3}\s*,\s*\d{1,3}%\s*,\s*\d{1,3}%\s*(,\s*[\d\.]+)?\s*\)/ig +var hexRegex = /#[a-f0-9]{3}([a-f0-9]{3})?/ig +var rgbRegex = /rgba?\(\s*\d{1,3}\s*,\s*\d{1,3}\s*,\s*\d{1,3}\s*(,\s*[\d\.]+)?\s*\)/ig + +function toLowerCase(value) { + return value.toLowerCase() +} + +function colorsToLowerCase(value) { + return value.replace(namedColorsRegex, toLowerCase) + .replace(hslRegex, toLowerCase) + .replace(hexRegex, toLowerCase) + .replace(rgbRegex, toLowerCase) +} + +function formatColors(value) { + return colorsToLowerCase(value) +} + +module.exports = formatColors diff --git a/lib/formatDecls.js b/lib/formatDecls.js index fe253da..29a8505 100644 --- a/lib/formatDecls.js +++ b/lib/formatDecls.js @@ -7,6 +7,9 @@ function formatDecls (rule) { if (hasDecls(rule)) { rule.walkDecls(function (decl) { + if (decl.prop) { + decl.prop = decl.prop.toLowerCase() + } var more = config.indentWidth decl.raws.before = '\n' + getIndent(rule) + more decl.raws.between = ': ' diff --git a/lib/formatSassVariables.js b/lib/formatSassVariables.js index d972c04..7832aa9 100644 --- a/lib/formatSassVariables.js +++ b/lib/formatSassVariables.js @@ -1,3 +1,6 @@ +var formatTransforms = require('./formatTransforms') +var formatColors = require('./formatColors') + function formatSassVariables (root) { root.walkDecls(function (decl) { if (isSassVariable(decl)) { @@ -15,6 +18,16 @@ function formatSassVariables (root) { decl.value = decl.value.trim().replace(/-(?=\d+)/g, ' $& ') } + var isDataUrl = (/data:.+\/(.+);base64,(.*)/).test(decl.value) + + if (!isDataUrl) { + // Remove spaces before commas and keep only one space after. + decl.value = decl.value.trim().replace(/(\s+)?,(\s)*/g, ', ') + } + + decl.value = formatColors(decl.value) + decl.value = formatTransforms(decl.value) + decl.raws.before = '\n' decl.raws.between = ': ' } diff --git a/lib/formatTransforms.js b/lib/formatTransforms.js new file mode 100644 index 0000000..0e80e39 --- /dev/null +++ b/lib/formatTransforms.js @@ -0,0 +1,27 @@ +var transformTypes = [ + 'translate', + 'matrix', + 'rotate', + 'scale', + 'skew' +] +var transformRegex = new RegExp('(' + transformTypes.join('|') + ')[xyz]?(3d)?\\(', 'ig') +var matrixRegex = /matrix\(/ig +var xyzRegex = /[xyz]{1}(?=\()/g + +function transformsToLowerCase(value) { + return value.replace(transformRegex, function(value) { + if (matrixRegex.test(value)) { + return value.toLowerCase() + } + return value.toLowerCase().replace(xyzRegex, function(value) { + return value.toUpperCase() + }) + }) +} + +function formatTransforms(value) { + return transformsToLowerCase(value) +} + +module.exports = formatTransforms diff --git a/lib/formatValues.js b/lib/formatValues.js index 649a7b4..b0048d4 100644 --- a/lib/formatValues.js +++ b/lib/formatValues.js @@ -1,4 +1,5 @@ -var isHex = require('./util').isHex +var formatTransforms = require('./formatTransforms') +var formatColors = require('./formatColors') function formatProperties (decl) { var isDataUrl = (/data:.+\/(.+);base64,(.*)/).test(decl.value) @@ -14,9 +15,8 @@ function formatProperties (decl) { } decl.value = decl.value.trim().replace(/[+\-*/%](?=\$|\()/g, ' $& ') - if (isHex(decl.value)) { - decl.value = decl.value.toLowerCase() - } + decl.value = formatColors(decl.value) + decl.value = formatTransforms(decl.value) if (decl.important) { decl.raws.important = " !important" diff --git a/lib/util.js b/lib/util.js index ef8eec9..88fc8c5 100644 --- a/lib/util.js +++ b/lib/util.js @@ -1,4 +1,3 @@ -var hexRegex = require('hex-color-regex') function inAtRule (rule) { var ret = false @@ -27,12 +26,5 @@ function getNestedRulesNum (rule) { return num } - -function isHex (str) { - return hexRegex({exact: true}).test(str) -} - - module.exports.inAtRule = inAtRule module.exports.getNestedRulesNum = getNestedRulesNum -module.exports.isHex = isHex diff --git a/package.json b/package.json index 2b2f36f..039f329 100644 --- a/package.json +++ b/package.json @@ -24,9 +24,9 @@ "author": "Masaaki Morishita", "license": "MIT", "dependencies": { + "css-color-list": "0.0.1", "editorconfig-indent": "^0.3.0", "find-config": "0.3.0", - "hex-color-regex": "^1.0.3", "minimist": "^1.1.2", "postcss": "^5.0.6", "postcss-scss": "^0.1.0", diff --git a/test/fixtures/lowercase.css b/test/fixtures/lowercase.css new file mode 100644 index 0000000..feac8a6 --- /dev/null +++ b/test/fixtures/lowercase.css @@ -0,0 +1,40 @@ +@charset "UTF-8"; + +$myVar: TRANSLATEX(0); +$myVar2: RGB(255,255,255); +$myVar3: MAROON; +$myVar4: HSLA(120,100%,50%,0.3); +$myVar5: RGBA(0,0,0,0.5); +$myVar6: HSL(120,100%,50%); +$myVar7: linear-gradient(to right, RGBA(0,0,0,0.5), RGB(255,255,255)); + +.class-1 { + BACKGROUND: HSL(120, 100%, 50%); + BACKGROUND: linear-gradient(to right, $myVar2, RGB(255,255,255)); + COLOR: RGB(0, 0, 0); + TRANSFORM: TRANSLATE(0,0) TRANSLATEX(0) TRANSLATEY(0) TRANSLATEZ(0) TRANSLATE3D(0,0,0) MATRIX(1,1,1,1); + TRANSFORM: TRANSLATE(0,0); + TRANSFORM: TRANSLATEX(0); + TRANSFORM: TRANSLATEY(0); + TRANSFORM: TRANSLATE3D(0,0,0); + TRANSFORM: MATRIX(1,1,1,1); + transform: translateY(0) $myVar; +} + +.class-2 { + BACKGROUND-COLOR: INDIGO; + BACKGROUND: HSLA(120, 100%, 50%, 0.3); + COLOR: RGBA(0, 0, 0, 0.5); + TRANSFORM: ROTATE(1deg) ROTATEX(1deg) ROTATEY(1deg) ROTATEZ(1deg) ROTATE3D(0,0,1,1deg) SKEW(1deg) SKEWX(1deg) SKEWY(1deg) SCALE(1, 1) SCALEX(1) SCALEY(1); + TRANSFORM: ROTATE(1deg); + TRANSFORM: ROTATEX(1deg); + TRANSFORM: ROTATEY(1deg); + TRANSFORM: ROTATEZ(1deg); + TRANSFORM: ROTATE3D(0,0,1,1deg); + TRANSFORM: SKEW(1deg); + TRANSFORM: SKEWX(1deg); + TRANSFORM: SKEWY(1deg); + TRANSFORM: SCALE(1, 1); + TRANSFORM: SCALEX(1); + TRANSFORM: SCALEY(1); +} diff --git a/test/fixtures/lowercase.out.css b/test/fixtures/lowercase.out.css new file mode 100644 index 0000000..f3629b6 --- /dev/null +++ b/test/fixtures/lowercase.out.css @@ -0,0 +1,39 @@ +@charset "utf-8"; +$myVar: translateX(0); +$myVar2: rgb(255, 255, 255); +$myVar3: maroon; +$myVar4: hsla(120, 100%, 50%, 0.3); +$myVar5: rgba(0, 0, 0, 0.5); +$myVar6: hsl(120, 100%, 50%); +$myVar7: linear-gradient(to right, rgba(0, 0, 0, 0.5), rgb(255, 255, 255)); + +.class-1 { + background: hsl(120, 100%, 50%); + background: linear-gradient(to right, $myVar2, rgb(255, 255, 255)); + color: rgb(0, 0, 0); + transform: translate(0, 0) translateX(0) translateY(0) translateZ(0) translate3d(0, 0, 0) matrix(1, 1, 1, 1); + transform: translate(0, 0); + transform: translateX(0); + transform: translateY(0); + transform: translate3d(0, 0, 0); + transform: matrix(1, 1, 1, 1); + transform: translateY(0) $myVar; +} + +.class-2 { + background-color: indigo; + background: hsla(120, 100%, 50%, 0.3); + color: rgba(0, 0, 0, 0.5); + transform: rotate(1deg) rotateX(1deg) rotateY(1deg) rotateZ(1deg) rotate3d(0, 0, 1, 1deg) skew(1deg) skewX(1deg) skewY(1deg) scale(1, 1) scaleX(1) scaleY(1); + transform: rotate(1deg); + transform: rotateX(1deg); + transform: rotateY(1deg); + transform: rotateZ(1deg); + transform: rotate3d(0, 0, 1, 1deg); + transform: skew(1deg); + transform: skewX(1deg); + transform: skewY(1deg); + transform: scale(1, 1); + transform: scaleX(1); + transform: scaleY(1); +} diff --git a/test/index.js b/test/index.js index 7ede13b..efaadff 100644 --- a/test/index.js +++ b/test/index.js @@ -59,3 +59,4 @@ test('sass-if-else-2') test('media-indent') test('media-indent-with-import') test('color-hex-lowercase') +test('lowercase')