Skip to content

Commit 086a0ab

Browse files
authored
Add support namespace of require() (stylelint#21)
1 parent 4982ee1 commit 086a0ab

File tree

6 files changed

+115
-67
lines changed

6 files changed

+115
-67
lines changed

extract.js

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -22,25 +22,27 @@ const extractDeclarations = (path) => {
2222
};
2323

2424
const isStyleModule = (node, references) => {
25-
if (node) {
26-
const nameSpace = [];
27-
do {
28-
if (node.name) {
29-
nameSpace.unshift(node.name);
30-
} else if (node.property && node.property.name) {
31-
nameSpace.unshift(node.property.name);
32-
}
25+
const nameSpace = [];
26+
do {
27+
if (node.name) {
28+
nameSpace.unshift(node.name);
29+
} else if (node.property && node.property.name) {
30+
nameSpace.unshift(node.property.name);
31+
}
3332

34-
node = node.object || node.callee;
35-
} while (node);
33+
node = node.object || node.callee;
34+
} while (node);
3635

37-
if (nameSpace.length && references[nameSpace[0]]) {
36+
if (nameSpace.length) {
37+
if (references[nameSpace[0]]) {
3838
nameSpace.unshift.apply(nameSpace, references[nameSpace.shift()]);
3939
const modeId = nameSpace[0];
4040
const prefix = partSport[modeId];
4141
if ((prefix && prefix.every((name, i) => name === nameSpace[i + 1])) || supports[modeId]) {
4242
return nameSpace;
4343
}
44+
} else if (/^(?:styled|StyleSheet)$/.test(nameSpace[0])) {
45+
return nameSpace;
4446
}
4547
}
4648
return false;
@@ -140,15 +142,13 @@ function literalParser (source, opts, styles) {
140142

141143
function getObjectExpression (path) {
142144
let objectExpression;
143-
if (path) {
144-
if (path.isObjectExpression()) {
145-
objectExpression = path;
146-
} else if (path.isIdentifier()) {
147-
const identifierName = path.node.name;
148-
if (objs[identifierName]) {
149-
objectExpression = objs[identifierName];
150-
delete objs[identifierName];
151-
}
145+
if (path.isObjectExpression()) {
146+
objectExpression = path;
147+
} else if (path.isIdentifier()) {
148+
const identifierName = path.node.name;
149+
if (objs[identifierName]) {
150+
objectExpression = objs[identifierName];
151+
delete objs[identifierName];
152152
}
153153
}
154154
return objectExpression;
@@ -200,7 +200,16 @@ function literalParser (source, opts, styles) {
200200
if (args && args.length && args[0].isStringLiteral()) {
201201
const moduleId = args[0].container[0].value;
202202
if ((moduleId in supports) || (moduleId in partSport)) {
203-
references[path.parent.id.name] = [moduleId];
203+
const nameSpace = [moduleId];
204+
do {
205+
if (path.parent.id) {
206+
references[path.parent.id.name] = nameSpace;
207+
break;
208+
} else if (path.parent.property) {
209+
nameSpace.push(path.parent.property.name);
210+
}
211+
path = path.parentPath;
212+
} while (path);
204213
}
205214
}
206215
} else if (isStyleModule(callee, references)) {
@@ -269,7 +278,6 @@ function literalParser (source, opts, styles) {
269278
startIndex: quasis[0].start,
270279
endIndex: quasis[quasis.length - 1].end,
271280
content: value.join(""),
272-
ignoreErrors: true,
273281
};
274282
if (value.length > 1) {
275283
style.syntax = loadSyntax(opts, "postcss-styled");

object-parser.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ class objectParser {
6161
constructor (input) {
6262
this.input = input;
6363
}
64-
parse (node, source) {
64+
parse (node) {
6565
const root = postcss.root({
6666
source: {
6767
input: this.input,

package.json

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "postcss-jsx",
3-
"version": "0.30.0",
3+
"version": "0.31.0",
44
"description": "PostCSS syntax for parsing CSS in JS literals",
55
"repository": {
66
"type": "git",
@@ -45,22 +45,22 @@
4545
"@babel/parser": "^7.0.0-beta.49",
4646
"@babel/traverse": "^7.0.0-beta.49",
4747
"@babel/types": "^7.0.0-beta.49",
48-
"postcss-styled": ">=0.30.0"
48+
"postcss-styled": ">=0.31.0"
4949
},
5050
"peerDependencies": {
5151
"postcss": ">=5.0.0",
52-
"postcss-syntax": ">=0.30.0"
52+
"postcss-syntax": ">=0.31.0"
5353
},
5454
"devDependencies": {
55-
"autoprefixer": "^8.6.3",
55+
"autoprefixer": "^8.6.4",
5656
"chai": "^4.1.2",
5757
"codecov": "^3.0.2",
5858
"json5": "^1.0.1",
5959
"mocha": "^5.2.0",
6060
"nyc": "^12.0.2",
61-
"postcss": "^6.0.22",
62-
"postcss-parser-tests": "^6.2.1",
61+
"postcss": "^6.0.23",
62+
"postcss-parser-tests": "^6.3.0",
6363
"postcss-safe-parser": "^3.0.1",
64-
"postcss-syntax": ">=0.30.0"
64+
"postcss-syntax": ">=0.31.0"
6565
}
6666
}

test/css-in-js.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,4 +149,20 @@ describe("CSS in JS", () => {
149149
});
150150
});
151151
});
152+
153+
it("incomplete code", () => {
154+
const filename = "fixtures/incomplete- react-native.mjs";
155+
const code = [
156+
`StyleSheet.create({
157+
box: { padding: 10 },
158+
text: { fontWeight: "bold" },
159+
});`,
160+
"styled.div`a{display: block}`",
161+
].join("\n");
162+
163+
const document = syntax.parse(code, {
164+
from: filename,
165+
});
166+
expect(document.nodes).to.have.lengthOf(2);
167+
});
152168
});

test/fixtures/styled.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,7 @@ padding: 0.25em 1em;
1111
border: 2px solid palevioletred;
1212
border-radius: 3px;
1313
`;
14+
require("styled");
15+
const StyledCounter = require("styled-components").div;
16+
StyledCounter(require("styled-components").div.b);
1417
module.exports = Button;

test/styled-components.js

Lines changed: 58 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,19 @@ describe("styled-components", () => {
88
const file = require.resolve("./fixtures/styled");
99
let code = fs.readFileSync(file);
1010

11-
const root = syntax.parse(code, {
11+
const document = syntax.parse(code, {
1212
from: file,
1313
});
1414

1515
code = code.toString();
16-
expect(root.toString(), code);
16+
expect(document.toString(), code);
17+
expect(document.source).to.haveOwnProperty("lang", "jsx");
1718

18-
expect(root.nodes).to.have.lengthOf(1);
19-
expect(root.first.nodes).to.have.lengthOf(8);
19+
expect(document.nodes).to.have.lengthOf(1);
20+
expect(document.first.nodes).to.have.lengthOf(8);
2021

2122
const lines = code.match(/^.+$/gm).slice(3).map(line => (line.replace(/^\s*(.+?);?\s*$/, "$1")));
22-
root.first.nodes.forEach((decl, i) => {
23+
document.first.nodes.forEach((decl, i) => {
2324
if (i) {
2425
expect(decl).to.have.property("type", "decl");
2526
} else {
@@ -37,37 +38,40 @@ describe("styled-components", () => {
3738
"}",
3839
"",
3940
].join("\n");
40-
const root = syntax.parse(code, {
41+
const document = syntax.parse(code, {
4142
from: "empty_template_literal.js",
4243
});
43-
expect(root.toString()).to.equal(code);
44-
expect(root.nodes).to.have.lengthOf(0);
44+
expect(document.toString()).to.equal(code);
45+
expect(document.source).to.haveOwnProperty("lang", "jsx");
46+
expect(document.nodes).to.have.lengthOf(0);
4547
});
4648

4749
it("skip javascript syntax error", () => {
4850
const code = "\\`";
49-
const root = syntax.parse(code, {
51+
const document = syntax.parse(code, {
5052
from: "syntax_error.js",
5153
});
52-
expect(root.toString()).to.equal(code);
53-
expect(root.nodes).to.have.lengthOf(0);
54+
expect(document.toString()).to.equal(code);
55+
expect(document.source).to.haveOwnProperty("lang", "jsx");
56+
expect(document.nodes).to.have.lengthOf(0);
5457
});
5558

5659
it("illegal template literal", () => {
5760
const code = [
5861
"const styled = require(\"styled-components\");",
5962
"styled.div`$\n{display: block}\n${g} {}`",
6063
].join("\n");
61-
const root = syntax.parse(code, {
64+
const document = syntax.parse(code, {
6265
from: "illegal_template_literal.js",
6366
});
64-
expect(root.toString()).to.equal(code);
65-
expect(root.nodes).to.have.lengthOf(1);
66-
expect(root.first.nodes).to.have.lengthOf(2);
67-
expect(root.first.first).have.property("type", "rule");
68-
expect(root.first.first).have.property("selector", "$");
69-
expect(root.last.last).have.property("type", "rule");
70-
expect(root.last.last).have.property("selector", "${g}");
67+
expect(document.toString()).to.equal(code);
68+
expect(document.source).to.haveOwnProperty("lang", "jsx");
69+
expect(document.nodes).to.have.lengthOf(1);
70+
expect(document.first.nodes).to.have.lengthOf(2);
71+
expect(document.first.first).have.property("type", "rule");
72+
expect(document.first.first).have.property("selector", "$");
73+
expect(document.last.last).have.property("type", "rule");
74+
expect(document.last.last).have.property("selector", "${g}");
7175
});
7276

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

88-
it("skip CSS syntax error", () => {
92+
it("throw CSS syntax error", () => {
8993
const code = [
9094
"const styled = require(\"styled-components\");",
9195
"styled.div`a{`;",
9296
].join("\n");
93-
const root = syntax.parse(code, {
94-
from: "css_syntax_error.js",
95-
});
96-
expect(root.toString()).to.equal(code);
97-
expect(root.nodes).to.have.lengthOf(0);
97+
98+
expect(() => {
99+
syntax.parse(code, {
100+
from: "css_syntax_error.js",
101+
});
102+
}).to.throw("css_syntax_error.js:2:12: Unclosed block");
98103
});
99104

100105
it("skip empty template literal", () => {
@@ -114,38 +119,54 @@ describe("styled-components", () => {
114119
"const styled = require(\"styled-components\");",
115120
"styled.div`a{`;",
116121
].join("\n");
117-
const root = syntax({
122+
const document = syntax({
118123
css: "safe-parser",
119124
}).parse(code, {
120125
from: "postcss-safe-parser.js",
121126
});
122-
expect(root.toString()).to.equal([
127+
expect(document.toString()).to.equal([
123128
"const styled = require(\"styled-components\");",
124129
"styled.div`a{}`;",
125130
].join("\n"));
126-
expect(root.nodes).to.have.lengthOf(1);
127-
expect(root.first.nodes).to.have.lengthOf(1);
128-
expect(root.first.first).have.property("type", "rule");
129-
expect(root.first.first).have.property("selector", "a");
131+
expect(document.source).to.haveOwnProperty("lang", "jsx");
132+
expect(document.nodes).to.have.lengthOf(1);
133+
expect(document.first.nodes).to.have.lengthOf(1);
134+
expect(document.first.first).have.property("type", "rule");
135+
expect(document.first.first).have.property("selector", "a");
130136
});
131137

132138
it("fix styled syntax error", () => {
133139
const code = [
134140
"const styled = require(\"styled-components\");",
135141
"styled.div`${ a } {`",
136142
].join("\n");
137-
const root = syntax({
143+
const document = syntax({
138144
css: "safe-parser",
139145
}).parse(code, {
140146
from: "styled-safe-parse.js",
141147
});
142-
expect(root.toString()).to.equal([
148+
expect(document.toString()).to.equal([
143149
"const styled = require(\"styled-components\");",
144150
"styled.div`${ a } {}`",
145151
].join("\n"));
146-
expect(root.nodes).to.have.lengthOf(1);
147-
expect(root.first.nodes).to.have.lengthOf(1);
148-
expect(root.first.first).have.property("type", "rule");
149-
expect(root.first.first).have.property("selector", "${ a }");
152+
expect(document.source).to.haveOwnProperty("lang", "jsx");
153+
expect(document.nodes).to.have.lengthOf(1);
154+
expect(document.first.nodes).to.have.lengthOf(1);
155+
expect(document.first.first).have.property("type", "rule");
156+
expect(document.first.first).have.property("selector", "${ a }");
157+
});
158+
159+
it("template literal in prop", () => {
160+
const code = [
161+
"const styled = require(\"styled-components\");",
162+
"styled.div`margin-${/* sc-custom 'left' */ rtlSwitch}: 12.5px;`",
163+
].join("\n");
164+
const document = syntax.parse(code, {
165+
from: "template_literal_in_prop.js",
166+
});
167+
expect(document.toString()).to.equal(code);
168+
expect(document.source).to.haveOwnProperty("lang", "jsx");
169+
expect(document.nodes).to.have.lengthOf(1);
170+
expect(document.first.first).to.haveOwnProperty("prop", "margin-${/* sc-custom 'left' */ rtlSwitch}");
150171
});
151172
});

0 commit comments

Comments
 (0)