@xiongtao.xt/tau-plugins 0.18.0 → 0.20.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 (79) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/PUBLISH-DATA.md +29 -0
  3. package/README.md +1 -1
  4. package/client/fuse-M2Z6NNAT.js +2000 -0
  5. package/package.json +15 -3
  6. package/publish-artifacts.js +252 -0
  7. package/publish-client.js +258 -0
  8. package/publish-data.js +1 -0
  9. package/types/packages/editor/api.d.ts +1 -1
  10. package/types/packages/editor/contracts.d.ts +2 -2
  11. package/types/packages/editor/source-contracts.d.ts +48 -0
  12. package/types/packages/editor/src/{services → core/services}/overlayBackDismiss.d.ts +1 -1
  13. package/types/packages/editor/src/{services → core/services}/registry.d.ts +2 -2
  14. package/types/packages/editor/src/{services → core/services}/tokens.d.ts +4 -4
  15. package/types/packages/editor/src/{types → core/types}/custom-element.d.ts +1 -1
  16. package/types/packages/editor/src/core/types/text.d.ts +1 -0
  17. package/types/packages/editor/src/{ui → core/ui}/Tooltip.d.ts +1 -1
  18. package/types/packages/editor/src/{utils → core/utils}/blockNavigation.d.ts +1 -1
  19. package/types/packages/markdown/src/codec.d.ts +2 -2
  20. package/types/packages/plugins/src/categories.d.ts +40 -0
  21. package/types/packages/plugins/src/ids.d.ts +1 -0
  22. package/types/packages/plugins/src/inline-source.d.ts +2 -13
  23. package/types/packages/plugins/src/package.d.ts +38 -0
  24. package/types/packages/plugins/src/publish-artifacts.d.ts +14 -0
  25. package/types/packages/plugins/src/publish-client.d.ts +8 -0
  26. package/types/packages/plugins/src/publish-data.d.ts +280 -0
  27. package/types/packages/plugins/src/render-artifact.d.ts +9 -0
  28. package/types/packages/plugins/src/source-editor.d.ts +2 -38
  29. package/types/packages/plugins/src/version.d.ts +4 -0
  30. package/types/packages/editor/src/types/text.d.ts +0 -1
  31. /package/types/packages/editor/src/{api → core/api}/command.d.ts +0 -0
  32. /package/types/packages/editor/src/{api → core/api}/copy.d.ts +0 -0
  33. /package/types/packages/editor/src/{api → core/api}/drag.d.ts +0 -0
  34. /package/types/packages/editor/src/{api → core/api}/extension.d.ts +0 -0
  35. /package/types/packages/editor/src/{api → core/api}/index.d.ts +0 -0
  36. /package/types/packages/editor/src/{api → core/api}/ingest.d.ts +0 -0
  37. /package/types/packages/editor/src/{api → core/api}/legacy.d.ts +0 -0
  38. /package/types/packages/editor/src/{api → core/api}/marks.d.ts +0 -0
  39. /package/types/packages/editor/src/{api → core/api}/menu.d.ts +0 -0
  40. /package/types/packages/editor/src/{api → core/api}/submission.d.ts +0 -0
  41. /package/types/packages/editor/src/{api → core/api}/toolbar.d.ts +0 -0
  42. /package/types/packages/editor/src/{components → core/components}/AddParagraph/index.d.ts +0 -0
  43. /package/types/packages/editor/src/{components → core/components}/BlockDrag/index.d.ts +0 -0
  44. /package/types/packages/editor/src/{components → core/components}/ElementMenu/index.d.ts +0 -0
  45. /package/types/packages/editor/src/{components → core/components}/FloatingToolbar/index.d.ts +0 -0
  46. /package/types/packages/editor/src/{components → core/components}/HoveringToolbar/FloatingSubmenu.d.ts +0 -0
  47. /package/types/packages/editor/src/{components → core/components}/HoveringToolbar/context.d.ts +0 -0
  48. /package/types/packages/editor/src/{components → core/components}/HoveringToolbar/floatingPosition.d.ts +0 -0
  49. /package/types/packages/editor/src/{components → core/components}/InlineChromiumBugFix/index.d.ts +0 -0
  50. /package/types/packages/editor/src/{components → core/components}/OverlayBackDismiss/index.d.ts +0 -0
  51. /package/types/packages/editor/src/{hooks → core/hooks}/useIsLastElement.d.ts +0 -0
  52. /package/types/packages/editor/src/{kit → core/kit}/elementEmpty.d.ts +0 -0
  53. /package/types/packages/editor/src/{menu → core/menu}/conversion.d.ts +0 -0
  54. /package/types/packages/editor/src/{model → core/model}/paragraph.d.ts +0 -0
  55. /package/types/packages/editor/src/{services → core/services}/editorNotifier.d.ts +0 -0
  56. /package/types/packages/editor/src/{services → core/services}/errorReporter.d.ts +0 -0
  57. /package/types/packages/editor/src/{services → core/services}/hooks.d.ts +0 -0
  58. /package/types/packages/editor/src/{services → core/services}/notifier.d.ts +0 -0
  59. /package/types/packages/editor/src/{theme → core/theme}/ThemeService.d.ts +0 -0
  60. /package/types/packages/editor/src/{theme → core/theme}/context.d.ts +0 -0
  61. /package/types/packages/editor/src/{types → core/types}/block-panel.d.ts +0 -0
  62. /package/types/packages/editor/src/{types → core/types}/editor.d.ts +0 -0
  63. /package/types/packages/editor/src/{types → core/types}/element/paragraph.d.ts +0 -0
  64. /package/types/packages/editor/src/{types → core/types}/hotkeys.d.ts +0 -0
  65. /package/types/packages/editor/src/{types → core/types}/hovering-bar.d.ts +0 -0
  66. /package/types/packages/editor/src/{types → core/types}/index.d.ts +0 -0
  67. /package/types/packages/editor/src/{types.d.ts → core/types.d.ts} +0 -0
  68. /package/types/packages/editor/src/{ui → core/ui}/CaretRight.d.ts +0 -0
  69. /package/types/packages/editor/src/{utils → core/utils}/commandTarget.d.ts +0 -0
  70. /package/types/packages/editor/src/{utils → core/utils}/container.d.ts +0 -0
  71. /package/types/packages/editor/src/{utils → core/utils}/editor.d.ts +0 -0
  72. /package/types/packages/editor/src/{utils → core/utils}/element.d.ts +0 -0
  73. /package/types/packages/editor/src/{utils → core/utils}/insertElement.d.ts +0 -0
  74. /package/types/packages/editor/src/{utils → core/utils}/nodeOperations.d.ts +0 -0
  75. /package/types/packages/editor/src/{utils → core/utils}/paragraphShortcut.d.ts +0 -0
  76. /package/types/packages/editor/src/{utils → core/utils}/path.d.ts +0 -0
  77. /package/types/packages/editor/src/{utils → core/utils}/plugin.d.ts +0 -0
  78. /package/types/packages/editor/src/{utils → core/utils}/selectionSnapshot.d.ts +0 -0
  79. /package/types/packages/editor/src/{utils → core/utils}/zoomPan.d.ts +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xiongtao.xt/tau-plugins",
