Merge pull request #2627 from lydell/css-numbers

Normalize numbers in CSS like JS
master
Simon Lydell 2017-08-22 19:05:08 +02:00 committed by GitHub
commit 854bb3ccc5
12 changed files with 262 additions and 34 deletions

View File

@ -32,7 +32,7 @@
"postcss-media-query-parser": "0.2.3", "postcss-media-query-parser": "0.2.3",
"postcss-scss": "1.0.0", "postcss-scss": "1.0.0",
"postcss-selector-parser": "2.2.3", "postcss-selector-parser": "2.2.3",
"postcss-values-parser": "git://github.com/shellscape/postcss-values-parser.git#5e351360479116f3fe309602cdd15b0a233bc29f", "postcss-values-parser": "git://github.com/lydell/postcss-values-parser.git#af2c80b2bb558a6e7d61540d97f068f9fa162b38",
"strip-bom": "3.0.0", "strip-bom": "3.0.0",
"typescript": "2.5.0-dev.20170617", "typescript": "2.5.0-dev.20170617",
"typescript-eslint-parser": "git://github.com/eslint/typescript-eslint-parser.git#01c34f44e7bb3b8a1ec3d28433a6e0c9b2901d3c" "typescript-eslint-parser": "git://github.com/eslint/typescript-eslint-parser.git#01c34f44e7bb3b8a1ec3d28433a6e0c9b2901d3c"

View File

