@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.
Files changed (55) hide show
  1. package/.turbo/turbo-build.log +4 -0
  2. package/dist/.tsbuildinfo +1 -0
  3. package/dist/error/boundary.d.ts +36 -0
  4. package/dist/error/boundary.d.ts.map +1 -0
  5. package/dist/error/boundary.js +60 -0
  6. package/dist/error/boundary.js.map +1 -0
  7. package/dist/error/error-page.d.ts +7 -0
  8. package/dist/error/error-page.d.ts.map +1 -0
  9. package/dist/error/error-page.js +132 -0
  10. package/dist/error/error-page.js.map +1 -0
  11. package/dist/error/types.d.ts +7 -0
  12. package/dist/error/types.d.ts.map +1 -0
  13. package/dist/error/types.js +2 -0
  14. package/dist/error/types.js.map +1 -0
  15. package/dist/html/escape.d.ts +19 -0
  16. package/dist/html/escape.d.ts.map +1 -0
  17. package/dist/html/escape.js +85 -0
  18. package/dist/html/escape.js.map +1 -0
  19. package/dist/html/serializer.d.ts +20 -0
  20. package/dist/html/serializer.d.ts.map +1 -0
  21. package/dist/html/serializer.js +132 -0
  22. package/dist/html/serializer.js.map +1 -0
  23. package/dist/index.d.ts +12 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +7 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/jsx/jsx-runtime.d.ts +213 -0
  28. package/dist/jsx/jsx-runtime.d.ts.map +1 -0
  29. package/dist/jsx/jsx-runtime.js +32 -0
  30. package/dist/jsx/jsx-runtime.js.map +1 -0
  31. package/dist/pipeline/context.d.ts +44 -0
  32. package/dist/pipeline/context.d.ts.map +1 -0
  33. package/dist/pipeline/context.js +2 -0
  34. package/dist/pipeline/context.js.map +1 -0
  35. package/dist/pipeline/renderer.d.ts +40 -0
  36. package/dist/pipeline/renderer.d.ts.map +1 -0
  37. package/dist/pipeline/renderer.js +95 -0
  38. package/dist/pipeline/renderer.js.map +1 -0
  39. package/package.json +38 -0
  40. package/src/error/boundary.ts +80 -0
  41. package/src/error/error-page.ts +137 -0
  42. package/src/error/types.ts +6 -0
  43. package/src/html/escape.ts +90 -0
  44. package/src/html/serializer.ts +161 -0
  45. package/src/index.ts +33 -0
  46. package/src/jsx/jsx-runtime.ts +247 -0
  47. package/src/pipeline/context.ts +45 -0
  48. package/src/pipeline/renderer.ts +138 -0
  49. package/test/unit/error/boundary.test.ts +78 -0
  50. package/test/unit/error/error-page.test.ts +63 -0
  51. package/test/unit/html/escape.test.ts +34 -0
  52. package/test/unit/html/renderer.test.ts +93 -0
  53. package/test/unit/html/serializer.test.ts +141 -0
  54. package/tsconfig.json +15 -0
  55. package/vitest.config.ts +4 -0
