@yunzai-ng/jsx 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 ADDED
@@ -0,0 +1,48 @@
1
+ # @yunzai-ng/jsx
2
+
3
+ 给写渲染模板的人的一个可选 JSX 运行时。产出 HTML 字符串,不涉及浏览器。
4
+
5
+ ## 为什么不是 core 的一个子路径
6
+
7
+ 分层门禁把 `@yunzai-ng/core/*` 的任意子路径判为「深引内核内部实现」。为一个 JSX 运行时给门禁
8
+ 开洞不划算;独立成包之后,第三方插件也能只依赖它而不牵入整个内核。
9
+
10
+ ## 用法
11
+
12
+ 在插件的 `tsconfig.json` 里指向它:
13
+
14
+ ```json
15
+ {
16
+ "compilerOptions": {
17
+ "jsx": "react-jsx",
18
+ "jsxImportSource": "@yunzai-ng/jsx"
19
+ }
20
+ }
21
+ ```
22
+
23
+ 然后模板就是一个函数:
24
+
25
+ ```tsx
26
+ import { Html, cx } from "@yunzai-ng/jsx"
27
+
28
+ export function Profile({ name, level }: { name: string; level: number }) {
29
+ return (
30
+ <Html title={name}>
31
+ <div class={cx("card", level >= 60 && "card-max")}>
32
+ <h1>{name}</h1>
33
+ <p>等级 {level}</p>
34
+ </div>
35
+ </Html>
36
+ )
37
+ }
38
+ ```
39
+
40
+ 把它的返回值交给 `ctx.render()`。
41
+
42
+ ## 两处要注意
43
+
44
+ **默认转义。** 插进去的值一律转义,故用户昵称里的 `<script>` 不会变成脚本。确实要插入原始
45
+ HTML 时用 `raw()` —— 它显眼,便于审阅时逐个确认。
46
+
47
+ **`cx()` 与 `style()` 是为条件拼接准备的。** 手写 `class={"a " + (b ? "c" : "")}` 会在条件为假时
48
+ 留下一个尾随空格,而某些工具类框架对空 class 的处理并不一致。
@@ -0,0 +1,16 @@
1
+ /**
2
+ * 序列化属性
3
+ * @param props 属性对象
4
+ * @returns 以空格开头的属性串;无属性时为空串
5
+ * @throws 属性名不合法时抛出 TypeError
6
+ */
7
+ export declare function attributes(props: Readonly<Record<string, unknown>>): string;
8
+ /**
9
+ * 序列化一个元素
10
+ * @param tag 标签名
11
+ * @param props 属性对象(含 `children`)
12
+ * @returns HTML 文本
13
+ * @throws 标签名不合法时抛出 TypeError
14
+ */
15
+ export declare function element(tag: string, props: Readonly<Record<string, unknown>>): string;
16
+ //# sourceMappingURL=element.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"element.d.ts","sourceRoot":"","sources":["../src/element.ts"],"names":[],"mappings":"AA+CA;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,MAAM,CAgC3E;AAED;;;;;;GAMG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,MAAM,CAKrF"}
@@ -0,0 +1,93 @@
1
+ /**
2
+ * 模块职责:把标签名与属性对象序列化成 HTML 文本
3
+ * 依赖方向:仅依赖同包的 `html.ts`
4
+ * 生命周期:无状态,纯函数
5
+ * 注意事项:标签名与属性名均须通过白名单校验。属性名并非全部来自源码字面量 ——
6
+ * `{...props}` 展开可以把任意键带进来,其中若含空格或引号,即可在生成的标签里
7
+ * 插入一个新属性。此处直接抛错而非静默丢弃:这类问题在模板作者一侧一次性可修,
8
+ * 悄悄少输出一个属性反而要到成品图上才被发现。
9
+ */
10
+ import { children, cx, escape, style } from "./html.js";
11
+ /**
12
+ * 空元素(HTML 规范中不允许有内容、也不写闭合标签的那些)
13
+ *
14
+ * 为它们补一个 `</img>` 会被解析器当作多余的结束标签忽略,看似无害;但 `<br></br>`
15
+ * 在部分场景下会被解析成两个换行。按规范只输出开始标签。
16
+ */
17
+ const VOID_TAGS = new Set([
18
+ "area",
19
+ "base",
20
+ "br",
21
+ "col",
22
+ "embed",
23
+ "hr",
24
+ "img",
25
+ "input",
26
+ "link",
27
+ "meta",
28
+ "param",
29
+ "source",
30
+ "track",
31
+ "wbr"
32
+ ]);
33
+ /** React 为规避 JS 保留字而改名的两个属性,作为别名接纳 */
34
+ const ALIASES = { className: "class", htmlFor: "for" };
35
+ /** 不参与属性输出的键 */
36
+ const DROPPED = new Set(["children", "key", "class", "className"]);
37
+ /** 合法标签名 */
38
+ const VALID_TAG = /^[A-Za-z][\w.:-]*$/;
39
+ /** 合法属性名;与 HTML 规范一致地允许连字符、点与冒号 */
40
+ const VALID_ATTR = /^[A-Za-z_:][\w.:-]*$/;
41
+ /**
42
+ * 序列化属性
43
+ * @param props 属性对象
44
+ * @returns 以空格开头的属性串;无属性时为空串
45
+ * @throws 属性名不合法时抛出 TypeError
46
+ */
47
+ export function attributes(props) {
48
+ let out = "";
49
+ // class 与 className 合并后一次输出:两者都写时分别输出会得到两个 class 属性,
50
+ // 浏览器只认第一个,后一个静默丢失
51
+ const classes = cx(props["class"], props["className"]);
52
+ if (classes)
53
+ out += ` class="${escape(classes)}"`;
54
+ for (const [key, value] of Object.entries(props)) {
55
+ if (DROPPED.has(key))
56
+ continue;
57
+ if (value === null || value === undefined || value === false)
58
+ continue;
59
+ const name = ALIASES[key] ?? key;
60
+ if (!VALID_ATTR.test(name))
61
+ throw new TypeError(`非法的属性名:${JSON.stringify(key)}`);
62
+ // 布尔属性(hidden、disabled 之类)输出裸属性名。写成 `hidden="false"` 反而是生效的,
63
+ // 因为 HTML 只看属性是否存在
64
+ if (value === true) {
65
+ out += ` ${name}`;
66
+ continue;
67
+ }
68
+ if (name === "style") {
69
+ const css = style(value);
70
+ if (css)
71
+ out += ` style="${escape(css)}"`;
72
+ continue;
73
+ }
74
+ out += ` ${name}="${escape(value)}"`;
75
+ }
76
+ return out;
77
+ }
78
+ /**
79
+ * 序列化一个元素
80
+ * @param tag 标签名
81
+ * @param props 属性对象(含 `children`)
82
+ * @returns HTML 文本
83
+ * @throws 标签名不合法时抛出 TypeError
84
+ */
85
+ export function element(tag, props) {
86
+ if (!VALID_TAG.test(tag))
87
+ throw new TypeError(`非法的标签名:${JSON.stringify(tag)}`);
88
+ const head = `<${tag}${attributes(props)}>`;
89
+ if (VOID_TAGS.has(tag.toLowerCase()))
90
+ return head;
91
+ return `${head}${children(props["children"])}</${tag}>`;
92
+ }
93
+ //# sourceMappingURL=element.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"element.js","sourceRoot":"","sources":["../src/element.ts"],"names":[],"mappings":"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"}
package/dist/html.d.ts ADDED
@@ -0,0 +1,84 @@
1
+ /**
2
+ * 模块职责:HTML 文本的载体、转义,以及 `class` / `style` / 子节点的求值
3
+ * 依赖方向:叶子模块,仅取同包的类型
4
+ * 生命周期:无状态,全部为纯函数
5
+ * 注意事项:默认行为是**转义**,`raw()` 是唯一的逃生口。反过来(默认原样输出、需要时
6
+ * 显式转义)在实践中必然遗漏 —— 米游社返回的昵称含一个尖括号即可破坏整张图的
7
+ * 结构,而这种数据只在真机上才会出现,单测覆盖不到。
8
+ */
9
+ import type { Child, ClassValue, StyleDict } from "./types.js";
10
+ /**
11
+ * 已完成转义、可直接写入文档的 HTML 文本
12
+ *
13
+ * 仅是一个带类型标记的字符串包装:模板的产物是一次性的文本,虚拟 DOM 的 diff 能力在此
14
+ * 毫无用处,而 react / preact 会为此引入数十个传递依赖。Termux 上包体越小越好,
15
+ * 这笔交换不成立。
16
+ */
17
+ export declare class Html {
18
+ /** HTML 文本 */
19
+ readonly value: string;
20
+ /**
21
+ * @param value 已转义的 HTML 文本
22
+ */
23
+ constructor(value: string);
24
+ /**
25
+ * 判定任意值是否为 Html
26
+ * @param input 待判定的值
27
+ * @returns 是 Html 则为真
28
+ */
29
+ static is(input: unknown): input is Html;
30
+ /**
31
+ * 取 HTML 文本
32
+ * @returns HTML 文本
33
+ */
34
+ toString(): string;
35
+ /**
36
+ * 参与 `JSON.stringify` 时退化为文本,使快照测试可直接序列化
37
+ * @returns HTML 文本
38
+ */
39
+ toJSON(): string;
40
+ }
41
+ /**
42
+ * 转义为 HTML 文本
43
+ *
44
+ * `null` 与 `undefined` 转为空串而非字面量 "null" —— 模板里 `{user.nick}` 取到空值时
45
+ * 应当什么都不显示,打印出 "undefined" 只会出现在成品图上。
46
+ * @param input 任意值
47
+ * @returns 转义后的文本
48
+ */
49
+ export declare function escape(input: unknown): string;
50
+ /**
51
+ * 声明一段文本已经是安全的 HTML,跳过转义
52
+ *
53
+ * 唯一的逃生口,仅用于本模块自己生成的标签、`<!DOCTYPE html>`,以及编译产物这类
54
+ * 确定安全的内容。**不要**用它包裹任何来自接口的数据。
55
+ * @param value HTML 文本
56
+ * @returns 载体
57
+ */
58
+ export declare function raw(value: string): Html;
59
+ /**
60
+ * 求值类名
61
+ *
62
+ * 接纳字符串、条件字典与任意嵌套数组三种形态,使 `class={["cont", full && "full"]}`
63
+ * 与 `class={{ up: delta > 0 }}` 都可直接书写,无需在模板里拼字符串。
64
+ * @param inputs 任意个类名输入
65
+ * @returns 以空格分隔、已去重的类名串
66
+ */
67
+ export declare function cx(...inputs: ClassValue[]): string;
68
+ /**
69
+ * 求值内联样式
70
+ *
71
+ * 数值不会被自动补上 `px`:React 的这套隐式补单位规则需要一张"哪些属性是长度"的名单,
72
+ * 名单不全时表现为样式静默失效。此处要求显式书写单位,宽度写成百分号模板串一目了然。
73
+ * 以 `--` 开头的自定义属性保留原始大小写 —— 它们区分大小写,转换会改变含义。
74
+ * @param input 样式字符串或字典
75
+ * @returns CSS 声明串
76
+ */
77
+ export declare function style(input: string | StyleDict): string;
78
+ /**
79
+ * 求值子节点
80
+ * @param child 子节点
81
+ * @returns 拼接好的 HTML 文本
82
+ */
83
+ export declare function children(child: Child): string;
84
+ //# sourceMappingURL=html.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html.d.ts","sourceRoot":"","sources":["../src/html.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAc9D;;;;;;GAMG;AACH,qBAAa,IAAI;IACf,cAAc;IACd,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IAEtB;;OAEG;gBACS,KAAK,EAAE,MAAM;IAIzB;;;;OAIG;IACH,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,IAAI;IAIxC;;;OAGG;IACH,QAAQ,IAAI,MAAM;IAIlB;;;OAGG;IACH,MAAM,IAAI,MAAM;CAGjB;AAED;;;;;;;GAOG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAG7C;AAED;;;;;;;GAOG;AACH,wBAAgB,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAEvC;AAED;;;;;;;GAOG;AACH,wBAAgB,EAAE,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,CAIlD;AAwBD;;;;;;;;GAQG;AACH,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CASvD;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAS7C"}
package/dist/html.js ADDED
@@ -0,0 +1,153 @@
1
+ /** 需要转义的五个字符 */
2
+ const ENTITIES = {
3
+ "&": "&amp;",
4
+ "<": "&lt;",
5
+ ">": "&gt;",
6
+ '"': "&quot;",
7
+ "'": "&#39;"
8
+ };
9
+ /** 转义匹配式;单引号一并处理,使属性值以单引号包裹时同样安全 */
10
+ const NEED_ESCAPE = /[&<>"']/g;
11
+ /**
12
+ * 已完成转义、可直接写入文档的 HTML 文本
13
+ *
14
+ * 仅是一个带类型标记的字符串包装:模板的产物是一次性的文本,虚拟 DOM 的 diff 能力在此
15
+ * 毫无用处,而 react / preact 会为此引入数十个传递依赖。Termux 上包体越小越好,
16
+ * 这笔交换不成立。
17
+ */
18
+ export class Html {
19
+ /** HTML 文本 */
20
+ value;
21
+ /**
22
+ * @param value 已转义的 HTML 文本
23
+ */
24
+ constructor(value) {
25
+ this.value = value;
26
+ }
27
+ /**
28
+ * 判定任意值是否为 Html
29
+ * @param input 待判定的值
30
+ * @returns 是 Html 则为真
31
+ */
32
+ static is(input) {
33
+ return input instanceof Html;
34
+ }
35
+ /**
36
+ * 取 HTML 文本
37
+ * @returns HTML 文本
38
+ */
39
+ toString() {
40
+ return this.value;
41
+ }
42
+ /**
43
+ * 参与 `JSON.stringify` 时退化为文本,使快照测试可直接序列化
44
+ * @returns HTML 文本
45
+ */
46
+ toJSON() {
47
+ return this.value;
48
+ }
49
+ }
50
+ /**
51
+ * 转义为 HTML 文本
52
+ *
53
+ * `null` 与 `undefined` 转为空串而非字面量 "null" —— 模板里 `{user.nick}` 取到空值时
54
+ * 应当什么都不显示,打印出 "undefined" 只会出现在成品图上。
55
+ * @param input 任意值
56
+ * @returns 转义后的文本
57
+ */
58
+ export function escape(input) {
59
+ if (input === null || input === undefined)
60
+ return "";
61
+ return String(input).replace(NEED_ESCAPE, ch => ENTITIES[ch] ?? ch);
62
+ }
63
+ /**
64
+ * 声明一段文本已经是安全的 HTML,跳过转义
65
+ *
66
+ * 唯一的逃生口,仅用于本模块自己生成的标签、`<!DOCTYPE html>`,以及编译产物这类
67
+ * 确定安全的内容。**不要**用它包裹任何来自接口的数据。
68
+ * @param value HTML 文本
69
+ * @returns 载体
70
+ */
71
+ export function raw(value) {
72
+ return new Html(value);
73
+ }
74
+ /**
75
+ * 求值类名
76
+ *
77
+ * 接纳字符串、条件字典与任意嵌套数组三种形态,使 `class={["cont", full && "full"]}`
78
+ * 与 `class={{ up: delta > 0 }}` 都可直接书写,无需在模板里拼字符串。
79
+ * @param inputs 任意个类名输入
80
+ * @returns 以空格分隔、已去重的类名串
81
+ */
82
+ export function cx(...inputs) {
83
+ const out = [];
84
+ push(inputs, out);
85
+ return [...new Set(out)].join(" ");
86
+ }
87
+ /**
88
+ * `cx` 的递归收集部分
89
+ * @param input 类名输入
90
+ * @param out 收集容器
91
+ */
92
+ function push(input, out) {
93
+ if (input === null || input === undefined || input === false || input === "")
94
+ return;
95
+ if (typeof input === "string") {
96
+ for (const part of input.split(/\s+/))
97
+ if (part)
98
+ out.push(part);
99
+ return;
100
+ }
101
+ if (typeof input === "number") {
102
+ out.push(String(input));
103
+ return;
104
+ }
105
+ if (Array.isArray(input)) {
106
+ for (const item of input)
107
+ push(item, out);
108
+ return;
109
+ }
110
+ for (const [name, on] of Object.entries(input))
111
+ if (on)
112
+ push(name, out);
113
+ }
114
+ /**
115
+ * 求值内联样式
116
+ *
117
+ * 数值不会被自动补上 `px`:React 的这套隐式补单位规则需要一张"哪些属性是长度"的名单,
118
+ * 名单不全时表现为样式静默失效。此处要求显式书写单位,宽度写成百分号模板串一目了然。
119
+ * 以 `--` 开头的自定义属性保留原始大小写 —— 它们区分大小写,转换会改变含义。
120
+ * @param input 样式字符串或字典
121
+ * @returns CSS 声明串
122
+ */
123
+ export function style(input) {
124
+ if (typeof input === "string")
125
+ return input;
126
+ const out = [];
127
+ for (const [property, value] of Object.entries(input)) {
128
+ if (value === null || value === undefined || value === false || value === "")
129
+ continue;
130
+ const name = property.startsWith("--") ? property : property.replace(/[A-Z]/g, ch => `-${ch.toLowerCase()}`);
131
+ out.push(`${name}: ${String(value)}`);
132
+ }
133
+ return out.join("; ");
134
+ }
135
+ /**
136
+ * 求值子节点
137
+ * @param child 子节点
138
+ * @returns 拼接好的 HTML 文本
139
+ */
140
+ export function children(child) {
141
+ if (child === null || child === undefined || typeof child === "boolean")
142
+ return "";
143
+ if (child instanceof Html)
144
+ return child.value;
145
+ if (Array.isArray(child)) {
146
+ let out = "";
147
+ for (const item of child)
148
+ out += children(item);
149
+ return out;
150
+ }
151
+ return escape(child);
152
+ }
153
+ //# sourceMappingURL=html.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html.js","sourceRoot":"","sources":["../src/html.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * 模块职责:`@yunzai-ng/jsx` 的公开入口
3
+ * 依赖方向:仅依赖 `@yunzai-ng/types`(取 `RenderablePage` 的形状)
4
+ * 生命周期:无状态
5
+ * 注意事项:本包独立于 `@yunzai-ng/core` 而非作为它的一个子路径导出。分层门禁把
6
+ * `@yunzai-ng/core/*` 的任意子路径判为"深引内核内部实现",为一个 JSX 运行时
7
+ * 给门禁开洞并不划算;独立成包后第三方插件也可单独依赖它而不必牵入整个内核。
8
+ */
9
+ import type { RenderablePage } from "@yunzai-ng/types";
10
+ import type { Child } from "./types.js";
11
+ export { Html, escape, raw, cx, style, children } from "./html.js";
12
+ export { attributes, element } from "./element.js";
13
+ export { Fragment, jsx, jsxs, jsxDEV } from "./jsx-runtime.js";
14
+ export type { ElementType } from "./jsx-runtime.js";
15
+ export type { Child, ClassDict, ClassValue, Component, HtmlAttributes, StyleDict } from "./types.js";
16
+ /**
17
+ * 把一个组件封装成模板
18
+ *
19
+ * 产物可直接交给 `ctx.render()` / `e.renderReply()`:
20
+ *
21
+ * ```tsx
22
+ * export const Abyss = defineTemplate("abyss", (view: AbyssView) => <Page>…</Page>)
23
+ * await e.renderReply(Abyss(view))
24
+ * ```
25
+ *
26
+ * 由此模板数据的类型在调用处即被检查 —— 视图层改了字段名,编译当场失败,而不是等到
27
+ * 真机出图时得到一张空白图。模板同时退化成纯函数,可直接快照测试,不需要浏览器。
28
+ * @param name 页面名,用于日志、临时文件名与统计
29
+ * @param component 组件;返回整份文档(不含 doctype,由本函数补上)
30
+ * @returns 接受同样属性、返回可渲染页面的函数
31
+ */
32
+ export declare function defineTemplate<P>(name: string, component: (props: P) => Child): (props: P) => RenderablePage;
33
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAEtD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAEvC,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AAClE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAClD,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAC9D,YAAY,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AACnD,YAAY,EAAE,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAKpG;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,KAAK,GAAG,CAAC,KAAK,EAAE,CAAC,KAAK,cAAc,CAE5G"}
package/dist/index.js ADDED
@@ -0,0 +1,26 @@
1
+ import { children } from "./html.js";
2
+ export { Html, escape, raw, cx, style, children } from "./html.js";
3
+ export { attributes, element } from "./element.js";
4
+ export { Fragment, jsx, jsxs, jsxDEV } from "./jsx-runtime.js";
5
+ /** HTML5 文档类型声明;缺了它浏览器进入怪异模式,盒模型与行高全部改变 */
6
+ const DOCTYPE = "<!DOCTYPE html>";
7
+ /**
8
+ * 把一个组件封装成模板
9
+ *
10
+ * 产物可直接交给 `ctx.render()` / `e.renderReply()`:
11
+ *
12
+ * ```tsx
13
+ * export const Abyss = defineTemplate("abyss", (view: AbyssView) => <Page>…</Page>)
14
+ * await e.renderReply(Abyss(view))
15
+ * ```
16
+ *
17
+ * 由此模板数据的类型在调用处即被检查 —— 视图层改了字段名,编译当场失败,而不是等到
18
+ * 真机出图时得到一张空白图。模板同时退化成纯函数,可直接快照测试,不需要浏览器。
19
+ * @param name 页面名,用于日志、临时文件名与统计
20
+ * @param component 组件;返回整份文档(不含 doctype,由本函数补上)
21
+ * @returns 接受同样属性、返回可渲染页面的函数
22
+ */
23
+ export function defineTemplate(name, component) {
24
+ return (props) => ({ name, html: DOCTYPE + children(component(props)) });
25
+ }
26
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AAGpC,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AAClE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAClD,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAI9D,2CAA2C;AAC3C,MAAM,OAAO,GAAG,iBAAiB,CAAA;AAEjC;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,cAAc,CAAI,IAAY,EAAE,SAA8B;IAC5E,OAAO,CAAC,KAAQ,EAAkB,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,GAAG,QAAQ,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAA;AAC7F,CAAC"}
@@ -0,0 +1,73 @@
1
+ /**
2
+ * 模块职责:TypeScript 自动 JSX 转换所要求的运行时入口(`jsx` / `jsxs` / `Fragment`)
3
+ * 依赖方向:仅依赖同包的 `html.ts` 与 `element.ts`
4
+ * 生命周期:无状态,纯函数
5
+ * 注意事项:`jsx` 与 `jsxs` 为同一实现。二者的区别在于 `jsxs` 保证 `children` 已是数组
6
+ * 且不会被改写,React 借此跳过 key 校验;此处不存在协调过程,无从利用该保证。
7
+ *
8
+ * `jsx-dev-runtime` 亦指向本文件:开发版签名多出 `isStaticChildren` / `source`
9
+ * / `self` 三个参数,全部用于 React 的错误提示,与产出的 HTML 无关。
10
+ */
11
+ import { Html } from "./html.js";
12
+ import type { Child, HtmlAttributes } from "./types.js";
13
+ /**
14
+ * JSX 标签位置可出现的类型
15
+ *
16
+ * 函数组件的属性类型声明为 `never`:函数类型的参数按逆变判定,`never` 可被任意参数类型
17
+ * 接受,因此这是"任意一元函数"的写法。真正的属性类型检查由 TSX 在标签处完成,
18
+ * 与此签名无关。
19
+ */
20
+ export type ElementType = string | ((props: never) => Child);
21
+ /**
22
+ * 片段:把多个同级节点合成一个返回值
23
+ *
24
+ * 它就是一个普通函数组件,`<>…</>` 编译成 `jsx(Fragment, { children })` 后自然生效,
25
+ * 无需在 `jsx()` 里为它开特例。
26
+ * @param props 仅取 `children`
27
+ * @returns 拼接好的子节点
28
+ */
29
+ export declare function Fragment(props: {
30
+ children?: Child;
31
+ }): Html;
32
+ /**
33
+ * 创建一个节点
34
+ * @param type 标签名或函数组件
35
+ * @param props 属性;`children` 亦在其中
36
+ * @returns 渲染好的 HTML
37
+ * @throws 标签名或属性名不合法时抛出 TypeError
38
+ */
39
+ export declare function jsx(type: ElementType, props?: Readonly<Record<string, unknown>>): Html;
40
+ export { jsx as jsxs, jsx as jsxDEV };
41
+ /**
42
+ * TSX 类型契约
43
+ *
44
+ * TypeScript 在 `jsxImportSource` 指向的模块上查找这个命名空间,用它判定标签合法性、
45
+ * 子节点属性名与元素类型。
46
+ */
47
+ export declare namespace JSX {
48
+ /** 一次渲染的产物 */
49
+ interface Element extends Html {
50
+ }
51
+ /** 告知 TypeScript 以 `children` 属性接收子节点 */
52
+ interface ElementChildrenAttribute {
53
+ /** 属性名本身才是这里唯一有意义的信息,类型不参与判定 */
54
+ children: object;
55
+ }
56
+ /**
57
+ * 内建标签
58
+ *
59
+ * 以索引签名放开全部标签:逐一枚举 HTML 元素及其专属属性需要数千行声明,而模板作者
60
+ * 真正需要的约束是 `class` / `style` / `children` 的形态,这三项已在 `HtmlAttributes`
61
+ * 中给出。拼错标签名的代价是浏览器把它当作未知内联元素,肉眼可见,不必由类型系统兜住。
62
+ */
63
+ interface IntrinsicElements {
64
+ /** 任意标签 */
65
+ [tag: string]: HtmlAttributes;
66
+ }
67
+ /** 所有元素隐含允许的属性 */
68
+ interface IntrinsicAttributes {
69
+ /** 兼容 React 写法而接纳,渲染时丢弃 */
70
+ key?: string | number;
71
+ }
72
+ }
73
+ //# sourceMappingURL=jsx-runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsx-runtime.d.ts","sourceRoot":"","sources":["../src/jsx-runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAY,IAAI,EAAO,MAAM,WAAW,CAAA;AAE/C,OAAO,KAAK,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAEvD;;;;;;GAMG;AACH,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,KAAK,KAAK,CAAC,CAAA;AAE5D;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE;IAAE,QAAQ,CAAC,EAAE,KAAK,CAAA;CAAE,GAAG,IAAI,CAE1D;AAED;;;;;;GAMG;AACH,wBAAgB,GAAG,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,GAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAM,GAAG,IAAI,CAK1F;AAED,OAAO,EAAE,GAAG,IAAI,IAAI,EAAE,GAAG,IAAI,MAAM,EAAE,CAAA;AAErC;;;;;GAKG;AACH,yBAAiB,GAAG,CAAC;IACnB,cAAc;IACd,UAAiB,OAAQ,SAAQ,IAAI;KAAG;IAExC,yCAAyC;IACzC,UAAiB,wBAAwB;QACvC,gCAAgC;QAChC,QAAQ,EAAE,MAAM,CAAA;KACjB;IAED;;;;;;OAMG;IACH,UAAiB,iBAAiB;QAChC,WAAW;QACX,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,CAAA;KAC9B;IAED,kBAAkB;IAClB,UAAiB,mBAAmB;QAClC,2BAA2B;QAC3B,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;KACtB;CACF"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * 模块职责:TypeScript 自动 JSX 转换所要求的运行时入口(`jsx` / `jsxs` / `Fragment`)
3
+ * 依赖方向:仅依赖同包的 `html.ts` 与 `element.ts`
4
+ * 生命周期:无状态,纯函数
5
+ * 注意事项:`jsx` 与 `jsxs` 为同一实现。二者的区别在于 `jsxs` 保证 `children` 已是数组
6
+ * 且不会被改写,React 借此跳过 key 校验;此处不存在协调过程,无从利用该保证。
7
+ *
8
+ * `jsx-dev-runtime` 亦指向本文件:开发版签名多出 `isStaticChildren` / `source`
9
+ * / `self` 三个参数,全部用于 React 的错误提示,与产出的 HTML 无关。
10
+ */
11
+ import { children, Html, raw } from "./html.js";
12
+ import { element } from "./element.js";
13
+ /**
14
+ * 片段:把多个同级节点合成一个返回值
15
+ *
16
+ * 它就是一个普通函数组件,`<>…</>` 编译成 `jsx(Fragment, { children })` 后自然生效,
17
+ * 无需在 `jsx()` 里为它开特例。
18
+ * @param props 仅取 `children`
19
+ * @returns 拼接好的子节点
20
+ */
21
+ export function Fragment(props) {
22
+ return raw(children(props.children));
23
+ }
24
+ /**
25
+ * 创建一个节点
26
+ * @param type 标签名或函数组件
27
+ * @param props 属性;`children` 亦在其中
28
+ * @returns 渲染好的 HTML
29
+ * @throws 标签名或属性名不合法时抛出 TypeError
30
+ */
31
+ export function jsx(type, props = {}) {
32
+ if (typeof type === "function") {
33
+ return raw(children(type(props)));
34
+ }
35
+ return raw(element(type, props));
36
+ }
37
+ export { jsx as jsxs, jsx as jsxDEV };
38
+ //# sourceMappingURL=jsx-runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsx-runtime.js","sourceRoot":"","sources":["../src/jsx-runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,WAAW,CAAA;AAC/C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAYtC;;;;;;;GAOG;AACH,MAAM,UAAU,QAAQ,CAAC,KAA2B;IAClD,OAAO,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAA;AACtC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,GAAG,CAAC,IAAiB,EAAE,QAA2C,EAAE;IAClF,IAAI,OAAO,IAAI,KAAK,UAAU,EAAE,CAAC;QAC/B,OAAO,GAAG,CAAC,QAAQ,CAAE,IAA4D,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;IAC5F,CAAC;IACD,OAAO,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAA;AAClC,CAAC;AAED,OAAO,EAAE,GAAG,IAAI,IAAI,EAAE,GAAG,IAAI,MAAM,EAAE,CAAA"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * 模块职责:JSX 层的公共类型契约
3
+ * 依赖方向:仅依赖同包的 `html.ts`(取 `Html` 作为节点类型),不引任何工作区包
4
+ * 生命周期:纯类型,编译后不留痕迹
5
+ * 注意事项:属性名**不作 camelCase 转换**,一律按真实 HTML 书写(`stroke-width`、
6
+ * `tabindex`、`data-x`)。TSX 语法本身允许带连字符的属性名,无需转换即可书写;
7
+ * 而一旦引入转换,`viewBox` 这类 SVG 属性与 `data-camelCase` 就会出现两套
8
+ * 互相冲突的规则。唯二的例外是 `className` 与 `htmlFor` —— 它们是 React 为
9
+ * 规避 JS 保留字留下的历史包袱,作为别名接纳以降低迁移成本。
10
+ */
11
+ import type { Html } from "./html.js";
12
+ /** 以键为类名、值为是否启用的字典 */
13
+ export interface ClassDict {
14
+ /** 类名 → 是否启用 */
15
+ [name: string]: boolean | null | undefined;
16
+ }
17
+ /** `class` 属性可接受的形态:字符串、条件字典、以及两者的任意嵌套数组 */
18
+ export type ClassValue = string | number | false | null | undefined | ClassDict | ClassValue[];
19
+ /** 内联样式字典;键为 CSS 属性名或 `--` 自定义属性 */
20
+ export interface StyleDict {
21
+ /** CSS 属性名 → 取值;数值不会被自动补单位,需要单位时自行拼接 */
22
+ [property: string]: string | number | null | undefined | false;
23
+ }
24
+ /**
25
+ * 子节点
26
+ *
27
+ * `null` / `undefined` / 布尔值渲染为空串,使 `{cond && <div/>}` 与 `{value ?? null}`
28
+ * 这两种最常用的条件写法无需额外处理。
29
+ */
30
+ export type Child = Html | string | number | bigint | boolean | null | undefined | Child[];
31
+ /** 元素属性 */
32
+ export interface HtmlAttributes {
33
+ /** 类名 */
34
+ class?: ClassValue;
35
+ /** 类名,`class` 的别名 */
36
+ className?: ClassValue;
37
+ /** 内联样式 */
38
+ style?: string | StyleDict;
39
+ /** 子节点 */
40
+ children?: Child;
41
+ /** 兼容 React 写法而接纳,渲染时丢弃 —— 此处没有需要复用节点的协调过程 */
42
+ key?: string | number;
43
+ /** 其余属性原样输出;值为 `true` 输出裸属性名,为 `false`/`null`/`undefined` 则整项省略 */
44
+ [attr: string]: unknown;
45
+ }
46
+ /** 函数组件:接收属性、返回一段 HTML */
47
+ export type Component<P = Record<string, never>> = (props: P) => Html;
48
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAErC,sBAAsB;AACtB,MAAM,WAAW,SAAS;IACxB,gBAAgB;IAChB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,CAAA;CAC3C;AAED,4CAA4C;AAC5C,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,IAAI,GAAG,SAAS,GAAG,SAAS,GAAG,UAAU,EAAE,CAAA;AAE9F,oCAAoC;AACpC,MAAM,WAAW,SAAS;IACxB,wCAAwC;IACxC,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,KAAK,CAAA;CAC/D;AAED;;;;;GAKG;AACH,MAAM,MAAM,KAAK,GAAG,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,GAAG,KAAK,EAAE,CAAA;AAE1F,WAAW;AACX,MAAM,WAAW,cAAc;IAC7B,SAAS;IACT,KAAK,CAAC,EAAE,UAAU,CAAA;IAClB,qBAAqB;IACrB,SAAS,CAAC,EAAE,UAAU,CAAA;IACtB,WAAW;IACX,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC1B,UAAU;IACV,QAAQ,CAAC,EAAE,KAAK,CAAA;IAChB,8CAA8C;IAC9C,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IACrB,mEAAmE;IACnE,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAA;CACxB;AAED,0BAA0B;AAC1B,MAAM,MAAM,SAAS,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAA"}