ezal-layout 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.
- package/LICENSE +21 -0
- package/dist/build-DiFbTFu2.js +66 -0
- package/dist/build-DiFbTFu2.js.map +1 -0
- package/dist/build.d.ts +4 -0
- package/dist/build.js +3 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/render-vDrLOFud.js +224 -0
- package/dist/render-vDrLOFud.js.map +1 -0
- package/dist/render.d.ts +1 -0
- package/dist/render.js +4 -0
- package/dist/runtime-DfpNzdnp.js +354 -0
- package/dist/runtime-DfpNzdnp.js.map +1 -0
- package/dist/runtime.d.ts +144 -0
- package/dist/runtime.js +10 -0
- package/dist/wrap-CrC23kjY.js +24 -0
- package/dist/wrap-CrC23kjY.js.map +1 -0
- package/dist/wrap.d.ts +2 -0
- package/dist/wrap.js +5 -0
- package/package.json +23 -0
- package/readme.md +28 -0
- package/readme_zh.md +28 -0
- package/runtime.d.ts +623 -0
- package/tsconfig.base.json +12 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Jonny
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
//#region rolldown:runtime
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __copyProps = (to, from, except, desc) => {
|
|
9
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
10
|
+
key = keys[i];
|
|
11
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
12
|
+
get: ((k) => from[k]).bind(null, key),
|
|
13
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
19
|
+
value: mod,
|
|
20
|
+
enumerable: true
|
|
21
|
+
}) : target, mod));
|
|
22
|
+
|
|
23
|
+
//#endregion
|
|
24
|
+
let node_path = require("node:path");
|
|
25
|
+
node_path = __toESM(node_path);
|
|
26
|
+
let esbuild = require("esbuild");
|
|
27
|
+
esbuild = __toESM(esbuild);
|
|
28
|
+
|
|
29
|
+
//#region packages/ezal-layout/src/build.ts
|
|
30
|
+
async function build(src, external) {
|
|
31
|
+
const { outputFiles, metafile: { inputs } } = await esbuild.default.build({
|
|
32
|
+
entryPoints: [src],
|
|
33
|
+
loader: {
|
|
34
|
+
".tsx": "tsx",
|
|
35
|
+
".ts": "ts",
|
|
36
|
+
".jsx": "jsx",
|
|
37
|
+
".js": "js"
|
|
38
|
+
},
|
|
39
|
+
bundle: true,
|
|
40
|
+
platform: "node",
|
|
41
|
+
format: "cjs",
|
|
42
|
+
target: "es2024",
|
|
43
|
+
write: false,
|
|
44
|
+
metafile: true,
|
|
45
|
+
sourcemap: "inline",
|
|
46
|
+
jsxFactory: "h",
|
|
47
|
+
jsxFragment: "Fragment",
|
|
48
|
+
external: external ? Object.keys(external) : void 0,
|
|
49
|
+
treeShaking: true,
|
|
50
|
+
minify: false
|
|
51
|
+
});
|
|
52
|
+
const cwd = process.cwd();
|
|
53
|
+
return {
|
|
54
|
+
content: outputFiles[0].text,
|
|
55
|
+
dependencies: Object.keys(inputs).map((src$1) => node_path.default.join(cwd, src$1))
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
//#endregion
|
|
60
|
+
Object.defineProperty(exports, 'build', {
|
|
61
|
+
enumerable: true,
|
|
62
|
+
get: function () {
|
|
63
|
+
return build;
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
//# sourceMappingURL=build-DiFbTFu2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-DiFbTFu2.js","names":["path","src"],"sources":["../src/build.ts"],"sourcesContent":["import path from 'node:path';\nimport esbuild from 'esbuild';\n\nexport async function build(src: string, external?: Record<string, any>) {\n\tconst {\n\t\toutputFiles,\n\t\tmetafile: { inputs },\n\t} = await esbuild.build({\n\t\t// Load\n\t\tentryPoints: [src],\n\t\tloader: { '.tsx': 'tsx', '.ts': 'ts', '.jsx': 'jsx', '.js': 'js' },\n\t\t// Output\n\t\tbundle: true,\n\t\tplatform: 'node',\n\t\tformat: 'cjs',\n\t\ttarget: 'es2024',\n\t\twrite: false,\n\t\tmetafile: true,\n\t\tsourcemap: 'inline',\n\t\t// JSX\n\t\tjsxFactory: 'h',\n\t\tjsxFragment: 'Fragment',\n\t\t// Other\n\t\texternal: external ? Object.keys(external) : undefined,\n\t\ttreeShaking: true,\n\t\tminify: false,\n\t});\n\tconst cwd = process.cwd();\n\tconst content = outputFiles[0].text;\n\tconst dependencies = Object.keys(inputs).map((src) => path.join(cwd, src));\n\treturn { content, dependencies };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAGA,eAAsB,MAAM,KAAa,UAAgC;CACxE,MAAM,EACL,aACA,UAAU,EAAE,aACT,MAAM,gBAAQ,MAAM;EAEvB,aAAa,CAAC,IAAI;EAClB,QAAQ;GAAE,QAAQ;GAAO,OAAO;GAAM,QAAQ;GAAO,OAAO;GAAM;EAElE,QAAQ;EACR,UAAU;EACV,QAAQ;EACR,QAAQ;EACR,OAAO;EACP,UAAU;EACV,WAAW;EAEX,YAAY;EACZ,aAAa;EAEb,UAAU,WAAW,OAAO,KAAK,SAAS,GAAG;EAC7C,aAAa;EACb,QAAQ;EACR,CAAC;CACF,MAAM,MAAM,QAAQ,KAAK;AAGzB,QAAO;EAAE,SAFO,YAAY,GAAG;EAEb,cADG,OAAO,KAAK,OAAO,CAAC,KAAK,UAAQA,kBAAK,KAAK,KAAKC,MAAI,CAAC;EAC1C"}
|
package/dist/build.d.ts
ADDED
package/dist/build.js
ADDED
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export type LayoutContext = Record<string | number | symbol, any>;
|
|
2
|
+
export type LayoutRenderer = (context: LayoutContext) => Promise<string>;
|
|
3
|
+
export interface EzalLayoutRenderer {
|
|
4
|
+
renderer: LayoutRenderer;
|
|
5
|
+
dependencies: string[];
|
|
6
|
+
}
|
|
7
|
+
export declare function compile(src: string, external?: Record<string, any>): Promise<EzalLayoutRenderer>;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const require_build = require('./build-DiFbTFu2.js');
|
|
2
|
+
require('./runtime-DfpNzdnp.js');
|
|
3
|
+
require('./render-vDrLOFud.js');
|
|
4
|
+
const require_wrap = require('./wrap-CrC23kjY.js');
|
|
5
|
+
|
|
6
|
+
//#region packages/ezal-layout/src/index.ts
|
|
7
|
+
async function compile(src, external) {
|
|
8
|
+
const { content, dependencies } = await require_build.build(src, external);
|
|
9
|
+
return {
|
|
10
|
+
renderer: await require_wrap.wrap(content, external),
|
|
11
|
+
dependencies
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
//#endregion
|
|
16
|
+
exports.compile = compile;
|
|
17
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":["build","wrap"],"sources":["../src/index.ts"],"sourcesContent":["import { build } from './build';\nimport wrap from './wrap';\n\nexport type LayoutContext = Record<string | number | symbol, any>;\nexport type LayoutRenderer = (context: LayoutContext) => Promise<string>;\nexport interface EzalLayoutRenderer {\n\trenderer: LayoutRenderer;\n\tdependencies: string[];\n}\n\nexport async function compile(\n\tsrc: string,\n\texternal?: Record<string, any>,\n): Promise<EzalLayoutRenderer> {\n\tconst { content, dependencies } = await build(src, external);\n\treturn { renderer: await wrap(content, external), dependencies };\n}\n"],"mappings":";;;;;;AAUA,eAAsB,QACrB,KACA,UAC8B;CAC9B,MAAM,EAAE,SAAS,iBAAiB,MAAMA,oBAAM,KAAK,SAAS;AAC5D,QAAO;EAAE,UAAU,MAAMC,kBAAK,SAAS,SAAS;EAAE;EAAc"}
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
const require_runtime = require('./runtime-DfpNzdnp.js');
|
|
2
|
+
|
|
3
|
+
//#region packages/ezal-layout/src/render.ts
|
|
4
|
+
const VOID_ELEMENT = new Set([
|
|
5
|
+
"area",
|
|
6
|
+
"base",
|
|
7
|
+
"br",
|
|
8
|
+
"embed",
|
|
9
|
+
"hr",
|
|
10
|
+
"img",
|
|
11
|
+
"input",
|
|
12
|
+
"link",
|
|
13
|
+
"meta",
|
|
14
|
+
"source",
|
|
15
|
+
"track",
|
|
16
|
+
"wbr"
|
|
17
|
+
]);
|
|
18
|
+
const PATTERN_HTML_CHAR = /[&<>"']/g;
|
|
19
|
+
const HTML_ESCAPE_MAP = {
|
|
20
|
+
"&": "&",
|
|
21
|
+
"<": "<",
|
|
22
|
+
">": ">",
|
|
23
|
+
"\"": """,
|
|
24
|
+
"'": "'"
|
|
25
|
+
};
|
|
26
|
+
/** 转义 HTML */
|
|
27
|
+
function escapeHTML(text) {
|
|
28
|
+
return text.replace(PATTERN_HTML_CHAR, (char) => HTML_ESCAPE_MAP[char]);
|
|
29
|
+
}
|
|
30
|
+
const ILLEGAL_ATTR_NAME_CHAR = /[ "'<=>/\t\n\f\r\0]/;
|
|
31
|
+
const BOOL_ATTR = new Set([
|
|
32
|
+
"autofocus",
|
|
33
|
+
"hidden",
|
|
34
|
+
"inert",
|
|
35
|
+
"itemscope"
|
|
36
|
+
]);
|
|
37
|
+
const LITERAL_ATTR = new Set([
|
|
38
|
+
"contenteditable",
|
|
39
|
+
"draggable",
|
|
40
|
+
"spellcheck"
|
|
41
|
+
]);
|
|
42
|
+
const TAG_BOOL_ATTR = new Map([
|
|
43
|
+
["audio", new Set([
|
|
44
|
+
"autoplay",
|
|
45
|
+
"loop",
|
|
46
|
+
"muted"
|
|
47
|
+
])],
|
|
48
|
+
["button", new Set(["disabled"])],
|
|
49
|
+
["fieldset", new Set(["disabled"])],
|
|
50
|
+
["details", new Set(["open"])],
|
|
51
|
+
["dialog", new Set(["open"])],
|
|
52
|
+
["form", new Set(["novalidate"])],
|
|
53
|
+
["img", new Set(["ismap"])],
|
|
54
|
+
["input", new Set([
|
|
55
|
+
"autocomplete",
|
|
56
|
+
"checked",
|
|
57
|
+
"disabled",
|
|
58
|
+
"multiple",
|
|
59
|
+
"readonly",
|
|
60
|
+
"required"
|
|
61
|
+
])],
|
|
62
|
+
["link", new Set(["disabled"])],
|
|
63
|
+
["ol", new Set(["reversed"])],
|
|
64
|
+
["optgroup", new Set(["disabled"])],
|
|
65
|
+
["option", new Set(["disabled", "selected"])],
|
|
66
|
+
["script", new Set([
|
|
67
|
+
"async",
|
|
68
|
+
"defer",
|
|
69
|
+
"nomodule"
|
|
70
|
+
])],
|
|
71
|
+
["select", new Set([
|
|
72
|
+
"autofocus",
|
|
73
|
+
"disabled",
|
|
74
|
+
"multiple",
|
|
75
|
+
"required"
|
|
76
|
+
])],
|
|
77
|
+
["textarea", new Set([
|
|
78
|
+
"autocapitalize",
|
|
79
|
+
"autofocus",
|
|
80
|
+
"disabled",
|
|
81
|
+
"readonly",
|
|
82
|
+
"required"
|
|
83
|
+
])],
|
|
84
|
+
["video", new Set([
|
|
85
|
+
"autoplay",
|
|
86
|
+
"disablepictureinpicture",
|
|
87
|
+
"disableremoteplayback",
|
|
88
|
+
"loop",
|
|
89
|
+
"muted",
|
|
90
|
+
"playsinline"
|
|
91
|
+
])]
|
|
92
|
+
]);
|
|
93
|
+
const TAG_LITERAL_ATTR = new Map([["audio", new Set(["controls"])], ["video", new Set(["controls"])]]);
|
|
94
|
+
const ATTRIBUTE_RULES = [
|
|
95
|
+
(value, name) => {
|
|
96
|
+
if (name !== "class") return null;
|
|
97
|
+
return `class="${escapeHTML(classList(value))}"`;
|
|
98
|
+
},
|
|
99
|
+
(value, name) => {
|
|
100
|
+
if (name !== "style") return null;
|
|
101
|
+
return `style="${escapeHTML(style(value))}"`;
|
|
102
|
+
},
|
|
103
|
+
(value, name, tag) => {
|
|
104
|
+
if (!TAG_BOOL_ATTR.get(tag)?.has(name)) return null;
|
|
105
|
+
return value ? name : "";
|
|
106
|
+
},
|
|
107
|
+
(value, name, tag) => {
|
|
108
|
+
if (!TAG_LITERAL_ATTR.get(tag)?.has(name)) return null;
|
|
109
|
+
return value ? name : "";
|
|
110
|
+
},
|
|
111
|
+
(value, name) => {
|
|
112
|
+
if (!BOOL_ATTR.has(name)) return null;
|
|
113
|
+
return value ? name : "";
|
|
114
|
+
},
|
|
115
|
+
(value, name) => LITERAL_ATTR.has(name) ? String(value) : null,
|
|
116
|
+
(value, name) => {
|
|
117
|
+
if (value === true) return name;
|
|
118
|
+
if (value === false) return "";
|
|
119
|
+
if (value instanceof URL) value = value.href;
|
|
120
|
+
return `${name}="${escapeHTML(String(value))}"`;
|
|
121
|
+
}
|
|
122
|
+
];
|
|
123
|
+
function classList(value) {
|
|
124
|
+
if (Array.isArray(value)) return value.map(String).join(" ");
|
|
125
|
+
if (typeof value === "string") return value;
|
|
126
|
+
if (!value || typeof value !== "object") return "";
|
|
127
|
+
return Object.entries(value).filter(([_, v]) => v).map(String).join(" ");
|
|
128
|
+
}
|
|
129
|
+
const PATTERN_CSS_VAR_DECLARE = /^\$/;
|
|
130
|
+
const PATTERN_CSS_UPPER = /[A-Z]/g;
|
|
131
|
+
const PATTERN_CSS_VAR = /\$[A-Za-z][A-Za-z0-9]*/g;
|
|
132
|
+
function style(value) {
|
|
133
|
+
if (typeof value === "string") return value;
|
|
134
|
+
return Object.entries(value).filter(([_, v]) => v !== null && v !== void 0).map(([name, value$1]) => {
|
|
135
|
+
if (typeof value$1 === "number") return [name, `${value$1}px`];
|
|
136
|
+
if (typeof value$1 !== "string") return [name, String(value$1)];
|
|
137
|
+
value$1 = value$1.replace(PATTERN_CSS_VAR, (v) => `var(${v.replace(PATTERN_CSS_VAR_DECLARE, "--").replaceAll(PATTERN_CSS_UPPER, (char) => `-${char.toLowerCase()}`)})`);
|
|
138
|
+
return [name, value$1];
|
|
139
|
+
}).map(([name, value$1]) => {
|
|
140
|
+
name = name.replace(PATTERN_CSS_VAR_DECLARE, "--").replaceAll(PATTERN_CSS_UPPER, (char) => `-${char.toLowerCase()}`);
|
|
141
|
+
return [name, value$1];
|
|
142
|
+
}).map(([name, value$1]) => `${name}:${value$1};`).join("");
|
|
143
|
+
}
|
|
144
|
+
function attr(node) {
|
|
145
|
+
const result = [];
|
|
146
|
+
for (const [name, value] of Object.entries(node.attr)) {
|
|
147
|
+
if (ILLEGAL_ATTR_NAME_CHAR.test(name)) throw new Error("Using illegal char in attribute name", { cause: node });
|
|
148
|
+
if (value === null || value === void 0) continue;
|
|
149
|
+
for (const r of ATTRIBUTE_RULES) {
|
|
150
|
+
const v = r(value, name, node.name);
|
|
151
|
+
if (v === null) continue;
|
|
152
|
+
result.push(v);
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return result.join("");
|
|
157
|
+
}
|
|
158
|
+
function head(node) {
|
|
159
|
+
if (node instanceof require_runtime.ContainerNode) return "";
|
|
160
|
+
let result = "";
|
|
161
|
+
if (node instanceof require_runtime.DocNode) result += "<!DOCTYPE html><html";
|
|
162
|
+
else result += `<${node.name}`;
|
|
163
|
+
const attrText = attr(node);
|
|
164
|
+
if (attrText) result += ` ${attrText}`;
|
|
165
|
+
result += ">";
|
|
166
|
+
return result;
|
|
167
|
+
}
|
|
168
|
+
function tail(node) {
|
|
169
|
+
if (node instanceof require_runtime.ContainerNode) return "";
|
|
170
|
+
if (node instanceof require_runtime.DocNode) return "</html>";
|
|
171
|
+
return `</${node.name}>`;
|
|
172
|
+
}
|
|
173
|
+
function render(input) {
|
|
174
|
+
if (Array.isArray(input)) return input.flat(Infinity).filter((v) => v !== null && v !== void 0).map(render).join("");
|
|
175
|
+
if (input === null) return "";
|
|
176
|
+
if (input === void 0) return "";
|
|
177
|
+
if (!(input instanceof require_runtime.Node)) return String(input);
|
|
178
|
+
if (input instanceof require_runtime.RawHTMLNode) return input.html;
|
|
179
|
+
const result = [];
|
|
180
|
+
const stack = [[input, input.entires()]];
|
|
181
|
+
result.push(head(input));
|
|
182
|
+
ENTER: while (true) {
|
|
183
|
+
const current = stack.at(-1);
|
|
184
|
+
if (!current) break;
|
|
185
|
+
const [node, generator] = current;
|
|
186
|
+
if (VOID_ELEMENT.has(node.name)) {
|
|
187
|
+
stack.pop();
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
while (true) {
|
|
191
|
+
const next = generator.next();
|
|
192
|
+
if (next.done) break;
|
|
193
|
+
const child = next.value;
|
|
194
|
+
if (typeof child === "string") {
|
|
195
|
+
result.push(escapeHTML(child));
|
|
196
|
+
continue;
|
|
197
|
+
}
|
|
198
|
+
if (child instanceof require_runtime.RawHTMLNode) {
|
|
199
|
+
result.push(child.html);
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
result.push(head(child));
|
|
203
|
+
if (VOID_ELEMENT.has(child.name)) continue;
|
|
204
|
+
if (child.childrenCount === 0) {
|
|
205
|
+
result.push(tail(child));
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
stack.push([child, child.entires()]);
|
|
209
|
+
continue ENTER;
|
|
210
|
+
}
|
|
211
|
+
stack.pop();
|
|
212
|
+
result.push(tail(node));
|
|
213
|
+
}
|
|
214
|
+
return result.join("");
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
//#endregion
|
|
218
|
+
Object.defineProperty(exports, 'render', {
|
|
219
|
+
enumerable: true,
|
|
220
|
+
get: function () {
|
|
221
|
+
return render;
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
//# sourceMappingURL=render-vDrLOFud.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-vDrLOFud.js","names":["HTML_ESCAPE_MAP: Record<string, string>","ATTRIBUTE_RULES: ((\n\tvalue: any,\n\tname: string,\n\ttag: string,\n) => string | null)[]","value","result: string[]","ContainerNode","DocNode","Node","RawHTMLNode","stack: [Node, Generator<string | Node>][]"],"sources":["../src/render.ts"],"sourcesContent":["import { ContainerNode, DocNode, Node, RawHTMLNode } from './runtime';\n\nconst VOID_ELEMENT = new Set([\n\t'area',\n\t'base',\n\t'br',\n\t'embed',\n\t'hr',\n\t'img',\n\t'input',\n\t'link',\n\t'meta',\n\t'source',\n\t'track',\n\t'wbr',\n]);\n\nconst PATTERN_HTML_CHAR = /[&<>\"']/g;\nconst HTML_ESCAPE_MAP: Record<string, string> = {\n\t'&': '&',\n\t'<': '<',\n\t'>': '>',\n\t'\"': '"',\n\t\"'\": ''',\n};\n/** 转义 HTML */\nfunction escapeHTML(text: string): string {\n\treturn text.replace(PATTERN_HTML_CHAR, (char) => HTML_ESCAPE_MAP[char]);\n}\n\nconst ILLEGAL_ATTR_NAME_CHAR = /[ \"'<=>/\\t\\n\\f\\r\\0]/;\nconst BOOL_ATTR = new Set(['autofocus', 'hidden', 'inert', 'itemscope']);\nconst LITERAL_ATTR = new Set(['contenteditable', 'draggable', 'spellcheck']);\nconst TAG_BOOL_ATTR = new Map([\n\t['audio', new Set(['autoplay', 'loop', 'muted'])],\n\t['button', new Set(['disabled'])],\n\t['fieldset', new Set(['disabled'])],\n\t['details', new Set(['open'])],\n\t['dialog', new Set(['open'])],\n\t['form', new Set(['novalidate'])],\n\t['img', new Set(['ismap'])],\n\t[\n\t\t'input',\n\t\tnew Set([\n\t\t\t'autocomplete',\n\t\t\t'checked',\n\t\t\t'disabled',\n\t\t\t'multiple',\n\t\t\t'readonly',\n\t\t\t'required',\n\t\t]),\n\t],\n\t['link', new Set(['disabled'])],\n\t['ol', new Set(['reversed'])],\n\t['optgroup', new Set(['disabled'])],\n\t['option', new Set(['disabled', 'selected'])],\n\t['script', new Set(['async', 'defer', 'nomodule'])],\n\t['select', new Set(['autofocus', 'disabled', 'multiple', 'required'])],\n\t[\n\t\t'textarea',\n\t\tnew Set(['autocapitalize', 'autofocus', 'disabled', 'readonly', 'required']),\n\t],\n\t[\n\t\t'video',\n\t\tnew Set([\n\t\t\t'autoplay',\n\t\t\t'disablepictureinpicture',\n\t\t\t'disableremoteplayback',\n\t\t\t'loop',\n\t\t\t'muted',\n\t\t\t'playsinline',\n\t\t]),\n\t],\n]);\nconst TAG_LITERAL_ATTR = new Map([\n\t['audio', new Set(['controls'])],\n\t['video', new Set(['controls'])],\n]);\n\nconst ATTRIBUTE_RULES: ((\n\tvalue: any,\n\tname: string,\n\ttag: string,\n) => string | null)[] = [\n\t(value, name) => {\n\t\tif (name !== 'class') return null;\n\t\treturn `class=\"${escapeHTML(classList(value))}\"`;\n\t},\n\t(value, name) => {\n\t\tif (name !== 'style') return null;\n\t\treturn `style=\"${escapeHTML(style(value))}\"`;\n\t},\n\t(value, name, tag) => {\n\t\tif (!TAG_BOOL_ATTR.get(tag)?.has(name)) return null;\n\t\treturn value ? name : '';\n\t},\n\t(value, name, tag) => {\n\t\tif (!TAG_LITERAL_ATTR.get(tag)?.has(name)) return null;\n\t\treturn value ? name : '';\n\t},\n\t(value, name) => {\n\t\tif (!BOOL_ATTR.has(name)) return null;\n\t\treturn value ? name : '';\n\t},\n\t(value, name) => (LITERAL_ATTR.has(name) ? String(value) : null),\n\t(value, name) => {\n\t\tif (value === true) return name;\n\t\tif (value === false) return '';\n\t\tif (value instanceof URL) value = value.href;\n\t\treturn `${name}=\"${escapeHTML(String(value))}\"`;\n\t},\n];\n\nfunction classList(value: any): string {\n\tif (Array.isArray(value)) return value.map(String).join(' ');\n\tif (typeof value === 'string') return value;\n\tif (!value || typeof value !== 'object') return '';\n\treturn Object.entries(value)\n\t\t.filter(([_, v]) => v)\n\t\t.map(String)\n\t\t.join(' ');\n}\n\nconst PATTERN_CSS_VAR_DECLARE = /^\\$/;\nconst PATTERN_CSS_UPPER = /[A-Z]/g;\nconst PATTERN_CSS_VAR = /\\$[A-Za-z][A-Za-z0-9]*/g;\n\nfunction style(value: any): string {\n\tif (typeof value === 'string') return value;\n\treturn Object.entries(value)\n\t\t.filter(([_, v]) => v !== null && v !== undefined)\n\t\t.map<[string, string]>(([name, value]) => {\n\t\t\tif (typeof value === 'number') return [name, `${value}px`];\n\t\t\tif (typeof value !== 'string') return [name, String(value)];\n\t\t\tvalue = value.replace(\n\t\t\t\tPATTERN_CSS_VAR,\n\t\t\t\t(v) =>\n\t\t\t\t\t`var(${v\n\t\t\t\t\t\t.replace(PATTERN_CSS_VAR_DECLARE, '--')\n\t\t\t\t\t\t.replaceAll(PATTERN_CSS_UPPER, (char) => `-${char.toLowerCase()}`)})`,\n\t\t\t);\n\t\t\treturn [name, value as string];\n\t\t})\n\t\t.map<[string, string]>(([name, value]) => {\n\t\t\tname = name\n\t\t\t\t.replace(PATTERN_CSS_VAR_DECLARE, '--')\n\t\t\t\t.replaceAll(PATTERN_CSS_UPPER, (char) => `-${char.toLowerCase()}`);\n\t\t\treturn [name, value];\n\t\t})\n\t\t.map(([name, value]) => `${name}:${value};`)\n\t\t.join('');\n}\n\nfunction attr(node: Node): string {\n\tconst result: string[] = [];\n\tfor (const [name, value] of Object.entries(node.attr)) {\n\t\tif (ILLEGAL_ATTR_NAME_CHAR.test(name)) {\n\t\t\tthrow new Error('Using illegal char in attribute name', { cause: node });\n\t\t}\n\t\tif (value === null || value === undefined) continue;\n\t\tfor (const r of ATTRIBUTE_RULES) {\n\t\t\tconst v = r(value, name, node.name);\n\t\t\tif (v === null) continue;\n\t\t\tresult.push(v);\n\t\t\tbreak;\n\t\t}\n\t}\n\treturn result.join('');\n}\n\nfunction head(node: Node): string {\n\tif (node instanceof ContainerNode) return '';\n\tlet result = '';\n\tif (node instanceof DocNode) result += '<!DOCTYPE html><html';\n\telse result += `<${node.name}`;\n\tconst attrText = attr(node);\n\tif (attrText) result += ` ${attrText}`;\n\tresult += '>';\n\treturn result;\n}\n\nfunction tail(node: Node): string {\n\tif (node instanceof ContainerNode) return '';\n\tif (node instanceof DocNode) return '</html>';\n\treturn `</${node.name}>`;\n}\n\nexport function render(input: any): string {\n\tif (Array.isArray(input)) {\n\t\treturn input\n\t\t\t.flat(Infinity)\n\t\t\t.filter((v) => v !== null && v !== undefined)\n\t\t\t.map(render)\n\t\t\t.join('');\n\t}\n\tif (input === null) return '';\n\tif (input === undefined) return '';\n\tif (!(input instanceof Node)) return String(input);\n\tif (input instanceof RawHTMLNode) return input.html;\n\tconst result: string[] = [];\n\tconst stack: [Node, Generator<string | Node>][] = [[input, input.entires()]];\n\tresult.push(head(input));\n\tENTER: while (true) {\n\t\tconst current = stack.at(-1);\n\t\tif (!current) break;\n\t\tconst [node, generator] = current;\n\t\tif (VOID_ELEMENT.has(node.name)) {\n\t\t\tstack.pop();\n\t\t\tcontinue;\n\t\t}\n\t\twhile (true) {\n\t\t\tconst next = generator.next();\n\t\t\tif (next.done) break;\n\t\t\tconst child = next.value;\n\t\t\tif (typeof child === 'string') {\n\t\t\t\tresult.push(escapeHTML(child));\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (child instanceof RawHTMLNode) {\n\t\t\t\tresult.push(child.html);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tresult.push(head(child));\n\t\t\tif (VOID_ELEMENT.has(child.name)) continue;\n\t\t\tif (child.childrenCount === 0) {\n\t\t\t\tresult.push(tail(child));\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tstack.push([child, child.entires()]);\n\t\t\tcontinue ENTER;\n\t\t}\n\t\tstack.pop();\n\t\tresult.push(tail(node));\n\t}\n\treturn result.join('');\n}\n"],"mappings":"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"}
|
package/dist/render.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function render(input: any): string;
|
package/dist/render.js
ADDED