3
- "version": "0.18.0",
3
+ "version": "0.20.0",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -11,7 +11,7 @@
11
11
  "registry": "https://registry.npmjs.org"
12
12
  },
13
13
  "type": "module",
14
- "description": "Tau 插件作者类型契约;运行时由宿主提供",
14
+ "description": "Tau 插件作者类型契约;插件实现由宿主提供,发布数据客户端可独立使用",
15
15
  "exports": {
16
16
  ".": {
17
17
  "types": "./types/packages/plugins/src/index.d.ts",
@@ -22,6 +22,18 @@
22
22
  "types": "./types/packages/plugins/src/sync.d.ts",
23
23
  "default": "./runtime.js"
24
24
  },
25
+ "./publish-data": {
26
+ "types": "./types/packages/plugins/src/publish-data.d.ts",
27
+ "default": "./publish-data.js"
28
+ },
29
+ "./publish-client": {
30
+ "types": "./types/packages/plugins/src/publish-client.d.ts",
31
+ "default": "./publish-client.js"
32
+ },
33
+ "./publish-artifacts": {
34
+ "types": "./types/packages/plugins/src/publish-artifacts.d.ts",
35
+ "default": "./publish-artifacts.js"
36
+ },
25
37
  "./whiteboard": {
26
38
  "types": "./types/packages/plugins/src/whiteboard.d.ts",
27
39
  "default": "./runtime.js"
@@ -30,7 +42,7 @@
30
42
  "dependencies": {
31
43
  "@types/react": "19.2.0",
32
44
  "@types/react-dom": "19.2.0",
33
- "lucide-react": "0.399.0",
45
+ "lucide-react": "0.468.0",
34
46
  "clsx": "2.1.1",
35
47
  "slate": "0.126.2",
36
48
  "slate-react": "0.126.4",
@@ -0,0 +1,252 @@
1
+ // packages/plugins/src/ids.ts
2
+ function assertLocalId(value) {
3
+ if (typeof value !== "string" || !/^[a-zA-Z0-9][a-zA-Z0-9._-]{0,127}$/.test(value)) {
4
+ throw new Error("\u63D2\u4EF6\u6807\u8BC6\u5FC5\u987B\u4E3A 1 \u81F3 128 \u4F4D\u5B57\u6BCD\u3001\u6570\u5B57\u3001\u70B9\u3001\u6A2A\u7EBF\u6216\u4E0B\u5212\u7EBF");
5
+ }
6
+ }
7
+
8
+ // packages/plugins/src/version.ts
9
+ function parseVersion(value) {
10
+ const match = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/.exec(
11
+ value
12
+ );
13
+ if (!match) throw new Error(`\u7248\u672C\u53F7\u65E0\u6548\uFF1A${value}`);
14
+ const pre = match[4]?.split(".") ?? [];
15
+ if (pre.some((part) => /^\d+$/.test(part) && part.length > 1 && part.startsWith("0")))
16
+ throw new Error(`\u7248\u672C\u53F7\u65E0\u6548\uFF1A${value}`);
17
+ return { core: match.slice(1, 4), pre };
18
+ }
19
+ function comparePluginVersions(left, right) {
20
+ const a = parseVersion(left);
21
+ const b = parseVersion(right);
22
+ const numeric = (x, y) => BigInt(x) === BigInt(y) ? 0 : BigInt(x) > BigInt(y) ? 1 : -1;
23
+ for (let index = 0; index < 3; index++) {
24
+ const result = numeric(a.core[index], b.core[index]);
25
+ if (result) return result;
26
+ }
27
+ if (!a.pre.length || !b.pre.length)
28
+ return a.pre.length === b.pre.length ? 0 : a.pre.length ? -1 : 1;
29
+ for (let index = 0; index < Math.max(a.pre.length, b.pre.length); index++) {
30
+ const x = a.pre[index], y = b.pre[index];
31
+ if (x === void 0 || y === void 0) return x === void 0 ? -1 : 1;
32
+ if (x === y) continue;
33
+ const nx = /^\d+$/.test(x), ny = /^\d+$/.test(y);
34
+ return nx && ny ? numeric(x, y) : nx !== ny ? nx ? -1 : 1 : x > y ? 1 : -1;
35
+ }
36
+ return 0;
37
+ }
38
+
39
+ // packages/plugins/src/categories.ts
40
+ var PLUGIN_CATEGORIES = [
41
+ { id: "sync", label: "\u540C\u6B65" },
42
+ { id: "upload", label: "\u8D44\u6E90\u4E0A\u4F20" },
43
+ { id: "editor", label: "\u7F16\u8F91\u5668" },
44
+ { id: "whiteboard", label: "\u767D\u677F" },
45
+ { id: "blog-template", label: "\u535A\u5BA2\u6A21\u677F" },
46
+ { id: "ai", label: "AI" },
47
+ { id: "voice", label: "\u8BED\u97F3" },
48
+ { id: "page", label: "\u9875\u9762" }
49
+ ];
50
+ var PLUGIN_KEYWORD_LIMIT = 5;
51
+ var PLUGIN_KEYWORD_MAX_LENGTH = 20;
52
+ var categoryIds = new Set(PLUGIN_CATEGORIES.map((item) => item.id));
53
+ var isPluginCategory = (value) => typeof value === "string" && categoryIds.has(value);
54
+ function readCatalogFields(item, strict) {
55
+ const fail = (message) => {
56
+ if (strict) throw new Error(message);
57
+ };
58
+ const list = (value, name) => {
59
+ if (value === void 0) return [];
60
+ if (Array.isArray(value)) return value;
61
+ fail(`${name} \u5FC5\u987B\u662F\u6570\u7EC4`);
62
+ return [];
63
+ };
64
+ const categories = [];
65
+ for (const value of list(item.categories, "categories")) {
66
+ if (!isPluginCategory(value)) fail(`\u672A\u77E5\u63D2\u4EF6\u5206\u7C7B\uFF1A${String(value)}`);
67
+ else if (!categories.includes(value)) categories.push(value);
68
+ }
69
+ const keywords = [];
70
+ for (const value of list(item.keywords, "keywords")) {
71
+ const keyword = typeof value === "string" ? value.trim() : "";
72
+ if (!keyword || keyword.length > PLUGIN_KEYWORD_MAX_LENGTH)
73
+ fail(`\u5173\u952E\u8BCD\u5FC5\u987B\u4E3A 1 \u81F3 ${PLUGIN_KEYWORD_MAX_LENGTH} \u5B57`);
74
+ else if (!keywords.includes(keyword)) keywords.push(keyword);
75
+ }
76
+ if (keywords.length > PLUGIN_KEYWORD_LIMIT) {
77
+ fail(`\u5173\u952E\u8BCD\u6700\u591A ${PLUGIN_KEYWORD_LIMIT} \u4E2A`);
78
+ keywords.length = PLUGIN_KEYWORD_LIMIT;
79
+ }
80
+ return {
81
+ ...categories.length ? { categories: Object.freeze(categories) } : {},
82
+ ...keywords.length ? { keywords: Object.freeze(keywords) } : {}
83
+ };
84
+ }
85
+
86
+ // packages/plugins/src/package.ts
87
+ var PLUGIN_SHARED_MODULES = [
88
+ "@tau/plugins",
89
+ "@tau/plugins/whiteboard",
90
+ "@tau/plugins/sync",
91
+ "@tau/ui",
92
+ "react",
93
+ "react-dom",
94
+ "react-dom/client",
95
+ "react/jsx-runtime",
96
+ "react/jsx-dev-runtime"
97
+ ];
98
+ function validatePluginManifest(value, options = {}) {
99
+ if (!value || typeof value !== "object" || Array.isArray(value))
100
+ throw new Error("\u63D2\u4EF6\u6E05\u5355\u5FC5\u987B\u662F\u5BF9\u8C61");
101
+ const item = value;
102
+ if (item.formatVersion !== 1 || item.apiVersion !== 1 || item.platform !== "desktop" || item.format !== "cjs")
103
+ throw new Error("\u63D2\u4EF6\u5305\u683C\u5F0F\u3001API \u7248\u672C\u6216\u5E73\u53F0\u4E0D\u517C\u5BB9");
104
+ if (typeof item.id !== "string") throw new Error("\u63D2\u4EF6 ID \u65E0\u6548");
105
+ assertLocalId(item.id);
106
+ if (typeof item.name !== "string" || !item.name.trim() || typeof item.version !== "string" || !/^\d+\.\d+\.\d+(?:-[\w.-]+)?$/.test(item.version))
107
+ throw new Error("\u63D2\u4EF6\u540D\u79F0\u6216\u7248\u672C\u65E0\u6548");
108
+ const file = (input, extension) => {
109
+ if (typeof input !== "string" || !/^[\w./-]+$/.test(input) || input.split("/").some((part) => !part || part === "." || part === "..") || !input.endsWith(extension))
110
+ throw new Error("\u63D2\u4EF6\u5165\u53E3\u6216\u6837\u5F0F\u8DEF\u5F84\u65E0\u6548");
111
+ return input;
112
+ };
113
+ const main = file(item.main, ".js");
114
+ if (item.sync !== void 0) throw new Error("Node\u540C\u6B65\u5165\u53E3\u5DF2\u505C\u7528\uFF0C\u8BF7\u66F4\u65B0\u63D2\u4EF6");
115
+ if (item.minAppVersion !== void 0) {
116
+ if (typeof item.minAppVersion !== "string") throw new Error("\u6700\u4F4E\u5BA2\u6237\u7AEF\u7248\u672C\u65E0\u6548");
117
+ comparePluginVersions(item.minAppVersion, item.minAppVersion);
118
+ }
119
+ const styles = item.styles === void 0 ? void 0 : file(item.styles, ".css");
120
+ if (item.editor !== void 0 && item.editor !== true) throw new Error("editor \u53EA\u80FD\u58F0\u660E\u4E3A true");
121
+ if (item.whiteboard !== void 0 && item.whiteboard !== true)
122
+ throw new Error("whiteboard \u53EA\u80FD\u58F0\u660E\u4E3A true");
123
+ const catalog = readCatalogFields(item, options.strict === true);
124
+ const integrity = {};
125
+ for (const name of [main, ...styles ? [styles] : []]) {
126
+ const hash = item.integrity && typeof item.integrity === "object" ? item.integrity[name] : void 0;
127
+ if (typeof hash !== "string" || !/^[a-f0-9]{64}$/.test(hash))
128
+ throw new Error("\u63D2\u4EF6\u4EA7\u7269\u7F3A\u5C11\u6709\u6548\u7684\u5B8C\u6574\u6027\u6458\u8981");
129
+ integrity[name] = hash;
130
+ }
131
+ return Object.freeze({
132
+ formatVersion: 1,
133
+ id: item.id,
134
+ name: item.name,
135
+ version: item.version,
136
+ ...typeof item.minAppVersion === "string" ? { minAppVersion: item.minAppVersion } : {},
137
+ apiVersion: 1,
138
+ platform: "desktop",
139
+ format: "cjs",
140
+ main,
141
+ ...item.editor === true ? { editor: true } : {},
142
+ ...item.whiteboard === true ? { whiteboard: true } : {},
143
+ ...catalog,
144
+ integrity: Object.freeze(integrity),
145
+ ...styles === void 0 ? {} : { styles }
146
+ });
147
+ }
148
+
149
+ // packages/plugins/src/rendering.ts
150
+ var PLUGIN_RENDER_VERSION = 1;
151
+ function evaluatePluginPackage(artifact, modules) {
152
+ const manifest = validatePluginManifest(artifact.manifest);
153
+ const module = { exports: {} };
154
+ new Function(
155
+ "require",
156
+ "module",
157
+ "exports",
158
+ '"use strict";\n' + artifact.code + `
159
+ //# sourceURL=tau-plugin://${manifest.id}/${manifest.version}/main.js`
160
+ )(
161
+ (id) => {
162
+ if (!PLUGIN_SHARED_MODULES.some((name) => name === id) || !Object.hasOwn(modules, id))
163
+ throw new Error(`\u63D2\u4EF6\u4F7F\u7528\u4E86\u672A\u63D0\u4F9B\u7684\u5BBF\u4E3B\u6A21\u5757\uFF1A${id}`);
164
+ return modules[id];
165
+ },
166
+ module,
167
+ module.exports
168
+ );
169
+ return validatePluginDefinition(manifest, module.exports.default);
170
+ }
171
+ function validatePluginDefinition(manifest, definition) {
172
+ if (!definition || typeof definition.create !== "function" || definition.id !== manifest.id || definition.name !== manifest.name || definition.version !== manifest.version || definition.apiVersion !== manifest.apiVersion)
173
+ throw new Error("\u63D2\u4EF6\u5165\u53E3\u5B9A\u4E49\u4E0E\u6E05\u5355\u4E0D\u4E00\u81F4");
174
+ if (Boolean(definition.editorExtensions?.length) !== Boolean(manifest.editor))
175
+ throw new Error("\u7F16\u8F91\u5668\u8D21\u732E\u5FC5\u987B\u4E0E manifest.editor \u58F0\u660E\u4E00\u81F4");
176
+ if (Boolean(definition.whiteboardExtensions?.length) !== Boolean(manifest.whiteboard))
177
+ throw new Error("\u767D\u677F\u8D21\u732E\u5FC5\u987B\u4E0E manifest.whiteboard \u58F0\u660E\u4E00\u81F4");
178
+ getPluginWhiteboardTypes(definition);
179
+ if (definition.editorCodecs?.length && !manifest.editor)
180
+ throw new Error("Markdown codec \u5FC5\u987B\u968F\u7F16\u8F91\u5668\u8D21\u732E\u58F0\u660E");
181
+ if (manifest.editor) {
182
+ const types = getPluginNodeTypes(definition);
183
+ if (definition.editorCodecs?.some((codec) => !types.includes(codec.type)))
184
+ throw new Error("\u63D2\u4EF6 codec \u53EA\u80FD\u58F0\u660E\u672C\u63D2\u4EF6\u63D0\u4F9B\u7684\u8282\u70B9\u7C7B\u578B");
185
+ }
186
+ return definition;
187
+ }
188
+ function getPluginNodeTypes(definition) {
189
+ const types = [];
190
+ for (const extension of definition.editorExtensions ?? []) {
191
+ if ("plugins" in extension) throw new Error("\u7F16\u8F91\u5668\u63D2\u4EF6\u4E0D\u652F\u6301\u539F\u59CB Slate \u5305\u88C5\u5668");
192
+ for (const element of extension.elements ?? []) {
193
+ if (!element.type || types.includes(element.type))
194
+ throw new Error(`\u63D2\u4EF6\u8282\u70B9\u7C7B\u578B\u4E3A\u7A7A\u6216\u91CD\u590D\uFF1A${element.type}`);
195
+ types.push(element.type);
196
+ }
197
+ }
198
+ if (definition.editorExtensions?.length && !types.length)
199
+ throw new Error("\u7F16\u8F91\u5668\u63D2\u4EF6\u5FC5\u987B\u58F0\u660E\u8282\u70B9\u7C7B\u578B");
200
+ const htmlTypes = /* @__PURE__ */ new Set();
201
+ for (const extension of definition.editorExtensions ?? []) {
202
+ for (const source of extension.styleSources ?? [])
203
+ if (!types.includes(source.type) || !source.field || !["html", "tsx"].includes(source.language))
204
+ throw new Error("\u63D2\u4EF6\u6837\u5F0F\u6E90\u7801\u5FC5\u987B\u58F0\u660E\u672C\u63D2\u4EF6\u7684\u8282\u70B9\u5B57\u6BB5\u548C\u8BED\u8A00");
205
+ for (const serializer of extension.htmlSerializers ?? []) {
206
+ if (!types.includes(serializer.type) || htmlTypes.has(serializer.type) || typeof serializer.toHtml !== "function")
207
+ throw new Error("\u63D2\u4EF6 HTML \u5BFC\u51FA\u7C7B\u578B\u91CD\u590D\u6216\u4E0D\u5C5E\u4E8E\u672C\u63D2\u4EF6");
208
+ htmlTypes.add(serializer.type);
209
+ }
210
+ }
211
+ return types;
212
+ }
213
+ function getPluginWhiteboardTypes(definition) {
214
+ if (definition.whiteboardExtensions !== void 0 && !Array.isArray(definition.whiteboardExtensions))
215
+ throw new Error("\u767D\u677F\u6269\u5C55\u58F0\u660E\u5FC5\u987B\u4E3A\u6570\u7EC4");
216
+ const types = /* @__PURE__ */ new Set();
217
+ const extensions = /* @__PURE__ */ new Set();
218
+ for (const extension of definition.whiteboardExtensions ?? []) {
219
+ if (!extension || typeof extension.id !== "string" || extension.apiVersion !== 1 || typeof extension.create !== "function" || extension.id !== definition.id && !extension.id.startsWith(`${definition.id}.`) || extensions.has(extension.id))
220
+ throw new Error("\u767D\u677F\u6269\u5C55\u8EAB\u4EFD\u91CD\u590D\u6216\u4E0D\u5C5E\u4E8E\u5F53\u524D\u63D2\u4EF6");
221
+ extensions.add(extension.id);
222
+ if (!Array.isArray(extension.elements) || !extension.elements.length)
223
+ throw new Error("\u767D\u677F\u63D2\u4EF6\u5FC5\u987B\u58F0\u660E\u9759\u6001\u5143\u7D20");
224
+ for (const element of extension.elements) {
225
+ if (!element || typeof element.type !== "string" || !element.type.startsWith(`${definition.id}.`) || types.has(element.type) || typeof element.render !== "function")
226
+ throw new Error("\u767D\u677F\u5143\u7D20\u91CD\u590D\u3001\u7F3A\u5C11\u6E32\u67D3\u6216\u4E0D\u5C5E\u4E8E\u5F53\u524D\u63D2\u4EF6");
227
+ types.add(element.type);
228
+ }
229
+ }
230
+ return [...types];
231
+ }
232
+ function assertRenderTypes(definition, expected) {
233
+ const actual = getPluginNodeTypes(definition);
234
+ if (actual.length !== expected.length || actual.some((type) => !expected.includes(type)))
235
+ throw new Error("\u53D1\u5E03\u7684\u8282\u70B9\u5F52\u5C5E\u4E0E\u63D2\u4EF6\u5B9A\u4E49\u4E0D\u4E00\u81F4");
236
+ }
237
+
238
+ // packages/plugins/src/publish-artifacts.ts
239
+ var PLUGIN_RENDER_VERSION2 = PLUGIN_RENDER_VERSION;
240
+ function evaluatePluginPackage2(artifact, modules) {
241
+ return evaluatePluginPackage(artifact, modules);
242
+ }
243
+ function assertRenderTypes2(definition, types) {
244
+ assertRenderTypes(definition, types);
245
+ }
246
+ export {
247
+ PLUGIN_RENDER_VERSION2 as PLUGIN_RENDER_VERSION,
248
+ PLUGIN_SHARED_MODULES,
249
+ assertRenderTypes2 as assertRenderTypes,
250
+ evaluatePluginPackage2 as evaluatePluginPackage,
251
+ validatePluginManifest
252
+ };
@@ -0,0 +1,258 @@
1
+ // packages/plugins/src/publish-client.ts
2
+ var DataError = class extends Error {
3
+ constructor(code, message) {
4
+ super(message);
5
+ this.code = code;
6
+ this.name = "DataError";
7
+ }
8
+ };
9
+ function assert(condition, code, message) {
10
+ if (!condition) throw new DataError(code, message);
11
+ }
12
+ function record(value) {
13
+ return !!value && typeof value === "object" && !Array.isArray(value);
14
+ }
15
+ function resourceUrl(relative, base) {
16
+ assert(
17
+ typeof relative === "string" && !!relative && !/[\\:%?#]/.test(relative) && relative.split("/").every((part) => part && part !== "." && part !== ".."),
18
+ "INVALID_DATA",
19
+ "\u6570\u636E\u8D44\u6E90\u8DEF\u5F84\u65E0\u6548"
20
+ );
21
+ return new URL(relative, base).href;
22
+ }
23
+ function cancelled(signal) {
24
+ if (signal?.aborted) throw new DOMException("\u8BFB\u53D6\u5DF2\u53D6\u6D88", "AbortError");
25
+ }
26
+ async function waitFor(pending, signal) {
27
+ cancelled(signal);
28
+ if (!signal) return pending;
29
+ let abort = () => {
30
+ };
31
+ try {
32
+ return await Promise.race([
33
+ pending,
34
+ new Promise((_resolve, reject) => {
35
+ abort = () => reject(new DOMException("\u8BFB\u53D6\u5DF2\u53D6\u6D88", "AbortError"));
36
+ signal.addEventListener("abort", abort, { once: true });
37
+ })
38
+ ]);
39
+ } finally {
40
+ signal.removeEventListener("abort", abort);
41
+ }
42
+ }
43
+ function createClient({ manifestUrl }) {
44
+ const origin = new URL(manifestUrl).href;
45
+ const cache = /* @__PURE__ */ new Map();
46
+ let manifestPromise;
47
+ let searchPromise;
48
+ let engine;
49
+ function json(url, expected) {
50
+ assert(/^[a-f0-9]{64}$/.test(expected), "INVALID_DATA", "\u6458\u8981\u683C\u5F0F\u9519\u8BEF");
51
+ const filenameHash = new URL(url).pathname.match(/\.([a-f0-9]{64})\.json$/)?.[1];
52
+ assert(filenameHash === expected, "INTEGRITY_MISMATCH", "\u6587\u4EF6\u540D\u4E0E\u58F0\u660E\u6458\u8981\u4E0D\u4E00\u81F4");
53
+ let pending = cache.get(url);
54
+ if (!pending) {
55
+ pending = (async () => {
56
+ const response = await fetch(url);
57
+ if (!response.ok)
58
+ throw new DataError("RESOURCE_LOAD_FAILED", `HTTP ${response.status}\uFF1A${url}`);
59
+ const bytes = await response.arrayBuffer();
60
+ const digest = [...new Uint8Array(await crypto.subtle.digest("SHA-256", bytes))].map((byte) => byte.toString(16).padStart(2, "0")).join("");
61
+ assert(digest === expected, "INTEGRITY_MISMATCH", `\u8D44\u6E90\u6458\u8981\u9519\u8BEF\uFF1A${url}`);
62
+ try {
63
+ return JSON.parse(new TextDecoder().decode(bytes));
64
+ } catch {
65
+ throw new DataError("INVALID_DATA", `JSON \u65E0\u6548\uFF1A${url}`);
66
+ }
67
+ })().catch((error) => {
68
+ cache.delete(url);
69
+ if (error instanceof DataError) throw error;
70
+ throw new DataError("RESOURCE_LOAD_FAILED", String(error));
71
+ });
72
+ cache.set(url, pending);
73
+ }
74
+ return pending;
75
+ }
76
+ function manifest() {
77
+ if (!manifestPromise) {
78
+ manifestPromise = (async () => {
79
+ const hash = new URL(origin).pathname.match(/site\.([a-f0-9]{64})\.json$/)?.[1];
80
+ assert(hash, "INVALID_DATA", "\u6E05\u5355 URL \u7F3A\u5C11\u6458\u8981");
81
+ const value = await json(origin, hash);
82
+ assert(record(value), "INVALID_DATA", "\u6E05\u5355\u5FC5\u987B\u662F\u5BF9\u8C61");
83
+ assert(value.version === 1, "PROTOCOL_MISMATCH", "\u6570\u636E\u534F\u8BAE\u7248\u672C\u4E0D\u5339\u914D");
84
+ assert(
85
+ record(value.site) && Array.isArray(value.items) && record(value.search),
86
+ "INVALID_DATA",
87
+ "\u6E05\u5355\u5B57\u6BB5\u7F3A\u5931"
88
+ );
89
+ const keys = /* @__PURE__ */ new Set();
90
+ assert(
91
+ typeof value.site.title === "string" && typeof value.site.description === "string" && typeof value.site.basePath === "string",
92
+ "INVALID_DATA",
93
+ "\u7AD9\u70B9\u6570\u636E\u7F3A\u5931"
94
+ );
95
+ for (const item of value.items) {
96
+ assert(
97
+ record(item) && typeof item.key === "string" && typeof item.type === "string",
98
+ "INVALID_DATA",
99
+ "\u6570\u636E\u8EAB\u4EFD\u7F3A\u5931"
100
+ );
101
+ assert(!keys.has(item.key), "INVALID_DATA", "\u6E05\u5355 key \u91CD\u590D");
102
+ assert(
103
+ typeof item.data === "string" && typeof item.integrity === "string",
104
+ "INVALID_DATA",
105
+ "\u6570\u636E\u6587\u4EF6\u5F15\u7528\u7F3A\u5931"
106
+ );
107
+ keys.add(item.key);
108
+ assert(
109
+ ["home", "card", "article", "doc", "quest", "list"].includes(String(item.type)) && typeof item.title === "string",
110
+ "INVALID_DATA",
111
+ "\u6570\u636E\u7C7B\u578B\u6216\u6807\u9898\u65E0\u6548"
112
+ );
113
+ resourceUrl(item.data, origin);
114
+ assert(/^[a-f0-9]{64}$/.test(item.integrity), "INVALID_DATA", "\u6570\u636E\u6458\u8981\u65E0\u6548");
115
+ }
116
+ assert(
117
+ typeof value.search.data === "string" && typeof value.search.integrity === "string",
118
+ "INVALID_DATA",
119
+ "\u7D22\u5F15\u5F15\u7528\u7F3A\u5931"
120
+ );
121
+ resourceUrl(value.search.data, origin);
122
+ assert(
123
+ /^[a-f0-9]{64}$/.test(value.search.integrity),
124
+ "INVALID_DATA",
125
+ "\u7D22\u5F15\u6458\u8981\u65E0\u6548"
126
+ );
127
+ return value;
128
+ })().catch((error) => {
129
+ manifestPromise = void 0;
130
+ cache.delete(origin);
131
+ throw error;
132
+ });
133
+ }
134
+ return manifestPromise;
135
+ }
136
+ function index() {
137
+ if (!searchPromise) {
138
+ searchPromise = (async () => {
139
+ const source = await manifest();
140
+ const url = resourceUrl(source.search.data, origin);
141
+ const value = await json(url, source.search.integrity);
142
+ assert(record(value), "INVALID_DATA", "\u7D22\u5F15\u5FC5\u987B\u662F\u5BF9\u8C61");
143
+ assert(value.version === 1, "PROTOCOL_MISMATCH", "\u7D22\u5F15\u7248\u672C\u4E0D\u5339\u914D");
144
+ assert(Array.isArray(value.documents), "INVALID_DATA", "\u7D22\u5F15\u7F3A\u5C11 documents");
145
+ const seen = /* @__PURE__ */ new Set();
146
+ for (const document of value.documents) {
147
+ assert(
148
+ record(document) && typeof document.key === "string",
149
+ "INVALID_DATA",
150
+ "\u641C\u7D22\u8EAB\u4EFD\u65E0\u6548"
151
+ );
152
+ const item = source.items.find((item2) => item2.key === document.key);
153
+ assert(
154
+ item && item.type === document.type && !seen.has(document.key),
155
+ "INVALID_DATA",
156
+ "\u641C\u7D22 key \u672A\u95ED\u5408\u6216\u91CD\u590D"
157
+ );
158
+ assert(
159
+ ["card", "article", "doc", "quest"].includes(String(document.type)),
160
+ "INVALID_DATA",
161
+ "\u641C\u7D22\u7C7B\u578B\u9519\u8BEF"
162
+ );
163
+ assert(
164
+ ["title", "summary", "content"].every((field) => typeof document[field] === "string"),
165
+ "INVALID_DATA",
166
+ "\u641C\u7D22\u6587\u672C\u7F3A\u5931"
167
+ );
168
+ assert(
169
+ Array.isArray(document.tags) && document.tags.every((tag) => typeof tag === "string"),
170
+ "INVALID_DATA",
171
+ "\u641C\u7D22\u6807\u7B7E\u65E0\u6548"
172
+ );
173
+ seen.add(document.key);
174
+ }
175
+ return value;
176
+ })().catch((error) => {
177
+ searchPromise = void 0;
178
+ if (manifestPromise)
179
+ void manifestPromise.then(
180
+ (source) => cache.delete(resourceUrl(source.search.data, origin)),
181
+ () => void 0
182
+ );
183
+ throw error;
184
+ });
185
+ }
186
+ return searchPromise;
187
+ }
188
+ return {
189
+ async readManifest({ signal } = {}) {
190
+ cancelled(signal);
191
+ return waitFor(manifest(), signal);
192
+ },
193
+ async readData({ key, signal }) {
194
+ cancelled(signal);
195
+ const source = await waitFor(manifest(), signal);
196
+ const item = source.items.find((item2) => item2.key === key);
197
+ assert(item, "DATA_NOT_FOUND", `\u672A\u53D1\u5E03\u5185\u5BB9\uFF1A${key}`);
198
+ const dataUrl = resourceUrl(item.data, origin);
199
+ const value = await waitFor(json(dataUrl, item.integrity), signal);
200
+ assert(
201
+ record(value) && record(value.meta) && record(value.content),
202
+ "INVALID_DATA",
203
+ "\u5185\u5BB9\u7ED3\u6784\u9519\u8BEF"
204
+ );
205
+ assert(value.version === 1, "PROTOCOL_MISMATCH", "\u5185\u5BB9\u534F\u8BAE\u7248\u672C\u4E0D\u5339\u914D");
206
+ assert(
207
+ value.key === key && value.meta.type === item.type && (item.id === void 0 || value.content.id === void 0 || value.content.id === item.id),
208
+ "IDENTITY_MISMATCH",
209
+ "\u5185\u5BB9\u8EAB\u4EFD\u4E0D\u5339\u914D"
210
+ );
211
+ return {
212
+ data: value,
213
+ dataUrl,
214
+ ...source.settings ? { settings: source.settings } : {}
215
+ };
216
+ },
217
+ async search(query, { limit = 12, signal } = {}) {
218
+ cancelled(signal);
219
+ const normalized = query.replace(/\s+/g, " ").trim();
220
+ if (!normalized) return [];
221
+ assert(Number.isInteger(limit) && limit > 0, "INVALID_DATA", "limit \u5FC5\u987B\u662F\u6B63\u6574\u6570");
222
+ const [{ documents }, { default: Fuse }] = await waitFor(
223
+ Promise.all([index(), import("./client/fuse-M2Z6NNAT.js")]),
224
+ signal
225
+ );
226
+ cancelled(signal);
227
+ if (engine?.documents !== documents)
228
+ engine = {
229
+ documents,
230
+ fuse: new Fuse(documents, {
231
+ keys: ["title", "summary", "content", "tags"],
232
+ includeMatches: true,
233
+ threshold: 0.3,
234
+ ignoreLocation: true
235
+ })
236
+ };
237
+ return engine.fuse.search(normalized, { limit }).map(({ item, matches }) => {
238
+ const { content: _content, ...hit } = item;
239
+ const ranges = (matches ?? []).flatMap((match) => {
240
+ if (!match.value || !["title", "summary", "content", "tags"].includes(match.key ?? ""))
241
+ return [];
242
+ return [
243
+ {
244
+ field: match.key,
245
+ text: match.value,
246
+ ranges: match.indices.map(([start, end]) => [start, end + 1])
247
+ }
248
+ ];
249
+ });
250
+ return { ...hit, matches: ranges };
251
+ });
252
+ }
253
+ };
254
+ }
255
+ export {
256
+ DataError,
257
+ createClient
258
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -1,4 +1,4 @@
1
- export * from "./src/api/index";
1
+ export * from "./src/core/api/index";
2
2
  /** 扩展包通过模块增强登记元素;不要求内核知道包名或实现文件。 */
3
3
  declare const extensionElementMapBrand: unique symbol;
4
4
  declare const extensionInlineElementMapBrand: unique symbol;
@@ -1,3 +1,3 @@
1
1
  /** 无 React/DOM 运行时代码的声明入口,供应用 SDK 适配现有扩展协议。 */
2
- export { defineExtension, defineElement } from "./src/api/extension";
3
- export type { EditorExtension, ElementSpec, ElementRenderProps } from "./src/api/extension";
2
+ export { defineExtension, defineElement } from "./src/core/api/extension";
3
+ export type { EditorExtension, ElementSpec, ElementRenderProps } from "./src/core/api/extension";
@@ -0,0 +1,48 @@
1
+ import type { ReactNode, ReactElement } from "react";
2
+ import type { LucideIcon } from "lucide-react";
3
+ import type { Editor, Element, Path } from "slate";
4
+ import type { ElementBehaviors, ParagraphElement, BlockElement } from "./api";
5
+ export interface SourceBlockEditorProps {
6
+ mode: string;
7
+ title: string;
8
+ icon: LucideIcon;
9
+ initValue: string;
10
+ onChange(value: string): void;
11
+ element: Element;
12
+ center?: boolean;
13
+ extend?: boolean;
14
+ fluid?: boolean;
15
+ children?: ReactNode;
16
+ }
17
+ export interface RuntimeStyleCompiler {
18
+ compile(request: {
19
+ source: string;
20
+ language: "html" | "tsx";
21
+ }): Promise<string>;
22
+ }
23
+ export interface SourceEditorRuntime {
24
+ SourceBlockEditor(props: SourceBlockEditorProps): ReactElement;
25
+ useSourceBlock(element: Element): {
26
+ theme: {
27
+ isDark: boolean;
28
+ token(word: string): string;
29
+ };
30
+ compiler: RuntimeStyleCompiler | undefined;
31
+ update(properties: Record<string, unknown>): void;
32
+ };
33
+ useReportPreviewError(error: string | null, options?: {
34
+ stale?: boolean;
35
+ }): boolean;
36
+ insertSourceBlock(editor: Editor, element: BlockElement, line?: number): Path | undefined;
37
+ sourceBlockParagraphBehavior(type: string): ElementBehaviors<ParagraphElement>;
38
+ }
39
+ export interface InlineSourceRuntime {
40
+ useInlineSource(element: Element): {
41
+ readOnly: boolean;
42
+ compiler: RuntimeStyleCompiler | undefined;
43
+ update(properties: Record<string, unknown>): void;
44
+ remove(): void;
45
+ };
46
+ insertInlineSource(editor: Editor, element: Element): void;
47
+ InlineSourceBoundary(): ReactElement;
48
+ }
@@ -7,4 +7,4 @@ export interface OverlayBackDismissAdapter {
7
7
  /** 在当前编辑器所在的页面上下文登记退场;不渲染 UI,不监听全局按键。 */
8
8
  Layer: ComponentType<OverlayBackDismissProps>;
9
9
  }
10
- export declare const IOverlayBackDismiss: import("../../../shared/service-contract").ServiceIdentifier<OverlayBackDismissAdapter>;
10
+ export declare const IOverlayBackDismiss: import("../../../../shared/service-contract").ServiceIdentifier<OverlayBackDismissAdapter>;
@@ -2,5 +2,5 @@
2
2
  * 服务注册表实现已下沉到 @tau/shared/service-registry(编辑器与白板等宿主共用),
3
3
  * 此处保留原导入路径与公共 API 不变。
4
4
  */
5
- export { createServiceRegistry, createChildRegistry } from "../../../shared/service-registry";
6
- export type { ServiceRegistry, ServiceRegister, ServiceRegistration, } from "../../../shared/service-registry";
5
+ export { createServiceRegistry, createChildRegistry } from "../../../../shared/service-registry";
6
+ export type { ServiceRegistry, ServiceRegister, ServiceRegistration, } from "../../../../shared/service-registry";
@@ -1,10 +1,10 @@
1
1
  import type { ThemeService } from "../theme/ThemeService";
2
2
  import type { ExtensionErrorReporter } from "./errorReporter";
3
3
  import type { EditorNotifier } from "./notifier";
4
- export { createServiceId, type ServiceIdentifier } from "../../../shared/service-contract";
4
+ export { createServiceId, type ServiceIdentifier } from "../../../../shared/service-contract";
5
5
  /** 主题服务:未注册时编辑器用 DOM 默认实现(读 <html> 的 data-mode / data-theme) */
6
- export declare const IThemeService: import("../../../shared/service-contract").ServiceIdentifier<ThemeService>;
6
+ export declare const IThemeService: import("../../../../shared/service-contract").ServiceIdentifier<ThemeService>;
7
7
  /** 轻提示与确认:未注册时用 @tau/ui 的 toast(宿主需挂 ToastHost)与原生 confirm */
8
- export declare const IEditorNotifier: import("../../../shared/service-contract").ServiceIdentifier<EditorNotifier>;
8
+ export declare const IEditorNotifier: import("../../../../shared/service-contract").ServiceIdentifier<EditorNotifier>;
9
9
  /** 扩展运行期错误上报:未注册时写控制台 */
10
- export declare const IExtensionErrorReporter: import("../../../shared/service-contract").ServiceIdentifier<ExtensionErrorReporter>;
10
+ export declare const IExtensionErrorReporter: import("../../../../shared/service-contract").ServiceIdentifier<ExtensionErrorReporter>;
@@ -1,6 +1,6 @@
1
1
  import type { ParagraphElement } from "./element/paragraph";
2
2
  import type { FormattedText } from "./text";
3
- import type { ExtensionElementMap, ExtensionInlineElementMap } from "../../api";
3
+ import type { ExtensionElementMap, ExtensionInlineElementMap } from "../../../api";
4
4
  export interface BuiltinElementMap {
5
5
  paragraph: ParagraphElement;
6
6
  }
@@ -0,0 +1 @@
1
+ export type { FormattedText } from "../../../../markdown/src/model";