@ -104,6 +104,16 @@ function massageAST(ast) {
delete newObj.quoted; delete newObj.quoted;
} }
if (
(ast.type === "media-value" || ast.type === "value-number") &&
newObj.value
) {
newObj.value = newObj.value.replace(/[\d.eE+-]+/g, match => {
const num = Number(match);
return isNaN(num) ? match : num;
});
}
// (TypeScript) Ignore `static` in `constructor(static p) {}` // (TypeScript) Ignore `static` in `constructor(static p) {}`
// and `export` in `constructor(export p) {}` // and `export` in `constructor(export p) {}`
if ( if (

View File

@ -179,7 +179,7 @@ function genericPrint(path, options, print) {
return concat([n.value, " "]); return concat([n.value, " "]);
} }
case "media-value": { case "media-value": {
return adjustStrings(n.value, options); return adjustNumbers(adjustStrings(n.value, options));
} }
case "media-keyword": { case "media-keyword": {
return n.value; return n.value;
@ -337,7 +337,7 @@ function genericPrint(path, options, print) {
return n.value; return n.value;
} }
case "value-number": { case "value-number": {
return concat([n.value, n.unit]); return concat([printNumber(n.value), n.unit]);
} }
case "value-operator": { case "value-operator": {
return n.value; return n.value;
@ -419,6 +419,11 @@ function printValue(value) {
} }
const STRING_REGEX = /(['"])(?:(?!\1)[^\\]|\\[\s\S])*\1/g; const STRING_REGEX = /(['"])(?:(?!\1)[^\\]|\\[\s\S])*\1/g;
const NUMBER_REGEX = /(?:\d*\.\d+|\d+\.?)(?:[eE][+-]?\d+)?/g;
const STRING_OR_NUMBER_REGEX = RegExp(
`${STRING_REGEX.source}|(${NUMBER_REGEX.source})`,
"g"
);
function adjustStrings(value, options) { function adjustStrings(value, options) {
return value.replace(STRING_REGEX, match => util.printString(match, options)); return value.replace(STRING_REGEX, match => util.printString(match, options));
@ -431,4 +436,20 @@ function quoteAttributeValue(value, options) {
: quote + value + quote; : quote + value + quote;
} }
function adjustNumbers(value) {
return value.replace(
STRING_OR_NUMBER_REGEX,
(match, quote, number) => (number ? printNumber(number) : match)
);
}
function printNumber(rawNumber) {
return (
util
.printNumber(rawNumber)
// Remove trailing `.0`.
.replace(/\.0(?=$|e)/, "")
);
}
module.exports = genericPrint; module.exports = genericPrint;

View File

@ -1159,7 +1159,7 @@ function genericPrintNoParens(path, options, print, args) {
case "RegExpLiteral": // Babel 6 Literal split case "RegExpLiteral": // Babel 6 Literal split
return printRegex(n); return printRegex(n);
case "NumericLiteral": // Babel 6 Literal split case "NumericLiteral": // Babel 6 Literal split
return printNumber(n.extra.raw); return util.printNumber(n.extra.raw);
case "BooleanLiteral": // Babel 6 Literal split case "BooleanLiteral": // Babel 6 Literal split
case "StringLiteral": // Babel 6 Literal split case "StringLiteral": // Babel 6 Literal split
case "Literal": { case "Literal": {
@ -1167,7 +1167,7 @@ function genericPrintNoParens(path, options, print, args) {
return printRegex(n.regex); return printRegex(n.regex);
} }
if (typeof n.value === "number") { if (typeof n.value === "number") {
return printNumber(n.raw); return util.printNumber(n.raw);
} }
if (typeof n.value !== "string") { if (typeof n.value !== "string") {
return "" + n.value; return "" + n.value;
@ -2239,9 +2239,9 @@ function genericPrintNoParens(path, options, print, args) {
assert.strictEqual(typeof n.value, "number"); assert.strictEqual(typeof n.value, "number");
if (n.extra != null) { if (n.extra != null) {
return printNumber(n.extra.raw); return util.printNumber(n.extra.raw);
} }
return printNumber(n.raw); return util.printNumber(n.raw);
case "StringTypeAnnotation": case "StringTypeAnnotation":
return "string"; return "string";
@ -4336,23 +4336,6 @@ function printRegex(node) {
return `/${node.pattern}/${flags}`; return `/${node.pattern}/${flags}`;
} }
function printNumber(rawNumber) {
return (
rawNumber
.toLowerCase()
// Remove unnecessary plus and zeroes from scientific notation.
.replace(/^([\d.]+e)(?:\+|(-))?0*(\d)/, "$1$2$3")
// Remove unnecessary scientific notation (1e0).
.replace(/^([\d.]+)e[+-]?0+$/, "$1")
// Make sure numbers always start with a digit.
.replace(/^\./, "0.")
// Remove extraneous trailing decimal zeroes.
.replace(/(\.\d+?)0+(?=e|$)/, "$1")
// Remove trailing dot.
.replace(/\.(?=e|$)/, "")
);
}
function isLastStatement(path) { function isLastStatement(path) {
const parent = path.getParentNode(); const parent = path.getParentNode();
if (!parent) { if (!parent) {

View File

@ -567,6 +567,23 @@ function makeString(rawContent, enclosingQuote, unescapeUnnecessaryEscapes) {
return enclosingQuote + newContent + enclosingQuote; return enclosingQuote + newContent + enclosingQuote;
} }
function printNumber(rawNumber) {
return (
rawNumber
.toLowerCase()
// Remove unnecessary plus and zeroes from scientific notation.
.replace(/^([\d.]+e)(?:\+|(-))?0*(\d)/, "$1$2$3")
// Remove unnecessary scientific notation (1e0).
.replace(/^([\d.]+)e[+-]?0+$/, "$1")
// Make sure numbers always start with a digit.
.replace(/^\./, "0.")
// Remove extraneous trailing decimal zeroes.
.replace(/(\.\d+?)0+(?=e|$)/, "$1")
// Remove trailing dot.
.replace(/\.(?=e|$)/, "")
);
}
module.exports = { module.exports = {
getPrecedence, getPrecedence,
shouldFlatten, shouldFlatten,
@ -593,5 +610,6 @@ module.exports = {
isBlockComment, isBlockComment,
hasClosureCompilerTypeCastComment, hasClosureCompilerTypeCastComment,
getAlignmentSize, getAlignmentSize,
printString printString,
printNumber
}; };

View File

@ -10,11 +10,11 @@ exports[`if-else.css 1`] = `
} }
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@if $media == phonePortrait { @if $media == phonePortrait {
$k: .15625; $k: 0.15625;
} @else if $media == phoneLandscape { } @else if $media == phoneLandscape {
$k: .08803; $k: 0.08803;
} @else if $media == tabletPortrait { } @else if $media == tabletPortrait {
$k: .065106; $k: 0.065106;
} }
`; `;

View File

@ -0,0 +1,132 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`numbers.css 1`] = `
@supports (margin: .5px ".30px" 1E+2px) {
a {
a: 0;
a: 1;
a: 0.1;
a: 1.1;
a: .1;
a: 1.;
a: 1e1;
a: 1e+1;
a: 1e-1;
a: 1.e1;
a: .1e1;
a: 1.1e1;
a: 1.1e0010;
a: .1e+0010;
a: .1e-0010;
a: 1E1;
a: 1E+1;
a: 1E-1;
a: 1.E1;
a: .1E1;
a: 1.1E1;
a: 1.1E0010;
a: .1E+0010;
a: .1E-0010;
a: 0.5e0;
a: 0.5e00;
a: 0.5e+0;
a: 0.5e+00;
a: 0.5e-0;
a: 0.5e-00;
a: 1;
a: 1.00500;
a: 1.0;
a: 1.5;
a: 1.50;
a: 0.00500;
a: 0.0;
a: 0.0000;
a: 500600.001230045000;
a: 1.00500e60;
a: 1.0e60;
a: 0.00500e60;
a: 0.0e60;
a: 0.0000e60;
a: .0e60;
a: 0.e60;
a: 0e60;
a: 500600.001230045000e60;
a: 10;
a: 9700;
a: 10e100;
}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@supports (margin: 0.5px ".30px" 1e2px) {
a {
a: 0;
a: 1;
a: 0.1;
a: 1.1;
a: 0.1;
a: 1;
a: 1e1;
a: 1e1;
a: 1e-1;
a: 1e1;
a: 0.1e1;
a: 1.1e1;
a: 1.1e10;
a: 0.1e10;
a: 0.1e-10;
a: 1e1;
a: 1e1;
a: 1e-1;
a: 1e1;
a: 0.1e1;
a: 1.1e1;
a: 1.1e10;
a: 0.1e10;
a: 0.1e-10;
a: 0.5;
a: 0.5;
a: 0.5;
a: 0.5;
a: 0.5;
a: 0.5;
a: 1;
a: 1.005;
a: 1;
a: 1.5;
a: 1.5;
a: 0.005;
a: 0;
a: 0;
a: 500600.001230045;
a: 1.005e60;
a: 1e60;
a: 0.005e60;
a: 0e60;
a: 0e60;
a: 0e60;
a: 0e60;
a: 0e60;
a: 500600.001230045e60;
a: 10;
a: 9700;
a: 10e100;
}
}
`;

View File

@ -0,0 +1 @@
run_spec(__dirname, { parser: "postcss" });

View File

@ -0,0 +1,63 @@
@supports (margin: .5px ".30px" 1E+2px) {
a {
a: 0;
a: 1;
a: 0.1;
a: 1.1;
a: .1;
a: 1.;
a: 1e1;
a: 1e+1;
a: 1e-1;
a: 1.e1;
a: .1e1;
a: 1.1e1;
a: 1.1e0010;
a: .1e+0010;
a: .1e-0010;
a: 1E1;
a: 1E+1;
a: 1E-1;
a: 1.E1;
a: .1E1;
a: 1.1E1;
a: 1.1E0010;
a: .1E+0010;
a: .1E-0010;
a: 0.5e0;
a: 0.5e00;
a: 0.5e+0;
a: 0.5e+00;
a: 0.5e-0;
a: 0.5e-00;
a: 1;
a: 1.00500;
a: 1.0;
a: 1.5;
a: 1.50;
a: 0.00500;
a: 0.0;
a: 0.0000;
a: 500600.001230045000;
a: 1.00500e60;
a: 1.0e60;
a: 0.00500e60;
a: 0.0e60;
a: 0.0000e60;
a: .0e60;
a: 0.e60;
a: 0e60;
a: 500600.001230045000e60;
a: 10;
a: 9700;
a: 10e100;
}
}

View File

@ -100,7 +100,7 @@ table {
filter: blur(4px); filter: blur(4px);
} }
.sepia { .sepia {
filter: sepia(.8); filter: sepia(0.8);
} }
`; `;

View File

@ -12,8 +12,8 @@ exports[`values.css 1`] = `
} }
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.class { .class {
background: linear-gradient(to bottom right, white, hsla(0, 0%, 100%, .8)); background: linear-gradient(to bottom right, white, hsla(0, 0%, 100%, 0.8));
border: 1px solid rgba(0, 0, 0, .3); border: 1px solid rgba(0, 0, 0, 0.3);
font-family: Arial, sans-serif; font-family: Arial, sans-serif;
color: rgba(0, 0, 0, 1); color: rgba(0, 0, 0, 1);
margin: 0 20px 0 -24px; margin: 0 20px 0 -24px;

View File

@ -2998,9 +2998,9 @@ postcss-selector-parser@2.2.3:
indexes-of "^1.0.1" indexes-of "^1.0.1"
uniq "^1.0.1" uniq "^1.0.1"
"postcss-values-parser@git://github.com/shellscape/postcss-values-parser.git#5e351360479116f3fe309602cdd15b0a233bc29f": "postcss-values-parser@git://github.com/lydell/postcss-values-parser.git#af2c80b2bb558a6e7d61540d97f068f9fa162b38":
version "1.2.2" version "1.3.0"
resolved "git://github.com/shellscape/postcss-values-parser.git#5e351360479116f3fe309602cdd15b0a233bc29f" resolved "git://github.com/lydell/postcss-values-parser.git#af2c80b2bb558a6e7d61540d97f068f9fa162b38"
dependencies: dependencies:
flatten "^1.0.2" flatten "^1.0.2"
indexes-of "^1.0.1" indexes-of "^1.0.1"