rumious-babel-plugin 0.0.1

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.
@@ -0,0 +1,109 @@
1
+
2
+ function generateAppendChild(t, target, child) {
3
+ return t.expressionStatement(
4
+ t.callExpression(t.memberExpression(target, t.identifier("appendChild")), [child])
5
+ );
6
+ }
7
+
8
+ function generateDynamicValueHandle(t, path, target, child, contextName) {
9
+ const tempId = path.scope.generateUidIdentifier("_rumious_dymanic_");
10
+ return [
11
+ t.variableDeclaration("const", [
12
+ t.variableDeclarator(
13
+ tempId,
14
+ t.callExpression(t.memberExpression(t.identifier("document"), t.identifier("createTextNode")), [
15
+ t.stringLiteral(""),
16
+ ])
17
+ ),
18
+ ]),
19
+ generateAppendChild(t,target,tempId),
20
+ t.expressionStatement(
21
+ t.callExpression(t.memberExpression(t.identifier("window.RUMIOUS_JSX"), t.identifier("dynamicValue"), false), [
22
+ target,
23
+ tempId,
24
+ child,
25
+ t.identifier(contextName)
26
+ ])
27
+ ),
28
+ ];
29
+ }
30
+
31
+ function generateCreateText(t, text) {
32
+ return t.callExpression(t.memberExpression(t.identifier("document"), t.identifier("createTextNode")), [
33
+ t.stringLiteral(text),
34
+ ]);
35
+ }
36
+
37
+ function generateCreateEl(t, varName, tagName) {
38
+ return t.variableDeclaration("const", [
39
+ t.variableDeclarator(
40
+ varName,
41
+ t.callExpression(t.memberExpression(t.identifier("document"), t.identifier("createElement")), [
42
+ t.stringLiteral(tagName),
43
+ ])
44
+ ),
45
+ ]);
46
+ }
47
+
48
+ function generateCreateFrag(t, varName) {
49
+ return t.variableDeclaration("const", [
50
+ t.variableDeclarator(
51
+ varName,
52
+ t.callExpression(t.memberExpression(t.identifier("document"), t.identifier("createDocumentFragment")), [
53
+ ])
54
+ ),
55
+ ]);
56
+ }
57
+
58
+
59
+ function generateSetAttr(t, target, name, value) {
60
+ return t.expressionStatement(
61
+ t.callExpression(t.memberExpression(target, t.identifier("setAttribute")), [t.stringLiteral(name), value])
62
+ );
63
+ }
64
+
65
+ function generateSetProps(t, target, key, value) {
66
+ return t.expressionStatement(
67
+ t.assignmentExpression(
68
+ "=",
69
+ t.memberExpression(t.memberExpression(target, t.identifier("props")), typeof key === "string" ? t.stringLiteral(key) : key, true),
70
+ value
71
+ )
72
+ );
73
+ }
74
+
75
+
76
+ function generateAddDirective(t, target, directive, modifier, value, contextName) {
77
+ return t.expressionStatement(
78
+ t.callExpression(t.memberExpression(t.identifier("window.RUMIOUS_JSX"), t.identifier("addDirective"), false), [
79
+ target,
80
+ t.identifier(contextName),
81
+ t.stringLiteral(directive),
82
+ t.stringLiteral(modifier),
83
+ value,
84
+ ])
85
+ );
86
+ }
87
+
88
+ function generateCreateComponent(t, varName, component){
89
+ return t.variableDeclaration("const", [
90
+ t.variableDeclarator(
91
+ varName,
92
+ t.callExpression(t.memberExpression(t.identifier("window.RUMIOUS_JSX"), t.identifier("createComponent")), [
93
+ component,
94
+ ])
95
+ ),
96
+ ]);
97
+ }
98
+
99
+ module.exports = {
100
+ generateAppendChild,
101
+ generateDynamicValueHandle,
102
+ generateCreateText,
103
+ generateCreateEl,
104
+ generateSetAttr,
105
+ generateSetProps,
106
+ generateAddDirective,
107
+ generateCreateComponent,
108
+ generateCreateFrag
109
+ };
package/index.js ADDED
@@ -0,0 +1,148 @@
1
+ const { declare } = require('@babel/helper-plugin-utils');
2
+ const { randomName } = require('./utils');
3
+ const {
4
+ generateCreateEl,
5
+ generateAppendChild,
6
+ generateDynamicValueHandle,
7
+ generateCreateText,
8
+ generateCreateComponent,
9
+ generateCreateFrag
10
+ } = require('./astGenerators');
11
+ const {
12
+ processAttributes,
13
+ processProps,
14
+ jsxNameToExpression,
15
+ } = require('./jsxProcessor');
16
+
17
+ function attachSourceMeta(t, elId, node, filename) {
18
+ if (process.env.NODE_ENV !== 'development' || !node.loc) return [];
19
+
20
+ const { line, column } = node.loc.start;
21
+
22
+ return [
23
+ t.expressionStatement(
24
+ t.assignmentExpression(
25
+ "=",
26
+ t.memberExpression(elId, t.identifier("_source")),
27
+ t.objectExpression([
28
+ t.objectProperty(t.identifier("fileName"), t.stringLiteral(filename)),
29
+ t.objectProperty(t.identifier("line"), t.numericLiteral(line)),
30
+ t.objectProperty(t.identifier("column"), t.numericLiteral(column)),
31
+ ])
32
+ )
33
+ )
34
+ ];
35
+ }
36
+
37
+ function transformJSXElement(t, path, element, contextName, filename) {
38
+ const tagName = element.openingElement ? element.openingElement.name : null;
39
+ const isComponent = tagName && (t.isJSXMemberExpression(tagName) || /^[A-Z]/.test(tagName.name));
40
+ const isFragment = isComponent && tagName.name === "Fragment";
41
+ const elId = isFragment ? path.scope.generateUidIdentifier("rumious_frag") : path.scope.generateUidIdentifier("rumious_el");
42
+ const statements = [];
43
+
44
+ if (isFragment) {
45
+ statements.push(generateCreateFrag(t, elId));
46
+ statements.push(...attachSourceMeta(t, elId, element, filename));
47
+
48
+ if (!element.children || element.children.length === 0) {
49
+ return { elId: elId, statements };
50
+ }
51
+
52
+ for (const child of element.children) {
53
+ if (t.isJSXText(child)) {
54
+ const text = child.value;
55
+ if (text) {
56
+ const textNode = generateCreateText(t, text);
57
+ statements.push(generateAppendChild(t, elId, textNode));
58
+ }
59
+ } else if (t.isJSXExpressionContainer(child)) {
60
+ if (child.expression.type !== "NullLiteral" && child.expression.type !== "UndefinedLiteral") {
61
+ statements.push(...generateDynamicValueHandle(t, path, elId, child.expression, contextName));
62
+ }
63
+ } else if (t.isJSXElement(child) || t.isJSXFragment(child)) {
64
+ const nested = transformJSXElement(t, path, child, contextName, filename);
65
+ statements.push(...nested.statements);
66
+ statements.push(generateAppendChild(t, elId, nested.elId));
67
+ }
68
+ }
69
+ return { elId: elId, statements };
70
+ }
71
+
72
+ if (isComponent) {
73
+ statements.push(generateCreateComponent(t, elId, jsxNameToExpression(t, tagName)));
74
+ statements.push(...attachSourceMeta(t, elId, element, filename));
75
+
76
+ statements.push(
77
+ t.expressionStatement(
78
+ t.callExpression(t.memberExpression(elId, t.identifier("setup")), [t.identifier(contextName), jsxNameToExpression(t, tagName)])
79
+ )
80
+ );
81
+ statements.push(...processProps(t, elId, element.openingElement.attributes));
82
+ } else {
83
+ statements.push(generateCreateEl(t, elId, tagName ? tagName.name : "div"));
84
+ statements.push(...attachSourceMeta(t, elId, element, filename));
85
+ statements.push(...processAttributes(t, elId, element.openingElement.attributes, contextName));
86
+ }
87
+
88
+ for (const child of element.children) {
89
+ if (t.isJSXText(child)) {
90
+ const text = child.value;
91
+ if (text) {
92
+ const textNode = generateCreateText(t, text);
93
+ statements.push(generateAppendChild(t, elId, textNode));
94
+ }
95
+ } else if (t.isJSXExpressionContainer(child)) {
96
+ if (child.expression.type !== "NullLiteral" && child.expression.type !== "UndefinedLiteral") {
97
+ statements.push(...generateDynamicValueHandle(t, path, elId, child.expression, contextName));
98
+ }
99
+ } else if (t.isJSXElement(child) || t.isJSXFragment(child)) {
100
+ const nested = transformJSXElement(t, path, child, contextName, filename);
101
+ statements.push(...nested.statements);
102
+ statements.push(generateAppendChild(t, elId, nested.elId));
103
+ }
104
+ }
105
+
106
+ return { elId, statements };
107
+ }
108
+
109
+ module.exports = declare((api) => {
110
+ api.assertVersion(7);
111
+ const t = api.types;
112
+
113
+ return {
114
+ name: "rumious-babel-plugin",
115
+ visitor: {
116
+ JSXElement(path) {
117
+ const rootName = randomName("rumious_root");
118
+ const contextName = randomName("rumious_ctx");
119
+ const filename = path.hub.file.opts.filename || "unknown_file";
120
+
121
+ const { elId, statements } = transformJSXElement(t, path, path.node, contextName, filename);
122
+
123
+ statements.push(
124
+ t.expressionStatement(
125
+ t.callExpression(t.memberExpression(t.identifier(rootName), t.identifier("appendChild")), [elId])
126
+ )
127
+ );
128
+ statements.push(t.returnStatement(t.identifier(rootName)));
129
+
130
+ const fn = t.functionExpression(
131
+ null,
132
+ [t.identifier(rootName), t.identifier(contextName)],
133
+ t.blockStatement(statements.map((s) => t.cloneNode(s, true)))
134
+ );
135
+
136
+ const callTemplate = t.callExpression(
137
+ t.memberExpression(
138
+ t.memberExpression(t.identifier("window"), t.identifier("RUMIOUS_JSX")),
139
+ t.identifier("template")
140
+ ),
141
+ [fn]
142
+ );
143
+
144
+ path.replaceWith(callTemplate);
145
+ },
146
+ },
147
+ };
148
+ });
@@ -0,0 +1,116 @@
1
+ const {
2
+ generateAddDirective,
3
+ generateSetAttr,
4
+ generateSetProps,
5
+ } = require('./astGenerators');
6
+
7
+ function processDirective(t, target, attr, directive, modifier, contextName) {
8
+ const value = attr.value ?
9
+ t.isStringLiteral(attr.value) ?
10
+ attr.value :
11
+ t.isJSXExpressionContainer(attr.value) ?
12
+ attr.value.expression :
13
+ t.stringLiteral("") :
14
+ t.booleanLiteral(true);
15
+ return generateAddDirective(t, target, directive, modifier, value, contextName);
16
+ }
17
+
18
+ function processNamespace(t, target, attr, contextName) {
19
+ const name = attr.name.name.name;
20
+ const namespace = attr.name.namespace.name;
21
+ if (["bind", "on"].includes(namespace)) {
22
+ return processDirective(t, target, attr, namespace, name, contextName);
23
+ }
24
+ const value = attr.value ?
25
+ t.isStringLiteral(attr.value) ?
26
+ attr.value :
27
+ t.isJSXExpressionContainer(attr.value) ?
28
+ attr.value.expression :
29
+ t.stringLiteral("") :
30
+ t.booleanLiteral(true);
31
+ return generateSetAttr(t, target, t.binaryExpression("+", t.stringLiteral(`${namespace}:`), t.stringLiteral(name)), value);
32
+ }
33
+
34
+ function processAttributes(t, elId, attributes, contextName) {
35
+ const statements = [];
36
+ const standaloneDirectives = ["ref", "model","inject"];
37
+
38
+ for (const attr of attributes) {
39
+ if (t.isJSXAttribute(attr) && !t.isJSXNamespacedName(attr.name)) {
40
+ const name = attr.name.name;
41
+ const value = attr.value ?
42
+ t.isStringLiteral(attr.value) ?
43
+ attr.value :
44
+ t.isJSXExpressionContainer(attr.value) ?
45
+ attr.value.expression :
46
+ t.stringLiteral("") :
47
+ t.booleanLiteral(true);
48
+ if (standaloneDirectives.includes(name)) {
49
+ statements.push(processDirective(t, elId, attr, name, "standalone", contextName));
50
+ } else {
51
+ statements.push(generateSetAttr(t, elId, name, value));
52
+ }
53
+ } else if (t.isJSXAttribute(attr) && t.isJSXNamespacedName(attr.name)) {
54
+ statements.push(processNamespace(t, elId, attr, contextName));
55
+ } else if (t.isJSXSpreadAttribute(attr)) {
56
+ const props = attr.argument;
57
+ const key = t.identifier("key");
58
+ const value = t.memberExpression(props, key, true);
59
+ statements.push(
60
+ t.forInStatement(
61
+ t.variableDeclaration("let", [t.variableDeclarator(key)]),
62
+ props,
63
+ t.blockStatement([
64
+ t.expressionStatement(t.callExpression(t.memberExpression(elId, t.identifier("setAttribute")), [key, value])),
65
+ ])
66
+ )
67
+ );
68
+ }
69
+ }
70
+ return statements;
71
+ }
72
+
73
+ function processProps(t, elId, props) {
74
+ const statements = [];
75
+ for (let prop of props) {
76
+ if (t.isJSXAttribute(prop)) {
77
+ const name = prop.name.name;
78
+ const value = prop.value ?
79
+ t.isStringLiteral(prop.value) ?
80
+ prop.value :
81
+ t.isJSXExpressionContainer(prop.value) ?
82
+ prop.value.expression :
83
+ t.stringLiteral("") :
84
+ t.booleanLiteral(true);
85
+ statements.push(generateSetProps(t, elId, name, value));
86
+ } else if (t.isJSXSpreadAttribute(prop)) {
87
+ const propExpr = prop.argument;
88
+ const key = t.identifier("key");
89
+ const value = t.memberExpression(propExpr, key, true);
90
+ statements.push(
91
+ t.forInStatement(
92
+ t.variableDeclaration("let", [t.variableDeclarator(key)]),
93
+ propExpr,
94
+ t.blockStatement([generateSetProps(t, elId, key, value)])
95
+ )
96
+ );
97
+ }
98
+ }
99
+ return statements;
100
+ }
101
+
102
+ function jsxNameToExpression(t, name) {
103
+ if (t.isJSXIdentifier(name)) return t.identifier(name.name);
104
+ if (t.isJSXMemberExpression(name)) {
105
+ return t.memberExpression(jsxNameToExpression(t, name.object), t.identifier(name.property.name));
106
+ }
107
+ return t.identifier("unknown");
108
+ }
109
+
110
+ module.exports = {
111
+ processDirective,
112
+ processNamespace,
113
+ processAttributes,
114
+ processProps,
115
+ jsxNameToExpression,
116
+ };
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "rumious-babel-plugin",
3
+ "version": "0.0.1",
4
+ "description":"Babel plugin for Rumious ",
5
+ "main": "./index.js",
6
+ "keywords": [
7
+ "rumious",
8
+ "core",
9
+ "framework",
10
+ "babel",
11
+ "plugin",
12
+ "babel-plugin"
13
+ ],
14
+ "scripts": {
15
+ },
16
+ "author": "smtdfc",
17
+ "license": "MIT",
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "https://github.com/smtdfc/rumious"
21
+ },
22
+ "bugs": {
23
+ "url": "https://github.com/smtdfc/rumious/issues"
24
+ },
25
+ "homepage": "https://github.com/smtdfc/rumious#readme",
26
+ "files": [
27
+ "index.js",
28
+ "jsxProcessor.js",
29
+ "utils.js",
30
+ "astGenerators.js",
31
+ "README.md"
32
+ ],
33
+ "engines": {
34
+ "node": ">=16"
35
+ },
36
+ "dependencies": {
37
+ }
38
+ }
package/utils.js ADDED
@@ -0,0 +1,6 @@
1
+
2
+ function randomName(prefix) {
3
+ return `_${prefix}_${Math.random().toString(16).slice(2, 10)}`;
4
+ }
5
+
6
+ module.exports = { randomName };