Skip to content

Commit

Permalink
Add support namespace of require() (#21)
Browse files Browse the repository at this point in the history
  • Loading branch information
gucong3000 committed Jun 29, 2018
1 parent 4982ee1 commit 086a0ab
Show file tree
Hide file tree
Showing 6 changed files with 115 additions and 67 deletions.
52 changes: 30 additions & 22 deletions extract.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,25 +22,27 @@ const extractDeclarations = (path) => {
};

const isStyleModule = (node, references) => {
if (node) {
const nameSpace = [];
do {
if (node.name) {
nameSpace.unshift(node.name);
} else if (node.property && node.property.name) {
nameSpace.unshift(node.property.name);
}
const nameSpace = [];
do {
if (node.name) {
nameSpace.unshift(node.name);
} else if (node.property && node.property.name) {
nameSpace.unshift(node.property.name);
}

node = node.object || node.callee;
} while (node);
node = node.object || node.callee;
} while (node);

if (nameSpace.length && references[nameSpace[0]]) {
if (nameSpace.length) {
if (references[nameSpace[0]]) {
nameSpace.unshift.apply(nameSpace, references[nameSpace.shift()]);
const modeId = nameSpace[0];
const prefix = partSport[modeId];
if ((prefix && prefix.every((name, i) => name === nameSpace[i + 1])) || supports[modeId]) {
return nameSpace;
}
} else if (/^(?:styled|StyleSheet)$/.test(nameSpace[0])) {
return nameSpace;
}
}
return false;
Expand Down Expand Up @@ -140,15 +142,13 @@ function literalParser (source, opts, styles) {

function getObjectExpression (path) {
let objectExpression;
if (path) {
if (path.isObjectExpression()) {
objectExpression = path;
} else if (path.isIdentifier()) {
const identifierName = path.node.name;
if (objs[identifierName]) {
objectExpression = objs[identifierName];
delete objs[identifierName];
}
if (path.isObjectExpression()) {
objectExpression = path;
} else if (path.isIdentifier()) {
const identifierName = path.node.name;
if (objs[identifierName]) {
objectExpression = objs[identifierName];
delete objs[identifierName];
}
}
return objectExpression;
Expand Down Expand Up @@ -200,7 +200,16 @@ function literalParser (source, opts, styles) {
if (args && args.length && args[0].isStringLiteral()) {
const moduleId = args[0].container[0].value;
if ((moduleId in supports) || (moduleId in partSport)) {
references[path.parent.id.name] = [moduleId];
const nameSpace = [moduleId];
do {
if (path.parent.id) {
references[path.parent.id.name] = nameSpace;
break;
} else if (path.parent.property) {
nameSpace.push(path.parent.property.name);
}
path = path.parentPath;
} while (path);
}
}
} else if (isStyleModule(callee, references)) {
Expand Down Expand Up @@ -269,7 +278,6 @@ function literalParser (source, opts, styles) {
startIndex: quasis[0].start,
endIndex: quasis[quasis.length - 1].end,
content: value.join(""),
ignoreErrors: true,
};
if (value.length > 1) {
style.syntax = loadSyntax(opts, "postcss-styled");
Expand Down
2 changes: 1 addition & 1 deletion object-parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ class objectParser {
constructor (input) {
this.input = input;
}
parse (node, source) {
parse (node) {
const root = postcss.root({
source: {
input: this.input,
Expand Down
14 changes: 7 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "postcss-jsx",
"version": "0.30.0",
"version": "0.31.0",
"description": "PostCSS syntax for parsing CSS in JS literals",
"repository": {
"type": "git",
Expand Down Expand Up @@ -45,22 +45,22 @@
"@babel/parser": "^7.0.0-beta.49",
"@babel/traverse": "^7.0.0-beta.49",
"@babel/types": "^7.0.0-beta.49",
"postcss-styled": ">=0.30.0"
"postcss-styled": ">=0.31.0"
},
"peerDependencies": {
"postcss": ">=5.0.0",
"postcss-syntax": ">=0.30.0"
"postcss-syntax": ">=0.31.0"
},
"devDependencies": {
"autoprefixer": "^8.6.3",
"autoprefixer": "^8.6.4",
"chai": "^4.1.2",
"codecov": "^3.0.2",
"json5": "^1.0.1",
"mocha": "^5.2.0",
"nyc": "^12.0.2",
"postcss": "^6.0.22",
"postcss-parser-tests": "^6.2.1",
"postcss": "^6.0.23",
"postcss-parser-tests": "^6.3.0",
"postcss-safe-parser": "^3.0.1",
"postcss-syntax": ">=0.30.0"
"postcss-syntax": ">=0.31.0"
}
}
16 changes: 16 additions & 0 deletions test/css-in-js.js
Original file line number Diff line number Diff line change
Expand Up @@ -149,4 +149,20 @@ describe("CSS in JS", () => {
});
});
});

it("incomplete code", () => {
const filename = "fixtures/incomplete- react-native.mjs";
const code = [
`StyleSheet.create({
box: { padding: 10 },
text: { fontWeight: "bold" },
});`,
"styled.div`a{display: block}`",
].join("\n");

const document = syntax.parse(code, {
from: filename,
});
expect(document.nodes).to.have.lengthOf(2);
});
});
3 changes: 3 additions & 0 deletions test/fixtures/styled.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,7 @@ padding: 0.25em 1em;
border: 2px solid palevioletred;
border-radius: 3px;
`;
require("styled");
const StyledCounter = require("styled-components").div;
StyledCounter(require("styled-components").div.b);
module.exports = Button;
95 changes: 58 additions & 37 deletions test/styled-components.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,19 @@ describe("styled-components", () => {
const file = require.resolve("./fixtures/styled");
let code = fs.readFileSync(file);

const root = syntax.parse(code, {
const document = syntax.parse(code, {
from: file,
});

code = code.toString();
expect(root.toString(), code);
expect(document.toString(), code);
expect(document.source).to.haveOwnProperty("lang", "jsx");

expect(root.nodes).to.have.lengthOf(1);
expect(root.first.nodes).to.have.lengthOf(8);
expect(document.nodes).to.have.lengthOf(1);
expect(document.first.nodes).to.have.lengthOf(8);

const lines = code.match(/^.+$/gm).slice(3).map(line => (line.replace(/^\s*(.+?);?\s*$/, "$1")));
root.first.nodes.forEach((decl, i) => {
document.first.nodes.forEach((decl, i) => {
if (i) {
expect(decl).to.have.property("type", "decl");
} else {
Expand All @@ -37,37 +38,40 @@ describe("styled-components", () => {
"}",
"",
].join("\n");
const root = syntax.parse(code, {
const document = syntax.parse(code, {
from: "empty_template_literal.js",
});
expect(root.toString()).to.equal(code);
expect(root.nodes).to.have.lengthOf(0);
expect(document.toString()).to.equal(code);
expect(document.source).to.haveOwnProperty("lang", "jsx");
expect(document.nodes).to.have.lengthOf(0);
});

it("skip javascript syntax error", () => {
const code = "\\`";
const root = syntax.parse(code, {
const document = syntax.parse(code, {
from: "syntax_error.js",
});
expect(root.toString()).to.equal(code);
expect(root.nodes).to.have.lengthOf(0);
expect(document.toString()).to.equal(code);
expect(document.source).to.haveOwnProperty("lang", "jsx");
expect(document.nodes).to.have.lengthOf(0);
});

it("illegal template literal", () => {
const code = [
"const styled = require(\"styled-components\");",
"styled.div`$\n{display: block}\n${g} {}`",
].join("\n");
const root = syntax.parse(code, {
const document = syntax.parse(code, {
from: "illegal_template_literal.js",
});
expect(root.toString()).to.equal(code);
expect(root.nodes).to.have.lengthOf(1);
expect(root.first.nodes).to.have.lengthOf(2);
expect(root.first.first).have.property("type", "rule");
expect(root.first.first).have.property("selector", "$");
expect(root.last.last).have.property("type", "rule");
expect(root.last.last).have.property("selector", "${g}");
expect(document.toString()).to.equal(code);
expect(document.source).to.haveOwnProperty("lang", "jsx");
expect(document.nodes).to.have.lengthOf(1);
expect(document.first.nodes).to.have.lengthOf(2);
expect(document.first.first).have.property("type", "rule");
expect(document.first.first).have.property("selector", "$");
expect(document.last.last).have.property("type", "rule");
expect(document.last.last).have.property("selector", "${g}");
});

it("styled.img", () => {
Expand All @@ -85,16 +89,17 @@ describe("styled-components", () => {
expect(root.toString()).to.equal(code);
});

it("skip CSS syntax error", () => {
it("throw CSS syntax error", () => {
const code = [
"const styled = require(\"styled-components\");",
"styled.div`a{`;",
].join("\n");
const root = syntax.parse(code, {
from: "css_syntax_error.js",
});
expect(root.toString()).to.equal(code);
expect(root.nodes).to.have.lengthOf(0);

expect(() => {
syntax.parse(code, {
from: "css_syntax_error.js",
});
}).to.throw("css_syntax_error.js:2:12: Unclosed block");
});

it("skip empty template literal", () => {
Expand All @@ -114,38 +119,54 @@ describe("styled-components", () => {
"const styled = require(\"styled-components\");",
"styled.div`a{`;",
].join("\n");
const root = syntax({
const document = syntax({
css: "safe-parser",
}).parse(code, {
from: "postcss-safe-parser.js",
});
expect(root.toString()).to.equal([
expect(document.toString()).to.equal([
"const styled = require(\"styled-components\");",
"styled.div`a{}`;",
].join("\n"));
expect(root.nodes).to.have.lengthOf(1);
expect(root.first.nodes).to.have.lengthOf(1);
expect(root.first.first).have.property("type", "rule");
expect(root.first.first).have.property("selector", "a");
expect(document.source).to.haveOwnProperty("lang", "jsx");
expect(document.nodes).to.have.lengthOf(1);
expect(document.first.nodes).to.have.lengthOf(1);
expect(document.first.first).have.property("type", "rule");
expect(document.first.first).have.property("selector", "a");
});

it("fix styled syntax error", () => {
const code = [
"const styled = require(\"styled-components\");",
"styled.div`${ a } {`",
].join("\n");
const root = syntax({
const document = syntax({
css: "safe-parser",
}).parse(code, {
from: "styled-safe-parse.js",
});
expect(root.toString()).to.equal([
expect(document.toString()).to.equal([
"const styled = require(\"styled-components\");",
"styled.div`${ a } {}`",
].join("\n"));
expect(root.nodes).to.have.lengthOf(1);
expect(root.first.nodes).to.have.lengthOf(1);
expect(root.first.first).have.property("type", "rule");
expect(root.first.first).have.property("selector", "${ a }");
expect(document.source).to.haveOwnProperty("lang", "jsx");
expect(document.nodes).to.have.lengthOf(1);
expect(document.first.nodes).to.have.lengthOf(1);
expect(document.first.first).have.property("type", "rule");
expect(document.first.first).have.property("selector", "${ a }");
});

it("template literal in prop", () => {
const code = [
"const styled = require(\"styled-components\");",
"styled.div`margin-${/* sc-custom 'left' */ rtlSwitch}: 12.5px;`",
].join("\n");
const document = syntax.parse(code, {
from: "template_literal_in_prop.js",
});
expect(document.toString()).to.equal(code);
expect(document.source).to.haveOwnProperty("lang", "jsx");
expect(document.nodes).to.have.lengthOf(1);
expect(document.first.first).to.haveOwnProperty("prop", "margin-${/* sc-custom 'left' */ rtlSwitch}");
});
});

0 comments on commit 086a0ab

Please sign in to comment.