chispa 0.1.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.
- package/README.md +108 -0
- package/dist/html-compiler/cli.d.ts +1 -0
- package/dist/html-compiler/cli.js +300 -0
- package/dist/html-compiler/cli.js.map +1 -0
- package/dist/html-compiler/vite-plugin.d.ts +14 -0
- package/dist/html-compiler/vite-plugin.js +335 -0
- package/dist/html-compiler/vite-plugin.js.map +1 -0
- package/dist/index.d.ts +150 -0
- package/dist/index.js +551 -0
- package/dist/index.js.map +1 -0
- package/package.json +47 -0
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
// src/html-compiler/html-compiler.ts
|
|
2
|
+
import { JSDOM } from "jsdom";
|
|
3
|
+
var VOID_ELEMENTS = ["area", "base", "br", "hr", "img", "input", "link", "meta", "param", "keygen", "source"];
|
|
4
|
+
var SVG_NAMESPACE = "http://www.w3.org/2000/svg";
|
|
5
|
+
var HtmlCompiler = class _HtmlCompiler {
|
|
6
|
+
constructor(htmlContent) {
|
|
7
|
+
this.components = {};
|
|
8
|
+
this.stack = ["fragment"];
|
|
9
|
+
this.componentsItems = {};
|
|
10
|
+
this.componentsTags = {};
|
|
11
|
+
this.isSvg = {};
|
|
12
|
+
this.inSvgContext = 0;
|
|
13
|
+
const dom = new JSDOM(htmlContent);
|
|
14
|
+
this.htmlDocument = dom.window.document;
|
|
15
|
+
}
|
|
16
|
+
static camelize(str) {
|
|
17
|
+
if (str.startsWith("--")) {
|
|
18
|
+
return str;
|
|
19
|
+
}
|
|
20
|
+
const arr = str.split("-");
|
|
21
|
+
let camelized = "";
|
|
22
|
+
arr.forEach((v, i) => {
|
|
23
|
+
camelized += i === 0 ? v : v.charAt(0).toUpperCase() + v.slice(1);
|
|
24
|
+
});
|
|
25
|
+
return camelized;
|
|
26
|
+
}
|
|
27
|
+
static parseStyle(cssCode) {
|
|
28
|
+
let out = "{";
|
|
29
|
+
const styles = cssCode.split(";");
|
|
30
|
+
styles.forEach((line) => {
|
|
31
|
+
const parts = line.split(":");
|
|
32
|
+
if (parts.length !== 2) return;
|
|
33
|
+
const prop = _HtmlCompiler.camelize(parts[0].trim());
|
|
34
|
+
out += ` ${prop}: '${parts[1].trim()}',`;
|
|
35
|
+
});
|
|
36
|
+
out += "}";
|
|
37
|
+
return out;
|
|
38
|
+
}
|
|
39
|
+
makeClassAttr(classAttr, isComponent) {
|
|
40
|
+
const tplClasses = (classAttr || "").split(" ");
|
|
41
|
+
let finalClass = "";
|
|
42
|
+
tplClasses.forEach((tplClass) => {
|
|
43
|
+
if (!tplClass.startsWith("-tpl--")) {
|
|
44
|
+
finalClass += tplClass + " ";
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
finalClass = finalClass.trim();
|
|
48
|
+
if (isComponent) {
|
|
49
|
+
finalClass = `buildClass('${finalClass}', props.addClass, props.classes)`;
|
|
50
|
+
return ` 'class': ${finalClass}, `;
|
|
51
|
+
} else {
|
|
52
|
+
return ` 'class': "${finalClass}", `;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
getHtmlNodeAttrs(domNode, isComponent) {
|
|
56
|
+
let attrsHtml = "{";
|
|
57
|
+
attrsHtml += this.makeClassAttr(domNode.getAttribute("class"), isComponent);
|
|
58
|
+
Array.from(domNode.attributes).forEach((attr) => {
|
|
59
|
+
const attrName = attr.name;
|
|
60
|
+
let attrValue = attr.value;
|
|
61
|
+
if (attrName === "data-cb") return;
|
|
62
|
+
if (attrName === "class") return;
|
|
63
|
+
attrValue = attrValue.replace(/\n/g, " ").replace(/"/g, '\\"');
|
|
64
|
+
if (attrName === "style") {
|
|
65
|
+
attrsHtml += ` '${attrName}': "${attrValue}", `;
|
|
66
|
+
} else {
|
|
67
|
+
attrsHtml += ` '${attrName}': "${attrValue}", `;
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
attrsHtml += "}";
|
|
71
|
+
return attrsHtml;
|
|
72
|
+
}
|
|
73
|
+
buildTsForNode(domNode, isComponent = false) {
|
|
74
|
+
let htmlNodeCode = "";
|
|
75
|
+
if (domNode.nodeType === 1) {
|
|
76
|
+
const element = domNode;
|
|
77
|
+
let tagName = element.tagName;
|
|
78
|
+
if (tagName === "svg") {
|
|
79
|
+
this.inSvgContext++;
|
|
80
|
+
}
|
|
81
|
+
let cbid = element.getAttribute("data-cb");
|
|
82
|
+
if (cbid) {
|
|
83
|
+
const currComp = this.stack[0];
|
|
84
|
+
element.removeAttribute("data-cb");
|
|
85
|
+
cbid = _HtmlCompiler.camelize(cbid);
|
|
86
|
+
if (!this.componentsItems[currComp]) {
|
|
87
|
+
this.componentsItems[currComp] = [];
|
|
88
|
+
}
|
|
89
|
+
this.componentsItems[currComp].push(cbid);
|
|
90
|
+
this.stack.unshift(cbid);
|
|
91
|
+
this.components[cbid] = this.buildTsForNode(element, true);
|
|
92
|
+
this.componentsTags[cbid] = element.tagName;
|
|
93
|
+
this.isSvg[cbid] = this.inSvgContext > 0;
|
|
94
|
+
this.stack.shift();
|
|
95
|
+
if (currComp === "fragment") {
|
|
96
|
+
htmlNodeCode += `getItem(Components, props, '${cbid}')`;
|
|
97
|
+
} else {
|
|
98
|
+
htmlNodeCode += `getItem(Components, props.items, '${cbid}')`;
|
|
99
|
+
}
|
|
100
|
+
} else {
|
|
101
|
+
const attrs = this.getHtmlNodeAttrs(element, isComponent);
|
|
102
|
+
if (!this.inSvgContext) {
|
|
103
|
+
tagName = tagName.toLowerCase();
|
|
104
|
+
htmlNodeCode += `(() => { const node = document.createElement('${tagName}');
|
|
105
|
+
`;
|
|
106
|
+
} else {
|
|
107
|
+
htmlNodeCode += `(() => { const node = document.createElementNS('${SVG_NAMESPACE}', '${tagName}');
|
|
108
|
+
`;
|
|
109
|
+
}
|
|
110
|
+
htmlNodeCode += `setAttributes(node, ${attrs});
|
|
111
|
+
`;
|
|
112
|
+
if (isComponent) {
|
|
113
|
+
htmlNodeCode += `setProps(node, getValidProps(props));
|
|
114
|
+
`;
|
|
115
|
+
}
|
|
116
|
+
let subTs = "";
|
|
117
|
+
element.childNodes.forEach((child) => {
|
|
118
|
+
const chCode = this.buildTsForNode(child);
|
|
119
|
+
if (chCode) {
|
|
120
|
+
subTs += `appendChild(node, ${chCode});
|
|
121
|
+
`;
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
if (!VOID_ELEMENTS.includes(tagName.toLowerCase())) {
|
|
125
|
+
if (isComponent) {
|
|
126
|
+
htmlNodeCode += `
|
|
127
|
+
if (props.inner === null) {
|
|
128
|
+
node.innerHTML = '';
|
|
129
|
+
} else if (props.inner !== undefined) {
|
|
130
|
+
node.innerHTML = '';
|
|
131
|
+
appendChild(node, props.inner);
|
|
132
|
+
} else {
|
|
133
|
+
${subTs}
|
|
134
|
+
}
|
|
135
|
+
`;
|
|
136
|
+
} else {
|
|
137
|
+
htmlNodeCode += subTs;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
if (isComponent) {
|
|
141
|
+
htmlNodeCode += `if (typeof props._ref === 'function') props._ref(node);
|
|
142
|
+
`;
|
|
143
|
+
}
|
|
144
|
+
htmlNodeCode += `return node;})()`;
|
|
145
|
+
if (tagName === "svg") {
|
|
146
|
+
this.inSvgContext--;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
} else if (domNode.nodeType === 3) {
|
|
150
|
+
const textNode = domNode;
|
|
151
|
+
const parent = textNode.parentNode;
|
|
152
|
+
const parentTag = parent ? parent.tagName.toLowerCase() : "";
|
|
153
|
+
const mustOmit = ["table", "thead", "tbody", "tfoot", "tr"].includes(parentTag);
|
|
154
|
+
if (!mustOmit && textNode.textContent) {
|
|
155
|
+
if (textNode.textContent.trim() === "") {
|
|
156
|
+
if (textNode.textContent.length > 0) {
|
|
157
|
+
htmlNodeCode += `document.createTextNode(' ')`;
|
|
158
|
+
}
|
|
159
|
+
} else {
|
|
160
|
+
htmlNodeCode = `document.createTextNode(${JSON.stringify(textNode.textContent)})`;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return htmlNodeCode.trim();
|
|
165
|
+
}
|
|
166
|
+
static getPropsTypename(cbid) {
|
|
167
|
+
return "T" + cbid.charAt(0).toUpperCase() + cbid.slice(1) + "Props";
|
|
168
|
+
}
|
|
169
|
+
wrapFnComponent(cbid, jsx) {
|
|
170
|
+
const typename = _HtmlCompiler.getPropsTypename(cbid);
|
|
171
|
+
return `(props: ${typename}) => {
|
|
172
|
+
return(${jsx});
|
|
173
|
+
}`;
|
|
174
|
+
}
|
|
175
|
+
createAllComponents() {
|
|
176
|
+
const body = this.htmlDocument.querySelector("body");
|
|
177
|
+
if (!body) throw new Error("Not valid HTML");
|
|
178
|
+
let rendererJsx = "(() => { const fragment = document.createDocumentFragment();\n";
|
|
179
|
+
body.childNodes.forEach((child) => {
|
|
180
|
+
const chCode = this.buildTsForNode(child);
|
|
181
|
+
if (chCode) {
|
|
182
|
+
rendererJsx += `appendChild(fragment, ${chCode});
|
|
183
|
+
`;
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
rendererJsx += "return fragment;\n";
|
|
187
|
+
rendererJsx += "})()";
|
|
188
|
+
this.components["fragment"] = rendererJsx;
|
|
189
|
+
}
|
|
190
|
+
getTypedef(cbid) {
|
|
191
|
+
const items = this.componentsItems[cbid] || [];
|
|
192
|
+
let itemsType = "{\n";
|
|
193
|
+
items.forEach((itemCbid) => {
|
|
194
|
+
const itemTypename = _HtmlCompiler.getPropsTypename(itemCbid);
|
|
195
|
+
itemsType += `${itemCbid}?: ${itemTypename} | TContent;
|
|
196
|
+
`;
|
|
197
|
+
});
|
|
198
|
+
itemsType += "}\n";
|
|
199
|
+
const typename = _HtmlCompiler.getPropsTypename(cbid);
|
|
200
|
+
if (cbid === "fragment") {
|
|
201
|
+
return `interface ${typename} ${itemsType}`;
|
|
202
|
+
} else {
|
|
203
|
+
const tagname = this.componentsTags[cbid];
|
|
204
|
+
if (this.isSvg[cbid]) {
|
|
205
|
+
return `type ${typename} = TItemBuilderProps<SVGElementTagNameMap['${tagname}'], ${itemsType}>;`;
|
|
206
|
+
} else {
|
|
207
|
+
return `type ${typename} = TItemBuilderProps<HTMLElementTagNameMap['${tagname.toLowerCase()}'], ${itemsType}>;`;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
compile() {
|
|
212
|
+
this.createAllComponents();
|
|
213
|
+
let componentsClasses = "";
|
|
214
|
+
let typedefs = "";
|
|
215
|
+
for (const [cbid, compJsx] of Object.entries(this.components)) {
|
|
216
|
+
typedefs += this.getTypedef(cbid) + "\n";
|
|
217
|
+
componentsClasses += `${cbid}: ${this.wrapFnComponent(cbid, compJsx)},
|
|
218
|
+
`;
|
|
219
|
+
}
|
|
220
|
+
const jsOutput = `
|
|
221
|
+
import { appendChild, getItem, getValidProps, buildClass, setAttributes, setProps, TContent, TItemBuilderProps } from 'chispa';
|
|
222
|
+
|
|
223
|
+
const SVG_NS = 'http://www.w3.org/2000/svg';
|
|
224
|
+
|
|
225
|
+
const Components = {
|
|
226
|
+
${componentsClasses}
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
export default Components;
|
|
230
|
+
`;
|
|
231
|
+
const dtsOutput = `
|
|
232
|
+
import { TContent, TItemBuilderProps } from 'chispa';
|
|
233
|
+
|
|
234
|
+
${typedefs}
|
|
235
|
+
|
|
236
|
+
declare const Components: {
|
|
237
|
+
${Object.keys(this.components).map((cbid) => {
|
|
238
|
+
const typename = _HtmlCompiler.getPropsTypename(cbid);
|
|
239
|
+
return `${cbid}: (props: ${typename}) => Node | DocumentFragment;`;
|
|
240
|
+
}).join("\n")}
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
export default Components;
|
|
244
|
+
`;
|
|
245
|
+
return { js: jsOutput, dts: dtsOutput };
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
// src/html-compiler/generator.ts
|
|
250
|
+
import * as fs from "fs";
|
|
251
|
+
import * as path from "path";
|
|
252
|
+
function generateTypes(filePath, content, rootDir) {
|
|
253
|
+
try {
|
|
254
|
+
const compiler = new HtmlCompiler(content);
|
|
255
|
+
const { dts } = compiler.compile();
|
|
256
|
+
const outDir = path.join(rootDir, ".chispa/types");
|
|
257
|
+
const relativePath = path.relative(rootDir, filePath);
|
|
258
|
+
const targetPath = path.join(outDir, relativePath + ".d.ts");
|
|
259
|
+
const targetDir = path.dirname(targetPath);
|
|
260
|
+
if (!fs.existsSync(targetDir)) {
|
|
261
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
262
|
+
}
|
|
263
|
+
fs.writeFileSync(targetPath, dts);
|
|
264
|
+
} catch (e) {
|
|
265
|
+
console.error(`[chispa] Error generating types for ${filePath}`, e);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
function findAndCompileHtmlFiles(dir, rootDir) {
|
|
269
|
+
if (!fs.existsSync(dir)) return;
|
|
270
|
+
const files = fs.readdirSync(dir);
|
|
271
|
+
files.forEach((file) => {
|
|
272
|
+
const fullPath = path.join(dir, file);
|
|
273
|
+
if (fullPath === path.join(rootDir, "index.html")) return;
|
|
274
|
+
if (fs.statSync(fullPath).isDirectory()) {
|
|
275
|
+
if (file !== "node_modules" && file !== ".git" && file !== "dist" && file !== ".chispa") {
|
|
276
|
+
findAndCompileHtmlFiles(fullPath, rootDir);
|
|
277
|
+
}
|
|
278
|
+
} else if (file.endsWith(".html")) {
|
|
279
|
+
console.log("Generating types for", fullPath);
|
|
280
|
+
const content = fs.readFileSync(fullPath, "utf-8");
|
|
281
|
+
generateTypes(fullPath, content, rootDir);
|
|
282
|
+
}
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// src/html-compiler/vite-plugin.ts
|
|
287
|
+
import * as fs2 from "fs";
|
|
288
|
+
function chispaHtmlPlugin() {
|
|
289
|
+
let rootDir = process.cwd();
|
|
290
|
+
return {
|
|
291
|
+
name: "chispa-html",
|
|
292
|
+
enforce: "pre",
|
|
293
|
+
configResolved(config) {
|
|
294
|
+
rootDir = config.root;
|
|
295
|
+
},
|
|
296
|
+
buildStart() {
|
|
297
|
+
findAndCompileHtmlFiles(rootDir, rootDir);
|
|
298
|
+
},
|
|
299
|
+
handleHotUpdate(ctx) {
|
|
300
|
+
if (ctx.file.endsWith(".html")) {
|
|
301
|
+
Promise.resolve(ctx.read()).then((content) => generateTypes(ctx.file, content, rootDir));
|
|
302
|
+
}
|
|
303
|
+
},
|
|
304
|
+
async resolveId(source, importer, options) {
|
|
305
|
+
if (source.endsWith(".html") && importer) {
|
|
306
|
+
const resolution = await this.resolve(source, importer, { skipSelf: true, ...options });
|
|
307
|
+
if (resolution && !resolution.external) {
|
|
308
|
+
return resolution.id + ".chispa.ts";
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
return null;
|
|
312
|
+
},
|
|
313
|
+
load(id) {
|
|
314
|
+
if (id.endsWith(".html.chispa.ts")) {
|
|
315
|
+
const realId = id.replace(".chispa.ts", "");
|
|
316
|
+
try {
|
|
317
|
+
const content = fs2.readFileSync(realId, "utf-8");
|
|
318
|
+
if (content.includes("<!DOCTYPE html>") || content.includes("<html")) {
|
|
319
|
+
return null;
|
|
320
|
+
}
|
|
321
|
+
const compiler = new HtmlCompiler(content);
|
|
322
|
+
const { js } = compiler.compile();
|
|
323
|
+
generateTypes(realId, content, rootDir);
|
|
324
|
+
return js;
|
|
325
|
+
} catch (e) {
|
|
326
|
+
return null;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
export {
|
|
333
|
+
chispaHtmlPlugin
|
|
334
|
+
};
|
|
335
|
+
//# sourceMappingURL=vite-plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/html-compiler/html-compiler.ts","../../src/html-compiler/generator.ts","../../src/html-compiler/vite-plugin.ts"],"sourcesContent":["import { JSDOM } from 'jsdom';\n\nconst VOID_ELEMENTS = ['area', 'base', 'br', 'hr', 'img', 'input', 'link', 'meta', 'param', 'keygen', 'source'];\n\nconst SVG_NAMESPACE = 'http://www.w3.org/2000/svg';\n\nexport class HtmlCompiler {\n\tprivate components: Record<string, string> = {};\n\tprivate stack: string[] = ['fragment'];\n\tprivate componentsItems: Record<string, string[]> = {};\n\tprivate componentsTags: Record<string, string> = {};\n\tprivate isSvg: Record<string, boolean> = {};\n\tprivate inSvgContext = 0;\n\tprivate htmlDocument: Document;\n\n\tconstructor(htmlContent: string) {\n\t\tconst dom = new JSDOM(htmlContent);\n\t\tthis.htmlDocument = dom.window.document;\n\t}\n\n\tprivate static camelize(str: string): string {\n\t\tif (str.startsWith('--')) {\n\t\t\treturn str;\n\t\t}\n\t\tconst arr = str.split('-');\n\t\tlet camelized = '';\n\t\tarr.forEach((v, i) => {\n\t\t\tcamelized += i === 0 ? v : v.charAt(0).toUpperCase() + v.slice(1);\n\t\t});\n\t\treturn camelized;\n\t}\n\n\tprivate static parseStyle(cssCode: string): string {\n\t\tlet out = '{';\n\t\tconst styles = cssCode.split(';');\n\t\tstyles.forEach((line) => {\n\t\t\tconst parts = line.split(':');\n\t\t\tif (parts.length !== 2) return;\n\t\t\tconst prop = HtmlCompiler.camelize(parts[0].trim());\n\t\t\tout += ` ${prop}: '${parts[1].trim()}',`;\n\t\t});\n\t\tout += '}';\n\t\treturn out;\n\t}\n\n\tprivate makeClassAttr(classAttr: string | null, isComponent: boolean): string {\n\t\tconst tplClasses = (classAttr || '').split(' ');\n\t\tlet finalClass = '';\n\n\t\ttplClasses.forEach((tplClass) => {\n\t\t\tif (!tplClass.startsWith('-tpl--')) {\n\t\t\t\tfinalClass += tplClass + ' ';\n\t\t\t}\n\t\t});\n\n\t\tfinalClass = finalClass.trim();\n\n\t\tif (isComponent) {\n\t\t\tfinalClass = `buildClass('${finalClass}', props.addClass, props.classes)`;\n\t\t\treturn ` 'class': ${finalClass}, `;\n\t\t} else {\n\t\t\treturn ` 'class': \"${finalClass}\", `;\n\t\t}\n\t}\n\n\tprivate getHtmlNodeAttrs(domNode: Element, isComponent: boolean): string {\n\t\tlet attrsHtml = '{';\n\t\tattrsHtml += this.makeClassAttr(domNode.getAttribute('class'), isComponent);\n\n\t\tArray.from(domNode.attributes).forEach((attr) => {\n\t\t\tconst attrName = attr.name;\n\t\t\tlet attrValue = attr.value;\n\n\t\t\tif (attrName === 'data-cb') return;\n\t\t\tif (attrName === 'class') return;\n\n\t\t\tattrValue = attrValue.replace(/\\n/g, ' ').replace(/\"/g, '\\\\\"');\n\n\t\t\t// Simplified logic compared to PHP which had cbt.prefixize... calls\n\t\t\t// Assuming we just output the value for now as I don't see cbt implementation here\n\t\t\t// The PHP code imported CoreBuilderTools but here we might not have it.\n\t\t\t// The user's example output imports from 'chispa'.\n\t\t\t// I will stick to simple string values for now unless I see cbt in chispa.\n\n\t\t\tif (attrName === 'style') {\n\t\t\t\t// PHP called cbt.prefixizeStyle, but also had parse_style static method.\n\t\t\t\t// Wait, the PHP code used cbt.prefixizeStyle inside get_html_node_attrs.\n\t\t\t\t// But parse_style was defined but not used in the snippet I read?\n\t\t\t\t// Ah, I should check if I should use parseStyle or just output string.\n\t\t\t\t// The PHP code: $attrs_html .= \" '$attr_name': cbt.prefixizeStyle('$attr_value'), \";\n\t\t\t\t// If cbt is a runtime helper, I should output the call.\n\t\t\t\t// But wait, the generated code imports CoreBuilderTools.\n\t\t\t\t// Does 'chispa' export CoreBuilderTools?\n\t\t\t\t// src/index.ts does NOT export CoreBuilderTools.\n\t\t\t\t// It exports appendChild, getItem, etc.\n\t\t\t\t// Maybe I should just output the string for now.\n\t\t\t\tattrsHtml += ` '${attrName}': \"${attrValue}\", `;\n\t\t\t} else {\n\t\t\t\tattrsHtml += ` '${attrName}': \"${attrValue}\", `;\n\t\t\t}\n\t\t});\n\n\t\tattrsHtml += '}';\n\t\treturn attrsHtml;\n\t}\n\n\tprivate buildTsForNode(domNode: Node, isComponent = false): string {\n\t\tlet htmlNodeCode = '';\n\n\t\tif (domNode.nodeType === 1) {\n\t\t\t// Element\n\t\t\tconst element = domNode as Element;\n\t\t\tlet tagName = element.tagName;\n\n\t\t\tif (tagName === 'svg') {\n\t\t\t\tthis.inSvgContext++;\n\t\t\t}\n\n\t\t\tlet cbid = element.getAttribute('data-cb');\n\n\t\t\tif (cbid) {\n\t\t\t\tconst currComp = this.stack[0];\n\t\t\t\telement.removeAttribute('data-cb');\n\t\t\t\tcbid = HtmlCompiler.camelize(cbid);\n\n\t\t\t\tif (!this.componentsItems[currComp]) {\n\t\t\t\t\tthis.componentsItems[currComp] = [];\n\t\t\t\t}\n\n\t\t\t\tthis.componentsItems[currComp].push(cbid);\n\t\t\t\tthis.stack.unshift(cbid);\n\t\t\t\tthis.components[cbid] = this.buildTsForNode(element, true);\n\t\t\t\tthis.componentsTags[cbid] = element.tagName;\n\t\t\t\tthis.isSvg[cbid] = this.inSvgContext > 0;\n\t\t\t\tthis.stack.shift();\n\n\t\t\t\tif (currComp === 'fragment') {\n\t\t\t\t\thtmlNodeCode += `getItem(Components, props, '${cbid}')`;\n\t\t\t\t} else {\n\t\t\t\t\thtmlNodeCode += `getItem(Components, props.items, '${cbid}')`;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconst attrs = this.getHtmlNodeAttrs(element, isComponent);\n\n\t\t\t\tif (!this.inSvgContext) {\n\t\t\t\t\ttagName = tagName.toLowerCase();\n\t\t\t\t\thtmlNodeCode += `(() => { const node = document.createElement('${tagName}');\\n`;\n\t\t\t\t} else {\n\t\t\t\t\thtmlNodeCode += `(() => { const node = document.createElementNS('${SVG_NAMESPACE}', '${tagName}');\\n`;\n\t\t\t\t}\n\n\t\t\t\thtmlNodeCode += `setAttributes(node, ${attrs});\\n`;\n\t\t\t\tif (isComponent) {\n\t\t\t\t\thtmlNodeCode += `setProps(node, getValidProps(props));\\n`;\n\t\t\t\t}\n\n\t\t\t\tlet subTs = '';\n\t\t\t\telement.childNodes.forEach((child) => {\n\t\t\t\t\tconst chCode = this.buildTsForNode(child);\n\t\t\t\t\tif (chCode) {\n\t\t\t\t\t\tsubTs += `appendChild(node, ${chCode});\\n`;\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tif (!VOID_ELEMENTS.includes(tagName.toLowerCase())) {\n\t\t\t\t\tif (isComponent) {\n\t\t\t\t\t\thtmlNodeCode += `\n if (props.inner === null) {\n node.innerHTML = '';\n } else if (props.inner !== undefined) {\n node.innerHTML = '';\n appendChild(node, props.inner);\n } else {\n ${subTs}\n }\n `;\n\t\t\t\t\t} else {\n\t\t\t\t\t\thtmlNodeCode += subTs;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (isComponent) {\n\t\t\t\t\thtmlNodeCode += `if (typeof props._ref === 'function') props._ref(node);\\n`;\n\t\t\t\t}\n\n\t\t\t\thtmlNodeCode += `return node;})()`;\n\n\t\t\t\tif (tagName === 'svg') {\n\t\t\t\t\tthis.inSvgContext--;\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (domNode.nodeType === 3) {\n\t\t\t// Text\n\t\t\tconst textNode = domNode as Text;\n\t\t\tconst parent = textNode.parentNode as Element;\n\t\t\tconst parentTag = parent ? parent.tagName.toLowerCase() : '';\n\n\t\t\tconst mustOmit = ['table', 'thead', 'tbody', 'tfoot', 'tr'].includes(parentTag);\n\n\t\t\tif (!mustOmit && textNode.textContent) {\n\t\t\t\tif (textNode.textContent.trim() === '') {\n\t\t\t\t\tif (textNode.textContent.length > 0) {\n\t\t\t\t\t\thtmlNodeCode += `document.createTextNode(' ')`;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\thtmlNodeCode = `document.createTextNode(${JSON.stringify(textNode.textContent)})`;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn htmlNodeCode.trim();\n\t}\n\n\tprivate static getPropsTypename(cbid: string): string {\n\t\treturn 'T' + cbid.charAt(0).toUpperCase() + cbid.slice(1) + 'Props';\n\t}\n\n\tprivate wrapFnComponent(cbid: string, jsx: string): string {\n\t\tconst typename = HtmlCompiler.getPropsTypename(cbid);\n\t\treturn `(props: ${typename}) => { \\n return(${jsx}); \\n }`;\n\t}\n\n\tprivate createAllComponents() {\n\t\tconst body = this.htmlDocument.querySelector('body');\n\t\tif (!body) throw new Error('Not valid HTML');\n\n\t\tlet rendererJsx = '(() => { const fragment = document.createDocumentFragment();\\n';\n\n\t\tbody.childNodes.forEach((child) => {\n\t\t\tconst chCode = this.buildTsForNode(child);\n\t\t\tif (chCode) {\n\t\t\t\trendererJsx += `appendChild(fragment, ${chCode});\\n`;\n\t\t\t}\n\t\t});\n\n\t\trendererJsx += 'return fragment;\\n';\n\t\trendererJsx += '})()';\n\n\t\tthis.components['fragment'] = rendererJsx;\n\t}\n\n\tprivate getTypedef(cbid: string): string {\n\t\tconst items = this.componentsItems[cbid] || [];\n\t\tlet itemsType = '{\\n';\n\t\titems.forEach((itemCbid) => {\n\t\t\tconst itemTypename = HtmlCompiler.getPropsTypename(itemCbid);\n\t\t\titemsType += `${itemCbid}?: ${itemTypename} | TContent;\\n`;\n\t\t});\n\t\titemsType += '}\\n';\n\n\t\tconst typename = HtmlCompiler.getPropsTypename(cbid);\n\n\t\tif (cbid === 'fragment') {\n\t\t\treturn `interface ${typename} ${itemsType}`;\n\t\t} else {\n\t\t\tconst tagname = this.componentsTags[cbid];\n\t\t\tif (this.isSvg[cbid]) {\n\t\t\t\treturn `type ${typename} = TItemBuilderProps<SVGElementTagNameMap['${tagname}'], ${itemsType}>;`;\n\t\t\t} else {\n\t\t\t\treturn `type ${typename} = TItemBuilderProps<HTMLElementTagNameMap['${tagname.toLowerCase()}'], ${itemsType}>;`;\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic compile(): { js: string; dts: string } {\n\t\tthis.createAllComponents();\n\n\t\tlet componentsClasses = '';\n\t\tlet typedefs = '';\n\n\t\tfor (const [cbid, compJsx] of Object.entries(this.components)) {\n\t\t\ttypedefs += this.getTypedef(cbid) + '\\n';\n\t\t\tcomponentsClasses += `${cbid}: ${this.wrapFnComponent(cbid, compJsx)},\\n`;\n\t\t}\n\n\t\tconst jsOutput = `\n import { appendChild, getItem, getValidProps, buildClass, setAttributes, setProps, TContent, TItemBuilderProps } from 'chispa';\n\n const SVG_NS = 'http://www.w3.org/2000/svg';\n \n const Components = {\n ${componentsClasses}\n };\n \n export default Components;\n `;\n\n\t\tconst dtsOutput = `\n import { TContent, TItemBuilderProps } from 'chispa';\n \n ${typedefs}\n \n declare const Components: {\n ${Object.keys(this.components)\n\t\t\t\t\t.map((cbid) => {\n\t\t\t\t\t\tconst typename = HtmlCompiler.getPropsTypename(cbid);\n\t\t\t\t\t\treturn `${cbid}: (props: ${typename}) => Node | DocumentFragment;`;\n\t\t\t\t\t})\n\t\t\t\t\t.join('\\n')}\n };\n \n export default Components;\n `;\n\n\t\treturn { js: jsOutput, dts: dtsOutput };\n\t}\n}\n","import * as fs from 'fs';\nimport * as path from 'path';\nimport { HtmlCompiler } from './html-compiler';\n\nexport function generateTypes(filePath: string, content: string, rootDir: string) {\n\ttry {\n\t\tconst compiler = new HtmlCompiler(content);\n\t\tconst { dts } = compiler.compile();\n\n\t\tconst outDir = path.join(rootDir, '.chispa/types');\n\t\tconst relativePath = path.relative(rootDir, filePath);\n\t\tconst targetPath = path.join(outDir, relativePath + '.d.ts');\n\t\tconst targetDir = path.dirname(targetPath);\n\n\t\tif (!fs.existsSync(targetDir)) {\n\t\t\tfs.mkdirSync(targetDir, { recursive: true });\n\t\t}\n\t\tfs.writeFileSync(targetPath, dts);\n\t} catch (e) {\n\t\tconsole.error(`[chispa] Error generating types for ${filePath}`, e);\n\t}\n}\n\nexport function findAndCompileHtmlFiles(dir: string, rootDir: string) {\n\tif (!fs.existsSync(dir)) return;\n\tconst files = fs.readdirSync(dir);\n\tfiles.forEach((file) => {\n\t\tconst fullPath = path.join(dir, file);\n\t\tif (fullPath === path.join(rootDir, 'index.html')) return;\n\t\tif (fs.statSync(fullPath).isDirectory()) {\n\t\t\tif (file !== 'node_modules' && file !== '.git' && file !== 'dist' && file !== '.chispa') {\n\t\t\t\tfindAndCompileHtmlFiles(fullPath, rootDir);\n\t\t\t}\n\t\t} else if (file.endsWith('.html')) {\n\t\t\tconsole.log('Generating types for', fullPath);\n\t\t\tconst content = fs.readFileSync(fullPath, 'utf-8');\n\t\t\tgenerateTypes(fullPath, content, rootDir);\n\t\t}\n\t});\n}\n","import { HtmlCompiler } from './html-compiler';\nimport { generateTypes, findAndCompileHtmlFiles } from './generator';\nimport * as fs from 'fs';\n\nexport function chispaHtmlPlugin() {\n\tlet rootDir = process.cwd();\n\n\treturn {\n\t\tname: 'chispa-html',\n\t\tenforce: 'pre' as 'pre',\n\t\tconfigResolved(config: any) {\n\t\t\trootDir = config.root;\n\t\t},\n\t\tbuildStart() {\n\t\t\tfindAndCompileHtmlFiles(rootDir, rootDir);\n\t\t},\n\t\thandleHotUpdate(ctx: { file: string; read: () => string | Promise<string> }) {\n\t\t\tif (ctx.file.endsWith('.html')) {\n\t\t\t\tPromise.resolve(ctx.read()).then((content) => generateTypes(ctx.file, content, rootDir));\n\t\t\t}\n\t\t},\n\t\tasync resolveId(source: string, importer: string, options: any) {\n\t\t\tif (source.endsWith('.html') && importer) {\n\t\t\t\tconst resolution = await this.resolve(source, importer, { skipSelf: true, ...options });\n\t\t\t\tif (resolution && !resolution.external) {\n\t\t\t\t\treturn resolution.id + '.chispa.ts';\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn null;\n\t\t},\n\t\tload(id: string) {\n\t\t\tif (id.endsWith('.html.chispa.ts')) {\n\t\t\t\tconst realId = id.replace('.chispa.ts', '');\n\t\t\t\ttry {\n\t\t\t\t\tconst content = fs.readFileSync(realId, 'utf-8');\n\t\t\t\t\tif (content.includes('<!DOCTYPE html>') || content.includes('<html')) {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst compiler = new HtmlCompiler(content);\n\t\t\t\t\tconst { js } = compiler.compile();\n\t\t\t\t\tgenerateTypes(realId, content, rootDir);\n\t\t\t\t\treturn js;\n\t\t\t\t} catch (e) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t};\n}\n"],"mappings":"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","names":["fs"]}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
type TExecutionProcess = 'createComponent' | 'computed' | 'addReactivity';
|
|
2
|
+
interface IDisposable {
|
|
3
|
+
dispose: () => void;
|
|
4
|
+
}
|
|
5
|
+
declare class AppContext {
|
|
6
|
+
private reactivityContextStack;
|
|
7
|
+
private refreshTimeout;
|
|
8
|
+
private dirtyReactivities;
|
|
9
|
+
private executionStack;
|
|
10
|
+
private componentStack;
|
|
11
|
+
pushComponentStack(cmp: Component | ComponentList): void;
|
|
12
|
+
popComponentStack(): void;
|
|
13
|
+
getCurrentComponent(): Component<any> | ComponentList<any>;
|
|
14
|
+
setCurrentReactivityContext(context: Reactivity): void;
|
|
15
|
+
restorePreviousReactivityContext(): void;
|
|
16
|
+
getCurrentRenderContext(): Reactivity;
|
|
17
|
+
scheduleRefresh(): void;
|
|
18
|
+
addReactivity(executor: () => void): Reactivity;
|
|
19
|
+
createRoot(component: () => Component, mountPoint: HTMLElement): void;
|
|
20
|
+
canReadSignal(): boolean;
|
|
21
|
+
pushExecutionStack(type: TExecutionProcess): void;
|
|
22
|
+
popExecutionStack(): void;
|
|
23
|
+
addDirtyContext(ctx: Reactivity): void;
|
|
24
|
+
removeDirtyContext(ctx: Reactivity): void;
|
|
25
|
+
}
|
|
26
|
+
declare class Reactivity implements IDisposable {
|
|
27
|
+
private readonly action;
|
|
28
|
+
private dirty;
|
|
29
|
+
private signals;
|
|
30
|
+
constructor(action: () => void);
|
|
31
|
+
markDirty(): void;
|
|
32
|
+
addSignal(signal: Signal<any>): void;
|
|
33
|
+
removeSignal(signal: Signal<any>): void;
|
|
34
|
+
process(): void;
|
|
35
|
+
exec(): void;
|
|
36
|
+
dispose(): void;
|
|
37
|
+
}
|
|
38
|
+
declare const globalContext: AppContext;
|
|
39
|
+
|
|
40
|
+
type TProps = Record<string, Signal<any>>;
|
|
41
|
+
type TDict = Record<string, any>;
|
|
42
|
+
type WithSignals<T> = {
|
|
43
|
+
[K in keyof T]: Signal<T[K]>;
|
|
44
|
+
};
|
|
45
|
+
type TComponentFactory<T extends TDict> = ((props: WithSignals<T>) => Node) | (() => Node);
|
|
46
|
+
declare class Component<T = any> {
|
|
47
|
+
private readonly factoryFn;
|
|
48
|
+
readonly key: any;
|
|
49
|
+
readonly props: WithSignals<T>;
|
|
50
|
+
onUnmount: (() => void) | null;
|
|
51
|
+
nodes: Node[] | null;
|
|
52
|
+
private container;
|
|
53
|
+
private anchor;
|
|
54
|
+
disposables: IDisposable[];
|
|
55
|
+
silent: boolean;
|
|
56
|
+
constructor(factoryFn: TComponentFactory<T>, key?: any, props?: WithSignals<T>);
|
|
57
|
+
mount(container: Node, anchor: Node): void;
|
|
58
|
+
reanchor(anchor: Node | null): void;
|
|
59
|
+
private insertNodes;
|
|
60
|
+
unmount(): void;
|
|
61
|
+
}
|
|
62
|
+
declare function component<T extends Record<string, any>>(factory: TComponentFactory<T>): (props?: WithSignals<T>) => Component<T>;
|
|
63
|
+
type ItemFactoryFn<T> = (item: Signal<T>, index: Signal<number>, list: WritableSignal<T[]>) => Node;
|
|
64
|
+
type KeyFn<T> = (item: T, index: number) => any;
|
|
65
|
+
declare class ComponentList<T = any> {
|
|
66
|
+
private readonly itemFactoryFn;
|
|
67
|
+
private readonly keyFn;
|
|
68
|
+
private readonly itemsSignal;
|
|
69
|
+
private readonly components;
|
|
70
|
+
private container;
|
|
71
|
+
private anchor;
|
|
72
|
+
private currentKeys;
|
|
73
|
+
disposables: any[];
|
|
74
|
+
constructor(itemFactoryFn: ItemFactoryFn<T>, keyFn: KeyFn<T>, itemsSignal: WritableSignal<T[]>);
|
|
75
|
+
/**
|
|
76
|
+
* Obtiene todos los componentes
|
|
77
|
+
*/
|
|
78
|
+
private getAllComponents;
|
|
79
|
+
/**
|
|
80
|
+
* Limpia todos los componentes
|
|
81
|
+
*/
|
|
82
|
+
private clear;
|
|
83
|
+
/**
|
|
84
|
+
* Elimina un componente completo
|
|
85
|
+
*/
|
|
86
|
+
private removeComponent;
|
|
87
|
+
/**
|
|
88
|
+
* Crea un nuevo componente
|
|
89
|
+
*/
|
|
90
|
+
private createNewComponent;
|
|
91
|
+
private getTargetAnchor;
|
|
92
|
+
/**
|
|
93
|
+
* Función principal que sincroniza los componentes DOM con un array de keys
|
|
94
|
+
*/
|
|
95
|
+
private synchronizeComponents;
|
|
96
|
+
mount(container: Node, anchor: Node): void;
|
|
97
|
+
unmount(): void;
|
|
98
|
+
}
|
|
99
|
+
declare function componentList<T>(itemFactoryFn: ItemFactoryFn<T>, keyFn: KeyFn<T>): (listSignal: WritableSignal<T[]>) => ComponentList<T>;
|
|
100
|
+
|
|
101
|
+
declare abstract class Signal<T> {
|
|
102
|
+
protected abstract value: T;
|
|
103
|
+
protected contexts: Set<Reactivity>;
|
|
104
|
+
constructor();
|
|
105
|
+
get(): T;
|
|
106
|
+
readonly computed: WithSignals<T>;
|
|
107
|
+
removeContext(ctx: Reactivity): void;
|
|
108
|
+
dispose(): void;
|
|
109
|
+
}
|
|
110
|
+
declare class WritableSignal<T> extends Signal<T> {
|
|
111
|
+
protected value: T;
|
|
112
|
+
readonly initialValue: T;
|
|
113
|
+
constructor(initialValue: T);
|
|
114
|
+
set(newValue: T): void;
|
|
115
|
+
update(updater: (value: T) => T): void;
|
|
116
|
+
}
|
|
117
|
+
declare function isSignal(value: any): value is Signal<any>;
|
|
118
|
+
declare function signal<T>(initialValue: T): WritableSignal<T>;
|
|
119
|
+
declare function computed<T>(fn: () => T): Signal<T>;
|
|
120
|
+
|
|
121
|
+
type TClasses = Record<string, boolean>;
|
|
122
|
+
type TNode = string | number | Node | null;
|
|
123
|
+
type TContent = TNode | TNode[] | Component | ComponentList | Signal<TNode | TNode[] | Component | ComponentList>;
|
|
124
|
+
type TCSSPropertiesStrings = {
|
|
125
|
+
[K in keyof CSSStyleDeclaration]?: string | Signal<string>;
|
|
126
|
+
};
|
|
127
|
+
type AllowSignals<T> = {
|
|
128
|
+
[K in keyof T]: T[K] | Signal<T[K]>;
|
|
129
|
+
};
|
|
130
|
+
type TItemBuilderBaseProps<T> = AllowSignals<Omit<Partial<T>, 'style' | 'dataset'>>;
|
|
131
|
+
interface IItemBuilderAdditionalProps<T, TItems> {
|
|
132
|
+
addClass?: string;
|
|
133
|
+
classes?: TClasses;
|
|
134
|
+
items?: TItems;
|
|
135
|
+
inner?: TContent;
|
|
136
|
+
style?: TCSSPropertiesStrings;
|
|
137
|
+
dataset?: Record<string, string>;
|
|
138
|
+
_ref?: (node: T) => void | {
|
|
139
|
+
current: T | null;
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
type TItemBuilderProps<T, TItems> = TItemBuilderBaseProps<T> & IItemBuilderAdditionalProps<T, TItems>;
|
|
143
|
+
declare function buildClass(literalValue: string, additionalValue?: string, classes?: TClasses): string;
|
|
144
|
+
declare function getValidProps(props: any): any;
|
|
145
|
+
declare function getItem<T>(Components: T, items: any, itemName: keyof T): any;
|
|
146
|
+
declare function setAttributes(node: Element, attributes: Record<string, string>): void;
|
|
147
|
+
declare function setProps<T extends Element>(node: T, props: any): void;
|
|
148
|
+
declare function appendChild(node: Element | DocumentFragment, child: TContent): void;
|
|
149
|
+
|
|
150
|
+
export { Signal, type TContent, type TItemBuilderProps, type TProps, appendChild, buildClass, component, componentList, computed, getItem, getValidProps, globalContext, isSignal, setAttributes, setProps, signal };
|