@@ -0,0 +1,132 @@
1
+ import { escapeHtml, VOID_ELEMENTS, RAW_TEXT_ELEMENTS, BOOLEAN_ATTRIBUTES, } from "./escape.js";
2
+ import { Fragment } from "../jsx/jsx-runtime.js";
3
+ /**
4
+ * Serializa un árbol JSX a una string HTML.
5
+ *
6
+ * Proceso:
7
+ * 1. Si el nodo es un string/number → escapar y retornar
8
+ * 2. Si el nodo es un componente (función) → llamarlo y serializar el resultado
9
+ * 3. Si el nodo es un elemento HTML → serializar tag + props + children
10
+ * 4. Si el nodo es un Fragment → serializar solo los children
11
+ */
12
+ export class HtmlSerializer {
13
+ serialize(node) {
14
+ // Nodos primitivos
15
+ if (node === null || node === undefined || node === false)
16
+ return "";
17
+ if (node === true)
18
+ return "";
19
+ if (typeof node === "number")
20
+ return String(node);
21
+ if (typeof node === "string")
22
+ return escapeHtml(node);
23
+ // Arrays
24
+ if (Array.isArray(node)) {
25
+ return node.map((child) => this.serialize(child)).join("");
26
+ }
27
+ // Elemento JSX
28
+ return this.serializeElement(node);
29
+ }
30
+ serializeElement(element) {
31
+ const { type, props } = element;
32
+ // Componente funcional — ejecutar y serializar el resultado
33
+ if (typeof type === "function") {
34
+ return this.serializeComponent(type, props);
35
+ }
36
+ // Fragment — solo los hijos
37
+ if (type === Fragment) {
38
+ return this.serializeChildren(props.children);
39
+ }
40
+ // Elemento HTML
41
+ return this.serializeHtmlElement(type, props);
42
+ }
43
+ serializeComponent(fn, props) {
44
+ try {
45
+ const result = fn(props);
46
+ return this.serialize(result);
47
+ }
48
+ catch (err) {
49
+ throw new Error(`Error rendering component '${fn.name || "anonymous"}': ${String(err)}`);
50
+ }
51
+ }
52
+ serializeHtmlElement(tag, props) {
53
+ const { children, ...attrs } = props;
54
+ const attrString = this.serializeAttributes(attrs);
55
+ const openTag = attrString ? `<${tag} ${attrString}>` : `<${tag}>`;
56
+ // Elementos void — no tienen closing tag ni children
57
+ if (VOID_ELEMENTS.has(tag)) {
58
+ return openTag;
59
+ }
60
+ // Elementos con contenido raw (script, style)
61
+ if (RAW_TEXT_ELEMENTS.has(tag)) {
62
+ const rawContent = typeof children === "string" ? children : "";
63
+ return `${openTag}${rawContent}</${tag}>`;
64
+ }
65
+ const childrenHtml = this.serializeChildren(children);
66
+ return `${openTag}${childrenHtml}</${tag}>`;
67
+ }
68
+ serializeAttributes(attrs) {
69
+ const parts = [];
70
+ for (const [key, value] of Object.entries(attrs)) {
71
+ // Ignorar atributos internos y undefined/null
72
+ if (key === "key" || value === undefined || value === null)
73
+ continue;
74
+ // className → class
75
+ const attrName = key === "className"
76
+ ? "class"
77
+ : key === "htmlFor"
78
+ ? "for"
79
+ : key === "tabIndex"
80
+ ? "tabindex"
81
+ : camelToKebab(key);
82
+ // Atributos booleanos
83
+ if (BOOLEAN_ATTRIBUTES.has(attrName)) {
84
+ if (value === true)
85
+ parts.push(attrName);
86
+ continue;
87
+ }
88
+ // style como objeto
89
+ if (key === "style" && typeof value === "object" && value !== null) {
90
+ const styleStr = this.serializeStyle(value);
91
+ if (styleStr)
92
+ parts.push(`style="${escapeHtml(styleStr)}"`);
93
+ continue;
94
+ }
95
+ // false → omitir el atributo
96
+ if (value === false)
97
+ continue;
98
+ // true → atributo sin valor (no booleano, ej: data-active)
99
+ if (value === true) {
100
+ parts.push(attrName);
101
+ continue;
102
+ }
103
+ parts.push(`${attrName}="${escapeHtml(value)}"`);
104
+ }
105
+ return parts.join(" ");
106
+ }
107
+ serializeStyle(style) {
108
+ return Object.entries(style)
109
+ .map(([prop, value]) => `${camelToKebab(prop)}: ${value}`)
110
+ .join("; ");
111
+ }
112
+ serializeChildren(children) {
113
+ if (children === undefined || children === null)
114
+ return "";
115
+ if (Array.isArray(children)) {
116
+ return children
117
+ .map((child) => this.serialize(child))
118
+ .join("");
119
+ }
120
+ return this.serialize(children);
121
+ }
122
+ }
123
+ // ── HELPERS ───────────────────────────────────────────────────────────────
124
+ /**
125
+ * Convierte camelCase a kebab-case para atributos HTML.
126
+ * backgroundColor → background-color
127
+ * dataTestId → data-test-id (los data- ya vienen bien)
128
+ */
129
+ function camelToKebab(str) {
130
+ return str.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`);
131
+ }
132
+ //# sourceMappingURL=serializer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serializer.js","sourceRoot":"","sources":["../../src/html/serializer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ export { SSRRenderer } from "./pipeline/renderer.js";
2
+ export { HtmlSerializer } from "./html/serializer.js";
3
+ export { escapeHtml, VOID_ELEMENTS, BOOLEAN_ATTRIBUTES, } from "./html/escape.js";
4
+ export { jsx, jsxs, jsxDEV, Fragment } from "./jsx/jsx-runtime.js";
5
+ export type { JamxNode, JamxElement, ComponentFn, Props, JSX, HtmlAttributes, } from "./jsx/jsx-runtime.js";
6
+ export type { RenderContext, RenderResult, PageHead, } from "./pipeline/context.js";
7
+ export type { PageComponentLike, LayoutComponentLike, } from "./pipeline/renderer.js";
8
+ export { ErrorBoundary } from "./error/boundary.js";
9
+ export { renderErrorPage } from "./error/error-page.js";
10
+ export type { RenderError } from "./error/types.js";
11
+ export type { BoundaryOptions, BoundaryResult } from "./error/boundary.js";
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EACL,UAAU,EACV,aAAa,EACb,kBAAkB,GACnB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAEnE,YAAY,EACV,QAAQ,EACR,WAAW,EACX,WAAW,EACX,KAAK,EACL,GAAG,EACH,cAAc,GACf,MAAM,sBAAsB,CAAC;AAE9B,YAAY,EACV,aAAa,EACb,YAAY,EACZ,QAAQ,GACT,MAAM,uBAAuB,CAAC;AAE/B,YAAY,EACV,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,YAAY,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,7 @@
1
+ export { SSRRenderer } from "./pipeline/renderer.js";
2
+ export { HtmlSerializer } from "./html/serializer.js";
3
+ export { escapeHtml, VOID_ELEMENTS, BOOLEAN_ATTRIBUTES, } from "./html/escape.js";
4
+ export { jsx, jsxs, jsxDEV, Fragment } from "./jsx/jsx-runtime.js";
5
+ export { ErrorBoundary } from "./error/boundary.js";
6
+ export { renderErrorPage } from "./error/error-page.js";
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EACL,UAAU,EACV,aAAa,EACb,kBAAkB,GACnB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAsBnE,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,213 @@
1
+ export type JamxNode = string | number | boolean | null | undefined | JamxElement | JamxNode[];
2
+ export interface JamxElement {
3
+ type: string | ComponentFn;
4
+ props: Props;
5
+ key: string | null;
6
+ }
7
+ export type Props = Record<string, unknown> & {
8
+ children?: JamxNode | JamxNode[];
9
+ };
10
+ export type ComponentFn = (props: Props) => JamxNode;
11
+ /**
12
+ * Función principal del JSX runtime.
13
+ * TypeScript llama esto cuando encuentra <Tag prop="value" />
14
+ *
15
+ * En lugar de React.createElement, JAMX usa esta función
16
+ * para construir el árbol de nodos que luego serializa a HTML.
17
+ */
18
+ export declare function jsx(type: string | ComponentFn, props: Props, key?: string): JamxElement;
19
+ /**
20
+ * Versión para elementos con múltiples hijos.
21
+ * TypeScript la usa cuando hay más de un hijo.
22
+ */
23
+ export declare const jsxs: typeof jsx;
24
+ /**
25
+ * Versión dev con información adicional para debugging.
26
+ * En producción es igual a jsx.
27
+ */
28
+ export declare const jsxDEV: typeof jsx;
29
+ /**
30
+ * Fragment — permite retornar múltiples elementos sin wrapper.
31
+ * Uso: <> <div/> <div/> </>
32
+ */
33
+ export declare const Fragment: "jamx.fragment";
34
+ /**
35
+ * Declaraciones de tipos para que TypeScript entienda el JSX de JAMX.
36
+ * Estas interfaces definen qué props acepta cada elemento HTML.
37
+ */
38
+ export declare namespace JSX {
39
+ type Element = JamxElement;
40
+ interface ElementChildrenAttribute {
41
+ children: JamxNode | JamxNode[];
42
+ }
43
+ interface IntrinsicElements {
44
+ html: HtmlAttributes & {
45
+ lang?: string;
46
+ };
47
+ head: HtmlAttributes;
48
+ body: HtmlAttributes;
49
+ title: HtmlAttributes;
50
+ meta: MetaAttributes;
51
+ link: LinkAttributes;
52
+ script: ScriptAttributes;
53
+ style: HtmlAttributes;
54
+ main: HtmlAttributes;
55
+ header: HtmlAttributes;
56
+ footer: HtmlAttributes;
57
+ nav: HtmlAttributes;
58
+ section: HtmlAttributes;
59
+ article: HtmlAttributes;
60
+ aside: HtmlAttributes;
61
+ h1: HtmlAttributes;
62
+ h2: HtmlAttributes;
63
+ h3: HtmlAttributes;
64
+ h4: HtmlAttributes;
65
+ h5: HtmlAttributes;
66
+ h6: HtmlAttributes;
67
+ p: HtmlAttributes;
68
+ span: HtmlAttributes;
69
+ strong: HtmlAttributes;
70
+ em: HtmlAttributes;
71
+ small: HtmlAttributes;
72
+ code: HtmlAttributes;
73
+ pre: HtmlAttributes;
74
+ ul: HtmlAttributes;
75
+ ol: HtmlAttributes;
76
+ li: HtmlAttributes;
77
+ a: AnchorAttributes;
78
+ button: ButtonAttributes;
79
+ input: InputAttributes;
80
+ textarea: TextareaAttributes;
81
+ select: HtmlAttributes;
82
+ option: HtmlAttributes & {
83
+ value?: string;
84
+ selected?: boolean;
85
+ };
86
+ form: FormAttributes;
87
+ label: HtmlAttributes & {
88
+ for?: string;
89
+ htmlFor?: string;
90
+ };
91
+ img: ImgAttributes;
92
+ video: HtmlAttributes & {
93
+ src?: string;
94
+ controls?: boolean;
95
+ autoplay?: boolean;
96
+ };
97
+ audio: HtmlAttributes & {
98
+ src?: string;
99
+ controls?: boolean;
100
+ };
101
+ canvas: HtmlAttributes & {
102
+ width?: number;
103
+ height?: number;
104
+ };
105
+ div: HtmlAttributes;
106
+ table: HtmlAttributes;
107
+ thead: HtmlAttributes;
108
+ tbody: HtmlAttributes;
109
+ tr: HtmlAttributes;
110
+ th: HtmlAttributes & {
111
+ colSpan?: number;
112
+ rowSpan?: number;
113
+ };
114
+ td: HtmlAttributes & {
115
+ colSpan?: number;
116
+ rowSpan?: number;
117
+ };
118
+ br: HtmlAttributes;
119
+ hr: HtmlAttributes;
120
+ slot: HtmlAttributes & {
121
+ name?: string;
122
+ };
123
+ [tag: string]: HtmlAttributes;
124
+ }
125
+ }
126
+ export interface HtmlAttributes {
127
+ id?: string;
128
+ class?: string;
129
+ className?: string;
130
+ style?: string | Record<string, string>;
131
+ children?: JamxNode | JamxNode[];
132
+ [key: `data-${string}`]: string | undefined;
133
+ role?: string;
134
+ "aria-label"?: string;
135
+ "aria-hidden"?: boolean;
136
+ "aria-expanded"?: boolean;
137
+ "aria-disabled"?: boolean;
138
+ "aria-selected"?: boolean;
139
+ "aria-controls"?: string;
140
+ "aria-describedby"?: string;
141
+ tabIndex?: number;
142
+ }
143
+ export interface AnchorAttributes extends HtmlAttributes {
144
+ href?: string;
145
+ target?: "_blank" | "_self" | "_parent" | "_top";
146
+ rel?: string;
147
+ download?: boolean | string;
148
+ }
149
+ export interface ButtonAttributes extends HtmlAttributes {
150
+ type?: "button" | "submit" | "reset";
151
+ disabled?: boolean;
152
+ name?: string;
153
+ value?: string;
154
+ }
155
+ export interface InputAttributes extends HtmlAttributes {
156
+ type?: string;
157
+ name?: string;
158
+ value?: string | number;
159
+ placeholder?: string;
160
+ required?: boolean;
161
+ disabled?: boolean;
162
+ readonly?: boolean;
163
+ checked?: boolean;
164
+ min?: string | number;
165
+ max?: string | number;
166
+ step?: string | number;
167
+ pattern?: string;
168
+ autocomplete?: string;
169
+ }
170
+ export interface TextareaAttributes extends HtmlAttributes {
171
+ name?: string;
172
+ rows?: number;
173
+ cols?: number;
174
+ placeholder?: string;
175
+ required?: boolean;
176
+ disabled?: boolean;
177
+ readonly?: boolean;
178
+ }
179
+ export interface FormAttributes extends HtmlAttributes {
180
+ action?: string;
181
+ method?: "get" | "post";
182
+ enctype?: string;
183
+ }
184
+ export interface ImgAttributes extends HtmlAttributes {
185
+ src?: string;
186
+ alt?: string;
187
+ width?: number | string;
188
+ height?: number | string;
189
+ loading?: "lazy" | "eager";
190
+ }
191
+ export interface MetaAttributes extends HtmlAttributes {
192
+ name?: string;
193
+ content?: string;
194
+ charset?: string;
195
+ httpEquiv?: string;
196
+ property?: string;
197
+ "http-equiv"?: string;
198
+ }
199
+ export interface LinkAttributes extends HtmlAttributes {
200
+ rel?: string;
201
+ href?: string;
202
+ type?: string;
203
+ media?: string;
204
+ as?: string;
205
+ }
206
+ export interface ScriptAttributes extends HtmlAttributes {
207
+ src?: string;
208
+ type?: string;
209
+ async?: boolean;
210
+ defer?: boolean;
211
+ module?: boolean;
212
+ }
213
+ //# sourceMappingURL=jsx-runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsx-runtime.d.ts","sourceRoot":"","sources":["../../src/jsx/jsx-runtime.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ // ── TIPOS DEL ÁRBOL JSX ───────────────────────────────────────────────────
2
+ // ── JSX RUNTIME ───────────────────────────────────────────────────────────
3
+ /**
4
+ * Función principal del JSX runtime.
5
+ * TypeScript llama esto cuando encuentra <Tag prop="value" />
6
+ *
7
+ * En lugar de React.createElement, JAMX usa esta función
8
+ * para construir el árbol de nodos que luego serializa a HTML.
9
+ */
10
+ export function jsx(type, props, key) {
11
+ return {
12
+ type,
13
+ props: props ?? {},
14
+ key: key ?? null,
15
+ };
16
+ }
17
+ /**
18
+ * Versión para elementos con múltiples hijos.
19
+ * TypeScript la usa cuando hay más de un hijo.
20
+ */
21
+ export const jsxs = jsx;
22
+ /**
23
+ * Versión dev con información adicional para debugging.
24
+ * En producción es igual a jsx.
25
+ */
26
+ export const jsxDEV = jsx;
27
+ /**
28
+ * Fragment — permite retornar múltiples elementos sin wrapper.
29
+ * Uso: <> <div/> <div/> </>
30
+ */
31
+ export const Fragment = "jamx.fragment";
32
+ //# sourceMappingURL=jsx-runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsx-runtime.js","sourceRoot":"","sources":["../../src/jsx/jsx-runtime.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAuB7E,6EAA6E;AAE7E;;;;;;GAMG;AACH,MAAM,UAAU,GAAG,CACjB,IAA0B,EAC1B,KAAY,EACZ,GAAY;IAEZ,OAAO;QACL,IAAI;QACJ,KAAK,EAAE,KAAK,IAAI,EAAE;QAClB,GAAG,EAAE,GAAG,IAAI,IAAI;KACjB,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG,GAAG,CAAC;AAExB;;;GAGG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,GAAG,CAAC;AAE1B;;;GAGG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,eAAwB,CAAC"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Contexto disponible durante el render de una página.
3
+ * Se pasa al componente para que pueda acceder a datos
4
+ * de la request sin importar directamente @jamx-framework/server.
5
+ */
6
+ export interface RenderContext {
7
+ /** Path de la ruta actual. Ej: /users/123 */
8
+ path: string;
9
+ /** Params de la ruta. Ej: { id: '123' } */
10
+ params: Record<string, string>;
11
+ /** Query string parseado */
12
+ query: Record<string, string | string[]>;
13
+ /** Headers de la request */
14
+ headers: Record<string, string | string[] | undefined>;
15
+ /** Entorno actual */
16
+ env: "development" | "production" | "test";
17
+ }
18
+ /**
19
+ * Resultado del render de una página.
20
+ */
21
+ export interface RenderResult {
22
+ /** HTML completo listo para enviar */
23
+ html: string;
24
+ /** Status HTTP a usar en la response */
25
+ statusCode: number;
26
+ /** Headers adicionales para la response */
27
+ headers: Record<string, string>;
28
+ }
29
+ /**
30
+ * Metadatos de una página para el <head>.
31
+ */
32
+ export interface PageHead {
33
+ title?: string;
34
+ description?: string;
35
+ canonical?: string;
36
+ og?: {
37
+ title?: string;
38
+ description?: string;
39
+ image?: string;
40
+ type?: string;
41
+ };
42
+ [key: string]: unknown;
43
+ }
44
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/pipeline/context.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,6CAA6C;IAC7C,IAAI,EAAE,MAAM,CAAC;IACb,2CAA2C;IAC3C,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,4BAA4B;IAC5B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;IACzC,4BAA4B;IAC5B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC;IACvD,qBAAqB;IACrB,GAAG,EAAE,aAAa,GAAG,YAAY,GAAG,MAAM,CAAC;CAC5C;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,sCAAsC;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,wCAAwC;IACxC,UAAU,EAAE,MAAM,CAAC;IACnB,2CAA2C;IAC3C,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,EAAE,CAAC,EAAE;QACH,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;IACF,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/pipeline/context.ts"],"names":[],"mappings":""}
@@ -0,0 +1,40 @@
1
+ import type { RenderContext, RenderResult, PageHead } from "./context.js";
2
+ import type { JamxNode } from "../jsx/jsx-runtime.js";
3
+ export interface PageComponentLike {
4
+ render: (ctx: RenderContext) => JamxNode;
5
+ meta?: (ctx: RenderContext) => PageHead;
6
+ layout?: LayoutComponentLike;
7
+ }
8
+ export interface LayoutComponentLike {
9
+ render: (props: {
10
+ children: JamxNode;
11
+ ctx: RenderContext;
12
+ }) => JamxNode;
13
+ }
14
+ /**
15
+ * Renderer SSR de JAMX.
16
+ *
17
+ * Convierte un componente de página en un string HTML completo,
18
+ * listo para ser enviado al cliente.
19
+ *
20
+ * Flujo:
21
+ * 1. Llamar page.meta() para obtener los metadatos del <head>
22
+ * 2. Llamar page.render() para obtener el árbol JSX del contenido
23
+ * 3. Si hay layout, envolver el contenido en él
24
+ * 4. Serializar el árbol completo a HTML string
25
+ * 5. Envolver en el documento HTML base
26
+ */
27
+ export declare class SSRRenderer {
28
+ private readonly serializer;
29
+ constructor();
30
+ /**
31
+ * Renderiza una página completa a HTML.
32
+ */
33
+ render(page: PageComponentLike, ctx: RenderContext): Promise<RenderResult>;
34
+ /**
35
+ * Construye el documento HTML completo con el <head> y el <body>.
36
+ */
37
+ private buildDocument;
38
+ private buildMetaTags;
39
+ }
40
+ //# sourceMappingURL=renderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../src/pipeline/renderer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAC1E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEtD,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,CAAC,GAAG,EAAE,aAAa,KAAK,QAAQ,CAAC;IACzC,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,aAAa,KAAK,QAAQ,CAAC;IACxC,MAAM,CAAC,EAAE,mBAAmB,CAAC;CAC9B;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,CAAC,KAAK,EAAE;QAAE,QAAQ,EAAE,QAAQ,CAAC;QAAC,GAAG,EAAE,aAAa,CAAA;KAAE,KAAK,QAAQ,CAAC;CACzE;AAED;;;;;;;;;;;;GAYG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAiB;;IAM5C;;OAEG;IACG,MAAM,CACV,IAAI,EAAE,iBAAiB,EACvB,GAAG,EAAE,aAAa,GACjB,OAAO,CAAC,YAAY,CAAC;IA2BxB;;OAEG;IACH,OAAO,CAAC,aAAa;IA4BrB,OAAO,CAAC,aAAa;CAyBtB"}
@@ -0,0 +1,95 @@
1
+ import { HtmlSerializer } from "../html/serializer.js";
2
+ /**
3
+ * Renderer SSR de JAMX.
4
+ *
5
+ * Convierte un componente de página en un string HTML completo,
6
+ * listo para ser enviado al cliente.
7
+ *
8
+ * Flujo:
9
+ * 1. Llamar page.meta() para obtener los metadatos del <head>
10
+ * 2. Llamar page.render() para obtener el árbol JSX del contenido
11
+ * 3. Si hay layout, envolver el contenido en él
12
+ * 4. Serializar el árbol completo a HTML string
13
+ * 5. Envolver en el documento HTML base
14
+ */
15
+ export class SSRRenderer {
16
+ serializer;
17
+ constructor() {
18
+ this.serializer = new HtmlSerializer();
19
+ }
20
+ /**
21
+ * Renderiza una página completa a HTML.
22
+ */
23
+ async render(page, ctx) {
24
+ // 1. Obtener metadatos
25
+ const head = page.meta?.(ctx) ?? {};
26
+ // 2. Renderizar el contenido de la página
27
+ const contentNode = page.render(ctx);
28
+ // 3. Aplicar layout si existe
29
+ const bodyNode = page.layout
30
+ ? page.layout.render({ children: contentNode, ctx })
31
+ : contentNode;
32
+ // 4. Serializar a string
33
+ const bodyHtml = this.serializer.serialize(bodyNode);
34
+ // 5. Construir el documento HTML completo
35
+ const html = this.buildDocument(bodyHtml, head, ctx);
36
+ return {
37
+ html,
38
+ statusCode: 200,
39
+ headers: {
40
+ "Content-Type": "text/html; charset=utf-8",
41
+ },
42
+ };
43
+ }
44
+ /**
45
+ * Construye el documento HTML completo con el <head> y el <body>.
46
+ */
47
+ buildDocument(bodyHtml, head, ctx) {
48
+ const title = head.title ?? "JAMX App";
49
+ const description = head.description ?? "";
50
+ const isDev = ctx.env === "development";
51
+ const metaTags = this.buildMetaTags(head);
52
+ return `<!DOCTYPE html>
53
+ <html lang="en">
54
+ <head>
55
+ <meta charset="UTF-8" />
56
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
57
+ <title>${escapeTitle(title)}</title>
58
+ ${description ? `<meta name="description" content="${escapeAttr(description)}" />` : ""}
59
+ ${metaTags}
60
+ <link rel="stylesheet" href="/__jamx/styles.css" />
61
+ </head>
62
+ <body>
63
+ <div id="__jamx_root__" data-route="${escapeAttr(ctx.path)}">${bodyHtml}</div>
64
+ <script type="module" src="/__jamx/client.js"${isDev ? ' data-dev="true"' : ""}></script>
65
+ </body>
66
+ </html>`;
67
+ }
68
+ buildMetaTags(head) {
69
+ const tags = [];
70
+ if (head.og) {
71
+ const og = head.og;
72
+ if (og.title)
73
+ tags.push(`<meta property="og:title" content="${escapeAttr(og.title)}" />`);
74
+ if (og.description)
75
+ tags.push(`<meta property="og:description" content="${escapeAttr(og.description)}" />`);
76
+ if (og.image)
77
+ tags.push(`<meta property="og:image" content="${escapeAttr(og.image)}" />`);
78
+ if (og.type)
79
+ tags.push(`<meta property="og:type" content="${escapeAttr(og.type)}" />`);
80
+ }
81
+ return tags.join("\n ");
82
+ }
83
+ }
84
+ // ── HELPERS ───────────────────────────────────────────────────────────────
85
+ function escapeTitle(str) {
86
+ return str.replace(/</g, "&lt;").replace(/>/g, "&gt;");
87
+ }
88
+ function escapeAttr(str) {
89
+ return str
90
+ .replace(/&/g, "&amp;")
91
+ .replace(/"/g, "&quot;")
92
+ .replace(/</g, "&lt;")
93
+ .replace(/>/g, "&gt;");
94
+ }
95
+ //# sourceMappingURL=renderer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"renderer.js","sourceRoot":"","sources":["../../src/pipeline/renderer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAcvD;;;;;;;;;;;;GAYG;AACH,MAAM,OAAO,WAAW;IACL,UAAU,CAAiB;IAE5C;QACE,IAAI,CAAC,UAAU,GAAG,IAAI,cAAc,EAAE,CAAC;IACzC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,MAAM,CACV,IAAuB,EACvB,GAAkB;QAElB,uBAAuB;QACvB,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;QAEpC,0CAA0C;QAC1C,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAErC,8BAA8B;QAC9B,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM;YAC1B,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,GAAG,EAAE,CAAC;YACpD,CAAC,CAAC,WAAW,CAAC;QAEhB,yBAAyB;QACzB,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QAErD,0CAA0C;QAC1C,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa,CAAC,QAAQ,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;QAErD,OAAO;YACL,IAAI;YACJ,UAAU,EAAE,GAAG;YACf,OAAO,EAAE;gBACP,cAAc,EAAE,0BAA0B;aAC3C;SACF,CAAC;IACJ,CAAC;IAED;;OAEG;IACK,aAAa,CACnB,QAAgB,EAChB,IAAc,EACd,GAAkB;QAElB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,UAAU,CAAC;QACvC,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,IAAI,EAAE,CAAC;QAC3C,MAAM,KAAK,GAAG,GAAG,CAAC,GAAG,KAAK,aAAa,CAAC;QAExC,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;QAE1C,OAAO;;;;;WAKA,WAAW,CAAC,KAAK,CAAC;IACzB,WAAW,CAAC,CAAC,CAAC,qCAAqC,UAAU,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE;IACrF,QAAQ;;;;wCAI4B,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,QAAQ;iDACxB,KAAK,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,EAAE;;QAExE,CAAC;IACP,CAAC;IAEO,aAAa,CAAC,IAAc;QAClC,MAAM,IAAI,GAAa,EAAE,CAAC;QAE1B,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC;YACnB,IAAI,EAAE,CAAC,KAAK;gBACV,IAAI,CAAC,IAAI,CACP,sCAAsC,UAAU,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,CACjE,CAAC;YACJ,IAAI,EAAE,CAAC,WAAW;gBAChB,IAAI,CAAC,IAAI,CACP,4CAA4C,UAAU,CAAC,EAAE,CAAC,WAAW,CAAC,MAAM,CAC7E,CAAC;YACJ,IAAI,EAAE,CAAC,KAAK;gBACV,IAAI,CAAC,IAAI,CACP,sCAAsC,UAAU,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,CACjE,CAAC;YACJ,IAAI,EAAE,CAAC,IAAI;gBACT,IAAI,CAAC,IAAI,CACP,qCAAqC,UAAU,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAC/D,CAAC;QACN,CAAC;QAED,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC3B,CAAC;CACF;AAED,6EAA6E;AAE7E,SAAS,WAAW,CAAC,GAAW;IAC9B,OAAO,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AACzD,CAAC;AAED,SAAS,UAAU,CAAC,GAAW;IAC7B,OAAO,GAAG;SACP,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC;SACvB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AAC3B,CAAC"}