@jamx-framework/renderer 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/.turbo/turbo-build.log +4 -0
- package/dist/.tsbuildinfo +1 -0
- package/dist/error/boundary.d.ts +36 -0
- package/dist/error/boundary.d.ts.map +1 -0
- package/dist/error/boundary.js +60 -0
- package/dist/error/boundary.js.map +1 -0
- package/dist/error/error-page.d.ts +7 -0
- package/dist/error/error-page.d.ts.map +1 -0
- package/dist/error/error-page.js +132 -0
- package/dist/error/error-page.js.map +1 -0
- package/dist/error/types.d.ts +7 -0
- package/dist/error/types.d.ts.map +1 -0
- package/dist/error/types.js +2 -0
- package/dist/error/types.js.map +1 -0
- package/dist/html/escape.d.ts +19 -0
- package/dist/html/escape.d.ts.map +1 -0
- package/dist/html/escape.js +85 -0
- package/dist/html/escape.js.map +1 -0
- package/dist/html/serializer.d.ts +20 -0
- package/dist/html/serializer.d.ts.map +1 -0
- package/dist/html/serializer.js +132 -0
- package/dist/html/serializer.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/jsx/jsx-runtime.d.ts +213 -0
- package/dist/jsx/jsx-runtime.d.ts.map +1 -0
- package/dist/jsx/jsx-runtime.js +32 -0
- package/dist/jsx/jsx-runtime.js.map +1 -0
- package/dist/pipeline/context.d.ts +44 -0
- package/dist/pipeline/context.d.ts.map +1 -0
- package/dist/pipeline/context.js +2 -0
- package/dist/pipeline/context.js.map +1 -0
- package/dist/pipeline/renderer.d.ts +40 -0
- package/dist/pipeline/renderer.d.ts.map +1 -0
- package/dist/pipeline/renderer.js +95 -0
- package/dist/pipeline/renderer.js.map +1 -0
- package/package.json +38 -0
- package/src/error/boundary.ts +80 -0
- package/src/error/error-page.ts +137 -0
- package/src/error/types.ts +6 -0
- package/src/html/escape.ts +90 -0
- package/src/html/serializer.ts +161 -0
- package/src/index.ts +33 -0
- package/src/jsx/jsx-runtime.ts +247 -0
- package/src/pipeline/context.ts +45 -0
- package/src/pipeline/renderer.ts +138 -0
- package/test/unit/error/boundary.test.ts +78 -0
- package/test/unit/error/error-page.test.ts +63 -0
- package/test/unit/html/escape.test.ts +34 -0
- package/test/unit/html/renderer.test.ts +93 -0
- package/test/unit/html/serializer.test.ts +141 -0
- package/tsconfig.json +15 -0
- package/vitest.config.ts +4 -0
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
// packages/renderer/tests/unit/html/serializer.test.ts
|
|
2
|
+
|
|
3
|
+
import { describe, it, expect } from "vitest";
|
|
4
|
+
import { HtmlSerializer } from "../../../src/html/serializer.js";
|
|
5
|
+
import { jsx, Fragment } from "../../../src/jsx/jsx-runtime.js";
|
|
6
|
+
import type { JamxNode } from "../../../src/jsx/jsx-runtime.js";
|
|
7
|
+
|
|
8
|
+
const s = new HtmlSerializer();
|
|
9
|
+
|
|
10
|
+
describe("HtmlSerializer", () => {
|
|
11
|
+
describe("nodos primitivos", () => {
|
|
12
|
+
it("serializa strings con escape", () => {
|
|
13
|
+
expect(s.serialize("hello <world>")).toBe("hello <world>");
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it("serializa números", () => {
|
|
17
|
+
expect(s.serialize(42)).toBe("42");
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it("ignora null, undefined, false", () => {
|
|
21
|
+
expect(s.serialize(null)).toBe("");
|
|
22
|
+
expect(s.serialize(undefined)).toBe("");
|
|
23
|
+
expect(s.serialize(false)).toBe("");
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it("ignora true", () => {
|
|
27
|
+
expect(s.serialize(true)).toBe("");
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
describe("elementos HTML", () => {
|
|
32
|
+
it("serializa un div simple", () => {
|
|
33
|
+
const el = jsx("div", { children: "hello" });
|
|
34
|
+
expect(s.serialize(el)).toBe("<div>hello</div>");
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it("serializa atributos", () => {
|
|
38
|
+
const el = jsx("div", { id: "app", class: "container" });
|
|
39
|
+
expect(s.serialize(el)).toContain('id="app"');
|
|
40
|
+
expect(s.serialize(el)).toContain('class="container"');
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it("convierte className a class", () => {
|
|
44
|
+
const el = jsx("div", { className: "my-class" });
|
|
45
|
+
expect(s.serialize(el)).toBe('<div class="my-class"></div>');
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it("serializa elementos void sin closing tag", () => {
|
|
49
|
+
const el = jsx("br", {});
|
|
50
|
+
expect(s.serialize(el)).toBe("<br>");
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it("serializa input void con atributos", () => {
|
|
54
|
+
const el = jsx("input", { type: "text", placeholder: "Enter text" });
|
|
55
|
+
const html = s.serialize(el);
|
|
56
|
+
expect(html).toContain('type="text"');
|
|
57
|
+
expect(html).not.toContain("</input>");
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it("serializa atributos booleanos correctamente", () => {
|
|
61
|
+
const el = jsx("input", {
|
|
62
|
+
type: "checkbox",
|
|
63
|
+
disabled: true,
|
|
64
|
+
checked: true,
|
|
65
|
+
});
|
|
66
|
+
const html = s.serialize(el);
|
|
67
|
+
expect(html).toContain("disabled");
|
|
68
|
+
expect(html).toContain("checked");
|
|
69
|
+
expect(html).not.toContain('disabled="true"');
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it("omite atributos booleanos false", () => {
|
|
73
|
+
const el = jsx("input", { type: "checkbox", disabled: false });
|
|
74
|
+
expect(s.serialize(el)).not.toContain("disabled");
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it("serializa style como objeto", () => {
|
|
78
|
+
const el = jsx("div", {
|
|
79
|
+
style: { backgroundColor: "red", fontSize: "16px" },
|
|
80
|
+
});
|
|
81
|
+
const html = s.serialize(el);
|
|
82
|
+
expect(html).toContain("background-color: red");
|
|
83
|
+
expect(html).toContain("font-size: 16px");
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it("escapa el contenido de texto", () => {
|
|
87
|
+
const el = jsx("p", { children: '<script>alert("xss")</script>' });
|
|
88
|
+
const html = s.serialize(el);
|
|
89
|
+
expect(html).not.toContain("<script>");
|
|
90
|
+
expect(html).toContain("<script>");
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
describe("componentes funcionales", () => {
|
|
95
|
+
it("serializa componentes funcionales simples", () => {
|
|
96
|
+
const Greeting = ({ name }: { name: string }) =>
|
|
97
|
+
jsx("p", { children: `Hello, ${name}!` });
|
|
98
|
+
|
|
99
|
+
const el = jsx(Greeting as never, { name: "James" });
|
|
100
|
+
expect(s.serialize(el)).toBe("<p>Hello, James!</p>");
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it("serializa componentes anidados", () => {
|
|
104
|
+
const Card = ({ children }: { children: JamxNode }) =>
|
|
105
|
+
jsx("div", { className: "card", children });
|
|
106
|
+
|
|
107
|
+
const el = jsx(Card as never, {
|
|
108
|
+
children: jsx("p", { children: "Content" }),
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
expect(s.serialize(el)).toBe('<div class="card"><p>Content</p></div>');
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
describe("Fragment", () => {
|
|
116
|
+
it("serializa Fragment sin wrapper", () => {
|
|
117
|
+
const el = jsx(Fragment as never, {
|
|
118
|
+
children: [
|
|
119
|
+
jsx("li", { children: "Item 1" }),
|
|
120
|
+
jsx("li", { children: "Item 2" }),
|
|
121
|
+
],
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
expect(s.serialize(el)).toBe("<li>Item 1</li><li>Item 2</li>");
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
describe("arrays de children", () => {
|
|
129
|
+
it("serializa múltiples children", () => {
|
|
130
|
+
const el = jsx("ul", {
|
|
131
|
+
children: [
|
|
132
|
+
jsx("li", { children: "A" }),
|
|
133
|
+
jsx("li", { children: "B" }),
|
|
134
|
+
jsx("li", { children: "C" }),
|
|
135
|
+
],
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
expect(s.serialize(el)).toBe("<ul><li>A</li><li>B</li><li>C</li></ul>");
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
});
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "../../tsconfig.base.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"rootDir": "src",
|
|
5
|
+
"outDir": "dist",
|
|
6
|
+
"tsBuildInfoFile": "dist/.tsbuildinfo",
|
|
7
|
+
"jsx": "react-jsx",
|
|
8
|
+
"jsxImportSource": "@jamx-framework/renderer"
|
|
9
|
+
},
|
|
10
|
+
"include": ["src/**/*"],
|
|
11
|
+
"references": [
|
|
12
|
+
{ "path": "../core" }
|
|
13
|
+
],
|
|
14
|
+
"exclude": ["node_modules", "dist", "tests"]
|
|
15
|
+
}
|
package/vitest.config.ts
ADDED