Add support for SCSS (#1790)

We use a heuristic to figure out if it's a SCSS or Less file. And if it doesn't work, we try again with the other one. We do the same for JSX and TypeScript.

Fixes #1784
master
Christopher Chedeau 2017-05-28 15:01:47 -07:00 committed by GitHub
parent 3d6acd8648
commit 97775dc94c
8 changed files with 114 additions and 29 deletions

View File

@ -30,6 +30,7 @@
"postcss": "^6.0.1",
"postcss-less": "^1.0.0",
"postcss-media-query-parser": "^0.2.3",
"postcss-scss": "1.0.0",
"postcss-selector-parser": "^2.2.3",
"postcss-values-parser": "git://github.com/shellscape/postcss-values-parser.git#5e351360479116f3fe309602cdd15b0a233bc29f",
"prettier": "^1.3.1",

View File

@ -28,7 +28,9 @@ function massageAST(ast) {
const newObj = {};
for (const key in ast) {
newObj[key] = massageAST(ast[key]);
if (typeof ast[key] !== "function") {
newObj[key] = massageAST(ast[key]);
}
}
[

View File

@ -306,16 +306,22 @@ function parseNestedCSS(node) {
parseNestedCSS(node[key]);
}
if (typeof node.selector === "string") {
try {
node.selector = parseSelector(
node.raws.selector ? node.raws.selector.raw : node.selector
);
} catch (e) {
throw createError(
e.toString(),
node.source.start.line,
node.source.start.column - 1
);
const selector = node.raws.selector
? node.raws.selector.raw
: node.selector;
if (selector.trim().endsWith(":")) {
node.selector = selector;
} else {
try {
node.selector = parseSelector(selector);
} catch (e) {
throw createError(
"(postcss-selector-parser) " + e.toString(),
node.source.start.line,
node.source.start.column - 1
);
}
}
}
if (node.type && typeof node.value === "string") {
@ -325,7 +331,7 @@ function parseNestedCSS(node) {
const line = +(e.toString().match(/line: ([0-9]+)/) || [1, 1])[1];
const column = +(e.toString().match(/column ([0-9]+)/) || [0, 0])[1];
throw createError(
e.toString(),
"(postcss-values-parser) " + e.toString(),
node.source.start.line + line - 1,
node.source.start.column + column + node.prop.length
);
@ -338,19 +344,38 @@ function parseNestedCSS(node) {
return node;
}
function parseWithPostCSS(text) {
const r = require;
const parser = r("postcss-less");
function parseWithPostCSSParser(parser, text) {
let result;
try {
const result = parser.parse(text);
const prefixedResult = addTypePrefix(result, "css-");
const parsedResult = parseNestedCSS(prefixedResult);
return parsedResult;
result = parser.parse(text);
} catch (e) {
if (typeof e.line !== "number") {
throw e;
}
throw createError(e.name + " " + e.reason, e.line, e.column);
throw createError("(postcss) " + e.name + " " + e.reason, e.line, e.column);
}
const prefixedResult = addTypePrefix(result, "css-");
const parsedResult = parseNestedCSS(prefixedResult);
return parsedResult;
}
function parseWithPostCSS(text) {
const r = require;
const isLikelySCSS = text.match(/(\w\s*: [^}:]+|#){/);
try {
return parseWithPostCSSParser(
r(isLikelySCSS ? "postcss-scss" : "postcss-less"),
text
);
} catch (e) {
try {
return parseWithPostCSSParser(
r(isLikelySCSS ? "postcss-less" : "postcss-scss"),
text
);
} catch (e2) {
throw e;
}
}
}

View File

@ -2532,7 +2532,9 @@ function genericPrintNoParens(path, options, print, args) {
return concat([printNodeSequence(path, options, print), hardline]);
}
case "css-comment": {
return n.raws.content;
return n.raws.content
? n.raws.content
: options.originalText.slice(util.locStart(n), util.locEnd(n));
}
case "css-rule": {
return concat([
@ -2558,7 +2560,16 @@ function genericPrintNoParens(path, options, print, args) {
": ",
path.call(print, "value"),
n.important ? " !important" : "",
";"
n.nodes
? concat([
" {",
indent(
concat([softline, printNodeSequence(path, options, print)])
),
softline,
"}"
])
: ";"
]);
}
case "css-atrule": {

View File

@ -0,0 +1,36 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`scss.css 1`] = `
@media #{$g-breakpoint-tiny} {}
.#{$fa-css-prefix}-glass:before { content: $fa-var-glass; }
a {height: calc(#{$foo} + 1);}
div {
background: {
size: auto 60%;
position: bottom 2px left;
}
}
a { margin: 0 { left: 10px; } }
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@media #{$g-breakpoint-tiny} {
}
.#{$fa-css-prefix}-glass:before {
content: $fa-var-glass;
}
a {
height: calc(#{$foo} + 1);
}
div {
background: {
size: auto 60%;
position: bottom 2px left;
}
}
a {
margin: 0 {
left: 10px;
}
}
`;

View File

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

10
tests/css_scss/scss.css Normal file
View File

@ -0,0 +1,10 @@
@media #{$g-breakpoint-tiny} {}
.#{$fa-css-prefix}-glass:before { content: $fa-var-glass; }
a {height: calc(#{$foo} + 1);}
div {
background: {
size: auto 60%;
position: bottom 2px left;
}
}
a { margin: 0 { left: 10px; } }

View File

@ -2199,6 +2199,12 @@ postcss-media-query-parser@^0.2.3:
version "0.2.3"
resolved "https://registry.yarnpkg.com/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz#27b39c6f4d94f81b1a73b8f76351c609e5cef244"
postcss-scss@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/postcss-scss/-/postcss-scss-1.0.0.tgz#4957013097973dfd5bd9b1ad8a6dc13456a5d1ba"
dependencies:
postcss "^6.0.1"
postcss-selector-parser@^2.2.3:
version "2.2.3"
resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz#f9437788606c3c9acee16ffe8d8b16297f27bb90"
@ -2815,13 +2821,6 @@ typedarray@^0.0.6:
lodash.unescape "4.0.1"
semver "5.3.0"
"typescript-eslint-parser@git://github.com/eslint/typescript-eslint-parser.git#a3610632a8bd1ee9ad4179ed01a01b7739143bf5":
version "3.0.0"
resolved "git://github.com/eslint/typescript-eslint-parser.git#a3610632a8bd1ee9ad4179ed01a01b7739143bf5"
dependencies:
lodash.unescape "4.0.1"
semver "5.3.0"
typescript@2.3.2:
version "2.3.2"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.3.2.tgz#f0f045e196f69a72f06b25fd3bd39d01c3ce9984"