@mteditor/renderer-mini 0.0.0-stage → 0.1.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.
Files changed (57) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +150 -2
  3. package/components/README.md +92 -0
  4. package/components/mt-node/index.js +123 -0
  5. package/components/mt-node/index.json +6 -0
  6. package/components/mt-node/index.wxml +95 -0
  7. package/components/mt-node/index.wxss +163 -0
  8. package/components/mt-renderer/index.js +51 -0
  9. package/components/mt-renderer/index.json +6 -0
  10. package/components/mt-renderer/index.wxml +24 -0
  11. package/components/mt-renderer/index.wxss +14 -0
  12. package/components/mt-theme.wxss +82 -0
  13. package/dist/alipay/index.cjs +4 -0
  14. package/dist/alipay/index.cjs.map +1 -0
  15. package/dist/alipay/index.d.cts +2 -0
  16. package/dist/alipay/index.d.ts +2 -0
  17. package/dist/alipay/index.js +3 -0
  18. package/dist/alipay/index.js.map +1 -0
  19. package/dist/arkts/index.cjs +4 -0
  20. package/dist/arkts/index.cjs.map +1 -0
  21. package/dist/arkts/index.d.cts +2 -0
  22. package/dist/arkts/index.d.ts +2 -0
  23. package/dist/arkts/index.js +3 -0
  24. package/dist/arkts/index.js.map +1 -0
  25. package/dist/bytedance/index.cjs +4 -0
  26. package/dist/bytedance/index.cjs.map +1 -0
  27. package/dist/bytedance/index.d.cts +2 -0
  28. package/dist/bytedance/index.d.ts +2 -0
  29. package/dist/bytedance/index.js +3 -0
  30. package/dist/bytedance/index.js.map +1 -0
  31. package/dist/index.cjs +259 -0
  32. package/dist/index.cjs.map +1 -0
  33. package/dist/index.d.cts +101 -0
  34. package/dist/index.d.ts +101 -0
  35. package/dist/index.js +247 -0
  36. package/dist/index.js.map +1 -0
  37. package/dist/taro/index.cjs +4 -0
  38. package/dist/taro/index.cjs.map +1 -0
  39. package/dist/taro/index.d.cts +2 -0
  40. package/dist/taro/index.d.ts +2 -0
  41. package/dist/taro/index.js +3 -0
  42. package/dist/taro/index.js.map +1 -0
  43. package/dist/theme-CXitJYrs.d.cts +214 -0
  44. package/dist/theme-CXitJYrs.d.ts +214 -0
  45. package/dist/uni-app/index.cjs +4 -0
  46. package/dist/uni-app/index.cjs.map +1 -0
  47. package/dist/uni-app/index.d.cts +2 -0
  48. package/dist/uni-app/index.d.ts +2 -0
  49. package/dist/uni-app/index.js +3 -0
  50. package/dist/uni-app/index.js.map +1 -0
  51. package/dist/wechat/index.cjs +259 -0
  52. package/dist/wechat/index.cjs.map +1 -0
  53. package/dist/wechat/index.d.cts +61 -0
  54. package/dist/wechat/index.d.ts +61 -0
  55. package/dist/wechat/index.js +250 -0
  56. package/dist/wechat/index.js.map +1 -0
  57. package/package.json +142 -3
