Skip to content
This repository was archived by the owner on Aug 7, 2021. It is now read-only.

Commit a5664e6

Browse files
author
vakrilov
committed
test: add tests for css2json-loader
1 parent 8921120 commit a5664e6

File tree

4 files changed

+103
-45
lines changed

4 files changed

+103
-45
lines changed

Diff for: .gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ bundle-config-loader.js
3434
xml-namespace-loader.d.ts
3535
xml-namespace-loader.js
3636

37+
css2json-loader.d.ts
38+
css2json-loader.js
39+
3740
**/*.spec.js*
3841
**/*.spec.d.ts*
3942

Diff for: css2json-loader.js

-45
This file was deleted.

Diff for: css2json-loader.spec.ts

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import css2jsonLoader from "./css2json-loader";
2+
3+
const importTestCases = [
4+
`@import url("custom.css");`,
5+
`@import url('custom.css');`,
6+
`@import url('custom.css') print;`,
7+
`@import url("custom.css") print;`,
8+
`@import url('custom.css') screen and (orientation:landscape);`,
9+
`@import url("custom.css") screen and (orientation:landscape);`,
10+
`@import 'custom.css';`,
11+
`@import "custom.css";`,
12+
`@import 'custom.css' screen;`,
13+
`@import "custom.css" screen;`,
14+
`@import url(custom.css);`,
15+
]
16+
17+
const someCSS = `
18+
.btn {
19+
background-color: #7f9
20+
}
21+
`
22+
23+
fdescribe("css2jsonLoader", () => {
24+
importTestCases.forEach((importTestCase) => {
25+
26+
it(`handles: ${importTestCase}`, (done) => {
27+
28+
const loaderContext = {
29+
callback: (error, source: string, map) => {
30+
expect(source).toContain("global.registerModule(\"custom.css\", () => require(\"custom.css\"))");
31+
expect(source).toContain(`{"type":"declaration","property":"background-color","value":"#7f9"}`);
32+
33+
done();
34+
}
35+
}
36+
37+
css2jsonLoader.call(loaderContext, importTestCase + someCSS);
38+
})
39+
})
40+
});

Diff for: css2json-loader.ts

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { parse, Rule, SyntaxTree } from "tns-core-modules/css";
2+
import { loader } from "webpack";
3+
4+
interface ImportRule extends Rule {
5+
import: string;
6+
}
7+
8+
const betweenQuotesPattern = /('|")(.*?)\1/;
9+
const unpackUrlPattern = /url\(([^\)]+)\)/;
10+
11+
const loader: loader.Loader = function (content: string, map) {
12+
const ast = parse(content, undefined);
13+
14+
let dependencies = [];
15+
getImportRules(ast)
16+
.map(extractUrlFromRule)
17+
.map(createRequireUri)
18+
.forEach(({ uri, requireURI }) => {
19+
dependencies.push(`global.registerModule("${uri}", () => require("${requireURI}"));`);
20+
21+
// Call registerModule with requireURI to handle cases like @import "~@nativescript/theme/css/blue.css";
22+
if (uri !== requireURI) {
23+
dependencies.push(`global.registerModule("${requireURI}", () => require("${requireURI}"));`);
24+
}
25+
});
26+
const str = JSON.stringify(ast, (k, v) => k === "position" ? undefined : v);
27+
this.callback(null, `${dependencies.join("\n")}module.exports = ${str};`, map);
28+
}
29+
30+
function getImportRules(ast: SyntaxTree): ImportRule[] {
31+
if (!ast || (<any>ast).type !== "stylesheet" || !ast.stylesheet) {
32+
return [];
33+
}
34+
return <ImportRule[]>ast.stylesheet.rules
35+
.filter(rule => rule.type === "import" && (<any>rule).import)
36+
}
37+
38+
/**
39+
* Extracts the url from import rule (ex. `url("./platform.css")`)
40+
*/
41+
function extractUrlFromRule(importRule: ImportRule): string {
42+
const urlValue = importRule.import;
43+
44+
const unpackedUrlMatch = urlValue.match(unpackUrlPattern);
45+
const unpackedValue = unpackedUrlMatch ? unpackedUrlMatch[1] : urlValue
46+
47+
const quotesMatch = unpackedValue.match(betweenQuotesPattern);
48+
return quotesMatch ? quotesMatch[2] : unpackedValue;
49+
};
50+
51+
function createRequireUri(uri): { uri: string, requireURI: string } {
52+
return {
53+
uri: uri,
54+
requireURI: uri[0] === "~" && uri[1] !== "/" ? uri.substr(1) : uri
55+
};
56+
}
57+
58+
59+
60+
export default loader;

0 commit comments

Comments
 (0)