Split Less and SCSS parsing into different parsers (#2844)

* Split Less and SCSS parsing into different parsers

Now, .less files are always parsed with postcss-less, and .scss files
areare always parsed with postcss-scss. This:

- Is less hacky.
- Is meant to avoid issues like #2829.
- Is probably more performant.

`parser: "postcss"` and `--parser postcss` continue to work like before:
First trying postcss-less, and if that fails, postcss-scss, unless a
regex says that we should try in the opposite order. The new values for
the parser option are "postcss-less" and "postcss-scss".

* Remove postcss from package.json since it is not used

* Rename parser-less to less and parser-scss to scss

* Deprecate parser:postcss in favor of parser:css

* Fix CSS tests
master
Simon Lydell 2017-09-26 07:08:11 +02:00 committed by GitHub
parent 70f5165bb1
commit c6bac7cfe6
83 changed files with 169 additions and 100 deletions

View File

@ -34,7 +34,6 @@
"minimatch": "3.0.4",
"minimist": "1.2.0",
"parse5": "3.0.2",
"postcss": "^6.0.1",
"postcss-less": "^1.0.0",
"postcss-media-query-parser": "0.2.3",
"postcss-scss": "1.0.0",

View File

@ -185,7 +185,17 @@ const detailedOptions = normalizeDetailedOptions({
category: CATEGORY_FORMAT,
forwardToApi: true,
exception: value => typeof value === "string", // Allow path to a parser module.
choices: ["flow", "babylon", "typescript", "postcss", "json", "graphql"],
choices: [
"flow",
"babylon",
"typescript",
"css",
{ value: "postcss", deprecated: true, redirect: "css" },
"less",
"scss",
"json",
"graphql"
],
description: "Which parser to use.",
getter: (value, argv) => (argv["flow-parser"] ? "flow" : value)
},

View File

@ -48,7 +48,7 @@ function fromBabylonFlowOrTypeScript(path) {
const rawQuasis = node.quasis.map(q => q.value.raw);
const text = rawQuasis.join("@prettier-placeholder");
return {
options: { parser: "postcss" },
options: { parser: "css" },
transformDoc: transformCssDoc,
text: text
};
@ -133,7 +133,7 @@ function fromHtmlParser2(path, options) {
// Inline Styles
if (parent.type === "style") {
return {
options: { parser: "postcss" },
options: { parser: "css" },
transformDoc: doc => concat([hardline, stripTrailingHardline(doc)]),
text: getText(options, node)
};

View File

@ -30,8 +30,12 @@ function normalize(options) {
const normalized = Object.assign({}, options || {});
const filepath = normalized.filepath;
if (/\.(css|less|scss)$/.test(filepath)) {
normalized.parser = "postcss";
if (/\.css$/.test(filepath)) {
normalized.parser = "css";
} else if (/\.less$/.test(filepath)) {
normalized.parser = "less";
} else if (/\.scss$/.test(filepath)) {
normalized.parser = "scss";
} else if (/\.html$/.test(filepath)) {
normalized.parser = "parse5";
} else if (/\.(ts|tsx)$/.test(filepath)) {
@ -58,6 +62,16 @@ function normalize(options) {
);
}
/* istanbul ignore if */
if (normalized.parser === "postcss") {
normalized.parser = "css";
console.warn(
'Warning: `parser` with value "postcss" is deprecated. ' +
'Use "css", "less" or "scss" instead.'
);
}
const parserBackup = normalized.parser;
if (typeof normalized.parser === "function") {
// Delete the function from the object to pass validation.

View File

@ -227,15 +227,27 @@ function requireParser(isSCSS) {
return require("postcss-less");
}
function parse(text /*, parsers, opts*/) {
const isLikelySCSS = !!text.match(/(\w\s*: [^}:]+|#){|@import[^\n]+(url|,)/);
const IS_POSSIBLY_SCSS = /(\w\s*: [^}:]+|#){|@import[^\n]+(url|,)/;
function parse(text, parsers, opts) {
const hasExplicitParserChoice =
opts.parser === "less" || opts.parser === "scss";
const isSCSS = hasExplicitParserChoice
? opts.parser === "scss"
: IS_POSSIBLY_SCSS.test(text);
try {
return parseWithParser(requireParser(isLikelySCSS), text);
} catch (e) {
return parseWithParser(requireParser(isSCSS), text);
} catch (originalError) {
if (hasExplicitParserChoice) {
throw originalError;
}
try {
return parseWithParser(requireParser(!isLikelySCSS), text);
} catch (e2) {
throw e;
return parseWithParser(requireParser(!isSCSS), text);
} catch (_secondError) {
throw originalError;
}
}
}

View File

@ -19,7 +19,13 @@ const parsers = {
get typescript() {
return eval("require")("./parser-typescript");
},
get postcss() {
get css() {
return eval("require")("./parser-postcss");
},
get less() {
return eval("require")("./parser-postcss");
},
get scss() {
return eval("require")("./parser-postcss");
},
get json() {

View File

@ -56,7 +56,9 @@ function getPrintFunction(options) {
return require("./printer-graphql");
case "parse5":
return require("./printer-htmlparser2");
case "postcss":
case "css":
case "less":
case "scss":
return require("./printer-postcss");
default:
return genericPrintNoParens;

View File

@ -526,7 +526,15 @@ function printString(raw, options, isDirectiveLiteral) {
// is enclosed with `enclosingQuote`, but it isn't. The string could contain
// unnecessary escapes (such as in `"\'"`). Always using `makeString` makes
// sure that we consistently output the minimum amount of escaped quotes.
return makeString(rawContent, enclosingQuote, options.parser !== "postcss");
return makeString(
rawContent,
enclosingQuote,
!(
options.parser === "css" ||
options.parser === "less" ||
options.parser === "scss"
)
);
}
function makeString(rawContent, enclosingQuote, unescapeUnnecessaryEscapes) {

View File

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

View File

@ -1,2 +1,2 @@
run_spec(__dirname, { parser: "postcss" });
run_spec(__dirname, { parser: "postcss", singleQuote: true });
run_spec(__dirname, { parser: "css" });
run_spec(__dirname, { parser: "css", singleQuote: true });

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,2 +1,2 @@
run_spec(__dirname, { parser: "postcss" });
run_spec(__dirname, { parser: "postcss", singleQuote: true });
run_spec(__dirname, { parser: "css" });
run_spec(__dirname, { parser: "css", singleQuote: true });

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -127,7 +127,7 @@ exports[`show detailed usage with --help no-semi 1`] = `
`;
exports[`show detailed usage with --help parser 1`] = `
"--parser <flow|babylon|typescript|postcss|json|graphql>
"--parser <flow|babylon|typescript|css|less|scss|json|graphql>
Which parser to use.
@ -136,7 +136,9 @@ Valid options:
flow
babylon
typescript
postcss
css
less
scss
json
graphql
@ -287,7 +289,7 @@ Format options:
--no-bracket-spacing Do not print spaces between brackets.
--jsx-bracket-same-line Put > on the last line instead of at a new line.
Defaults to false.
--parser <flow|babylon|typescript|postcss|json|graphql>
--parser <flow|babylon|typescript|css|less|scss|json|graphql>
Which parser to use.
Defaults to babylon.
--print-width <int> The line length where Prettier will try wrap.
@ -347,7 +349,7 @@ Other options:
`;
exports[`show warning with --help not-found (typo) 1`] = `
"--parser <flow|babylon|typescript|postcss|json|graphql>
"--parser <flow|babylon|typescript|css|less|scss|json|graphql>
Which parser to use.
@ -356,7 +358,9 @@ Valid options:
flow
babylon
typescript
postcss
css
less
scss
json
graphql
@ -400,7 +404,7 @@ Format options:
--no-bracket-spacing Do not print spaces between brackets.
--jsx-bracket-same-line Put > on the last line instead of at a new line.
Defaults to false.
--parser <flow|babylon|typescript|postcss|json|graphql>
--parser <flow|babylon|typescript|css|less|scss|json|graphql>
Which parser to use.
Defaults to babylon.
--print-width <int> The line length where Prettier will try wrap.

View File

@ -359,7 +359,7 @@
</div>
<div class="options last">
<label>--trailing-comma <select id="trailingComma"><option value="none">none</option><option value="es5">es5</option><option value="all">all</option></select></label>
<label>--parser <select id="parser"><option value="babylon">babylon</option><option value="flow">flow</option><option value="typescript">typescript</option><option value="postcss">postcss</option><option value="json">json</option><option value="graphql">graphql</option></select></label>
<label>--parser <select id="parser"><option value="babylon">babylon</option><option value="flow">flow</option><option value="typescript">typescript</option><option value="postcss">postcss</option><!-- TODO: Enable these and remove the "postcss" option when prettier@>1.7.0 has been released. <option value="css">css</option><option value="less">less</option><option value="scss">scss</option>--><option value="json">json</option><option value="graphql">graphql</option></select></label>
<span style="flex: 0.3"></span>
<label><input type="checkbox" id="ast"> show AST (debug)</label>
<label><input type="checkbox" id="doc"> show doc (debug)</label>

View File

@ -49,8 +49,9 @@
return "jsx";
case "typescript":
return "tsx";
// TODO: Remove the "postcss" case when prettier@>1.7.0 is released.
case "postcss":
return "scss";
return "css";
default:
return options.parser;
}

View File

@ -238,7 +238,11 @@ function replaceHash(hash) {
function getCodemirrorMode(options) {
switch (options.parser) {
// TODO: Remove the "postcss" case when prettier@>1.7.0 is released.
case "css":
case "postcss":
case "less":
case "scss":
return "css";
default:
return "jsx";

View File

@ -98,11 +98,20 @@ function formatCode(text, options) {
}
function lazyLoadParser(parser) {
var script =
parser === "json" ? "parser-babylon.js" : "parser-" + parser + ".js";
var actualParser =
parser === "json"
? "babylon"
: parser === "css" ||
// TODO: Remove "postcss" when prettier@>1.7.0 is released.
parser === "postcss" ||
parser === "less" ||
parser === "scss"
? "css"
: parser;
var script = "parser-" + actualParser + ".js";
if (!parsersLoaded[parser]) {
if (!parsersLoaded[actualParser]) {
importScripts("lib/" + script);
parsersLoaded[parser] = true;
parsersLoaded[actualParser] = true;
}
}