diff --git a/package.json b/package.json index d1e2b51..809d4d2 100644 --- a/package.json +++ b/package.json @@ -28,13 +28,16 @@ "repository": "https://github.com/postcss/postcss-calc.git", "eslintConfig": { "extends": [ - "eslint:recommended" + "eslint:recommended", + "prettier" ], "env": { "node": true, "es2017": true }, - "ignorePatterns": ["src/parser.js"], + "ignorePatterns": [ + "src/parser.js" + ], "rules": { "curly": "error" } @@ -42,8 +45,10 @@ "devDependencies": { "@types/node": "^17.0.14", "eslint": "^8.7.0", + "eslint-config-prettier": "^8.3.0", "jison-gho": "^0.6.1-216", "postcss": "^8.2.2", + "prettier": "^2.5.1", "typescript": "^4.5.5", "uvu": "^0.5.3" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6fec6c1..fd1f22a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -3,10 +3,12 @@ lockfileVersion: 5.3 specifiers: '@types/node': ^17.0.14 eslint: ^8.7.0 + eslint-config-prettier: ^8.3.0 jison-gho: ^0.6.1-216 postcss: ^8.2.2 postcss-selector-parser: ^6.0.2 postcss-value-parser: ^4.0.2 + prettier: ^2.5.1 typescript: ^4.5.5 uvu: ^0.5.3 @@ -17,8 +19,10 @@ dependencies: devDependencies: '@types/node': 17.0.14 eslint: 8.7.0 + eslint-config-prettier: 8.3.0_eslint@8.7.0 jison-gho: 0.6.1-216 postcss: 8.4.5 + prettier: 2.5.1 typescript: 4.5.5 uvu: 0.5.3 @@ -328,6 +332,15 @@ packages: engines: {node: '>=10'} dev: true + /eslint-config-prettier/8.3.0_eslint@8.7.0: + resolution: {integrity: sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew==} + hasBin: true + peerDependencies: + eslint: '>=7.0.0' + dependencies: + eslint: 8.7.0 + dev: true + /eslint-scope/7.1.0: resolution: {integrity: sha512-aWwkhnS0qAXqNOgKOK0dJ2nvzEbhEvpy8OlJ9kZ0FeZnA6zpjv1/Vei+puGFFX7zkPCkHHXb7IDX3A+7yPrRWg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -836,6 +849,12 @@ packages: engines: {node: '>= 0.8.0'} dev: true + /prettier/2.5.1: + resolution: {integrity: sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==} + engines: {node: '>=10.13.0'} + hasBin: true + dev: true + /private/0.1.7: resolution: {integrity: sha1-aM5eih7woju1cMwoU3tTMqumPvE=} engines: {node: '>= 0.6'} diff --git a/src/__tests__/convertUnit.js b/src/__tests__/convertUnit.js index a94ad52..49f60fa 100644 --- a/src/__tests__/convertUnit.js +++ b/src/__tests__/convertUnit.js @@ -1,125 +1,378 @@ -"use strict"; +'use strict'; const { test } = require('uvu'); const assert = require('uvu/assert'); const convertUnit = require('../lib/convertUnit.js'); -test("valid conversions", () => { +test('valid conversions', () => { const conversions = [ // source value, source unit, expected value, target unit - [ 10, 'px', 10, 'px'], - [ 10, 'px', 0.26458, 'cm'], - [ 10, 'px', 2.64583, 'mm'], - [ 10, 'px', 10.58333, 'q'], - [ 10, 'px', 0.10417, 'in'], - [ 10, 'px', 7.5, 'pt'], - [ 10, 'px', 0.625, 'pc'], - [ 10, 'cm', 377.95276, 'px'], - [ 10, 'cm', 10, 'cm'], - [ 10, 'cm', 100, 'mm'], - [ 10, 'cm', 400, 'q'], - [ 10, 'cm', 3.93701, 'in'], - [ 10, 'cm', 283.46457, 'pt'], - [ 10, 'cm', 23.62205, 'pc'], - [ 10, 'mm', 37.79528, 'px'], - [ 10, 'mm', 1, 'cm'], - [ 10, 'mm', 10, 'mm'], - [ 10, 'mm', 40, 'q'], - [ 10, 'mm', 0.3937, 'in'], - [ 10, 'mm', 28.34646, 'pt'], - [ 10, 'mm', 2.3622, 'pc'], - [ 10, 'q', 9.44882, 'px'], - [ 10, 'q', 0.25, 'cm'], - [ 10, 'q', 2.5, 'mm'], - [ 10, 'q', 0.09843, 'in'], - [ 10, 'q', 7.08661, 'pt'], - [ 10, 'q', 0.59055, 'pc'], - [ 10, 'in', 960, 'px'], - [ 10, 'in', 25.4, 'cm'], - [ 10, 'in', 254, 'mm'], - [ 10, 'in', 1016, 'q'], - [ 10, 'in', 10, 'in'], - [ 10, 'in', 720, 'pt'], - [ 10, 'in', 60, 'pc'], - [ 10, 'pt', 13.33333, 'px'], - [ 10, 'pt', 0.35278, 'cm'], - [ 10, 'pt', 3.52778, 'mm'], - [ 10, 'pt', 14.11111, 'q'], - [ 10, 'pt', 0.13889, 'in'], - [ 10, 'pt', 10, 'pt'], - [ 10, 'pt', 0.83333, 'pc'], - [ 10, 'pc', 160, 'px'], - [ 10, 'pc', 4.23333, 'cm'], - [ 10, 'pc', 42.33333, 'mm'], - [ 10, 'pc', 169.33333, 'q'], - [ 10, 'pc', 1.66667, 'in'], - [ 10, 'pc', 120, 'pt'], - [ 10, 'pc', 10, 'pc'], - [ 10, 'deg', 10, 'deg'], - [ 10, 'deg', 11.11111, 'grad'], - [ 10, 'deg', 0.17453, 'rad'], - [ 10, 'deg', 0.02778, 'turn'], - [ 10, 'grad', 9, 'deg'], - [ 10, 'grad', 10, 'grad'], - [ 10, 'grad', 0.15708, 'rad'], - [ 10, 'grad', 0.025, 'turn'], - [ 10, 'rad', 572.9578, 'deg'], - [ 10, 'rad', 636.61977, 'grad'], - [ 10, 'rad', 10, 'rad'], - [ 10, 'rad', 1.59155, 'turn'], - [ 10, 'turn', 3600, 'deg'], - [ 10, 'turn', 4000, 'grad'], - [ 10, 'turn', 62.83185, 'rad'], - [ 10, 'turn', 10, 'turn'], - [ 10, 's', 10, 's'], - [ 10, 's', 10000, 'ms'], - [ 10, 'ms', 0.01, 's'], - [ 10, 'ms', 10, 'ms'], - [ 10, 'Hz', 10, 'Hz'], - [ 10, 'Hz', 0.01, 'kHz'], - [ 10, 'kHz', 10000, 'Hz'], - [ 10, 'kHz', 10, 'kHz'], - [ 10, 'dpi', 10, 'dpi'], - [ 10, 'dpi', 25.4, 'dpcm'], - [ 10, 'dpi', 960, 'dppx'], - [ 10, 'dpcm', 3.93701, 'dpi'], - [ 10, 'dpcm', 10, 'dpcm'], - [ 10, 'dpcm', 377.95276, 'dppx'], - [ 10, 'dppx', 0.10417, 'dpi'], - [ 10, 'dppx', 0.26458, 'dpcm'], - [ 10, 'dppx', 10, 'dppx'] + [10, 'px', 10, 'px'], + [10, 'px', 0.26458, 'cm'], + [10, 'px', 2.64583, 'mm'], + [10, 'px', 10.58333, 'q'], + [10, 'px', 0.10417, 'in'], + [10, 'px', 7.5, 'pt'], + [10, 'px', 0.625, 'pc'], + [10, 'cm', 377.95276, 'px'], + [10, 'cm', 10, 'cm'], + [10, 'cm', 100, 'mm'], + [10, 'cm', 400, 'q'], + [10, 'cm', 3.93701, 'in'], + [10, 'cm', 283.46457, 'pt'], + [10, 'cm', 23.62205, 'pc'], + [10, 'mm', 37.79528, 'px'], + [10, 'mm', 1, 'cm'], + [10, 'mm', 10, 'mm'], + [10, 'mm', 40, 'q'], + [10, 'mm', 0.3937, 'in'], + [10, 'mm', 28.34646, 'pt'], + [10, 'mm', 2.3622, 'pc'], + [10, 'q', 9.44882, 'px'], + [10, 'q', 0.25, 'cm'], + [10, 'q', 2.5, 'mm'], + [10, 'q', 0.09843, 'in'], + [10, 'q', 7.08661, 'pt'], + [10, 'q', 0.59055, 'pc'], + [10, 'in', 960, 'px'], + [10, 'in', 25.4, 'cm'], + [10, 'in', 254, 'mm'], + [10, 'in', 1016, 'q'], + [10, 'in', 10, 'in'], + [10, 'in', 720, 'pt'], + [10, 'in', 60, 'pc'], + [10, 'pt', 13.33333, 'px'], + [10, 'pt', 0.35278, 'cm'], + [10, 'pt', 3.52778, 'mm'], + [10, 'pt', 14.11111, 'q'], + [10, 'pt', 0.13889, 'in'], + [10, 'pt', 10, 'pt'], + [10, 'pt', 0.83333, 'pc'], + [10, 'pc', 160, 'px'], + [10, 'pc', 4.23333, 'cm'], + [10, 'pc', 42.33333, 'mm'], + [10, 'pc', 169.33333, 'q'], + [10, 'pc', 1.66667, 'in'], + [10, 'pc', 120, 'pt'], + [10, 'pc', 10, 'pc'], + [10, 'deg', 10, 'deg'], + [10, 'deg', 11.11111, 'grad'], + [10, 'deg', 0.17453, 'rad'], + [10, 'deg', 0.02778, 'turn'], + [10, 'grad', 9, 'deg'], + [10, 'grad', 10, 'grad'], + [10, 'grad', 0.15708, 'rad'], + [10, 'grad', 0.025, 'turn'], + [10, 'rad', 572.9578, 'deg'], + [10, 'rad', 636.61977, 'grad'], + [10, 'rad', 10, 'rad'], + [10, 'rad', 1.59155, 'turn'], + [10, 'turn', 3600, 'deg'], + [10, 'turn', 4000, 'grad'], + [10, 'turn', 62.83185, 'rad'], + [10, 'turn', 10, 'turn'], + [10, 's', 10, 's'], + [10, 's', 10000, 'ms'], + [10, 'ms', 0.01, 's'], + [10, 'ms', 10, 'ms'], + [10, 'Hz', 10, 'Hz'], + [10, 'Hz', 0.01, 'kHz'], + [10, 'kHz', 10000, 'Hz'], + [10, 'kHz', 10, 'kHz'], + [10, 'dpi', 10, 'dpi'], + [10, 'dpi', 25.4, 'dpcm'], + [10, 'dpi', 960, 'dppx'], + [10, 'dpcm', 3.93701, 'dpi'], + [10, 'dpcm', 10, 'dpcm'], + [10, 'dpcm', 377.95276, 'dppx'], + [10, 'dppx', 0.10417, 'dpi'], + [10, 'dppx', 0.26458, 'dpcm'], + [10, 'dppx', 10, 'dppx'], ]; - conversions.forEach(function(e) { + conversions.forEach(function (e) { const value = e[0]; const unit = e[1]; const expected = e[2]; const targetUnit = e[3]; - assert.is(convertUnit(value, unit, targetUnit), expected, unit + ' -> ' + targetUnit); + assert.is( + convertUnit(value, unit, targetUnit), + expected, + unit + ' -> ' + targetUnit + ); }); }); -test("invalid conversions", () => { +test('invalid conversions', () => { const invalid_units = { - 'px': ['deg', 'grad', 'rad', 'turn', 's', 'ms', 'Hz', 'kHz', 'dpi', 'dpcm', 'dppx'], - 'cm': ['deg', 'grad', 'rad', 'turn', 's', 'ms', 'Hz', 'kHz', 'dpi', 'dpcm', 'dppx'], - 'mm': ['deg', 'grad', 'rad', 'turn', 's', 'ms', 'Hz', 'kHz', 'dpi', 'dpcm', 'dppx'], - 'q': ['deg', 'grad', 'rad', 'turn', 's', 'ms', 'Hz', 'kHz', 'dpi', 'dpcm', 'dppx'], - 'in': ['deg', 'grad', 'rad', 'turn', 's', 'ms', 'Hz', 'kHz', 'dpi', 'dpcm', 'dppx'], - 'pt': ['deg', 'grad', 'rad', 'turn', 's', 'ms', 'Hz', 'kHz', 'dpi', 'dpcm', 'dppx'], - 'pc': ['deg', 'grad', 'rad', 'turn', 's', 'ms', 'Hz', 'kHz', 'dpi', 'dpcm', 'dppx'], - 'deg': ['px', 'cm', 'mm', 'in', 'pt', 'pc', 's', 'ms', 'Hz', 'kHz', 'dpi', 'dpcm', 'dppx'], - 'grad': ['px', 'cm', 'mm', 'in', 'pt', 'pc', 's', 'ms', 'Hz', 'kHz', 'dpi', 'dpcm', 'dppx'], - 'rad': ['px', 'cm', 'mm', 'in', 'pt', 'pc', 's', 'ms', 'Hz', 'kHz', 'dpi', 'dpcm', 'dppx'], - 'turn': ['px', 'cm', 'mm', 'in', 'pt', 'pc', 's', 'ms', 'Hz', 'kHz', 'dpi', 'dpcm', 'dppx'], - 's': ['px', 'cm', 'mm', 'in', 'pt', 'pc', 'deg', 'grad', 'rad', 'turn', 'Hz', 'kHz', 'dpi', 'dpcm', 'dppx'], - 'ms': ['px', 'cm', 'mm', 'in', 'pt', 'pc', 'deg', 'grad', 'rad', 'turn', 'Hz', 'kHz', 'dpi', 'dpcm', 'dppx'], - 'Hz': ['px', 'cm', 'mm', 'in', 'pt', 'pc', 'deg', 'grad', 'rad', 'turn', 's', 'ms', 'dpi', 'dpcm', 'dppx'], - 'kHz': ['px', 'cm', 'mm', 'in', 'pt', 'pc', 'deg', 'grad', 'rad', 'turn', 's', 'ms', 'dpi', 'dpcm', 'dppx'], - 'dpi': ['px', 'cm', 'mm', 'in', 'pt', 'pc', 'deg', 'grad', 'rad', 'turn', 's', 'ms', 'Hz', 'kHz'], - 'dpcm': ['px', 'cm', 'mm', 'in', 'pt', 'pc', 'deg', 'grad', 'rad', 'turn', 's', 'ms', 'Hz', 'kHz'], - 'dppx': ['px', 'cm', 'mm', 'in', 'pt', 'pc', 'deg', 'grad', 'rad', 'turn', 's', 'ms', 'Hz', 'kHz'] + px: [ + 'deg', + 'grad', + 'rad', + 'turn', + 's', + 'ms', + 'Hz', + 'kHz', + 'dpi', + 'dpcm', + 'dppx', + ], + cm: [ + 'deg', + 'grad', + 'rad', + 'turn', + 's', + 'ms', + 'Hz', + 'kHz', + 'dpi', + 'dpcm', + 'dppx', + ], + mm: [ + 'deg', + 'grad', + 'rad', + 'turn', + 's', + 'ms', + 'Hz', + 'kHz', + 'dpi', + 'dpcm', + 'dppx', + ], + q: [ + 'deg', + 'grad', + 'rad', + 'turn', + 's', + 'ms', + 'Hz', + 'kHz', + 'dpi', + 'dpcm', + 'dppx', + ], + in: [ + 'deg', + 'grad', + 'rad', + 'turn', + 's', + 'ms', + 'Hz', + 'kHz', + 'dpi', + 'dpcm', + 'dppx', + ], + pt: [ + 'deg', + 'grad', + 'rad', + 'turn', + 's', + 'ms', + 'Hz', + 'kHz', + 'dpi', + 'dpcm', + 'dppx', + ], + pc: [ + 'deg', + 'grad', + 'rad', + 'turn', + 's', + 'ms', + 'Hz', + 'kHz', + 'dpi', + 'dpcm', + 'dppx', + ], + deg: [ + 'px', + 'cm', + 'mm', + 'in', + 'pt', + 'pc', + 's', + 'ms', + 'Hz', + 'kHz', + 'dpi', + 'dpcm', + 'dppx', + ], + grad: [ + 'px', + 'cm', + 'mm', + 'in', + 'pt', + 'pc', + 's', + 'ms', + 'Hz', + 'kHz', + 'dpi', + 'dpcm', + 'dppx', + ], + rad: [ + 'px', + 'cm', + 'mm', + 'in', + 'pt', + 'pc', + 's', + 'ms', + 'Hz', + 'kHz', + 'dpi', + 'dpcm', + 'dppx', + ], + turn: [ + 'px', + 'cm', + 'mm', + 'in', + 'pt', + 'pc', + 's', + 'ms', + 'Hz', + 'kHz', + 'dpi', + 'dpcm', + 'dppx', + ], + s: [ + 'px', + 'cm', + 'mm', + 'in', + 'pt', + 'pc', + 'deg', + 'grad', + 'rad', + 'turn', + 'Hz', + 'kHz', + 'dpi', + 'dpcm', + 'dppx', + ], + ms: [ + 'px', + 'cm', + 'mm', + 'in', + 'pt', + 'pc', + 'deg', + 'grad', + 'rad', + 'turn', + 'Hz', + 'kHz', + 'dpi', + 'dpcm', + 'dppx', + ], + Hz: [ + 'px', + 'cm', + 'mm', + 'in', + 'pt', + 'pc', + 'deg', + 'grad', + 'rad', + 'turn', + 's', + 'ms', + 'dpi', + 'dpcm', + 'dppx', + ], + kHz: [ + 'px', + 'cm', + 'mm', + 'in', + 'pt', + 'pc', + 'deg', + 'grad', + 'rad', + 'turn', + 's', + 'ms', + 'dpi', + 'dpcm', + 'dppx', + ], + dpi: [ + 'px', + 'cm', + 'mm', + 'in', + 'pt', + 'pc', + 'deg', + 'grad', + 'rad', + 'turn', + 's', + 'ms', + 'Hz', + 'kHz', + ], + dpcm: [ + 'px', + 'cm', + 'mm', + 'in', + 'pt', + 'pc', + 'deg', + 'grad', + 'rad', + 'turn', + 's', + 'ms', + 'Hz', + 'kHz', + ], + dppx: [ + 'px', + 'cm', + 'mm', + 'in', + 'pt', + 'pc', + 'deg', + 'grad', + 'rad', + 'turn', + 's', + 'ms', + 'Hz', + 'kHz', + ], }; for (const unit in invalid_units) { @@ -137,14 +390,14 @@ test("invalid conversions", () => { } }); -test("precision", () => { +test('precision', () => { const precision = 10; const conversions = [ // source value, source unit, expected value, target unit - [ 10, 'px', 0.2645833333, 'cm'], - [ 10, 'px', 2.6458333333, 'mm'], - [ 10, 'px', 0.1041666667, 'in'], - [ 10, 'cm', 377.9527559055, 'px'] + [10, 'px', 0.2645833333, 'cm'], + [10, 'px', 2.6458333333, 'mm'], + [10, 'px', 0.1041666667, 'in'], + [10, 'cm', 377.9527559055, 'px'], ]; conversions.forEach((e) => { @@ -153,15 +406,16 @@ test("precision", () => { const expected = e[2]; const targetUnit = e[3]; - assert.is(convertUnit(value, unit, targetUnit, precision), expected, unit + ' -> ' + targetUnit); + assert.is( + convertUnit(value, unit, targetUnit, precision), + expected, + unit + ' -> ' + targetUnit + ); }); }); -test("falsey precision", () => { - assert.is( - convertUnit(10, 'px', 'cm', false), - 0.26458333333333334 - ); +test('falsey precision', () => { + assert.is(convertUnit(10, 'px', 'cm', false), 0.26458333333333334); }); test.run(); diff --git a/src/__tests__/index.js b/src/__tests__/index.js index fd89155..9113f8d 100644 --- a/src/__tests__/index.js +++ b/src/__tests__/index.js @@ -1,4 +1,4 @@ -"use strict"; +'use strict'; const { test } = require('uvu'); const assert = require('uvu/assert'); const postcss = require('postcss'); diff --git a/src/index.js b/src/index.js index 2d88d03..9e3333b 100644 --- a/src/index.js +++ b/src/index.js @@ -3,46 +3,49 @@ const transform = require('./lib/transform.js'); /** * @typedef {{precision?: number | false, - * preserve?: boolean, - * warnWhenCannotResolve?: boolean, - * mediaQueries?: boolean, + * preserve?: boolean, + * warnWhenCannotResolve?: boolean, + * mediaQueries?: boolean, * selectors?: boolean}} PostCssCalcOptions */ - /** +/** * @type {import('postcss').PluginCreator} * @param {PostCssCalcOptions} opts * @return {import('postcss').Plugin} */ function pluginCreator(opts) { - const options = Object.assign({ - precision: 5, - preserve: false, - warnWhenCannotResolve: false, - mediaQueries: false, - selectors: false - }, opts); + const options = Object.assign( + { + precision: 5, + preserve: false, + warnWhenCannotResolve: false, + mediaQueries: false, + selectors: false, + }, + opts + ); return { postcssPlugin: 'postcss-calc', OnceExit(css, { result }) { - css.walk(node => { + css.walk((node) => { const { type } = node; if (type === 'decl') { - transform(node, "value", options, result); + transform(node, 'value', options, result); } - + if (type === 'atrule' && options.mediaQueries) { - transform(node, "params", options, result); + transform(node, 'params', options, result); } if (type === 'rule' && options.selectors) { - transform(node, "selector", options, result); + transform(node, 'selector', options, result); } }); - } - } + }, + }; } pluginCreator.postcss = true; -module.exports = pluginCreator; +module.exports = pluginCreator; diff --git a/src/lib/convertUnit.js b/src/lib/convertUnit.js index 2627a3a..5f7bc26 100644 --- a/src/lib/convertUnit.js +++ b/src/lib/convertUnit.js @@ -1,151 +1,152 @@ -"use strict"; +'use strict'; /** * @type {{[key:string]: {[key:string]: number}}} */ const conversions = { // Absolute length units - 'px': { - 'px': 1, - 'cm': 96 / 2.54, - 'mm': 96 / 25.4, - 'q': 96 / 101.6, - 'in': 96, - 'pt': 96 / 72, - 'pc': 16 - }, - 'cm': { - 'px': 2.54 / 96, - 'cm': 1, - 'mm': 0.1, - 'q': 0.025, - 'in': 2.54, - 'pt': 2.54 / 72, - 'pc': 2.54 / 6 - }, - 'mm': { - 'px': 25.4 / 96, - 'cm': 10, - 'mm': 1, - 'q': 0.25, - 'in': 25.4, - 'pt': 25.4 / 72, - 'pc': 25.4 / 6 - }, - 'q': { - 'px': 101.6 / 96, - 'cm': 40, - 'mm': 4, - 'q': 1, - 'in': 101.6, - 'pt': 101.6 / 72, - 'pc': 101.6 / 6 - }, - 'in': { - 'px': 1 / 96, - 'cm': 1 / 2.54, - 'mm': 1 / 25.4, - 'q': 1 / 101.6, - 'in': 1, - 'pt': 1 / 72, - 'pc': 1 / 6 - }, - 'pt': { - 'px': 0.75, - 'cm': 72 / 2.54, - 'mm': 72 / 25.4, - 'q': 72 / 101.6, - 'in': 72, - 'pt': 1, - 'pc': 12 - }, - 'pc': { - 'px': 0.0625, - 'cm': 6 / 2.54, - 'mm': 6 / 25.4, - 'q': 6 / 101.6, - 'in': 6, - 'pt': 6 / 72, - 'pc': 1 + px: { + px: 1, + cm: 96 / 2.54, + mm: 96 / 25.4, + q: 96 / 101.6, + in: 96, + pt: 96 / 72, + pc: 16, + }, + cm: { + px: 2.54 / 96, + cm: 1, + mm: 0.1, + q: 0.025, + in: 2.54, + pt: 2.54 / 72, + pc: 2.54 / 6, + }, + mm: { + px: 25.4 / 96, + cm: 10, + mm: 1, + q: 0.25, + in: 25.4, + pt: 25.4 / 72, + pc: 25.4 / 6, + }, + q: { + px: 101.6 / 96, + cm: 40, + mm: 4, + q: 1, + in: 101.6, + pt: 101.6 / 72, + pc: 101.6 / 6, + }, + in: { + px: 1 / 96, + cm: 1 / 2.54, + mm: 1 / 25.4, + q: 1 / 101.6, + in: 1, + pt: 1 / 72, + pc: 1 / 6, + }, + pt: { + px: 0.75, + cm: 72 / 2.54, + mm: 72 / 25.4, + q: 72 / 101.6, + in: 72, + pt: 1, + pc: 12, + }, + pc: { + px: 0.0625, + cm: 6 / 2.54, + mm: 6 / 25.4, + q: 6 / 101.6, + in: 6, + pt: 6 / 72, + pc: 1, }, // Angle units - 'deg': { - 'deg': 1, - 'grad': 0.9, - 'rad': 180 / Math.PI, - 'turn': 360 - }, - 'grad': { - 'deg': 400 / 360, - 'grad': 1, - 'rad': 200 / Math.PI, - 'turn': 400 - }, - 'rad': { - 'deg': Math.PI / 180, - 'grad': Math.PI / 200, - 'rad': 1, - 'turn': Math.PI * 2 - }, - 'turn': { - 'deg': 1 / 360, - 'grad': 0.0025, - 'rad': 0.5 / Math.PI, - 'turn': 1 + deg: { + deg: 1, + grad: 0.9, + rad: 180 / Math.PI, + turn: 360, + }, + grad: { + deg: 400 / 360, + grad: 1, + rad: 200 / Math.PI, + turn: 400, + }, + rad: { + deg: Math.PI / 180, + grad: Math.PI / 200, + rad: 1, + turn: Math.PI * 2, + }, + turn: { + deg: 1 / 360, + grad: 0.0025, + rad: 0.5 / Math.PI, + turn: 1, }, // Duration units - 's': { - 's': 1, - 'ms': 0.001 + s: { + s: 1, + ms: 0.001, }, - 'ms': { - 's': 1000, - 'ms': 1 + ms: { + s: 1000, + ms: 1, }, // Frequency units - 'hz': { - 'hz': 1, - 'khz': 1000 + hz: { + hz: 1, + khz: 1000, }, - 'khz': { - 'hz': 0.001, - 'khz': 1 + khz: { + hz: 0.001, + khz: 1, }, // Resolution units - 'dpi': { - 'dpi': 1, - 'dpcm': 1 / 2.54, - 'dppx': 1 / 96 - }, - 'dpcm': { - 'dpi': 2.54, - 'dpcm': 1, - 'dppx': 2.54 / 96 - }, - 'dppx': { - 'dpi': 96, - 'dpcm': 96 / 2.54, - 'dppx': 1 - } + dpi: { + dpi: 1, + dpcm: 1 / 2.54, + dppx: 1 / 96, + }, + dpcm: { + dpi: 2.54, + dpcm: 1, + dppx: 2.54 / 96, + }, + dppx: { + dpi: 96, + dpcm: 96 / 2.54, + dppx: 1, + }, }; /** * @param {number} value * @param {string} sourceUnit * @param {string} targetUnit - * @param {number|false} precision + * @param {number|false} precision */ function convertUnit(value, sourceUnit, targetUnit, precision) { const sourceUnitNormalized = sourceUnit.toLowerCase(); const targetUnitNormalized = targetUnit.toLowerCase(); if (!conversions[targetUnitNormalized]) { - throw new Error("Cannot convert to " + targetUnit); + throw new Error('Cannot convert to ' + targetUnit); } if (!conversions[targetUnitNormalized][sourceUnitNormalized]) { - throw new Error("Cannot convert from " + sourceUnit + " to " + targetUnit); + throw new Error('Cannot convert from ' + sourceUnit + ' to ' + targetUnit); } - const converted = conversions[targetUnitNormalized][sourceUnitNormalized] * value; + const converted = + conversions[targetUnitNormalized][sourceUnitNormalized] * value; if (precision !== false) { precision = Math.pow(10, Math.ceil(precision) || 5); diff --git a/src/lib/reducer.js b/src/lib/reducer.js index b624fb0..8a36bf1 100644 --- a/src/lib/reducer.js +++ b/src/lib/reducer.js @@ -1,5 +1,5 @@ -"use strict"; -const convertUnit = require("./convertUnit.js"); +'use strict'; +const convertUnit = require('./convertUnit.js'); /** * @param {import('../parser').CalcNode} node @@ -42,69 +42,87 @@ function isAddSubOperator(operator) { /** * @typedef {{preOperator: '+'|'-', node: import('../parser').CalcNode}} Collectible -*/ + */ /** * @param {'+'|'-'} preOperator * @param {import('../parser').CalcNode} node - * @param {Collectible[]} collected + * @param {Collectible[]} collected * @param {number} precision */ function collectAddSubItems(preOperator, node, collected, precision) { - if (!isAddSubOperator(preOperator)) { throw new Error(`invalid operator ${preOperator}`); } + if (!isAddSubOperator(preOperator)) { + throw new Error(`invalid operator ${preOperator}`); + } if (isValueType(node)) { - const itemIndex = collected.findIndex(x => x.node.type === node.type); + const itemIndex = collected.findIndex((x) => x.node.type === node.type); if (itemIndex >= 0) { - if (node.value === 0) { return; } + if (node.value === 0) { + return; + } // can cast because of the criterion used to find itemIndex - const otherValueNode = /** @type import('../parser').ValueExpression*/(collected[itemIndex].node); - const {left: reducedNode, right: current} = convertNodesUnits(otherValueNode, node, precision) + const otherValueNode = /** @type import('../parser').ValueExpression*/ ( + collected[itemIndex].node + ); + const { left: reducedNode, right: current } = convertNodesUnits( + otherValueNode, + node, + precision + ); if (collected[itemIndex].preOperator === '-') { collected[itemIndex].preOperator = '+'; reducedNode.value *= -1; } - if (preOperator === "+") { - reducedNode.value += current.value + if (preOperator === '+') { + reducedNode.value += current.value; } else { - reducedNode.value -= current.value + reducedNode.value -= current.value; } // make sure reducedNode.value >= 0 if (reducedNode.value >= 0) { - collected[itemIndex] = {node: reducedNode, preOperator: '+'}; + collected[itemIndex] = { node: reducedNode, preOperator: '+' }; } else { reducedNode.value *= -1; - collected[itemIndex] = {node: reducedNode, preOperator: '-'}; + collected[itemIndex] = { node: reducedNode, preOperator: '-' }; } } else { // make sure node.value >= 0 if (node.value >= 0) { - collected.push({node, preOperator}); + collected.push({ node, preOperator }); } else { node.value *= -1; - collected.push({node, preOperator: flip(preOperator)}); + collected.push({ node, preOperator: flip(preOperator) }); } } - } else if (node.type === "MathExpression") { + } else if (node.type === 'MathExpression') { if (isAddSubOperator(node.operator)) { collectAddSubItems(preOperator, node.left, collected, precision); - const collectRightOperator = preOperator === '-' ? flip(node.operator) : node.operator; - collectAddSubItems(collectRightOperator, node.right, collected, precision); + const collectRightOperator = + preOperator === '-' ? flip(node.operator) : node.operator; + collectAddSubItems( + collectRightOperator, + node.right, + collected, + precision + ); } else { // * or / const reducedNode = reduce(node, precision); // prevent infinite recursive call - if (reducedNode.type !== "MathExpression" || - isAddSubOperator(reducedNode.operator)) { + if ( + reducedNode.type !== 'MathExpression' || + isAddSubOperator(reducedNode.operator) + ) { collectAddSubItems(preOperator, reducedNode, collected, precision); } else { - collected.push({node: reducedNode, preOperator}); + collected.push({ node: reducedNode, preOperator }); } } } else if (node.type === 'ParenthesizedExpression') { collectAddSubItems(preOperator, node.content, collected, precision); } else { - collected.push({node, preOperator}); + collected.push({ node, preOperator }); } } @@ -117,26 +135,33 @@ function reduceAddSubExpression(node, precision) { const collected = []; collectAddSubItems('+', node, collected, precision); - const withoutZeroItem = collected.filter((item) => !(isValueType(item.node) && item.node.value === 0)); + const withoutZeroItem = collected.filter( + (item) => !(isValueType(item.node) && item.node.value === 0) + ); const firstNonZeroItem = withoutZeroItem[0]; // could be undefined // prevent producing "calc(-var(--a))" or "calc()" // which is invalid css - if (!firstNonZeroItem || - firstNonZeroItem.preOperator === '-' && - !isValueType(firstNonZeroItem.node)) { - const firstZeroItem = collected.find((item) => - isValueType(item.node) && item.node.value === 0); - if (firstZeroItem) { - withoutZeroItem.unshift(firstZeroItem) - } + if ( + !firstNonZeroItem || + (firstNonZeroItem.preOperator === '-' && + !isValueType(firstNonZeroItem.node)) + ) { + const firstZeroItem = collected.find( + (item) => isValueType(item.node) && item.node.value === 0 + ); + if (firstZeroItem) { + withoutZeroItem.unshift(firstZeroItem); + } } // make sure the preOperator of the first item is + - if (withoutZeroItem[0].preOperator === '-' && - isValueType(withoutZeroItem[0].node)) { - withoutZeroItem[0].node.value *= -1; - withoutZeroItem[0].preOperator = '+'; + if ( + withoutZeroItem[0].preOperator === '-' && + isValueType(withoutZeroItem[0].node) + ) { + withoutZeroItem[0].node.value *= -1; + withoutZeroItem[0].preOperator = '+'; } let root = withoutZeroItem[0].node; @@ -145,8 +170,8 @@ function reduceAddSubExpression(node, precision) { type: 'MathExpression', operator: withoutZeroItem[i].preOperator, left: root, - right: withoutZeroItem[i].node - } + right: withoutZeroItem[i].node, + }; } return root; @@ -163,7 +188,7 @@ function reduceDivisionExpression(node) { throw new Error(`Cannot divide by "${node.right.unit}", number expected`); } - return applyNumberDivision(node.left, node.right.value) + return applyNumberDivision(node.left, node.right.value); } /** @@ -172,7 +197,7 @@ function reduceDivisionExpression(node) { * @param {import('../parser').CalcNode} node * @param {number} divisor * @return {import('../parser').CalcNode} -*/ + */ function applyNumberDivision(node, divisor) { if (divisor === 0) { throw new Error('Cannot divide by zero'); @@ -181,30 +206,30 @@ function applyNumberDivision(node, divisor) { node.value /= divisor; return node; } - if (node.type === "MathExpression" && isAddSubOperator(node.operator)) { + if (node.type === 'MathExpression' && isAddSubOperator(node.operator)) { // turn (a + b) / num into a/num + b/num // is good for further reduction // checkout the test case // "should reduce division before reducing additions" return { - type: "MathExpression", + type: 'MathExpression', operator: node.operator, left: applyNumberDivision(node.left, divisor), - right: applyNumberDivision(node.right, divisor) - } + right: applyNumberDivision(node.right, divisor), + }; } // it is impossible to reduce it into a single value // .e.g the node contains css variable // so we just preserve the division and let browser do it return { - type: "MathExpression", + type: 'MathExpression', operator: '/', left: node, right: { - type: "Number", + type: 'Number', value: divisor, - } - } + }, + }; } /** * @param {import('../parser').MathExpression} node @@ -232,30 +257,30 @@ function applyNumberMultiplication(node, multiplier) { node.value *= multiplier; return node; } - if (node.type === "MathExpression" && isAddSubOperator(node.operator)) { + if (node.type === 'MathExpression' && isAddSubOperator(node.operator)) { // turn (a + b) * num into a*num + b*num // is good for further reduction // checkout the test case // "should reduce multiplication before reducing additions" return { - type: "MathExpression", + type: 'MathExpression', operator: node.operator, left: applyNumberMultiplication(node.left, multiplier), - right: applyNumberMultiplication(node.right, multiplier) - } + right: applyNumberMultiplication(node.right, multiplier), + }; } // it is impossible to reduce it into a single value // .e.g the node contains css variable // so we just preserve the division and let browser do it return { - type: "MathExpression", + type: 'MathExpression', operator: '*', left: node, right: { - type: "Number", + type: 'Number', value: multiplier, - } - } + }, + }; } /** @@ -271,7 +296,12 @@ function convertNodesUnits(left, right, precision) { case 'FrequencyValue': case 'ResolutionValue': if (right.type === left.type && right.unit && left.unit) { - const converted = convertUnit(right.value, right.unit, left.unit, precision); + const converted = convertUnit( + right.value, + right.unit, + left.unit, + precision + ); right = { type: left.type, @@ -290,11 +320,12 @@ function convertNodesUnits(left, right, precision) { * @param {import('../parser').ParenthesizedExpression} node */ function includesNoCssProperties(node) { - return node.content.type !== 'Function' && + return ( + node.content.type !== 'Function' && (node.content.type !== 'MathExpression' || (node.content.right.type !== 'Function' && - node.content.left.type !== 'Function') - ); + node.content.left.type !== 'Function')) + ); } /** * @param {import('../parser').CalcNode} node @@ -302,7 +333,7 @@ function includesNoCssProperties(node) { * @return {import('../parser').CalcNode} */ function reduce(node, precision) { - if (node.type === "MathExpression") { + if (node.type === 'MathExpression') { if (isAddSubOperator(node.operator)) { // reduceAddSubExpression will call reduce recursively return reduceAddSubExpression(node, precision); @@ -310,9 +341,9 @@ function reduce(node, precision) { node.left = reduce(node.left, precision); node.right = reduce(node.right, precision); switch (node.operator) { - case "/": + case '/': return reduceDivisionExpression(node); - case "*": + case '*': return reduceMultiplicationExpression(node); } diff --git a/src/lib/stringifier.js b/src/lib/stringifier.js index 561cf9b..afd631c 100644 --- a/src/lib/stringifier.js +++ b/src/lib/stringifier.js @@ -1,9 +1,9 @@ -"use strict"; +'use strict'; const order = { - "*": 0, - "/": 0, - "+": 1, - "-": 1, + '*': 0, + '/': 0, + '+': 1, + '-': 1, }; /** @@ -26,9 +26,9 @@ function round(value, prec) { */ function stringify(node, prec) { switch (node.type) { - case "MathExpression": { - const {left, right, operator: op} = node; - let str = ""; + case 'MathExpression': { + const { left, right, operator: op } = node; + let str = ''; if (left.type === 'MathExpression' && order[op] < order[left.operator]) { str += `(${stringify(left, prec)})`; } else { @@ -37,7 +37,10 @@ function stringify(node, prec) { str += order[op] ? ` ${node.operator} ` : node.operator; - if (right.type === 'MathExpression' && order[op] < order[right.operator]) { + if ( + right.type === 'MathExpression' && + order[op] < order[right.operator] + ) { str += `(${stringify(right, prec)})`; } else { str += stringify(right, prec); @@ -66,17 +69,11 @@ function stringify(node, prec) { * * @returns {string} */ -module.exports = function ( - calc, - node, - originalValue, - options, - result, - item - ) { +module.exports = function (calc, node, originalValue, options, result, item) { let str = stringify(node, options.precision); - const shouldPrintCalc = node.type === "MathExpression" || node.type === "Function"; + const shouldPrintCalc = + node.type === 'MathExpression' || node.type === 'Function'; if (shouldPrintCalc) { // if calc expression couldn't be resolved to a single value, re-wrap it as @@ -86,10 +83,11 @@ module.exports = function ( // if the warnWhenCannotResolve option is on, inform the user that the calc // expression could not be resolved to a single value if (options.warnWhenCannotResolve) { - result.warn( - "Could not reduce expression: " + originalValue, - { plugin: 'postcss-calc', node: item }); + result.warn('Could not reduce expression: ' + originalValue, { + plugin: 'postcss-calc', + node: item, + }); } } return str; -} +}; diff --git a/src/lib/transform.js b/src/lib/transform.js index b48f755..78bff2e 100644 --- a/src/lib/transform.js +++ b/src/lib/transform.js @@ -1,11 +1,11 @@ -"use strict"; -const selectorParser = require("postcss-selector-parser"); -const valueParser = require("postcss-value-parser"); +'use strict'; +const selectorParser = require('postcss-selector-parser'); +const valueParser = require('postcss-value-parser'); -const { parser } = require("../parser.js"); +const { parser } = require('../parser.js'); -const reducer = require("./reducer.js"); -const stringifier = require("./stringifier.js"); +const reducer = require('./reducer.js'); +const stringifier = require('./stringifier.js'); const MATCH_CALC = /((?:-(moz|webkit)-)?calc)/i; @@ -17,9 +17,9 @@ const MATCH_CALC = /((?:-(moz|webkit)-)?calc)/i; */ function transformValue(value, options, result, item) { return valueParser(value) - .walk(node => { + .walk((node) => { // skip anything which isn't a calc() function - if (node.type !== "function" || !MATCH_CALC.test(node.value)) { + if (node.type !== 'function' || !MATCH_CALC.test(node.value)) { return; } @@ -32,7 +32,7 @@ function transformValue(value, options, result, item) { const reducedAst = reducer(ast, options.precision); // stringify AST and write it back - (/** @type {valueParser.Node} */(node)).type = "word"; + /** @type {valueParser.Node} */ (node).type = 'word'; node.value = stringifier( node.value, reducedAst, @@ -53,17 +53,17 @@ function transformValue(value, options, result, item) { * @param {import("postcss").ChildNode} item */ function transformSelector(value, options, result, item) { - return selectorParser(selectors => { - selectors.walk(node => { + return selectorParser((selectors) => { + selectors.walk((node) => { // attribute value // e.g. the "calc(3*3)" part of "div[data-size="calc(3*3)"]" - if (node.type === "attribute" && node.value) { + if (node.type === 'attribute' && node.value) { node.setValue(transformValue(node.value, options, result, item)); } // tag value // e.g. the "calc(3*3)" part of "div:nth-child(2n + calc(3*3))" - if (node.type === "tag") { + if (node.type === 'tag') { node.value = transformValue(node.value, options, result, item); } @@ -72,8 +72,7 @@ function transformSelector(value, options, result, item) { }).processSync(value); } - -/** +/** * @param {any} node * @param {{precision: number, preserve: boolean, warnWhenCannotResolve: boolean}} options * @param {'value'|'params'|'selector'} property @@ -84,7 +83,7 @@ module.exports = (node, property, options, result) => { try { value = - property === "selector" + property === 'selector' ? transformSelector(node[property], options, result, node) : transformValue(node[property], options, result, node); } catch (error) { diff --git a/types/index.d.ts b/types/index.d.ts index d670a14..7373891 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -7,10 +7,10 @@ export = pluginCreator; * selectors?: boolean}} PostCssCalcOptions */ /** -* @type {import('postcss').PluginCreator} -* @param {PostCssCalcOptions} opts -* @return {import('postcss').Plugin} -*/ + * @type {import('postcss').PluginCreator} + * @param {PostCssCalcOptions} opts + * @return {import('postcss').Plugin} + */ declare function pluginCreator(opts: PostCssCalcOptions): import('postcss').Plugin; declare namespace pluginCreator { export { postcss, PostCssCalcOptions };