@yunzai-ng/jsx 0.1.0 → 0.2.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/dist/index.d.ts +22 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -2
- package/dist/index.js.map +1 -1
- package/package.json +12 -2
- package/src/index.test.ts +14 -0
- package/src/index.ts +34 -2
package/dist/index.d.ts
CHANGED
|
@@ -13,6 +13,20 @@ export { attributes, element } from "./element.js";
|
|
|
13
13
|
export { Fragment, jsx, jsxs, jsxDEV } from "./jsx-runtime.js";
|
|
14
14
|
export type { ElementType } from "./jsx-runtime.js";
|
|
15
15
|
export type { Child, ClassDict, ClassValue, Component, HtmlAttributes, StyleDict } from "./types.js";
|
|
16
|
+
/** `defineTemplate()` 的可选声明 */
|
|
17
|
+
export interface TemplateOptions {
|
|
18
|
+
/**
|
|
19
|
+
* 该模板是否使用 Tailwind 工具类
|
|
20
|
+
*
|
|
21
|
+
* **由模板自己声明,渲染器不揣度。** 渲染器拿到的只是一段 HTML,无从判断其中的
|
|
22
|
+
* `class="flex"` 是 Tailwind 的工具类还是模板自带的一条 CSS 规则。声明 `true` 才编译,
|
|
23
|
+
* 于是不用工具类的模板既省去一次候选扫描与编译,也不会被 preflight 重置版式。
|
|
24
|
+
*
|
|
25
|
+
* 不填时沿用渲染器自身的配置,而那一项缺省关闭 —— 即**不声明就不编译**。
|
|
26
|
+
* 于是不用工具类的插件既不必装 `tailwindcss`,也不会收到与它无关的编译告警。
|
|
27
|
+
*/
|
|
28
|
+
tailwind?: boolean;
|
|
29
|
+
}
|
|
16
30
|
/**
|
|
17
31
|
* 把一个组件封装成模板
|
|
18
32
|
*
|
|
@@ -23,11 +37,18 @@ export type { Child, ClassDict, ClassValue, Component, HtmlAttributes, StyleDict
|
|
|
23
37
|
* await e.renderReply(Abyss(view))
|
|
24
38
|
* ```
|
|
25
39
|
*
|
|
40
|
+
* 用了 Tailwind 工具类的模板在第三参里声明,渲染器据此决定是否编译:
|
|
41
|
+
*
|
|
42
|
+
* ```tsx
|
|
43
|
+
* export const Card = defineTemplate("card", (v: View) => <Page>…</Page>, { tailwind: true })
|
|
44
|
+
* ```
|
|
45
|
+
*
|
|
26
46
|
* 由此模板数据的类型在调用处即被检查 —— 视图层改了字段名,编译当场失败,而不是等到
|
|
27
47
|
* 真机出图时得到一张空白图。模板同时退化成纯函数,可直接快照测试,不需要浏览器。
|
|
28
48
|
* @param name 页面名,用于日志、临时文件名与统计
|
|
29
49
|
* @param component 组件;返回整份文档(不含 doctype,由本函数补上)
|
|
50
|
+
* @param opts 模板级声明
|
|
30
51
|
* @returns 接受同样属性、返回可渲染页面的函数
|
|
31
52
|
*/
|
|
32
|
-
export declare function defineTemplate<P>(name: string, component: (props: P) => Child): (props: P) => RenderablePage;
|
|
53
|
+
export declare function defineTemplate<P>(name: string, component: (props: P) => Child, opts?: TemplateOptions): (props: P) => RenderablePage;
|
|
33
54
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +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
|
|
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,+BAA+B;AAC/B,MAAM,WAAW,eAAe;IAC9B;;;;;;;;;OASG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAC9B,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,KAAK,EAC9B,IAAI,GAAE,eAAoB,GACzB,CAAC,KAAK,EAAE,CAAC,KAAK,cAAc,CAQ9B"}
|
package/dist/index.js
CHANGED
|
@@ -14,13 +14,26 @@ const DOCTYPE = "<!DOCTYPE html>";
|
|
|
14
14
|
* await e.renderReply(Abyss(view))
|
|
15
15
|
* ```
|
|
16
16
|
*
|
|
17
|
+
* 用了 Tailwind 工具类的模板在第三参里声明,渲染器据此决定是否编译:
|
|
18
|
+
*
|
|
19
|
+
* ```tsx
|
|
20
|
+
* export const Card = defineTemplate("card", (v: View) => <Page>…</Page>, { tailwind: true })
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
17
23
|
* 由此模板数据的类型在调用处即被检查 —— 视图层改了字段名,编译当场失败,而不是等到
|
|
18
24
|
* 真机出图时得到一张空白图。模板同时退化成纯函数,可直接快照测试,不需要浏览器。
|
|
19
25
|
* @param name 页面名,用于日志、临时文件名与统计
|
|
20
26
|
* @param component 组件;返回整份文档(不含 doctype,由本函数补上)
|
|
27
|
+
* @param opts 模板级声明
|
|
21
28
|
* @returns 接受同样属性、返回可渲染页面的函数
|
|
22
29
|
*/
|
|
23
|
-
export function defineTemplate(name, component) {
|
|
24
|
-
return (props) => ({
|
|
30
|
+
export function defineTemplate(name, component, opts = {}) {
|
|
31
|
+
return (props) => ({
|
|
32
|
+
name,
|
|
33
|
+
html: DOCTYPE + children(component(props)),
|
|
34
|
+
// 未声明时不带该键:`tailwind: undefined` 与"未声明"在结构上须一致,
|
|
35
|
+
// 否则下游的 `!== undefined` 判定会把它当成一次明确的声明
|
|
36
|
+
...(opts.tailwind !== undefined ? { tailwind: opts.tailwind } : {})
|
|
37
|
+
});
|
|
25
38
|
}
|
|
26
39
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +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;
|
|
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;AAiBjC;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,UAAU,cAAc,CAC5B,IAAY,EACZ,SAA8B,EAC9B,OAAwB,EAAE;IAE1B,OAAO,CAAC,KAAQ,EAAkB,EAAE,CAAC,CAAC;QACpC,IAAI;QACJ,IAAI,EAAE,OAAO,GAAG,QAAQ,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAC1C,gDAAgD;QAChD,uCAAuC;QACvC,GAAG,CAAC,IAAI,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACpE,CAAC,CAAA;AACJ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,9 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yunzai-ng/jsx",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Yunzai NG 模板用 JSX 运行时(字符串直出,无虚拟 DOM)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "AGPL-3.0-or-later",
|
|
7
|
+
"homepage": "https://github.com/Yunzai-NG/yunzai-ng#readme",
|
|
8
|
+
"bugs": "https://github.com/Yunzai-NG/yunzai-ng/issues",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/Yunzai-NG/yunzai-ng.git",
|
|
12
|
+
"directory": "packages/jsx"
|
|
13
|
+
},
|
|
14
|
+
"engines": {
|
|
15
|
+
"node": ">=20.11.0"
|
|
16
|
+
},
|
|
7
17
|
"main": "./dist/index.js",
|
|
8
18
|
"types": "./dist/index.d.ts",
|
|
9
19
|
"exports": {
|
|
@@ -26,7 +36,7 @@
|
|
|
26
36
|
"src"
|
|
27
37
|
],
|
|
28
38
|
"dependencies": {
|
|
29
|
-
"@yunzai-ng/types": "0.
|
|
39
|
+
"@yunzai-ng/types": "0.2.0"
|
|
30
40
|
},
|
|
31
41
|
"scripts": {
|
|
32
42
|
"build": "tsc -b"
|
package/src/index.test.ts
CHANGED
|
@@ -167,4 +167,18 @@ describe("defineTemplate", () => {
|
|
|
167
167
|
const Page = defineTemplate("demo", (props: { uid: string }) => jsx("html", { children: props.uid }))
|
|
168
168
|
expect(Page({ uid: "1" })).toEqual({ name: "demo", html: "<!DOCTYPE html><html>1</html>" })
|
|
169
169
|
})
|
|
170
|
+
|
|
171
|
+
it("未声明 tailwind 时不带该键", () => {
|
|
172
|
+
// 与「声明了 false」必须在结构上可区分:下游以 `!== undefined` 判定是否为一次明确声明,
|
|
173
|
+
// 带上 `tailwind: undefined` 会让"未声明"被当作"声明不编译",从而盖掉渲染器的配置
|
|
174
|
+
const Page = defineTemplate("demo", () => jsx("html"))
|
|
175
|
+
expect("tailwind" in Page({})).toBe(false)
|
|
176
|
+
})
|
|
177
|
+
|
|
178
|
+
it("声明 tailwind 后直通页面对象", () => {
|
|
179
|
+
const On = defineTemplate("on", () => jsx("html"), { tailwind: true })
|
|
180
|
+
const Off = defineTemplate("off", () => jsx("html"), { tailwind: false })
|
|
181
|
+
expect(On({}).tailwind).toBe(true)
|
|
182
|
+
expect(Off({}).tailwind).toBe(false)
|
|
183
|
+
})
|
|
170
184
|
})
|
package/src/index.ts
CHANGED
|
@@ -19,6 +19,21 @@ export type { Child, ClassDict, ClassValue, Component, HtmlAttributes, StyleDict
|
|
|
19
19
|
/** HTML5 文档类型声明;缺了它浏览器进入怪异模式,盒模型与行高全部改变 */
|
|
20
20
|
const DOCTYPE = "<!DOCTYPE html>"
|
|
21
21
|
|
|
22
|
+
/** `defineTemplate()` 的可选声明 */
|
|
23
|
+
export interface TemplateOptions {
|
|
24
|
+
/**
|
|
25
|
+
* 该模板是否使用 Tailwind 工具类
|
|
26
|
+
*
|
|
27
|
+
* **由模板自己声明,渲染器不揣度。** 渲染器拿到的只是一段 HTML,无从判断其中的
|
|
28
|
+
* `class="flex"` 是 Tailwind 的工具类还是模板自带的一条 CSS 规则。声明 `true` 才编译,
|
|
29
|
+
* 于是不用工具类的模板既省去一次候选扫描与编译,也不会被 preflight 重置版式。
|
|
30
|
+
*
|
|
31
|
+
* 不填时沿用渲染器自身的配置,而那一项缺省关闭 —— 即**不声明就不编译**。
|
|
32
|
+
* 于是不用工具类的插件既不必装 `tailwindcss`,也不会收到与它无关的编译告警。
|
|
33
|
+
*/
|
|
34
|
+
tailwind?: boolean
|
|
35
|
+
}
|
|
36
|
+
|
|
22
37
|
/**
|
|
23
38
|
* 把一个组件封装成模板
|
|
24
39
|
*
|
|
@@ -29,12 +44,29 @@ const DOCTYPE = "<!DOCTYPE html>"
|
|
|
29
44
|
* await e.renderReply(Abyss(view))
|
|
30
45
|
* ```
|
|
31
46
|
*
|
|
47
|
+
* 用了 Tailwind 工具类的模板在第三参里声明,渲染器据此决定是否编译:
|
|
48
|
+
*
|
|
49
|
+
* ```tsx
|
|
50
|
+
* export const Card = defineTemplate("card", (v: View) => <Page>…</Page>, { tailwind: true })
|
|
51
|
+
* ```
|
|
52
|
+
*
|
|
32
53
|
* 由此模板数据的类型在调用处即被检查 —— 视图层改了字段名,编译当场失败,而不是等到
|
|
33
54
|
* 真机出图时得到一张空白图。模板同时退化成纯函数,可直接快照测试,不需要浏览器。
|
|
34
55
|
* @param name 页面名,用于日志、临时文件名与统计
|
|
35
56
|
* @param component 组件;返回整份文档(不含 doctype,由本函数补上)
|
|
57
|
+
* @param opts 模板级声明
|
|
36
58
|
* @returns 接受同样属性、返回可渲染页面的函数
|
|
37
59
|
*/
|
|
38
|
-
export function defineTemplate<P>(
|
|
39
|
-
|
|
60
|
+
export function defineTemplate<P>(
|
|
61
|
+
name: string,
|
|
62
|
+
component: (props: P) => Child,
|
|
63
|
+
opts: TemplateOptions = {}
|
|
64
|
+
): (props: P) => RenderablePage {
|
|
65
|
+
return (props: P): RenderablePage => ({
|
|
66
|
+
name,
|
|
67
|
+
html: DOCTYPE + children(component(props)),
|
|
68
|
+
// 未声明时不带该键:`tailwind: undefined` 与"未声明"在结构上须一致,
|
|
69
|
+
// 否则下游的 `!== undefined` 判定会把它当成一次明确的声明
|
|
70
|
+
...(opts.tailwind !== undefined ? { tailwind: opts.tailwind } : {})
|
|
71
|
+
})
|
|
40
72
|
}
|