@@ -0,0 +1,51 @@
1
+ /**
2
+ * `mt-renderer` —— 双通道入口组件。
3
+ *
4
+ * 页面只需要把 `render()` 的返回值原样喂进来,**由组件按 `mode` 分支**:
5
+ *
6
+ * ```js
7
+ * const { mode, nodes } = render(doc, { theme: 'dark' })
8
+ * this.setData({ mode, nodes })
9
+ * ```
10
+ *
11
+ * ```xml
12
+ * <mt-renderer mode="{{mode}}" nodes="{{nodes}}" bind:mttap="onItemTap" />
13
+ * ```
14
+ *
15
+ * ## 为什么由组件分支,而不是让页面写 `wx:if`
16
+ *
17
+ * 通道选择是**渲染器**的职责:`mode: 'auto'` 的解析结果
18
+ * 只有渲染器知道。要求页面自己写两条分支,等于把这个知识推给每一个宿主,
19
+ * 而宿主写错时不会报错 —— 只会渲染出空白。
20
+ *
21
+ * ## `mode` 必须传「实际使用」的通道
22
+ *
23
+ * 请传 `render()` 返回的 `mode`,**不要传你传进去的 `'auto'`**。
24
+ */
25
+
26
+ Component({
27
+ options: {
28
+ virtualHost: true,
29
+ addGlobalClass: true,
30
+ },
31
+
32
+ properties: {
33
+ /** `render()` 产出的 nodes(**Array 形式**) */
34
+ nodes: { type: Array, value: [] },
35
+ /** `render()` 返回的**实际**通道:`'component' | 'richText'` */
36
+ mode: { type: String, value: 'component' },
37
+ /** 是否允许长按选中文本 */
38
+ selectable: { type: Boolean, value: true },
39
+ },
40
+
41
+ methods: {
42
+ /**
43
+ * 把节点树冒上来的 `mttap` 原样抛给页面。
44
+ *
45
+ * @param {object} event `mttap` 事件
46
+ */
47
+ onBubble(event) {
48
+ this.triggerEvent('mttap', event.detail)
49
+ },
50
+ },
51
+ })
@@ -0,0 +1,6 @@
1
+ {
2
+ "component": true,
3
+ "usingComponents": {
4
+ "mt-node": "../mt-node/index"
5
+ }
6
+ }
@@ -0,0 +1,24 @@
1
+ <!--
2
+ mt-renderer —— 按 mode 选择通道
3
+
4
+ mode 由 renderMiniDocument() 返回,是**解析后**的实际通道:
5
+ 'richText' 走原生 <rich-text>,'component' 走递归自定义组件。
6
+ 两条通道消费的是**同一份 nodes**,切换不会换内容。
7
+ -->
8
+ <rich-text
9
+ wx:if="{{mode === 'richText'}}"
10
+ nodes="{{nodes}}"
11
+ user-select="{{selectable}}"
12
+ />
13
+
14
+ <block wx:else>
15
+ <!-- class="mt-renderer" 经 virtualHost 透传到每个节点的根元素,提供容器级排版 -->
16
+ <mt-node
17
+ wx:for="{{nodes}}"
18
+ wx:key="index"
19
+ class="mt-renderer"
20
+ node="{{item}}"
21
+ selectable="{{selectable}}"
22
+ bind:mttap="onBubble"
23
+ />
24
+ </block>
@@ -0,0 +1,14 @@
1
+ /**
2
+ * mt-renderer 自身的样式。
3
+ *
4
+ * 内容样式在 `mt-node/index.wxss`(每个节点的 className 由序列化器给出);
5
+ * 这里只放容器级约定。
6
+ */
7
+
8
+ .mt-renderer {
9
+ display: block;
10
+ color: var(--mt-color-text, #1f2329);
11
+ font-family: var(--mt-font-family, -apple-system, sans-serif);
12
+ font-size: var(--mt-font-size, 15px);
13
+ line-height: var(--mt-line-height, 1.7);
14
+ }
@@ -0,0 +1,82 @@
1
+ /**
2
+ * 主题变量(宿主 `@import` 一次即可)。
3
+ *
4
+ * ## 用法
5
+ *
6
+ * 在 `app.wxss` 顶部 `@import "@mteditor/renderer-mini/components/mt-theme.wxss";`
7
+ * (或把它复制进项目)即可拿到全部变量。
8
+ *
9
+ * 亮色为默认值;要切暗色,在页面根节点加 `mt-theme-dark` class:
10
+ *
11
+ * ```xml
12
+ * <view class="mt-theme-dark">
13
+ * <mt-renderer mode="{{mode}}" nodes="{{nodes}}" />
14
+ * </view>
15
+ * ```
16
+ *
17
+ * ## 为什么放在这里而不是组件内
18
+ *
19
+ * 组件 wxss 默认是**样式隔离**的,规则不会作用到页面节点;而 CSS 变量是
20
+ * **继承**的 —— 页面上定义的变量会自然流进组件内部。所以变量表必须定义在
21
+ * 宿主能控制的层级上,组件只负责**消费**它(见 `mt-node/index.wxss`)。
22
+ *
23
+ * ## 只对「组件通道」有意义
24
+ *
25
+ * `rich-text` 通道内的 `style` 不参与宿主变量继承,那条通道的主题
26
+ * 由 `render(doc, { theme, themeTokens })` 在序列化时内联为字面量。
27
+ * 两套机制并存不是历史包袱,而是小程序两条渲染路径的客观差异。
28
+ */
29
+
30
+ page,
31
+ :root {
32
+ --mt-color-primary: #2563eb;
33
+ --mt-color-link: #2563eb;
34
+ --mt-color-success: #16a34a;
35
+ --mt-color-warning: #d97706;
36
+ --mt-color-danger: #dc2626;
37
+ --mt-color-text: #1f2329;
38
+ --mt-color-text-secondary: #646a73;
39
+ --mt-color-text-disabled: #a6a9ad;
40
+ --mt-color-bg: #fff;
41
+ --mt-color-bg-muted: #f5f7fa;
42
+ --mt-color-border: #dee0e3;
43
+ --mt-color-border-strong: #babdbf;
44
+ --mt-color-code-bg: #f5f5f5;
45
+ --mt-color-code-text: #c0392b;
46
+ --mt-color-quote-border: #dee0e3;
47
+ --mt-color-mark-bg: #fff3a3;
48
+ --mt-font-family:
49
+ -apple-system, blinkmacsystemfont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB',
50
+ 'Microsoft YaHei', sans-serif;
51
+ --mt-font-family-mono: 'SFMono-Regular', consolas, 'Liberation Mono', menlo, monospace;
52
+ --mt-font-size: 15px;
53
+ --mt-font-size-sm: 13px;
54
+ --mt-font-size-lg: 17px;
55
+ --mt-line-height: 1.7;
56
+ --mt-h1-font-size: 28px;
57
+ --mt-h2-font-size: 24px;
58
+ --mt-h3-font-size: 20px;
59
+ --mt-h4-font-size: 18px;
60
+ --mt-h5-font-size: 16px;
61
+ --mt-h6-font-size: 15px;
62
+ --mt-radius-md: 6px;
63
+ }
64
+
65
+ .mt-theme-dark {
66
+ --mt-color-primary: #3b82f6;
67
+ --mt-color-link: #60a5fa;
68
+ --mt-color-success: #22c55e;
69
+ --mt-color-warning: #f59e0b;
70
+ --mt-color-danger: #ef4444;
71
+ --mt-color-text: #e5e6eb;
72
+ --mt-color-text-secondary: #a3a6ad;
73
+ --mt-color-text-disabled: #6b6f76;
74
+ --mt-color-bg: #1f2329;
75
+ --mt-color-bg-muted: #282c33;
76
+ --mt-color-border: #3a3f47;
77
+ --mt-color-border-strong: #4e545d;
78
+ --mt-color-code-bg: #2b2f36;
79
+ --mt-color-code-text: #f87171;
80
+ --mt-color-quote-border: #3a3f47;
81
+ --mt-color-mark-bg: #6b5a1a;
82
+ }
@@ -0,0 +1,4 @@
1
+ 'use strict';
2
+
3
+ //# sourceMappingURL=index.cjs.map
4
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.cjs"}
@@ -0,0 +1,2 @@
1
+
2
+ export { }
@@ -0,0 +1,2 @@
1
+
2
+ export { }
@@ -0,0 +1,3 @@
1
+
2
+ //# sourceMappingURL=index.js.map
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
@@ -0,0 +1,4 @@
1
+ 'use strict';
2
+
3
+ //# sourceMappingURL=index.cjs.map
4
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.cjs"}
@@ -0,0 +1,2 @@
1
+
2
+ export { }
@@ -0,0 +1,2 @@
1
+
2
+ export { }
@@ -0,0 +1,3 @@
1
+
2
+ //# sourceMappingURL=index.js.map
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
@@ -0,0 +1,4 @@
1
+ 'use strict';
2
+
3
+ //# sourceMappingURL=index.cjs.map
4
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.cjs"}
@@ -0,0 +1,2 @@
1
+
2
+ export { }
@@ -0,0 +1,2 @@
1
+
2
+ export { }
@@ -0,0 +1,3 @@
1
+
2
+ //# sourceMappingURL=index.js.map
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
package/dist/index.cjs ADDED
@@ -0,0 +1,259 @@
1
+ 'use strict';
2
+
3
+ var document = require('@mteditor/document');
4
+
5
+ // src/render.ts
6
+
7
+ // src/capabilities.ts
8
+ var MT_WECHAT_RICH_TEXT_TAGS = [
9
+ "a",
10
+ "abbr",
11
+ "address",
12
+ "article",
13
+ "aside",
14
+ "b",
15
+ "bdi",
16
+ "bdo",
17
+ "big",
18
+ "blockquote",
19
+ "br",
20
+ "caption",
21
+ "center",
22
+ "cite",
23
+ "code",
24
+ "col",
25
+ "colgroup",
26
+ "dd",
27
+ "del",
28
+ "div",
29
+ "dl",
30
+ "dt",
31
+ "em",
32
+ "fieldset",
33
+ "font",
34
+ "footer",
35
+ "h1",
36
+ "h2",
37
+ "h3",
38
+ "h4",
39
+ "h5",
40
+ "h6",
41
+ "header",
42
+ "hr",
43
+ "i",
44
+ "img",
45
+ "ins",
46
+ "label",
47
+ "legend",
48
+ "li",
49
+ "mark",
50
+ "nav",
51
+ "ol",
52
+ "p",
53
+ "pre",
54
+ "q",
55
+ "rt",
56
+ "ruby",
57
+ "s",
58
+ "section",
59
+ "small",
60
+ "span",
61
+ "strong",
62
+ "sub",
63
+ "sup",
64
+ "table",
65
+ "tbody",
66
+ "td",
67
+ "tfoot",
68
+ "th",
69
+ "thead",
70
+ "tr",
71
+ "tt",
72
+ "u",
73
+ "ul"
74
+ ];
75
+ var MT_WECHAT_TAG_ATTRS = {
76
+ img: ["alt", "src", "height", "width"],
77
+ table: ["width"],
78
+ col: ["span", "width"],
79
+ colgroup: ["span", "width"],
80
+ td: ["colspan", "height", "rowspan", "width"],
81
+ th: ["colspan", "height", "rowspan", "width"],
82
+ tr: ["colspan", "height", "rowspan", "width"],
83
+ ol: ["start", "type"]
84
+ };
85
+ var MT_MINI_CAPABILITIES = {
86
+ wechat: {
87
+ platform: "wechat",
88
+ verified: true,
89
+ tags: MT_WECHAT_RICH_TEXT_TAGS,
90
+ globalAttrs: ["class", "style"],
91
+ supportsId: false,
92
+ tagAttrs: MT_WECHAT_TAG_ATTRS,
93
+ /**
94
+ * `rich-text` 下不可表达、必须拆到组件外的节点。
95
+ * 组件通道下这些节点走原生组件,不受 `rich-text` 白名单限制。
96
+ */
97
+ nativeComponents: ["video", "audio"]
98
+ }
99
+ };
100
+ var resolveCapabilities = (platform) => {
101
+ const found = MT_MINI_CAPABILITIES[platform];
102
+ if (found === void 0) {
103
+ throw new RangeError(
104
+ `@mteditor/renderer-mini \u5C1A\u672A\u652F\u6301\u5E73\u53F0 "${platform}"\uFF1A\u5176 rich-text \u767D\u540D\u5355\u672A\u7ECF\u5B9E\u6D4B\u6838\u5B9E\uFF0C\u4E0D\u63A5\u53D7\u51ED\u731C\u6D4B\u63D0\u4F9B\u7684\u6620\u5C04\u8868\u3002\u5F53\u524D\u53EF\u7528\u5E73\u53F0\uFF1Awechat\u3002`
105
+ );
106
+ }
107
+ return found;
108
+ };
109
+ var resolveChannel = (doc, option, maxNodes) => {
110
+ if (option !== "auto") return { mode: option, switched: null };
111
+ const { nodeCount } = document.computeTreeStats(doc.content);
112
+ if (nodeCount <= maxNodes) return { mode: "component", switched: null };
113
+ return {
114
+ mode: "richText",
115
+ switched: { from: "component", to: "richText", nodeCount, maxNodes }
116
+ };
117
+ };
118
+
119
+ // src/options.ts
120
+ var MT_DEFAULT_MAX_NODES = 3e3;
121
+ var MT_DEFAULT_MODE = "auto";
122
+ var MT_DEFAULT_PLATFORM = "wechat";
123
+
124
+ // src/theme.ts
125
+ var MT_MINI_TOKENS_LIGHT = {
126
+ "--mt-color-primary": "#2563eb",
127
+ "--mt-color-primary-hover": "#1d4ed8",
128
+ "--mt-color-primary-active": "#1e40af",
129
+ "--mt-color-success": "#16a34a",
130
+ "--mt-color-warning": "#d97706",
131
+ "--mt-color-danger": "#dc2626",
132
+ "--mt-color-link": "#2563eb",
133
+ "--mt-color-text": "#1f2329",
134
+ "--mt-color-text-secondary": "#646a73",
135
+ "--mt-color-text-disabled": "#a6a9ad",
136
+ "--mt-color-text-inverse": "#fff",
137
+ "--mt-color-bg": "#fff",
138
+ "--mt-color-bg-elevated": "#fff",
139
+ "--mt-color-bg-muted": "#f5f7fa",
140
+ "--mt-color-bg-hover": "#f2f3f5",
141
+ "--mt-color-border": "#dee0e3",
142
+ "--mt-color-border-strong": "#babdbf",
143
+ "--mt-color-selection": "rgb(37 99 235 / 18%)",
144
+ "--mt-color-code-bg": "#f5f5f5",
145
+ "--mt-color-code-text": "#c0392b",
146
+ "--mt-color-quote-border": "#dee0e3",
147
+ "--mt-color-mark-bg": "#fff3a3",
148
+ "--mt-font-family": "-apple-system, blinkmacsystemfont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif",
149
+ "--mt-font-family-mono": "'SFMono-Regular', consolas, 'Liberation Mono', menlo, monospace",
150
+ "--mt-font-size": "15px",
151
+ "--mt-font-size-sm": "13px",
152
+ "--mt-font-size-lg": "17px",
153
+ "--mt-line-height": "1.7",
154
+ "--mt-letter-spacing": "normal",
155
+ "--mt-h1-font-size": "28px",
156
+ "--mt-h2-font-size": "24px",
157
+ "--mt-h3-font-size": "20px",
158
+ "--mt-h4-font-size": "18px",
159
+ "--mt-h5-font-size": "16px",
160
+ "--mt-h6-font-size": "15px",
161
+ "--mt-space-1": "4px",
162
+ "--mt-space-2": "8px",
163
+ "--mt-space-3": "12px",
164
+ "--mt-space-4": "16px",
165
+ "--mt-space-5": "24px",
166
+ "--mt-space-6": "32px",
167
+ "--mt-radius-sm": "3px",
168
+ "--mt-radius-md": "6px",
169
+ "--mt-radius-lg": "10px",
170
+ "--mt-radius-full": "9999px",
171
+ "--mt-shadow-sm": "0 1px 3px rgb(0 0 0 / 8%)",
172
+ "--mt-shadow-md": "0 4px 12px rgb(0 0 0 / 10%)",
173
+ "--mt-toolbar-height": "40px",
174
+ "--mt-content-max-width": "860px",
175
+ "--mt-content-padding": "20px",
176
+ "--mt-control-size": "30px",
177
+ "--mt-control-icon-size": "18px",
178
+ "--mt-control-gap": "2px",
179
+ "--mt-popup-padding": "4px",
180
+ "--mt-popup-gap": "6px",
181
+ "--mt-drawer-max-height": "60vh",
182
+ "--mt-block-handle-width": "46px",
183
+ "--mt-block-indicator-height": "2px",
184
+ "--mt-outline-width": "200px",
185
+ "--mt-outline-top": "0px",
186
+ "--mt-z-toolbar": "100",
187
+ "--mt-z-dropdown": "200",
188
+ "--mt-z-popover": "300",
189
+ "--mt-z-modal": "400",
190
+ "--mt-z-toast": "500",
191
+ "--mt-transition-fast": "120ms ease",
192
+ "--mt-transition-base": "200ms ease"
193
+ };
194
+ var MT_MINI_TOKENS_DARK_OVERRIDES = {
195
+ "--mt-color-primary": "#3b82f6",
196
+ "--mt-color-primary-hover": "#60a5fa",
197
+ "--mt-color-primary-active": "#2563eb",
198
+ "--mt-color-success": "#22c55e",
199
+ "--mt-color-warning": "#f59e0b",
200
+ "--mt-color-danger": "#ef4444",
201
+ "--mt-color-link": "#60a5fa",
202
+ "--mt-color-text": "#e5e6eb",
203
+ "--mt-color-text-secondary": "#a3a6ad",
204
+ "--mt-color-text-disabled": "#6b6f76",
205
+ "--mt-color-text-inverse": "#1f2329",
206
+ "--mt-color-bg": "#1f2329",
207
+ "--mt-color-bg-elevated": "#282c33",
208
+ "--mt-color-bg-muted": "#282c33",
209
+ "--mt-color-bg-hover": "#32363d",
210
+ "--mt-color-border": "#3a3f47",
211
+ "--mt-color-border-strong": "#4e545d",
212
+ "--mt-color-selection": "rgb(59 130 246 / 28%)",
213
+ "--mt-color-code-bg": "#2b2f36",
214
+ "--mt-color-code-text": "#f87171",
215
+ "--mt-color-quote-border": "#3a3f47",
216
+ "--mt-color-mark-bg": "#6b5a1a",
217
+ "--mt-shadow-sm": "0 1px 3px rgb(0 0 0 / 40%)",
218
+ "--mt-shadow-md": "0 4px 12px rgb(0 0 0 / 50%)"
219
+ };
220
+ var MT_MINI_TOKENS_DARK = {
221
+ ...MT_MINI_TOKENS_LIGHT,
222
+ ...MT_MINI_TOKENS_DARK_OVERRIDES
223
+ };
224
+ var resolveThemeTokens = (theme, override) => {
225
+ const base = theme === void 0 || theme === "light" ? MT_MINI_TOKENS_LIGHT : theme === "dark" ? MT_MINI_TOKENS_DARK : theme;
226
+ return override === void 0 ? { ...base } : { ...base, ...override };
227
+ };
228
+
229
+ // src/render.ts
230
+ var renderMiniDocument = (doc, options = {}) => {
231
+ const platform = options.platform ?? MT_DEFAULT_PLATFORM;
232
+ void resolveCapabilities(platform);
233
+ const { mode, switched } = resolveChannel(
234
+ doc,
235
+ options.mode ?? MT_DEFAULT_MODE,
236
+ options.maxNodes ?? MT_DEFAULT_MAX_NODES
237
+ );
238
+ const { output, report, stats } = document.serializeDocumentToMini(doc, {
239
+ platform,
240
+ mode,
241
+ themeTokens: resolveThemeTokens(options.theme, options.themeTokens),
242
+ ...options.preRendered === void 0 ? {} : { preRendered: options.preRendered }
243
+ });
244
+ return { platform, mode, nodes: output, report, stats, autoSwitched: switched };
245
+ };
246
+
247
+ exports.MT_DEFAULT_MAX_NODES = MT_DEFAULT_MAX_NODES;
248
+ exports.MT_DEFAULT_MODE = MT_DEFAULT_MODE;
249
+ exports.MT_DEFAULT_PLATFORM = MT_DEFAULT_PLATFORM;
250
+ exports.MT_MINI_CAPABILITIES = MT_MINI_CAPABILITIES;
251
+ exports.MT_MINI_TOKENS_DARK = MT_MINI_TOKENS_DARK;
252
+ exports.MT_MINI_TOKENS_DARK_OVERRIDES = MT_MINI_TOKENS_DARK_OVERRIDES;
253
+ exports.MT_MINI_TOKENS_LIGHT = MT_MINI_TOKENS_LIGHT;
254
+ exports.renderMiniDocument = renderMiniDocument;
255
+ exports.resolveCapabilities = resolveCapabilities;
256
+ exports.resolveChannel = resolveChannel;
257
+ exports.resolveThemeTokens = resolveThemeTokens;
258
+ //# sourceMappingURL=index.cjs.map
259
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/capabilities.ts","../src/channel.ts","../src/options.ts","../src/theme.ts","../src/render.ts"],"names":["computeTreeStats","serializeDocumentToMini"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * 各端 `rich-text` 能力表。\n *\n * **准入条件:必须实测核实。** 各子路径必须各自维护映射差异,\n * 禁止共用一份映射表;反过来说,**没有实测过就不能让别人用**——\n * 一份「看起来能跑」的错误白名单比明确的报错危险得多。\n *\n * 因此本文件当前只包含 `wechat`。支付宝 / 抖音的表在各自实测完成后\n * (需各自开发者工具)追加,并同时回填待确认项。\n */\n\nimport type { MtMiniCapabilities, MtMiniPlatform } from './types'\n\n/**\n * 微信小程序 `rich-text` 受信任标签白名单(**已核实**)。\n *\n * 顺序与官方文档一致,便于逐条比对;`Set` 查询由调用方按需构造。\n */\nexport const MT_WECHAT_RICH_TEXT_TAGS: readonly string[] = [\n 'a',\n 'abbr',\n 'address',\n 'article',\n 'aside',\n 'b',\n 'bdi',\n 'bdo',\n 'big',\n 'blockquote',\n 'br',\n 'caption',\n 'center',\n 'cite',\n 'code',\n 'col',\n 'colgroup',\n 'dd',\n 'del',\n 'div',\n 'dl',\n 'dt',\n 'em',\n 'fieldset',\n 'font',\n 'footer',\n 'h1',\n 'h2',\n 'h3',\n 'h4',\n 'h5',\n 'h6',\n 'header',\n 'hr',\n 'i',\n 'img',\n 'ins',\n 'label',\n 'legend',\n 'li',\n 'mark',\n 'nav',\n 'ol',\n 'p',\n 'pre',\n 'q',\n 'rt',\n 'ruby',\n 's',\n 'section',\n 'small',\n 'span',\n 'strong',\n 'sub',\n 'sup',\n 'table',\n 'tbody',\n 'td',\n 'tfoot',\n 'th',\n 'thead',\n 'tr',\n 'tt',\n 'u',\n 'ul',\n]\n\n/**\n * 逐标签属性白名单(**已核实**)。\n *\n * 未在表中的标签不接受额外属性;全局属性(`class` / `style`)单独由\n * `globalAttrs` 描述。**`id` 不在任何一张表里** —— 微信全局不支持 `id`。\n */\nexport const MT_WECHAT_TAG_ATTRS: Readonly<Record<string, readonly string[]>> = {\n img: ['alt', 'src', 'height', 'width'],\n table: ['width'],\n col: ['span', 'width'],\n colgroup: ['span', 'width'],\n td: ['colspan', 'height', 'rowspan', 'width'],\n th: ['colspan', 'height', 'rowspan', 'width'],\n tr: ['colspan', 'height', 'rowspan', 'width'],\n ol: ['start', 'type'],\n}\n\n/**\n * 小程序平台能力表。\n *\n * 当前只登记 `wechat`(已核实)。缺失的平台在\n * `resolveCapabilities` 处**抛错**,不做容错。\n */\nexport const MT_MINI_CAPABILITIES: Readonly<Partial<Record<MtMiniPlatform, MtMiniCapabilities>>> = {\n wechat: {\n platform: 'wechat',\n verified: true,\n tags: MT_WECHAT_RICH_TEXT_TAGS,\n globalAttrs: ['class', 'style'],\n supportsId: false,\n tagAttrs: MT_WECHAT_TAG_ATTRS,\n /**\n * `rich-text` 下不可表达、必须拆到组件外的节点。\n * 组件通道下这些节点走原生组件,不受 `rich-text` 白名单限制。\n */\n nativeComponents: ['video', 'audio'],\n },\n}\n\n/**\n * 取某个平台的能力表。\n *\n * @param platform 平台标识\n * @returns 该平台的能力描述\n * @throws {RangeError} 该平台尚未实测核实\n *\n * @example\n * ```ts\n * resolveCapabilities('wechat').supportsId // false\n * resolveCapabilities('alipay') // 抛 RangeError:尚未实测\n * ```\n */\nexport const resolveCapabilities = (platform: MtMiniPlatform): MtMiniCapabilities => {\n const found = MT_MINI_CAPABILITIES[platform]\n if (found === undefined) {\n throw new RangeError(\n `@mteditor/renderer-mini 尚未支持平台 \"${platform}\":其 rich-text 白名单未经实测核实,` +\n '不接受凭猜测提供的映射表。当前可用平台:wechat。',\n )\n }\n return found\n}\n","/**\n * 通道解析(双通道)。\n *\n * `@mteditor/document` 只接受显式的 `'component' | 'richText'`;把 `'auto'`\n * 解析成具体通道是**渲染层**的职责 —— 因为它需要知道 `maxNodes` 这类\n * 宿主侧的渲染成本概念,而 `document` 是零框架的文档模型层。\n */\n\nimport { computeTreeStats } from '@mteditor/document'\nimport type { MtDocument } from '@mteditor/document'\nimport type { MtMiniChannelOption, MtMiniChannelSwitch, MtMiniMode } from './types'\n\n/** 通道解析结果 */\nexport interface MtChannelResolution {\n /** 实际使用的通道 */\n mode: MtMiniMode\n /** 自动切换记录;未发生切换时为 `null` */\n switched: MtMiniChannelSwitch | null\n}\n\n/**\n * 解析渲染通道。\n *\n * 规则:\n * - 显式给出 `'component'` / `'richText'` 时**原样采用**,不做阈值判定\n * —— 宿主显式指定就代表它知道自己在做什么;\n * - `'auto'` 时按**文档节点数**判定:`nodeCount > maxNodes` 走 `richText`。\n *\n * @param doc 文档\n * @param option 通道选择\n * @param maxNodes `'auto'` 的阈值(文档节点数)\n * @returns 通道与该次判定是否发生了切换\n *\n * @example\n * ```ts\n * // 3000 节点以内:组件通道\n * resolveChannel(doc, 'auto', 3000).mode // 'component'\n * // 显式指定时不看阈值\n * resolveChannel(hugeDoc, 'component', 1).mode // 'component'\n * ```\n */\nexport const resolveChannel = (\n doc: MtDocument,\n option: MtMiniChannelOption,\n maxNodes: number,\n): MtChannelResolution => {\n if (option !== 'auto') return { mode: option, switched: null }\n\n const { nodeCount } = computeTreeStats(doc.content)\n if (nodeCount <= maxNodes) return { mode: 'component', switched: null }\n\n return {\n mode: 'richText',\n switched: { from: 'component', to: 'richText', nodeCount, maxNodes },\n }\n}\n","/**\n * 渲染层默认值。\n *\n * 单独成文件的理由:这些数值同时出现在**文档**与\n * **测试**(阈值边界用例)里,散落在实现里会让「改默认值」变成一次考古。\n */\n\nimport type { MtMiniMode } from './types'\n\n/**\n * `mode: 'auto'` 的降级阈值,单位是**文档节点数**。\n *\n * 判定依据不是「输出 nodes 数」:那需要先序列化一次才能判定,而判定的意义\n * 正是避免一次昂贵序列化。\n */\nexport const MT_DEFAULT_MAX_NODES = 3000\n\n/** 缺省通道选择 */\nexport const MT_DEFAULT_MODE: 'auto' | MtMiniMode = 'auto'\n\n/** 缺省主题名 */\nexport const MT_DEFAULT_THEME = 'light'\n\n/** 缺省平台 */\nexport const MT_DEFAULT_PLATFORM = 'wechat'\n","/**\n * 内置主题字面量。\n *\n * ## 为什么这份数据必须存在于本包\n *\n * 小程序端 `rich-text` 内的 `style` **不参与宿主 CSS 变量继承**,\n * 所有主题值必须在序列化时解析为字面量,而 `@mteditor/theme-default`\n * 只产出 CSS、没有 JS 导出 —— 若要求宿主自备这份表,每个项目都要手抄\n * `tokens.css` 的 65 个键,抄错还**没有报错**(本仓库自己就踩过:\n * `mini.ts` 读的 `--mt-font-mono` 与 `tokens.css` 的 `--mt-font-family-mono`\n * 不一致,两个引用点恒走 fallback)。\n *\n * ## 与 tokens.css 的关系:允许独立,禁止无守卫地独立\n *\n * 本文件是 `packages/theme-default/src/tokens.css` 的**逐键镜像**\n * (`dark` 是 `light` 上的部分覆盖,与 CSS 的层叠语义一致)。\n * `scripts/check-theme-tokens.mjs` 断言两者键集合与取值完全一致 ——\n * 改任一侧而漏改另一侧会让 `pnpm verify` 失败。\n *\n * 取值风格与 CSS 一致:保留 `rgb(37 99 235 / 18%)` 这类现代空格语法,\n * 不自作主张转换为逗号语法(`@mteditor/document` 原样内联,不做解析)。\n */\n\nimport type { MtMiniTheme } from './types'\n\n/** 亮色主题:`tokens.css` 中 `:root, [data-mt-theme='light']` 块的完整镜像 */\nexport const MT_MINI_TOKENS_LIGHT: Readonly<Record<string, string>> = {\n '--mt-color-primary': '#2563eb',\n '--mt-color-primary-hover': '#1d4ed8',\n '--mt-color-primary-active': '#1e40af',\n '--mt-color-success': '#16a34a',\n '--mt-color-warning': '#d97706',\n '--mt-color-danger': '#dc2626',\n '--mt-color-link': '#2563eb',\n '--mt-color-text': '#1f2329',\n '--mt-color-text-secondary': '#646a73',\n '--mt-color-text-disabled': '#a6a9ad',\n '--mt-color-text-inverse': '#fff',\n '--mt-color-bg': '#fff',\n '--mt-color-bg-elevated': '#fff',\n '--mt-color-bg-muted': '#f5f7fa',\n '--mt-color-bg-hover': '#f2f3f5',\n '--mt-color-border': '#dee0e3',\n '--mt-color-border-strong': '#babdbf',\n '--mt-color-selection': 'rgb(37 99 235 / 18%)',\n '--mt-color-code-bg': '#f5f5f5',\n '--mt-color-code-text': '#c0392b',\n '--mt-color-quote-border': '#dee0e3',\n '--mt-color-mark-bg': '#fff3a3',\n '--mt-font-family':\n \"-apple-system, blinkmacsystemfont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif\",\n '--mt-font-family-mono': \"'SFMono-Regular', consolas, 'Liberation Mono', menlo, monospace\",\n '--mt-font-size': '15px',\n '--mt-font-size-sm': '13px',\n '--mt-font-size-lg': '17px',\n '--mt-line-height': '1.7',\n '--mt-letter-spacing': 'normal',\n '--mt-h1-font-size': '28px',\n '--mt-h2-font-size': '24px',\n '--mt-h3-font-size': '20px',\n '--mt-h4-font-size': '18px',\n '--mt-h5-font-size': '16px',\n '--mt-h6-font-size': '15px',\n '--mt-space-1': '4px',\n '--mt-space-2': '8px',\n '--mt-space-3': '12px',\n '--mt-space-4': '16px',\n '--mt-space-5': '24px',\n '--mt-space-6': '32px',\n '--mt-radius-sm': '3px',\n '--mt-radius-md': '6px',\n '--mt-radius-lg': '10px',\n '--mt-radius-full': '9999px',\n '--mt-shadow-sm': '0 1px 3px rgb(0 0 0 / 8%)',\n '--mt-shadow-md': '0 4px 12px rgb(0 0 0 / 10%)',\n '--mt-toolbar-height': '40px',\n '--mt-content-max-width': '860px',\n '--mt-content-padding': '20px',\n '--mt-control-size': '30px',\n '--mt-control-icon-size': '18px',\n '--mt-control-gap': '2px',\n '--mt-popup-padding': '4px',\n '--mt-popup-gap': '6px',\n '--mt-drawer-max-height': '60vh',\n '--mt-block-handle-width': '46px',\n '--mt-block-indicator-height': '2px',\n '--mt-outline-width': '200px',\n '--mt-outline-top': '0px',\n '--mt-z-toolbar': '100',\n '--mt-z-dropdown': '200',\n '--mt-z-popover': '300',\n '--mt-z-modal': '400',\n '--mt-z-toast': '500',\n '--mt-transition-fast': '120ms ease',\n '--mt-transition-base': '200ms ease',\n}\n\n/**\n * 暗色主题对亮色的**覆盖项**(与 `tokens.css` 的 `[data-mt-theme='dark']` 块一致)。\n *\n * 单独导出是为了让卡口脚本能分别比对「覆盖集」与「派生全集」——\n * 若只导出派生的全集,CSS 里删掉一个覆盖项(于是暗色回退到亮色值)\n * 在 TS 侧不可见。\n */\nexport const MT_MINI_TOKENS_DARK_OVERRIDES: Readonly<Record<string, string>> = {\n '--mt-color-primary': '#3b82f6',\n '--mt-color-primary-hover': '#60a5fa',\n '--mt-color-primary-active': '#2563eb',\n '--mt-color-success': '#22c55e',\n '--mt-color-warning': '#f59e0b',\n '--mt-color-danger': '#ef4444',\n '--mt-color-link': '#60a5fa',\n '--mt-color-text': '#e5e6eb',\n '--mt-color-text-secondary': '#a3a6ad',\n '--mt-color-text-disabled': '#6b6f76',\n '--mt-color-text-inverse': '#1f2329',\n '--mt-color-bg': '#1f2329',\n '--mt-color-bg-elevated': '#282c33',\n '--mt-color-bg-muted': '#282c33',\n '--mt-color-bg-hover': '#32363d',\n '--mt-color-border': '#3a3f47',\n '--mt-color-border-strong': '#4e545d',\n '--mt-color-selection': 'rgb(59 130 246 / 28%)',\n '--mt-color-code-bg': '#2b2f36',\n '--mt-color-code-text': '#f87171',\n '--mt-color-quote-border': '#3a3f47',\n '--mt-color-mark-bg': '#6b5a1a',\n '--mt-shadow-sm': '0 1px 3px rgb(0 0 0 / 40%)',\n '--mt-shadow-md': '0 4px 12px rgb(0 0 0 / 50%)',\n}\n\n/** 暗色主题全集(亮色为基底 + 覆盖项) */\nexport const MT_MINI_TOKENS_DARK: Readonly<Record<string, string>> = {\n ...MT_MINI_TOKENS_LIGHT,\n ...MT_MINI_TOKENS_DARK_OVERRIDES,\n}\n\n/**\n * 解析主题字面量表。\n *\n * 合并顺序:内置名(或自定义表)→ `themeTokens` 覆盖项。\n *\n * @param theme 内置主题名或自定义字面量表,缺省 `'light'`\n * @param override 覆盖项,键含 `--` 前缀;缺省不覆盖\n * @returns 可直接传给 `serializeDocumentToMini` 的 `themeTokens`\n *\n * @example\n * ```ts\n * resolveThemeTokens('dark') // 65 个键的暗色表\n * resolveThemeTokens(undefined, { '--mt-color-link': '#f00' })\n * // 亮色表,但链接色为 #f00\n * ```\n */\nexport const resolveThemeTokens = (\n theme?: MtMiniTheme,\n override?: Record<string, string>,\n): Record<string, string> => {\n const base =\n theme === undefined || theme === 'light'\n ? MT_MINI_TOKENS_LIGHT\n : theme === 'dark'\n ? MT_MINI_TOKENS_DARK\n : theme\n return override === undefined ? { ...base } : { ...base, ...override }\n}\n","/**\n * 渲染层主入口。\n *\n * 本函数的职责边界刻意很窄 —— 只做三件事,**不自己拼 nodes**:\n *\n * | 步骤 | 说明 |\n * |---|---|\n * | ① 平台准入 | 能力表未登记的平台直接抛错,不做容错 |\n * | ② 通道解析 | `'auto'` → 按 `maxNodes` 判定,并记录是否发生切换 |\n * | ③ 主题注入 | 内置 light / dark 字面量(小程序无 CSS 变量) |\n *\n * `nodes` 一律由 `@mteditor/document` 的 `serializeDocumentToMini` 产出\n * —— 这是 「序列化真相源唯一」在小程序端的同一条原则。\n */\n\nimport { serializeDocumentToMini } from '@mteditor/document'\nimport type { MtDocument } from '@mteditor/document'\nimport { resolveCapabilities } from './capabilities'\nimport { resolveChannel } from './channel'\nimport { MT_DEFAULT_MAX_NODES, MT_DEFAULT_MODE, MT_DEFAULT_PLATFORM } from './options'\nimport { resolveThemeTokens } from './theme'\nimport type { MtMiniRenderOptions, MtMiniRenderResult } from './types'\n\n/**\n * 把 `MtDocument` 渲染为小程序可直接 `setData` 的 payload。\n *\n * @param doc 文档(唯一真相源)\n * @param options 渲染选项\n * @returns 通道、nodes、降级报告、统计与自动切换记录\n * @throws {RangeError} `options.platform` 的能力表未经实测核实\n *\n * @example\n * ```ts\n * import { renderMiniDocument } from '@mteditor/renderer-mini'\n *\n * const { mode, nodes, report, autoSwitched } = renderMiniDocument(doc, {\n * theme: 'dark',\n * mode: 'auto',\n * })\n *\n * if (autoSwitched) console.warn(`节点数 ${autoSwitched.nodeCount} 超过阈值,已切到 rich-text`)\n * if (report.length > 0) console.warn('内容有降级', report)\n * ```\n */\nexport const renderMiniDocument = (\n doc: MtDocument,\n options: MtMiniRenderOptions = {},\n): MtMiniRenderResult => {\n const platform = options.platform ?? MT_DEFAULT_PLATFORM\n // 平台准入:未实测核实的平台在此抛错,而不是拿微信的表硬跑\n void resolveCapabilities(platform)\n\n const { mode, switched } = resolveChannel(\n doc,\n options.mode ?? MT_DEFAULT_MODE,\n options.maxNodes ?? MT_DEFAULT_MAX_NODES,\n )\n\n const { output, report, stats } = serializeDocumentToMini(doc, {\n platform,\n mode,\n themeTokens: resolveThemeTokens(options.theme, options.themeTokens),\n ...(options.preRendered === undefined ? {} : { preRendered: options.preRendered }),\n })\n\n return { platform, mode, nodes: output, report, stats, autoSwitched: switched }\n}\n"]}