rollup-plugin-react-scoped-css 0.2.3 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/.github/workflows/pull-request.yml +19 -0
  2. package/.github/workflows/release.yml +30 -0
  3. package/.releaserc +12 -0
  4. package/README.md +40 -6
  5. package/dist/ast-iterator.d.ts +1 -0
  6. package/dist/ast-iterator.js +114 -0
  7. package/dist/ast-transformer.d.ts +1 -0
  8. package/dist/ast-transformer.js +50 -0
  9. package/dist/ast.utils.d.ts +4 -0
  10. package/dist/ast.utils.js +46 -82
  11. package/dist/index.d.ts +27 -0
  12. package/dist/index.js +21 -11
  13. package/dist/parsers/classic-parser.d.ts +7 -0
  14. package/dist/parsers/classic-parser.js +95 -0
  15. package/dist/parsers/jsx-parser.model.d.ts +9 -0
  16. package/dist/parsers/jsx-parser.model.js +8 -0
  17. package/dist/parsers/new-parser.d.ts +7 -0
  18. package/dist/parsers/new-parser.js +94 -0
  19. package/package.json +21 -3
  20. package/src/__mocks__/{compiled-jsx-with-attr.js → classic-compiled-jsx-with-attr.js} +0 -0
  21. package/src/__mocks__/{compiled-jsx.js → classic-compiled-jsx.js} +0 -0
  22. package/src/__mocks__/new-compiled-jsx-with-attr.js +101 -0
  23. package/src/__mocks__/new-compiled-jsx.js +64 -0
  24. package/src/__mocks__/sample-code-file.js +4 -0
  25. package/src/ast-iterator.spec.ts +19 -0
  26. package/src/ast-iterator.ts +27 -0
  27. package/src/ast-transformer.spec.ts +20 -0
  28. package/src/ast-transformer.ts +24 -0
  29. package/src/ast.utils.spec.ts +36 -12
  30. package/src/ast.utils.ts +33 -68
  31. package/src/index.ts +52 -6
  32. package/src/parsers/classic-parser.ts +58 -0
  33. package/src/parsers/jsx-parser.model.ts +10 -0
  34. package/src/parsers/new-parser.ts +58 -0
  35. package/tsconfig.json +2 -1
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
13
+ var __read = (this && this.__read) || function (o, n) {
14
+ var m = typeof Symbol === "function" && o[Symbol.iterator];
15
+ if (!m) return o;
16
+ var i = m.call(o), r, ar = [], e;
17
+ try {
18
+ while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
19
+ }
20
+ catch (error) { e = { error: error }; }
21
+ finally {
22
+ try {
23
+ if (r && !r.done && (m = i["return"])) m.call(i);
24
+ }
25
+ finally { if (e) throw e.error; }
26
+ }
27
+ return ar;
28
+ };
29
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
30
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
31
+ if (ar || !(i in from)) {
32
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
33
+ ar[i] = from[i];
34
+ }
35
+ }
36
+ return to.concat(ar || Array.prototype.slice.call(from));
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.ClassicJsxParser = void 0;
40
+ var ClassicJsxParser = /** @class */ (function () {
41
+ function ClassicJsxParser() {
42
+ }
43
+ ClassicJsxParser.prototype.isNodeReactFragment = function (node) {
44
+ var _a, _b, _c, _d, _e, _f;
45
+ return ((_c = (_b = (_a = node === null || node === void 0 ? void 0 : node.arguments) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.object) === null || _c === void 0 ? void 0 : _c.name) === "React" &&
46
+ ((_f = (_e = (_d = node === null || node === void 0 ? void 0 : node.arguments) === null || _d === void 0 ? void 0 : _d[0]) === null || _e === void 0 ? void 0 : _e.property) === null || _f === void 0 ? void 0 : _f.name) === "Fragment";
47
+ };
48
+ ClassicJsxParser.prototype.isNodeReactElement = function (node) {
49
+ var _a, _b, _c, _d;
50
+ return (node === null || node === void 0 ? void 0 : node.type) === 'CallExpression' &&
51
+ ((_b = (_a = node === null || node === void 0 ? void 0 : node.callee) === null || _a === void 0 ? void 0 : _a.object) === null || _b === void 0 ? void 0 : _b.name) === 'React' &&
52
+ ((_d = (_c = node === null || node === void 0 ? void 0 : node.callee) === null || _c === void 0 ? void 0 : _c.property) === null || _d === void 0 ? void 0 : _d.name) === 'createElement';
53
+ };
54
+ ClassicJsxParser.prototype.extendNodeWithAttributes = function (node, attr) {
55
+ var _this = this;
56
+ var _a;
57
+ var arg = (_a = node === null || node === void 0 ? void 0 : node.arguments) === null || _a === void 0 ? void 0 : _a[1];
58
+ return __assign(__assign({}, node), { arguments: node === null || node === void 0 ? void 0 : node.arguments.map(function (v, i) {
59
+ if (i === 1) {
60
+ if (v.type === 'ObjectExpression') {
61
+ return __assign(__assign({}, v), { properties: __spreadArray(__spreadArray([], __read(arg.properties), false), [
62
+ _this.createAttributeNode(attr)
63
+ ], false) });
64
+ }
65
+ else {
66
+ return {
67
+ type: 'ObjectExpression',
68
+ properties: [_this.createAttributeNode(attr)]
69
+ };
70
+ }
71
+ }
72
+ return v;
73
+ }) });
74
+ };
75
+ ClassicJsxParser.prototype.createAttributeNode = function (attr) {
76
+ return {
77
+ type: 'Property',
78
+ method: false,
79
+ shorthand: false,
80
+ computed: false,
81
+ key: {
82
+ type: 'Identifier',
83
+ name: "\"".concat(attr, "\"")
84
+ },
85
+ value: {
86
+ type: 'Literal',
87
+ value: true,
88
+ raw: "true"
89
+ },
90
+ kind: 'init'
91
+ };
92
+ };
93
+ return ClassicJsxParser;
94
+ }());
95
+ exports.ClassicJsxParser = ClassicJsxParser;
@@ -0,0 +1,9 @@
1
+ export interface JsxParser {
2
+ isNodeReactElement: (node: any) => boolean;
3
+ isNodeReactFragment: (node: any) => boolean;
4
+ extendNodeWithAttributes: (node: any, attr: string) => any;
5
+ }
6
+ export declare enum ParserImplementations {
7
+ new = "new",
8
+ classic = "classic"
9
+ }
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ParserImplementations = void 0;
4
+ var ParserImplementations;
5
+ (function (ParserImplementations) {
6
+ ParserImplementations["new"] = "new";
7
+ ParserImplementations["classic"] = "classic";
8
+ })(ParserImplementations = exports.ParserImplementations || (exports.ParserImplementations = {}));
@@ -0,0 +1,7 @@
1
+ import { JsxParser } from "./jsx-parser.model";
2
+ export declare class NewJsxParser implements JsxParser {
3
+ isNodeReactFragment(node: any): boolean;
4
+ isNodeReactElement(node: any): boolean;
5
+ extendNodeWithAttributes(node: any, attr: string): any;
6
+ private createAttributeNode;
7
+ }
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
13
+ var __read = (this && this.__read) || function (o, n) {
14
+ var m = typeof Symbol === "function" && o[Symbol.iterator];
15
+ if (!m) return o;
16
+ var i = m.call(o), r, ar = [], e;
17
+ try {
18
+ while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
19
+ }
20
+ catch (error) { e = { error: error }; }
21
+ finally {
22
+ try {
23
+ if (r && !r.done && (m = i["return"])) m.call(i);
24
+ }
25
+ finally { if (e) throw e.error; }
26
+ }
27
+ return ar;
28
+ };
29
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
30
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
31
+ if (ar || !(i in from)) {
32
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
33
+ ar[i] = from[i];
34
+ }
35
+ }
36
+ return to.concat(ar || Array.prototype.slice.call(from));
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.NewJsxParser = void 0;
40
+ var NewJsxParser = /** @class */ (function () {
41
+ function NewJsxParser() {
42
+ }
43
+ NewJsxParser.prototype.isNodeReactFragment = function (node) {
44
+ var _a, _b, _c, _d;
45
+ return ((_b = (_a = node.arguments) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.type) === "Identifier" &&
46
+ ['_Fragment', 'Fragment'].includes((_d = (_c = node.arguments) === null || _c === void 0 ? void 0 : _c[0]) === null || _d === void 0 ? void 0 : _d.name);
47
+ };
48
+ NewJsxParser.prototype.isNodeReactElement = function (node) {
49
+ var _a;
50
+ return (node === null || node === void 0 ? void 0 : node.type) === 'CallExpression' &&
51
+ ['_jsxDEV', '_jsx', '_jsxs', 'jsxDev', 'jsx', 'jsxs'].includes((_a = node === null || node === void 0 ? void 0 : node.callee) === null || _a === void 0 ? void 0 : _a.name);
52
+ };
53
+ NewJsxParser.prototype.extendNodeWithAttributes = function (node, attr) {
54
+ var _this = this;
55
+ var _a;
56
+ var arg = (_a = node === null || node === void 0 ? void 0 : node.arguments) === null || _a === void 0 ? void 0 : _a[1];
57
+ return __assign(__assign({}, node), { arguments: node === null || node === void 0 ? void 0 : node.arguments.map(function (v, i) {
58
+ if (i === 1) {
59
+ if (v.type === 'ObjectExpression') {
60
+ return __assign(__assign({}, v), { properties: __spreadArray(__spreadArray([], __read(arg.properties), false), [
61
+ _this.createAttributeNode(attr)
62
+ ], false) });
63
+ }
64
+ else {
65
+ return {
66
+ type: 'ObjectExpression',
67
+ properties: [_this.createAttributeNode(attr)]
68
+ };
69
+ }
70
+ }
71
+ return v;
72
+ }) });
73
+ };
74
+ NewJsxParser.prototype.createAttributeNode = function (attr) {
75
+ return {
76
+ type: 'Property',
77
+ method: false,
78
+ shorthand: false,
79
+ computed: false,
80
+ key: {
81
+ type: 'Identifier',
82
+ name: "\"".concat(attr, "\"")
83
+ },
84
+ value: {
85
+ type: 'Literal',
86
+ value: true,
87
+ raw: "true"
88
+ },
89
+ kind: 'init'
90
+ };
91
+ };
92
+ return NewJsxParser;
93
+ }());
94
+ exports.NewJsxParser = NewJsxParser;
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "rollup-plugin-react-scoped-css",
3
- "version": "0.2.3",
3
+ "version": "0.5.0",
4
4
  "description": "A rollup plugin designed to allow scoped css to be run in react (Compatible with vite and rollup)",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "scripts": {
8
8
  "build": "tsc",
9
- "prepare": "npm run build && npm test",
9
+ "build:watch": "tsc --watch",
10
10
  "test": "jest"
11
11
  },
12
12
  "repository": {
@@ -14,6 +14,18 @@
14
14
  "url": "git+https://github.com/cmseguin/rollup-plugin-react-scoped-css.git"
15
15
  },
16
16
  "author": "cmseguin",
17
+ "contributors": [
18
+ "cmseguin (https://github.com/cmseguin)",
19
+ "helianthuswhite (https://github.com/helianthuswhite)"
20
+ ],
21
+ "keywords": [
22
+ "rollup",
23
+ "react",
24
+ "css",
25
+ "scoped",
26
+ "vite",
27
+ "vitejs"
28
+ ],
17
29
  "license": "ISC",
18
30
  "bugs": {
19
31
  "url": "https://github.com/cmseguin/rollup-plugin-react-scoped-css/issues"
@@ -29,9 +41,15 @@
29
41
  "devDependencies": {
30
42
  "@babel/preset-env": "^7.15.0",
31
43
  "@babel/preset-typescript": "^7.15.0",
44
+ "@semantic-release/commit-analyzer": "^9.0.2",
45
+ "@semantic-release/git": "^10.0.1",
46
+ "@semantic-release/npm": "^8.0.3",
47
+ "@semantic-release/release-notes-generator": "^10.0.3",
32
48
  "@types/escodegen": "0.0.7",
33
49
  "@types/estree": "0.0.50",
34
50
  "@types/jest": "^27.0.1",
35
- "jest": "^27.0.6"
51
+ "acorn": "^8.6.0",
52
+ "jest": "^27.0.6",
53
+ "semantic-release": "^18.0.1"
36
54
  }
37
55
  }
@@ -0,0 +1,101 @@
1
+ import {
2
+ j as jsxRuntime,
3
+ r as react,
4
+ R as ReactDOM,
5
+ a as React
6
+ } from "./vendor.1137a3d7.js";
7
+ var index = "body {\n margin: 0;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',\n 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',\n sans-serif;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n\ncode {\n font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',\n monospace;\n}\n";
8
+ var App$1 = ".sub {\n color: green;\n}";
9
+ var App_scoped = ".App {\n text-align: center;\n}\n\n.sub {\n color: blue !important;\n}\n\n.App-logo {\n height: 40vmin;\n pointer-events: none;\n}\n\n@media (prefers-reduced-motion: no-preference) {\n .App-logo {\n animation: App-logo-spin infinite 20s linear;\n }\n}\n\n.App-header {\n background-color: #282c34;\n min-height: 100vh;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n font-size: calc(10px + 2vmin);\n color: white;\n}\n\n.App-link {\n color: #61dafb;\n}\n\n@keyframes App-logo-spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n\nbutton {\n font-size: calc(10px + 2vmin);\n}\n";
10
+ var logo = "/assets/logo.ecc203fb.svg";
11
+ var Sub_scoped = ".sub {\n color: red;\n}\n.sub__test {\n margin: 0;\n}\n.sub h2 {\n font-weight: 300;\n font-size: 3rem;\n}\n\nh2 {\n font-size: 10rem;\n}\n\n.drawer {\n width: 400px;\n}\n.drawer__list-item {\n padding: 0;\n}\n.drawer__list-item-icon {\n margin-right: 1rem;\n}\n.drawer__link {\n display: flex;\n width: 300px;\n padding: 1rem;\n align-items: center;\n text-decoration: none;\n border: 0;\n outline: 0;\n background: transparent;\n font-family: \"Quicksand\", \"Roboto\", sans-serif;\n font-size: 1rem;\n font-weight: 400;\n}\n.drawer__link:hover {\n background-color: #fafafa;\n}";
12
+ const jsx = jsxRuntime.exports.jsx;
13
+ const jsxs = jsxRuntime.exports.jsxs;
14
+ const Fragment = jsxRuntime.exports.Fragment;
15
+ function Sub() {
16
+ return jsx("div", {
17
+ className: "sub",
18
+ children: jsx("h2", {
19
+ children: "Sub",
20
+ "data-v-123456": true
21
+ }),
22
+ "data-v-123456": true
23
+ });
24
+ }
25
+ function App() {
26
+ const [count, setCount] = react.exports.useState(0);
27
+ return jsx(Fragment, {
28
+ children: jsxs("div", {
29
+ className: "App",
30
+ children: [
31
+ jsxs("header", {
32
+ className: "App-header",
33
+ children: [
34
+ jsx("img", {
35
+ src: logo,
36
+ className: "App-logo",
37
+ alt: "logo",
38
+ "data-v-123456": true
39
+ }),
40
+ jsx("p", {
41
+ children: "Hello Vite + React!",
42
+ "data-v-123456": true
43
+ }),
44
+ jsx("p", {
45
+ children: jsxs("button", {
46
+ type: "button",
47
+ onClick: () => setCount(count2 => count2 + 1),
48
+ children: [
49
+ "count is: ",
50
+ count
51
+ ],
52
+ "data-v-123456": true
53
+ }),
54
+ "data-v-123456": true
55
+ }),
56
+ jsxs("p", {
57
+ children: [
58
+ "Edit ",
59
+ jsx("code", {
60
+ children: "App.jsx",
61
+ "data-v-123456": true
62
+ }),
63
+ " and save to test HMR updates."
64
+ ],
65
+ "data-v-123456": true
66
+ }),
67
+ jsxs("p", {
68
+ children: [
69
+ jsx("a", {
70
+ className: "App-link",
71
+ href: "https://reactjs.org",
72
+ target: "_blank",
73
+ rel: "noopener noreferrer",
74
+ children: "Learn React",
75
+ "data-v-123456": true
76
+ }),
77
+ " | ",
78
+ jsx("a", {
79
+ className: "App-link",
80
+ href: "https://vitejs.dev/guide/features.html",
81
+ target: "_blank",
82
+ rel: "noopener noreferrer",
83
+ children: "Vite Docs",
84
+ "data-v-123456": true
85
+ })
86
+ ],
87
+ "data-v-123456": true
88
+ })
89
+ ],
90
+ "data-v-123456": true
91
+ }),
92
+ jsx(Fragment, { children: jsx(Sub, { "data-v-123456": true }) })
93
+ ],
94
+ "data-v-123456": true
95
+ })
96
+ });
97
+ }
98
+ ReactDOM.render(jsx(React.StrictMode, {
99
+ children: jsx(App, { "data-v-123456": true }),
100
+ "data-v-123456": true
101
+ }), document.getElementById("root"));
@@ -0,0 +1,64 @@
1
+ import { j as jsxRuntime, r as react, R as ReactDOM, a as React } from "./vendor.1137a3d7.js";
2
+ var index = "body {\n margin: 0;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',\n 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',\n sans-serif;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n\ncode {\n font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',\n monospace;\n}\n";
3
+ var App$1 = ".sub {\n color: green;\n}";
4
+ var App_scoped = ".App {\n text-align: center;\n}\n\n.sub {\n color: blue !important;\n}\n\n.App-logo {\n height: 40vmin;\n pointer-events: none;\n}\n\n@media (prefers-reduced-motion: no-preference) {\n .App-logo {\n animation: App-logo-spin infinite 20s linear;\n }\n}\n\n.App-header {\n background-color: #282c34;\n min-height: 100vh;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n font-size: calc(10px + 2vmin);\n color: white;\n}\n\n.App-link {\n color: #61dafb;\n}\n\n@keyframes App-logo-spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n\nbutton {\n font-size: calc(10px + 2vmin);\n}\n";
5
+ var logo = "/assets/logo.ecc203fb.svg";
6
+ var Sub_scoped = '.sub {\n color: red;\n}\n.sub__test {\n margin: 0;\n}\n.sub h2 {\n font-weight: 300;\n font-size: 3rem;\n}\n\nh2 {\n font-size: 10rem;\n}\n\n.drawer {\n width: 400px;\n}\n.drawer__list-item {\n padding: 0;\n}\n.drawer__list-item-icon {\n margin-right: 1rem;\n}\n.drawer__link {\n display: flex;\n width: 300px;\n padding: 1rem;\n align-items: center;\n text-decoration: none;\n border: 0;\n outline: 0;\n background: transparent;\n font-family: "Quicksand", "Roboto", sans-serif;\n font-size: 1rem;\n font-weight: 400;\n}\n.drawer__link:hover {\n background-color: #fafafa;\n}';
7
+ const jsx = jsxRuntime.exports.jsx;
8
+ const jsxs = jsxRuntime.exports.jsxs;
9
+ const Fragment = jsxRuntime.exports.Fragment;
10
+ function Sub() {
11
+ return /* @__PURE__ */ jsx("div", {
12
+ className: "sub",
13
+ children: /* @__PURE__ */ jsx("h2", {
14
+ children: "Sub"
15
+ })
16
+ });
17
+ }
18
+ function App() {
19
+ const [count, setCount] = react.exports.useState(0);
20
+ return /* @__PURE__ */ jsx(Fragment, {
21
+ children: /* @__PURE__ */ jsxs("div", {
22
+ className: "App",
23
+ children: [/* @__PURE__ */ jsxs("header", {
24
+ className: "App-header",
25
+ children: [/* @__PURE__ */ jsx("img", {
26
+ src: logo,
27
+ className: "App-logo",
28
+ alt: "logo"
29
+ }), /* @__PURE__ */ jsx("p", {
30
+ children: "Hello Vite + React!"
31
+ }), /* @__PURE__ */ jsx("p", {
32
+ children: /* @__PURE__ */ jsxs("button", {
33
+ type: "button",
34
+ onClick: () => setCount((count2) => count2 + 1),
35
+ children: ["count is: ", count]
36
+ })
37
+ }), /* @__PURE__ */ jsxs("p", {
38
+ children: ["Edit ", /* @__PURE__ */ jsx("code", {
39
+ children: "App.jsx"
40
+ }), " and save to test HMR updates."]
41
+ }), /* @__PURE__ */ jsxs("p", {
42
+ children: [/* @__PURE__ */ jsx("a", {
43
+ className: "App-link",
44
+ href: "https://reactjs.org",
45
+ target: "_blank",
46
+ rel: "noopener noreferrer",
47
+ children: "Learn React"
48
+ }), " | ", /* @__PURE__ */ jsx("a", {
49
+ className: "App-link",
50
+ href: "https://vitejs.dev/guide/features.html",
51
+ target: "_blank",
52
+ rel: "noopener noreferrer",
53
+ children: "Vite Docs"
54
+ })]
55
+ })]
56
+ }), /* @__PURE__ */ jsx(Fragment, {
57
+ children: /* @__PURE__ */ jsx(Sub, {})
58
+ })]
59
+ })
60
+ });
61
+ }
62
+ ReactDOM.render(/* @__PURE__ */ jsx(React.StrictMode, {
63
+ children: /* @__PURE__ */ jsx(App, {})
64
+ }), document.getElementById("root"));
@@ -0,0 +1,4 @@
1
+ let array = [1, 2, 3];
2
+
3
+ const multiply = (arr) => arr.map(x => x * 2);
4
+ const newArray = multiply(array);
@@ -0,0 +1,19 @@
1
+ import { readFile } from "fs/promises";
2
+ import { resolve } from "path";
3
+ import { parse } from "acorn";
4
+ import { astIterator } from "./ast-iterator";
5
+
6
+ describe('astIterator', () => {
7
+ it('should iterate through all nodes', async () => {
8
+ let iterationCount = 0;
9
+ const file = await readFile(resolve(__dirname, './__mocks__/sample-code-file.js'), { encoding: 'utf-8' })
10
+ const ast = parse(file, { sourceType: 'module', ecmaVersion: 2022 });
11
+
12
+ for (const node of astIterator(ast)) {
13
+ iterationCount++;
14
+ expect(node).toBeTruthy();
15
+ }
16
+
17
+ expect(iterationCount).toBe(28);
18
+ });
19
+ })
@@ -0,0 +1,27 @@
1
+
2
+ const isNode = (obj: any) => {
3
+ return typeof obj === 'object' &&
4
+ typeof (obj as any)?.end === 'number' &&
5
+ typeof (obj as any)?.start === 'number' &&
6
+ typeof (obj as any)?.type === 'string'
7
+ }
8
+
9
+ export const astIterator = function* (ast: any): IterableIterator<any> {
10
+ if (!ast) { return }
11
+
12
+ for (let key of Object.keys(ast)) {
13
+ // Skip useless keys
14
+ if (['end', 'start', 'type'].includes(key)) { continue; }
15
+
16
+ // If key value is an array, iterate over it
17
+ if (Array.isArray(ast[key])) {
18
+ for (let nodeIndex in ast[key]) {
19
+ yield *astIterator(ast[key][nodeIndex])
20
+ }
21
+ } else if(isNode(ast[key])) {
22
+ yield *astIterator(ast[key])
23
+ }
24
+ }
25
+
26
+ yield ast
27
+ }
@@ -0,0 +1,20 @@
1
+ import { readFile } from "fs/promises";
2
+ import { resolve } from "path";
3
+ import { parse } from "acorn";
4
+ import { astTransformer } from "./ast-transformer";
5
+
6
+ describe('astTransformer', () => {
7
+ it('should iterate through all nodes', async () => {
8
+ let iterationCount = 0;
9
+ const file = await readFile(resolve(__dirname, './__mocks__/sample-code-file.js'), { encoding: 'utf-8' })
10
+ const ast = parse(file, { sourceType: 'module', ecmaVersion: 2022 });
11
+
12
+ const newAst = astTransformer(ast, (node) => {
13
+ iterationCount++;
14
+ expect(node).toBeTruthy();
15
+ })
16
+
17
+ expect(newAst).toBeDefined();
18
+ expect(iterationCount).toBe(28);
19
+ });
20
+ })
@@ -0,0 +1,24 @@
1
+ const isNode = (obj: any) => {
2
+ return typeof obj === 'object' &&
3
+ typeof (obj as any)?.end === 'number' &&
4
+ typeof (obj as any)?.start === 'number' &&
5
+ typeof (obj as any)?.type === 'string'
6
+ }
7
+
8
+ export const astTransformer = (ast: any, callback: Function) => {
9
+ for (let key of Object.keys(ast)) {
10
+ if (['end', 'start', 'type'].includes(key)) { continue; }
11
+
12
+ if (Array.isArray(ast[key])) {
13
+ for (let nodeIndex in ast[key]) {
14
+ ast[key][nodeIndex] = astTransformer(ast[key][nodeIndex], callback)
15
+ }
16
+ } else if(isNode(ast[key])) {
17
+ ast[key] = astTransformer(ast[key], callback)
18
+ }
19
+ }
20
+
21
+ const result = callback(ast);
22
+
23
+ return typeof result !== 'undefined' ? result : ast
24
+ }
@@ -5,18 +5,42 @@ import { generate } from 'escodegen'
5
5
  import { addHashAttributesToJsxTagsAst } from './ast.utils'
6
6
 
7
7
  describe('AST Utils', () => {
8
- it('Should add the attr to the right elements', async () => {
9
- const compiled = await readFile(resolve(__dirname, './__mocks__/compiled-jsx.js'), { encoding: 'utf-8' })
10
- const compiledWithAttr = await readFile(resolve(__dirname, './__mocks__/compiled-jsx-with-attr.js'), { encoding: 'utf-8' })
11
- const ast = parse(compiled, { ecmaVersion: 2021, sourceType: "module" })
12
- const modifiedAst = addHashAttributesToJsxTagsAst(ast, 'data-v-123456')
13
- const modifiedCompiled = generate(modifiedAst, { format: {
14
- indent: {
15
- style: ' ',
16
- },
17
- quotes: 'double',
18
- } })
8
+ beforeEach(() => {
9
+ global.implementation = null
10
+ })
19
11
 
20
- expect(modifiedCompiled).toEqual(compiledWithAttr)
12
+ describe('classic implementation', () => {
13
+ it('Should add the attr to the right elements', async () => {
14
+ const compiled = await readFile(resolve(__dirname, './__mocks__/classic-compiled-jsx.js'), { encoding: 'utf-8' })
15
+ const compiledWithAttr = await readFile(resolve(__dirname, './__mocks__/classic-compiled-jsx-with-attr.js'), { encoding: 'utf-8' })
16
+ const ast = parse(compiled, { ecmaVersion: 2021, sourceType: "module" })
17
+ const modifiedAst = addHashAttributesToJsxTagsAst(ast, 'data-v-123456')
18
+ const modifiedCompiled = generate(modifiedAst, { format: {
19
+ indent: {
20
+ style: ' ',
21
+ },
22
+ quotes: 'double',
23
+ } })
24
+
25
+ expect(modifiedCompiled).toEqual(compiledWithAttr)
26
+ })
27
+ })
28
+
29
+ describe('new implementation', () => {
30
+ it('Should add the attr to the right elements', async () => {
31
+ const compiled = await readFile(resolve(__dirname, './__mocks__/new-compiled-jsx.js'), { encoding: 'utf-8' })
32
+ const compiledWithAttr = await readFile(resolve(__dirname, './__mocks__/new-compiled-jsx-with-attr.js'), { encoding: 'utf-8' })
33
+ const ast = parse(compiled, { ecmaVersion: 2021, sourceType: "module" })
34
+ const modifiedAst = addHashAttributesToJsxTagsAst(ast, 'data-v-123456')
35
+ const modifiedCompiled = generate(modifiedAst, { format: {
36
+ indent: {
37
+ style: ' ',
38
+ },
39
+ quotes: 'double',
40
+ } })
41
+
42
+ expect(modifiedCompiled).toEqual(compiledWithAttr)
43
+ })
21
44
  })
45
+
22
46
  })