@openeditor/core 0.0.27 → 0.0.29
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 +13 -1
- package/dist/index.d.ts +52 -10
- package/dist/index.js +49 -14
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,12 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
Canonical SDK contract for OpenEditor documents.
|
|
4
4
|
|
|
5
|
-
The package exports
|
|
5
|
+
The package exports portable attachment contracts and the shared
|
|
6
|
+
`OpenEditorPageRuntime` used by web and native page surfaces. A web host can use
|
|
7
|
+
`File` as an attachment source; native hosts can use a document-picker asset
|
|
8
|
+
without introducing platform types here.
|
|
9
|
+
|
|
10
|
+
Public renderers share `openEditorPublicUrlPolicy`, a context-aware URL contract
|
|
11
|
+
for links, images, pages, and attachments. It preserves normal web and relative
|
|
12
|
+
references while rejecting executable, local-file, data, and temporary object
|
|
13
|
+
URL schemes by default. Hosts may supply an `OpenEditorUrlPolicy` for trusted
|
|
14
|
+
preview requirements; `openEditorUnsafeUrlPolicy` is an explicit trusted-boundary
|
|
15
|
+
escape hatch rather than a public-rendering default.
|
|
6
16
|
|
|
7
17
|
## Public surface
|
|
8
18
|
|
|
9
19
|
- `OpenEditorDocument` and related types
|
|
10
20
|
- document creation, normalization, validation, parsing, and platform support helpers
|
|
21
|
+
- strict `parseOpenEditorDocument` for versioned documents and explicit `importProseMirrorDocument` for unversioned ProseMirror JSON
|
|
22
|
+
- shared authoring capabilities and page metadata runtime contracts
|
|
11
23
|
- platform-neutral command and transaction helpers
|
|
12
24
|
- top-level block transforms and text extraction
|
|
13
25
|
|
package/dist/index.d.ts
CHANGED
|
@@ -37,7 +37,6 @@ type OpenEditorDocumentMeta = {
|
|
|
37
37
|
source?: string;
|
|
38
38
|
createdAt?: string;
|
|
39
39
|
updatedAt?: string;
|
|
40
|
-
schemaVersion?: number;
|
|
41
40
|
platform?: EditorPlatform;
|
|
42
41
|
custom?: Record<string, unknown>;
|
|
43
42
|
};
|
|
@@ -129,8 +128,49 @@ type OpenEditorAttachmentRuntime<TSource = unknown> = {
|
|
|
129
128
|
renameAttachment?: (attachmentId: string, name: string) => void | Promise<void>;
|
|
130
129
|
replaceAttachment?: (attachmentId: string, input: OpenEditorAttachmentUploadInput<TSource>, callbacks?: OpenEditorAttachmentUploadCallbacks) => Promise<OpenEditorAttachmentSnapshot>;
|
|
131
130
|
};
|
|
131
|
+
type OpenEditorPageSnapshot = {
|
|
132
|
+
pageId: string;
|
|
133
|
+
title: string;
|
|
134
|
+
icon?: string | null;
|
|
135
|
+
href?: string | null;
|
|
136
|
+
};
|
|
137
|
+
type OpenEditorPageUpdate = {
|
|
138
|
+
title?: string;
|
|
139
|
+
icon?: string | null;
|
|
140
|
+
};
|
|
141
|
+
/** Host-owned page identity, persistence, navigation, and metadata lifecycle. */
|
|
142
|
+
type OpenEditorPageRuntime = {
|
|
143
|
+
createPage?: (input: {
|
|
144
|
+
title: string;
|
|
145
|
+
icon?: string | null;
|
|
146
|
+
}) => Promise<OpenEditorPageSnapshot>;
|
|
147
|
+
resolvePage?: (pageId: string) => Promise<OpenEditorPageSnapshot | null>;
|
|
148
|
+
updatePage: (pageId: string, update: OpenEditorPageUpdate) => Promise<OpenEditorPageSnapshot | void> | OpenEditorPageSnapshot | void;
|
|
149
|
+
openPage?: (page: OpenEditorPageSnapshot) => Promise<void> | void;
|
|
150
|
+
};
|
|
151
|
+
/** Built-in URL-bearing surfaces rendered from portable document data. */
|
|
152
|
+
type OpenEditorUrlContext = "link" | "image" | "page" | "attachment";
|
|
153
|
+
/**
|
|
154
|
+
* Returns the URL that may be rendered for a context, or `null` to omit the
|
|
155
|
+
* navigation/resource. Policies are pure so the same contract can be shared by
|
|
156
|
+
* React viewers, HTML exporters, and other public renderers.
|
|
157
|
+
*/
|
|
158
|
+
type OpenEditorUrlPolicy = (value: string, context: OpenEditorUrlContext) => string | null;
|
|
159
|
+
/**
|
|
160
|
+
* Safe default for public rendering. Ordinary relative references (including
|
|
161
|
+
* query strings and fragments) are preserved; explicit schemes are allowlisted
|
|
162
|
+
* per context. Local preview schemes such as `blob:` require a host policy.
|
|
163
|
+
*/
|
|
164
|
+
declare const openEditorPublicUrlPolicy: OpenEditorUrlPolicy;
|
|
165
|
+
/** Explicit trusted-host escape hatch. Never use this for untrusted documents. */
|
|
166
|
+
declare const openEditorUnsafeUrlPolicy: OpenEditorUrlPolicy;
|
|
132
167
|
declare const createAttachmentSnapshot: (attrs?: Partial<OpenEditorAttachmentSnapshot>) => OpenEditorAttachmentSnapshot;
|
|
133
168
|
type OpenEditorFeatureSet = Readonly<Record<OpenEditorFeatureName, boolean>>;
|
|
169
|
+
/** Controls which schema-supported blocks may be created by an editor surface. */
|
|
170
|
+
type OpenEditorAuthoringCapabilities = {
|
|
171
|
+
enabledBlocks?: readonly string[];
|
|
172
|
+
};
|
|
173
|
+
declare const isOpenEditorBlockEnabled: (blockName: string, capabilities?: OpenEditorAuthoringCapabilities) => boolean;
|
|
134
174
|
declare const DEFAULT_CALLOUT_EMOJI = "\uD83D\uDCA1";
|
|
135
175
|
declare const DEFAULT_PAGE_EMOJI = "\uD83D\uDCC4";
|
|
136
176
|
declare const normalizeEmoji: (value: unknown, fallback: string) => string;
|
|
@@ -172,9 +212,6 @@ type OpenEditorCommand = {
|
|
|
172
212
|
type: "undo";
|
|
173
213
|
} | {
|
|
174
214
|
type: "redo";
|
|
175
|
-
} | {
|
|
176
|
-
type: "replaceDocument";
|
|
177
|
-
document: OpenEditorDocument;
|
|
178
215
|
} | {
|
|
179
216
|
type: "setSelection";
|
|
180
217
|
selection: EditorSelection;
|
|
@@ -189,16 +226,15 @@ type OpenEditorEventHandlers = {
|
|
|
189
226
|
onCommand?: (command: OpenEditorCommand, transaction: EditorTransaction) => void;
|
|
190
227
|
};
|
|
191
228
|
type OpenEditorConfig = OpenEditorEventHandlers & {
|
|
192
|
-
|
|
229
|
+
initialDocument?: OpenEditorDocument;
|
|
193
230
|
editable?: boolean;
|
|
194
231
|
placeholder?: string;
|
|
195
232
|
enabledBlocks?: readonly string[];
|
|
196
233
|
theme?: Record<string, string | number>;
|
|
197
|
-
features?: Partial<OpenEditorFeatureSet>;
|
|
198
234
|
};
|
|
199
235
|
type OpenEditorController = {
|
|
200
|
-
|
|
201
|
-
|
|
236
|
+
getContent: () => OpenEditorDocument;
|
|
237
|
+
setContent: (document: OpenEditorDocument) => void;
|
|
202
238
|
getSelection: () => EditorSelection;
|
|
203
239
|
execute: (command: OpenEditorCommand) => void;
|
|
204
240
|
};
|
|
@@ -239,7 +275,13 @@ declare const findBlockLocation: (document: OpenEditorDocument, id: string) => O
|
|
|
239
275
|
declare const normalizeDocument: (document: OpenEditorDocument) => OpenEditorDocument;
|
|
240
276
|
declare const validateDocument: (document: unknown) => DocumentValidationResult;
|
|
241
277
|
declare const isOpenEditorDocument: (value: unknown) => value is OpenEditorDocument;
|
|
242
|
-
declare
|
|
278
|
+
declare class OpenEditorDocumentParseError extends Error {
|
|
279
|
+
readonly validation: DocumentValidationResult;
|
|
280
|
+
constructor(validation: DocumentValidationResult);
|
|
281
|
+
}
|
|
282
|
+
declare const parseOpenEditorDocument: (value: unknown) => OpenEditorDocument;
|
|
283
|
+
/** Imports unversioned ProseMirror JSON. Versioned values require strict OpenEditor parsing. */
|
|
284
|
+
declare const importProseMirrorDocument: (value: unknown, meta?: OpenEditorDocumentMeta) => OpenEditorDocument;
|
|
243
285
|
declare const serializeEditorState: (state: SerializedEditorState) => string;
|
|
244
286
|
declare const parseEditorState: (value: unknown, defaultState?: SerializedEditorState) => SerializedEditorState;
|
|
245
287
|
declare const getPlatformDocument: (document: OpenEditorDocument, registry: BlockRegistry, platform: EditorPlatform) => OpenEditorDocument;
|
|
@@ -253,4 +295,4 @@ declare const duplicateTopLevelBlock: (document: OpenEditorDocument, index: numb
|
|
|
253
295
|
declare const deleteTopLevelBlock: (document: OpenEditorDocument, index: number, emptyBlock?: OpenEditorBlock) => OpenEditorDocument;
|
|
254
296
|
declare const createTransaction: (before: OpenEditorDocument, after: OpenEditorDocument, command?: EditorCommand) => EditorTransaction;
|
|
255
297
|
|
|
256
|
-
export { type BlockGroup, type BlockRegistry, type BlockSpec, DEFAULT_CALLOUT_EMOJI, DEFAULT_PAGE_EMOJI, type DocumentValidationIssue, type DocumentValidationResult, type EditorCommand, type EditorPlatform, type EditorSelection, type EditorTransaction, type JsonObject, type JsonPrimitive, type JsonValue, OPENEDITOR_BLOCK_ID_ATTR, type OpenEditorAttachmentRuntime, type OpenEditorAttachmentSnapshot, type OpenEditorAttachmentUploadCallbacks, type OpenEditorAttachmentUploadInput, type OpenEditorAttachmentValidationResult, type OpenEditorBlock, type OpenEditorBlockLocation, type OpenEditorBlockRef, type OpenEditorCommand, type OpenEditorConfig, type OpenEditorController, type OpenEditorDocument, type OpenEditorDocumentMeta, type OpenEditorEventHandlers, type OpenEditorFeatureName, type OpenEditorFeatureSet, type OpenEditorMarkName, type PlatformSupport, type PlatformSupportIssue, type PlatformSupportLevel, type PlatformSupportResult, type ProseMirrorAttrs, type ProseMirrorDocument, type ProseMirrorMark, type ProseMirrorNode, type SerializedEditorState, applyCommand, cloneNode, createAttachmentSnapshot, createBlockId, createBlockRegistry, createDocument, createEditorState, createTextNode, createTransaction, deleteTopLevelBlock, duplicateTopLevelBlock, ensureBlockIds, findBlockLocation, findBlockSpecForNode, fromProseMirrorDocument, getBlockId, getDocumentText, getPlatformDocument, getPlatformSupport, isOpenEditorDocument, moveTopLevelBlock, normalizeDocument, normalizeEmoji, parseEditorState, parseOpenEditorDocument, replaceTopLevelNode, replaceTopLevelRange, serializeEditorState, textBlock, toProseMirrorDocument, validateDocument, withBlockId };
|
|
298
|
+
export { type BlockGroup, type BlockRegistry, type BlockSpec, DEFAULT_CALLOUT_EMOJI, DEFAULT_PAGE_EMOJI, type DocumentValidationIssue, type DocumentValidationResult, type EditorCommand, type EditorPlatform, type EditorSelection, type EditorTransaction, type JsonObject, type JsonPrimitive, type JsonValue, OPENEDITOR_BLOCK_ID_ATTR, type OpenEditorAttachmentRuntime, type OpenEditorAttachmentSnapshot, type OpenEditorAttachmentUploadCallbacks, type OpenEditorAttachmentUploadInput, type OpenEditorAttachmentValidationResult, type OpenEditorAuthoringCapabilities, type OpenEditorBlock, type OpenEditorBlockLocation, type OpenEditorBlockRef, type OpenEditorCommand, type OpenEditorConfig, type OpenEditorController, type OpenEditorDocument, type OpenEditorDocumentMeta, OpenEditorDocumentParseError, type OpenEditorEventHandlers, type OpenEditorFeatureName, type OpenEditorFeatureSet, type OpenEditorMarkName, type OpenEditorPageRuntime, type OpenEditorPageSnapshot, type OpenEditorPageUpdate, type OpenEditorUrlContext, type OpenEditorUrlPolicy, type PlatformSupport, type PlatformSupportIssue, type PlatformSupportLevel, type PlatformSupportResult, type ProseMirrorAttrs, type ProseMirrorDocument, type ProseMirrorMark, type ProseMirrorNode, type SerializedEditorState, applyCommand, cloneNode, createAttachmentSnapshot, createBlockId, createBlockRegistry, createDocument, createEditorState, createTextNode, createTransaction, deleteTopLevelBlock, duplicateTopLevelBlock, ensureBlockIds, findBlockLocation, findBlockSpecForNode, fromProseMirrorDocument, getBlockId, getDocumentText, getPlatformDocument, getPlatformSupport, importProseMirrorDocument, isOpenEditorBlockEnabled, isOpenEditorDocument, moveTopLevelBlock, normalizeDocument, normalizeEmoji, openEditorPublicUrlPolicy, openEditorUnsafeUrlPolicy, parseEditorState, parseOpenEditorDocument, replaceTopLevelNode, replaceTopLevelRange, serializeEditorState, textBlock, toProseMirrorDocument, validateDocument, withBlockId };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,23 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
|
+
var OPENEDITOR_URL_SCHEME = /^([a-z][a-z\d+.-]*):/i;
|
|
3
|
+
var OPENEDITOR_URL_CONTROL_CHARACTER = /[\u0000-\u001f\u007f]/;
|
|
4
|
+
var OPENEDITOR_PUBLIC_SCHEMES = {
|
|
5
|
+
link: /* @__PURE__ */ new Set(["http", "https", "mailto", "tel"]),
|
|
6
|
+
image: /* @__PURE__ */ new Set(["http", "https"]),
|
|
7
|
+
page: /* @__PURE__ */ new Set(["http", "https"]),
|
|
8
|
+
attachment: /* @__PURE__ */ new Set(["http", "https"])
|
|
9
|
+
};
|
|
10
|
+
var openEditorPublicUrlPolicy = (value, context) => {
|
|
11
|
+
const normalized = value.trim();
|
|
12
|
+
if (!normalized || OPENEDITOR_URL_CONTROL_CHARACTER.test(normalized)) return null;
|
|
13
|
+
const scheme = OPENEDITOR_URL_SCHEME.exec(normalized)?.[1]?.toLowerCase();
|
|
14
|
+
if (!scheme) return normalized;
|
|
15
|
+
return OPENEDITOR_PUBLIC_SCHEMES[context].has(scheme) ? normalized : null;
|
|
16
|
+
};
|
|
17
|
+
var openEditorUnsafeUrlPolicy = (value) => {
|
|
18
|
+
const normalized = value.trim();
|
|
19
|
+
return normalized || null;
|
|
20
|
+
};
|
|
2
21
|
var createAttachmentSnapshot = (attrs = {}) => ({
|
|
3
22
|
attachmentId: typeof attrs.attachmentId === "string" ? attrs.attachmentId : null,
|
|
4
23
|
name: typeof attrs.name === "string" ? attrs.name : "",
|
|
@@ -6,6 +25,7 @@ var createAttachmentSnapshot = (attrs = {}) => ({
|
|
|
6
25
|
size: typeof attrs.size === "number" && Number.isFinite(attrs.size) && attrs.size >= 0 ? attrs.size : null,
|
|
7
26
|
url: typeof attrs.url === "string" ? attrs.url : null
|
|
8
27
|
});
|
|
28
|
+
var isOpenEditorBlockEnabled = (blockName, capabilities) => capabilities?.enabledBlocks === void 0 || capabilities.enabledBlocks.includes(blockName);
|
|
9
29
|
var DEFAULT_CALLOUT_EMOJI = "\u{1F4A1}";
|
|
10
30
|
var DEFAULT_PAGE_EMOJI = "\u{1F4C4}";
|
|
11
31
|
var normalizeEmoji = (value, fallback) => typeof value === "string" && value.trim() ? value.trim() : fallback;
|
|
@@ -227,14 +247,28 @@ var validateDocument = (document) => {
|
|
|
227
247
|
};
|
|
228
248
|
};
|
|
229
249
|
var isOpenEditorDocument = (value) => validateDocument(value).valid;
|
|
230
|
-
var
|
|
231
|
-
|
|
232
|
-
|
|
250
|
+
var OpenEditorDocumentParseError = class extends Error {
|
|
251
|
+
validation;
|
|
252
|
+
constructor(validation) {
|
|
253
|
+
super(validation.issues.map((issue) => `${issue.path}: ${issue.message}`).join("\n"));
|
|
254
|
+
this.name = "OpenEditorDocumentParseError";
|
|
255
|
+
this.validation = validation;
|
|
233
256
|
}
|
|
234
|
-
|
|
235
|
-
|
|
257
|
+
};
|
|
258
|
+
var parseOpenEditorDocument = (value) => {
|
|
259
|
+
const validation = validateDocument(value);
|
|
260
|
+
if (!validation.valid) throw new OpenEditorDocumentParseError(validation);
|
|
261
|
+
return normalizeDocument(value);
|
|
262
|
+
};
|
|
263
|
+
var importProseMirrorDocument = (value, meta) => {
|
|
264
|
+
if (isRecord(value) && "version" in value) {
|
|
265
|
+
throw new Error("Versioned documents must be parsed with parseOpenEditorDocument().");
|
|
236
266
|
}
|
|
237
|
-
|
|
267
|
+
const validation = validateDocument(
|
|
268
|
+
isRecord(value) ? { ...value, version: 1 } : value
|
|
269
|
+
);
|
|
270
|
+
if (!validation.valid) throw new OpenEditorDocumentParseError(validation);
|
|
271
|
+
return fromProseMirrorDocument(value, meta);
|
|
238
272
|
};
|
|
239
273
|
var serializeEditorState = (state) => JSON.stringify({
|
|
240
274
|
document: normalizeDocument(state.document),
|
|
@@ -250,10 +284,14 @@ var parseEditorState = (value, defaultState = createEditorState(createDocument()
|
|
|
250
284
|
if (!isRecord(parsed)) {
|
|
251
285
|
return defaultState;
|
|
252
286
|
}
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
287
|
+
try {
|
|
288
|
+
return {
|
|
289
|
+
document: parseOpenEditorDocument(parsed.document),
|
|
290
|
+
selection: isRecord(parsed.selection) ? parsed.selection : defaultState.selection
|
|
291
|
+
};
|
|
292
|
+
} catch {
|
|
293
|
+
return defaultState;
|
|
294
|
+
}
|
|
257
295
|
};
|
|
258
296
|
var getPlatformDocument = (document, registry, platform) => getPlatformSupport(document, registry, platform).document;
|
|
259
297
|
var getPlatformSupport = (document, registry, platform) => {
|
|
@@ -302,9 +340,6 @@ var applyCommand = (document, registry, command) => {
|
|
|
302
340
|
if (command.type === "setContent") {
|
|
303
341
|
return normalizeDocument(command.document);
|
|
304
342
|
}
|
|
305
|
-
if (command.type === "replaceDocument") {
|
|
306
|
-
return normalizeDocument(command.document);
|
|
307
|
-
}
|
|
308
343
|
if (command.type === "setSelection") {
|
|
309
344
|
return document;
|
|
310
345
|
}
|
|
@@ -382,6 +417,6 @@ var createTransaction = (before, after, command) => ({
|
|
|
382
417
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
383
418
|
});
|
|
384
419
|
|
|
385
|
-
export { DEFAULT_CALLOUT_EMOJI, DEFAULT_PAGE_EMOJI, OPENEDITOR_BLOCK_ID_ATTR, applyCommand, cloneNode, createAttachmentSnapshot, createBlockId, createBlockRegistry, createDocument, createEditorState, createTextNode, createTransaction, deleteTopLevelBlock, duplicateTopLevelBlock, ensureBlockIds, findBlockLocation, findBlockSpecForNode, fromProseMirrorDocument, getBlockId, getDocumentText, getPlatformDocument, getPlatformSupport, isOpenEditorDocument, moveTopLevelBlock, normalizeDocument, normalizeEmoji, parseEditorState, parseOpenEditorDocument, replaceTopLevelNode, replaceTopLevelRange, serializeEditorState, textBlock, toProseMirrorDocument, validateDocument, withBlockId };
|
|
420
|
+
export { DEFAULT_CALLOUT_EMOJI, DEFAULT_PAGE_EMOJI, OPENEDITOR_BLOCK_ID_ATTR, OpenEditorDocumentParseError, applyCommand, cloneNode, createAttachmentSnapshot, createBlockId, createBlockRegistry, createDocument, createEditorState, createTextNode, createTransaction, deleteTopLevelBlock, duplicateTopLevelBlock, ensureBlockIds, findBlockLocation, findBlockSpecForNode, fromProseMirrorDocument, getBlockId, getDocumentText, getPlatformDocument, getPlatformSupport, importProseMirrorDocument, isOpenEditorBlockEnabled, isOpenEditorDocument, moveTopLevelBlock, normalizeDocument, normalizeEmoji, openEditorPublicUrlPolicy, openEditorUnsafeUrlPolicy, parseEditorState, parseOpenEditorDocument, replaceTopLevelNode, replaceTopLevelRange, serializeEditorState, textBlock, toProseMirrorDocument, validateDocument, withBlockId };
|
|
386
421
|
//# sourceMappingURL=index.js.map
|
|
387
422
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"names":["content"],"mappings":"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","file":"index.js","sourcesContent":["export type JsonPrimitive = string | number | boolean | null;\nexport type JsonValue = JsonPrimitive | JsonObject | JsonValue[];\nexport type JsonObject = { [key: string]: JsonValue | undefined };\n\nexport type ProseMirrorAttrs = Record<string, unknown>;\n\nexport type ProseMirrorMark = {\n type: string;\n attrs?: ProseMirrorAttrs;\n};\n\nexport type ProseMirrorNode = {\n type: string;\n attrs?: ProseMirrorAttrs;\n content?: ProseMirrorNode[];\n marks?: ProseMirrorMark[];\n text?: string;\n};\n\nexport type OpenEditorBlock = ProseMirrorNode & {\n attrs?: ProseMirrorAttrs & {\n \"openeditor-id\"?: string;\n };\n};\n\n/** Stable identity used by commands and interaction adapters. */\nexport type OpenEditorBlockRef = {\n id: string;\n nodeType: string;\n blockName?: string;\n};\n\nexport type OpenEditorBlockLocation = OpenEditorBlockRef & {\n parentId: string | null;\n index: number;\n path: readonly number[];\n};\n\nexport type OpenEditorDocumentMeta = {\n id?: string;\n title?: string;\n source?: string;\n createdAt?: string;\n updatedAt?: string;\n schemaVersion?: number;\n platform?: EditorPlatform;\n custom?: Record<string, unknown>;\n};\n\nexport type OpenEditorDocument = {\n type: \"doc\";\n version: 1;\n content: OpenEditorBlock[];\n meta?: OpenEditorDocumentMeta;\n};\n\nexport type ProseMirrorDocument = {\n type: \"doc\";\n content: ProseMirrorNode[];\n};\n\nexport type EditorPlatform = \"web\" | \"native\";\n\nexport type PlatformSupportLevel = \"supported\" | \"unsupported\";\n\nexport type PlatformSupport = {\n web: PlatformSupportLevel;\n native: PlatformSupportLevel;\n};\n\nexport type BlockGroup = \"text\" | \"media\" | \"layout\" | \"structure\" | \"embed\";\n\nexport type BlockSpec = {\n name: string;\n /** ProseMirror node type. Defaults to `name`. */\n nodeType?: string;\n label: string;\n group: BlockGroup;\n defaultNode: () => OpenEditorBlock;\n matchNode?: (node: ProseMirrorNode) => boolean;\n support?: PlatformSupport;\n};\n\nexport type BlockRegistry = ReadonlyMap<string, BlockSpec>;\n\nexport type EditorSelection =\n | { type: \"none\" }\n | { type: \"text\"; anchor: number; head: number }\n | { type: \"node\"; from: number; to: number; nodeType?: string }\n | { type: \"block\"; blockId: string };\n\nexport type OpenEditorMarkName =\n | \"bold\"\n | \"italic\"\n | \"underline\"\n | \"strike\"\n | \"code\"\n | \"link\";\n\nexport type OpenEditorFeatureName =\n | \"headings\"\n | \"lists\"\n | \"taskLists\"\n | \"quotes\"\n | \"codeBlocks\"\n | \"dividers\"\n | \"links\"\n | \"images\"\n | \"columns\"\n | \"tables\"\n | \"toggleLists\"\n | \"callouts\"\n | \"diagrams\"\n | \"pages\"\n | \"attachments\";\n\n/** Durable, portable attributes stored on an attachment node. */\nexport type OpenEditorAttachmentSnapshot = {\n attachmentId: string | null;\n name: string;\n mimeType: string | null;\n size: number | null;\n url: string | null;\n};\n\n/**\n * A host-selected local file. `source` is deliberately opaque: on web it may\n * be a File, while native hosts typically use a picker result or local URI.\n * OpenEditor never serializes it.\n */\nexport type OpenEditorAttachmentUploadInput<TSource = unknown> = {\n name: string;\n mimeType: string | null;\n size: number | null;\n source: TSource;\n};\n\nexport type OpenEditorAttachmentUploadCallbacks = {\n onProgress?: (progress: number) => void;\n signal?: AbortSignal;\n};\n\nexport type OpenEditorAttachmentValidationResult =\n | { accepted: true }\n | { accepted: false; message: string };\n\n/** Host-owned storage, picker, policy, resolution, and platform actions. */\nexport type OpenEditorAttachmentRuntime<TSource = unknown> = {\n selectAttachment?: (options?: { signal?: AbortSignal }) =>\n | Promise<OpenEditorAttachmentUploadInput<TSource> | null>\n | OpenEditorAttachmentUploadInput<TSource>\n | null;\n validateAttachment?: (\n input: OpenEditorAttachmentUploadInput<TSource>,\n ) => OpenEditorAttachmentValidationResult | Promise<OpenEditorAttachmentValidationResult>;\n uploadAttachment?: (\n input: OpenEditorAttachmentUploadInput<TSource>,\n callbacks?: OpenEditorAttachmentUploadCallbacks,\n ) => Promise<OpenEditorAttachmentSnapshot>;\n resolveAttachment?: (attachmentId: string, options?: { signal?: AbortSignal }) =>\n Promise<OpenEditorAttachmentSnapshot | null>;\n openAttachment?: (attachment: OpenEditorAttachmentSnapshot) => void | Promise<void>;\n renameAttachment?: (attachmentId: string, name: string) => void | Promise<void>;\n replaceAttachment?: (\n attachmentId: string,\n input: OpenEditorAttachmentUploadInput<TSource>,\n callbacks?: OpenEditorAttachmentUploadCallbacks,\n ) => Promise<OpenEditorAttachmentSnapshot>;\n};\n\nexport const createAttachmentSnapshot = (\n attrs: Partial<OpenEditorAttachmentSnapshot> = {},\n): OpenEditorAttachmentSnapshot => ({\n attachmentId: typeof attrs.attachmentId === \"string\" ? attrs.attachmentId : null,\n name: typeof attrs.name === \"string\" ? attrs.name : \"\",\n mimeType: typeof attrs.mimeType === \"string\" ? attrs.mimeType : null,\n size: typeof attrs.size === \"number\" && Number.isFinite(attrs.size) && attrs.size >= 0 ? attrs.size : null,\n url: typeof attrs.url === \"string\" ? attrs.url : null,\n});\n\nexport type OpenEditorFeatureSet = Readonly<Record<OpenEditorFeatureName, boolean>>;\n\nexport const DEFAULT_CALLOUT_EMOJI = \"💡\";\nexport const DEFAULT_PAGE_EMOJI = \"📄\";\n\nexport const normalizeEmoji = (value: unknown, fallback: string) =>\n typeof value === \"string\" && value.trim() ? value.trim() : fallback;\n\nexport type SerializedEditorState = {\n document: OpenEditorDocument;\n selection?: EditorSelection;\n};\n\nexport type EditorTransaction = {\n before: OpenEditorDocument;\n after: OpenEditorDocument;\n command?: OpenEditorCommand;\n timestamp: string;\n};\n\nexport type OpenEditorCommand =\n | { type: \"setContent\"; document: OpenEditorDocument }\n | { type: \"insertBlock\"; block: string; at?: number; attrs?: ProseMirrorAttrs }\n | { type: \"moveBlock\"; from: number; to: number }\n | { type: \"duplicateBlock\"; index: number }\n | { type: \"deleteBlock\"; index: number }\n | { type: \"setLink\"; href?: string }\n | { type: \"toggleMark\"; mark: OpenEditorMarkName }\n | { type: \"undo\" }\n | { type: \"redo\" }\n | { type: \"replaceDocument\"; document: OpenEditorDocument }\n | { type: \"setSelection\"; selection: EditorSelection };\n\nexport type EditorCommand = OpenEditorCommand;\n\nexport type OpenEditorEventHandlers = {\n onChange?: (document: OpenEditorDocument) => void;\n onSelectionChange?: (selection: EditorSelection) => void;\n onFocus?: () => void;\n onBlur?: () => void;\n onReady?: (controller: OpenEditorController) => void;\n onCommand?: (command: OpenEditorCommand, transaction: EditorTransaction) => void;\n};\n\nexport type OpenEditorConfig = OpenEditorEventHandlers & {\n document?: OpenEditorDocument;\n editable?: boolean;\n placeholder?: string;\n enabledBlocks?: readonly string[];\n theme?: Record<string, string | number>;\n features?: Partial<OpenEditorFeatureSet>;\n};\n\nexport type OpenEditorController = {\n getDocument: () => OpenEditorDocument;\n setDocument: (document: OpenEditorDocument) => void;\n getSelection: () => EditorSelection;\n execute: (command: OpenEditorCommand) => void;\n};\n\nexport type DocumentValidationIssue = {\n path: string;\n message: string;\n};\n\nexport type DocumentValidationResult = {\n valid: boolean;\n issues: DocumentValidationIssue[];\n};\n\nexport type PlatformSupportIssue = {\n path: string;\n block: string;\n platform: EditorPlatform;\n support: PlatformSupportLevel;\n};\n\nexport type PlatformSupportResult = {\n platform: EditorPlatform;\n document: OpenEditorDocument;\n issues: PlatformSupportIssue[];\n};\n\nexport const OPENEDITOR_BLOCK_ID_ATTR = \"openeditor-id\";\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nconst normalizeMeta = (meta?: OpenEditorDocumentMeta): OpenEditorDocumentMeta | undefined =>\n meta && Object.keys(meta).length ? { ...meta } : undefined;\n\nconst cloneAttrs = (attrs?: ProseMirrorAttrs): ProseMirrorAttrs | undefined =>\n attrs ? { ...attrs } : undefined;\n\nconst cloneMark = (mark: ProseMirrorMark): ProseMirrorMark => ({\n type: mark.type,\n ...(mark.attrs ? { attrs: cloneAttrs(mark.attrs) } : {}),\n});\n\nconst cloneNodeShallow = <T extends ProseMirrorNode>(node: T): T => ({\n ...node,\n ...(node.attrs ? { attrs: cloneAttrs(node.attrs) } : {}),\n ...(node.marks ? { marks: node.marks.map(cloneMark) } : {}),\n});\n\nexport const cloneNode = <T extends ProseMirrorNode>(node: T): T => ({\n ...cloneNodeShallow(node),\n ...(node.content ? { content: node.content.map(cloneNode) } : {}),\n});\n\nexport const createBlockId = (prefix = \"oe\"): string => {\n const random =\n typeof globalThis.crypto?.randomUUID === \"function\"\n ? globalThis.crypto.randomUUID()\n : Math.random().toString(36).slice(2);\n\n return `${prefix}_${random.replaceAll(\"-\", \"\").slice(0, 24)}`;\n};\n\nconst cloneNodeWithIds = (\n node: ProseMirrorNode,\n createId: () => string,\n seenIds: Set<string>,\n): ProseMirrorNode => {\n if (node.type === \"text\") return cloneNode(node);\n const cloned = cloneNodeShallow(node);\n const existingId = getBlockId(cloned);\n let id = existingId && !seenIds.has(existingId) ? existingId : createId();\n while (!id.trim() || seenIds.has(id)) id = createId();\n seenIds.add(id);\n const withId = withBlockId(cloned, id);\n return {\n ...withId,\n ...(node.content\n ? { content: node.content.map((child) => cloneNodeWithIds(child, createId, seenIds)) }\n : {}),\n };\n};\n\nconst createDocumentWithIds = (\n content: ProseMirrorNode[] = [],\n meta?: OpenEditorDocumentMeta,\n createId: () => string = createBlockId,\n): OpenEditorDocument => {\n const normalizedMeta = normalizeMeta(meta);\n const seenIds = new Set<string>();\n return {\n type: \"doc\",\n version: 1,\n content: content.map((node) => cloneNodeWithIds(node, createId, seenIds)) as OpenEditorBlock[],\n ...(normalizedMeta ? { meta: normalizedMeta } : {}),\n };\n};\n\nexport const createDocument = (\n content: ProseMirrorNode[] = [],\n meta?: OpenEditorDocumentMeta,\n): OpenEditorDocument => createDocumentWithIds(content, meta);\n\nexport const createEditorState = (\n document: OpenEditorDocument,\n selection: EditorSelection = { type: \"none\" },\n): SerializedEditorState => ({\n document: normalizeDocument(document),\n selection,\n});\n\nexport const toProseMirrorDocument = (document: OpenEditorDocument): ProseMirrorDocument => ({\n type: \"doc\",\n content: document.content.map(cloneNode),\n});\n\nexport const fromProseMirrorDocument = (\n document: ProseMirrorDocument,\n meta?: OpenEditorDocumentMeta,\n): OpenEditorDocument => createDocument(document.content, meta);\n\nexport const createTextNode = (text: string, marks?: ProseMirrorMark[]): ProseMirrorNode => ({\n type: \"text\",\n text,\n ...(marks?.length ? { marks: marks.map(cloneMark) } : {}),\n});\n\nexport const textBlock = (type: string, text: string, attrs?: ProseMirrorAttrs): OpenEditorBlock => ({\n type,\n ...(attrs ? { attrs: cloneAttrs(attrs) } : {}),\n content: text ? [createTextNode(text)] : [],\n});\n\nexport const createBlockRegistry = (specs: readonly BlockSpec[]): BlockRegistry => {\n const registry = new Map<string, BlockSpec>();\n const nodeTypes = new Map<string, string>();\n\n for (const spec of specs) {\n if (!spec.name.trim()) {\n throw new Error(\"OpenEditor block names must not be empty.\");\n }\n if (registry.has(spec.name)) {\n throw new Error(`Duplicate OpenEditor block name \"${spec.name}\".`);\n }\n\n const nodeType = spec.nodeType ?? spec.name;\n const existing = nodeTypes.get(nodeType);\n if (existing) {\n throw new Error(\n `OpenEditor blocks \"${existing}\" and \"${spec.name}\" both claim node type \"${nodeType}\".`,\n );\n }\n\n registry.set(spec.name, spec);\n nodeTypes.set(nodeType, spec.name);\n }\n\n return registry;\n};\n\nexport const findBlockSpecForNode = (\n registry: BlockRegistry,\n node: ProseMirrorNode,\n): BlockSpec | undefined => {\n for (const spec of registry.values()) {\n if (spec.matchNode?.(node) || (spec.nodeType ?? spec.name) === node.type) {\n return spec;\n }\n }\n\n return undefined;\n};\n\nexport const getBlockId = (node: ProseMirrorNode): string | undefined => {\n const value = node.attrs?.[OPENEDITOR_BLOCK_ID_ATTR];\n return typeof value === \"string\" && value.trim() ? value : undefined;\n};\n\nexport const withBlockId = <T extends ProseMirrorNode>(node: T, id: string): T => ({\n ...node,\n attrs: {\n ...cloneAttrs(node.attrs),\n [OPENEDITOR_BLOCK_ID_ATTR]: id,\n },\n});\n\nexport const ensureBlockIds = (\n document: OpenEditorDocument,\n createId: () => string = createBlockId,\n): OpenEditorDocument => createDocumentWithIds(document.content, document.meta, createId);\n\nexport const findBlockLocation = (\n document: OpenEditorDocument,\n id: string,\n): OpenEditorBlockLocation | null => {\n const visit = (\n nodes: readonly ProseMirrorNode[],\n parentId: string | null,\n path: readonly number[],\n ): OpenEditorBlockLocation | null => {\n for (let index = 0; index < nodes.length; index += 1) {\n const node = nodes[index];\n if (!node) continue;\n const nodeId = getBlockId(node);\n const nodePath = [...path, index];\n if (nodeId === id) {\n return { id, nodeType: node.type, parentId, index, path: nodePath };\n }\n const nested = node.content?.length\n ? visit(node.content, nodeId ?? parentId, nodePath)\n : null;\n if (nested) return nested;\n }\n return null;\n };\n\n return visit(document.content, null, []);\n};\n\nconst normalizeNode = (node: ProseMirrorNode): OpenEditorBlock => {\n if (node.type === \"heading\") {\n const level = typeof node.attrs?.level === \"number\" ? node.attrs.level : 2;\n const content = node.content?.map(normalizeNode);\n\n return {\n ...cloneNode(node),\n attrs: { ...node.attrs, level: Math.min(Math.max(level, 1), 6) },\n ...(content ? { content } : {}),\n };\n }\n\n if (node.type === \"columns\") {\n const content = node.content?.length\n ? node.content.map(normalizeNode)\n : [\n { type: \"column\", content: [textBlock(\"paragraph\", \"\")] },\n { type: \"column\", content: [textBlock(\"paragraph\", \"\")] },\n ];\n\n return {\n ...cloneNode(node),\n attrs: Object.fromEntries(\n Object.entries(node.attrs ?? {}).filter(([name]) => name !== \"count\"),\n ),\n content,\n };\n }\n\n if (node.type === \"column\" && !node.content?.length) {\n return { ...cloneNode(node), content: [textBlock(\"paragraph\", \"\")] };\n }\n\n const content = node.content?.map(normalizeNode);\n return {\n ...cloneNode(node),\n ...(content ? { content } : {}),\n };\n};\n\nexport const normalizeDocument = (document: OpenEditorDocument): OpenEditorDocument =>\n createDocument(document.content.map(normalizeNode), document.meta);\n\nexport const validateDocument = (document: unknown): DocumentValidationResult => {\n const issues: DocumentValidationIssue[] = [];\n const push = (path: string, message: string) => issues.push({ path, message });\n\n const validateNode = (node: unknown, path: string) => {\n if (!isRecord(node)) {\n push(path, \"Node must be an object.\");\n return;\n }\n\n if (typeof node.type !== \"string\" || !node.type) {\n push(`${path}.type`, \"Node type must be a non-empty string.\");\n }\n\n if (\"text\" in node && typeof node.text !== \"string\") {\n push(`${path}.text`, \"Text node content must be a string.\");\n }\n\n if (\"attrs\" in node && node.attrs !== undefined && !isRecord(node.attrs)) {\n push(`${path}.attrs`, \"Node attrs must be an object.\");\n }\n\n if (\"marks\" in node && node.marks !== undefined) {\n if (!Array.isArray(node.marks)) {\n push(`${path}.marks`, \"Marks must be an array.\");\n } else {\n node.marks.forEach((mark, index) => {\n if (!isRecord(mark) || typeof mark.type !== \"string\" || !mark.type) {\n push(`${path}.marks.${index}`, \"Mark must have a non-empty type.\");\n }\n });\n }\n }\n\n if (\"content\" in node && node.content !== undefined) {\n if (!Array.isArray(node.content)) {\n push(`${path}.content`, \"Node content must be an array.\");\n } else {\n node.content.forEach((child, index) => validateNode(child, `${path}.content.${index}`));\n }\n }\n };\n\n if (!isRecord(document)) {\n return {\n valid: false,\n issues: [{ path: \"$\", message: \"Document must be an object.\" }],\n };\n }\n\n if (document.type !== \"doc\") {\n push(\"$.type\", 'Document type must be \"doc\".');\n }\n\n if (document.version !== 1) {\n push(\"$.version\", \"Document version must be 1.\");\n }\n\n if (!Array.isArray(document.content)) {\n push(\"$.content\", \"Document content must be an array.\");\n } else {\n document.content.forEach((node, index) => validateNode(node, `$.content.${index}`));\n }\n\n if (\"meta\" in document && document.meta !== undefined && !isRecord(document.meta)) {\n push(\"$.meta\", \"Document meta must be an object.\");\n }\n\n return {\n valid: issues.length === 0,\n issues,\n };\n};\n\nexport const isOpenEditorDocument = (value: unknown): value is OpenEditorDocument =>\n validateDocument(value).valid;\n\nexport const parseOpenEditorDocument = (\n value: unknown,\n defaultDocument: OpenEditorDocument = createDocument(),\n): OpenEditorDocument => {\n if (isOpenEditorDocument(value)) {\n return normalizeDocument(value);\n }\n\n if (isRecord(value) && value.type === \"doc\" && Array.isArray(value.content)) {\n return fromProseMirrorDocument(value as ProseMirrorDocument, defaultDocument.meta);\n }\n\n return defaultDocument;\n};\n\nexport const serializeEditorState = (state: SerializedEditorState): string =>\n JSON.stringify({\n document: normalizeDocument(state.document),\n ...(state.selection ? { selection: state.selection } : {}),\n });\n\nexport const parseEditorState = (\n value: unknown,\n defaultState: SerializedEditorState = createEditorState(createDocument()),\n): SerializedEditorState => {\n let parsed: unknown;\n\n try {\n parsed = typeof value === \"string\" ? JSON.parse(value) : value;\n } catch {\n return defaultState;\n }\n\n if (!isRecord(parsed)) {\n return defaultState;\n }\n\n return {\n document: parseOpenEditorDocument(parsed.document, defaultState.document),\n selection: isRecord(parsed.selection) ? (parsed.selection as EditorSelection) : defaultState.selection,\n };\n};\n\nexport const getPlatformDocument = (\n document: OpenEditorDocument,\n registry: BlockRegistry,\n platform: EditorPlatform,\n): OpenEditorDocument => getPlatformSupport(document, registry, platform).document;\n\nexport const getPlatformSupport = (\n document: OpenEditorDocument,\n registry: BlockRegistry,\n platform: EditorPlatform,\n): PlatformSupportResult => {\n const issues: PlatformSupportIssue[] = [];\n\n const mapNode = (node: OpenEditorBlock, path: string): OpenEditorBlock => {\n const spec = findBlockSpecForNode(registry, node);\n const support = spec?.support?.[platform] ?? \"supported\";\n\n if (support !== \"supported\") {\n issues.push({\n path,\n block: spec?.name ?? node.type,\n platform,\n support,\n });\n }\n\n return normalizeNode({\n ...cloneNode(node),\n content: node.content?.map((child, index) => mapNode(child, `${path}.content.${index}`)),\n });\n };\n\n return {\n platform,\n document: createDocument(\n document.content.map((node, index) => mapNode(node, `$.content.${index}`)),\n { ...document.meta, platform },\n ),\n issues,\n };\n};\n\nconst INLINE_NODE_TYPES = new Set([\"text\", \"hardBreak\"]);\n\nexport const getDocumentText = (node: OpenEditorDocument | ProseMirrorNode): string => {\n if (\"text\" in node && typeof node.text === \"string\") {\n return node.text;\n }\n\n const content = \"content\" in node ? node.content : undefined;\n\n if (!content?.length) {\n return \"\";\n }\n\n const isInlineContainer = content.every(\n (child) => INLINE_NODE_TYPES.has(child.type) || child.type === \"link\",\n );\n const joiner = isInlineContainer ? \"\" : \"\\n\";\n return content.map(getDocumentText).filter(Boolean).join(joiner);\n};\n\nexport const applyCommand = (\n document: OpenEditorDocument,\n registry: BlockRegistry,\n command: OpenEditorCommand,\n): OpenEditorDocument => {\n if (command.type === \"setContent\") {\n return normalizeDocument(command.document);\n }\n\n if (command.type === \"replaceDocument\") {\n return normalizeDocument(command.document);\n }\n\n if (command.type === \"setSelection\") {\n return document;\n }\n\n if (command.type === \"moveBlock\") {\n return moveTopLevelBlock(document, command.from, command.to);\n }\n\n if (command.type === \"duplicateBlock\") {\n return duplicateTopLevelBlock(document, command.index);\n }\n\n if (command.type === \"deleteBlock\") {\n return deleteTopLevelBlock(document, command.index);\n }\n\n if (\n command.type === \"setLink\"\n || command.type === \"toggleMark\"\n || command.type === \"undo\"\n || command.type === \"redo\"\n ) {\n return normalizeDocument(document);\n }\n\n const spec = registry.get(command.block);\n if (!spec) {\n throw new Error(`Unknown block \"${command.block}\"`);\n }\n\n const nextContent = [...document.content];\n const index = command.at ?? nextContent.length;\n const defaultNode = spec.defaultNode();\n const node = command.attrs\n ? { ...defaultNode, attrs: { ...defaultNode.attrs, ...command.attrs } }\n : defaultNode;\n\n nextContent.splice(index, 0, node);\n return normalizeDocument(createDocument(nextContent, document.meta));\n};\n\nexport const replaceTopLevelRange = (\n document: OpenEditorDocument,\n start: number,\n length: number,\n replacement: ProseMirrorNode[],\n): OpenEditorDocument =>\n normalizeDocument({\n ...document,\n content: [\n ...document.content.slice(0, start),\n ...replacement.map(cloneNode),\n ...document.content.slice(start + length),\n ],\n });\n\nexport const replaceTopLevelNode = (\n document: OpenEditorDocument,\n index: number,\n replacement: ProseMirrorNode,\n): OpenEditorDocument =>\n normalizeDocument({\n ...document,\n content: document.content.map((node, nodeIndex) => nodeIndex === index ? cloneNode(replacement) : cloneNode(node)),\n });\n\nexport const moveTopLevelBlock = (\n document: OpenEditorDocument,\n from: number,\n to: number,\n): OpenEditorDocument => {\n if (from < 0 || from >= document.content.length || to < 0 || to >= document.content.length || from === to) {\n return normalizeDocument(document);\n }\n\n const nextContent = document.content.map(cloneNode);\n const [item] = nextContent.splice(from, 1);\n if (!item) {\n return normalizeDocument(document);\n }\n\n nextContent.splice(to, 0, item);\n return normalizeDocument({ ...document, content: nextContent });\n};\n\nexport const duplicateTopLevelBlock = (\n document: OpenEditorDocument,\n index: number,\n): OpenEditorDocument => {\n if (index < 0 || index >= document.content.length) {\n return normalizeDocument(document);\n }\n\n const nextContent = document.content.map(cloneNode);\n nextContent.splice(index + 1, 0, cloneNode(document.content[index]));\n return normalizeDocument({ ...document, content: nextContent });\n};\n\nexport const deleteTopLevelBlock = (\n document: OpenEditorDocument,\n index: number,\n emptyBlock: OpenEditorBlock = textBlock(\"paragraph\", \"\"),\n): OpenEditorDocument => {\n if (document.content.length <= 1) {\n return normalizeDocument({ ...document, content: [cloneNode(emptyBlock)] });\n }\n\n if (index < 0 || index >= document.content.length) {\n return normalizeDocument(document);\n }\n\n return normalizeDocument({\n ...document,\n content: document.content.filter((_, currentIndex) => currentIndex !== index).map(cloneNode),\n });\n};\n\nexport const createTransaction = (\n before: OpenEditorDocument,\n after: OpenEditorDocument,\n command?: EditorCommand,\n): EditorTransaction => ({\n before,\n after,\n ...(command ? { command } : {}),\n timestamp: new Date().toISOString(),\n});\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"names":["content"],"mappings":"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","file":"index.js","sourcesContent":["export type JsonPrimitive = string | number | boolean | null;\nexport type JsonValue = JsonPrimitive | JsonObject | JsonValue[];\nexport type JsonObject = { [key: string]: JsonValue | undefined };\n\nexport type ProseMirrorAttrs = Record<string, unknown>;\n\nexport type ProseMirrorMark = {\n type: string;\n attrs?: ProseMirrorAttrs;\n};\n\nexport type ProseMirrorNode = {\n type: string;\n attrs?: ProseMirrorAttrs;\n content?: ProseMirrorNode[];\n marks?: ProseMirrorMark[];\n text?: string;\n};\n\nexport type OpenEditorBlock = ProseMirrorNode & {\n attrs?: ProseMirrorAttrs & {\n \"openeditor-id\"?: string;\n };\n};\n\n/** Stable identity used by commands and interaction adapters. */\nexport type OpenEditorBlockRef = {\n id: string;\n nodeType: string;\n blockName?: string;\n};\n\nexport type OpenEditorBlockLocation = OpenEditorBlockRef & {\n parentId: string | null;\n index: number;\n path: readonly number[];\n};\n\nexport type OpenEditorDocumentMeta = {\n id?: string;\n title?: string;\n source?: string;\n createdAt?: string;\n updatedAt?: string;\n platform?: EditorPlatform;\n custom?: Record<string, unknown>;\n};\n\nexport type OpenEditorDocument = {\n type: \"doc\";\n version: 1;\n content: OpenEditorBlock[];\n meta?: OpenEditorDocumentMeta;\n};\n\nexport type ProseMirrorDocument = {\n type: \"doc\";\n content: ProseMirrorNode[];\n};\n\nexport type EditorPlatform = \"web\" | \"native\";\n\nexport type PlatformSupportLevel = \"supported\" | \"unsupported\";\n\nexport type PlatformSupport = {\n web: PlatformSupportLevel;\n native: PlatformSupportLevel;\n};\n\nexport type BlockGroup = \"text\" | \"media\" | \"layout\" | \"structure\" | \"embed\";\n\nexport type BlockSpec = {\n name: string;\n /** ProseMirror node type. Defaults to `name`. */\n nodeType?: string;\n label: string;\n group: BlockGroup;\n defaultNode: () => OpenEditorBlock;\n matchNode?: (node: ProseMirrorNode) => boolean;\n support?: PlatformSupport;\n};\n\nexport type BlockRegistry = ReadonlyMap<string, BlockSpec>;\n\nexport type EditorSelection =\n | { type: \"none\" }\n | { type: \"text\"; anchor: number; head: number }\n | { type: \"node\"; from: number; to: number; nodeType?: string }\n | { type: \"block\"; blockId: string };\n\nexport type OpenEditorMarkName =\n | \"bold\"\n | \"italic\"\n | \"underline\"\n | \"strike\"\n | \"code\"\n | \"link\";\n\nexport type OpenEditorFeatureName =\n | \"headings\"\n | \"lists\"\n | \"taskLists\"\n | \"quotes\"\n | \"codeBlocks\"\n | \"dividers\"\n | \"links\"\n | \"images\"\n | \"columns\"\n | \"tables\"\n | \"toggleLists\"\n | \"callouts\"\n | \"diagrams\"\n | \"pages\"\n | \"attachments\";\n\n/** Durable, portable attributes stored on an attachment node. */\nexport type OpenEditorAttachmentSnapshot = {\n attachmentId: string | null;\n name: string;\n mimeType: string | null;\n size: number | null;\n url: string | null;\n};\n\n/**\n * A host-selected local file. `source` is deliberately opaque: on web it may\n * be a File, while native hosts typically use a picker result or local URI.\n * OpenEditor never serializes it.\n */\nexport type OpenEditorAttachmentUploadInput<TSource = unknown> = {\n name: string;\n mimeType: string | null;\n size: number | null;\n source: TSource;\n};\n\nexport type OpenEditorAttachmentUploadCallbacks = {\n onProgress?: (progress: number) => void;\n signal?: AbortSignal;\n};\n\nexport type OpenEditorAttachmentValidationResult =\n | { accepted: true }\n | { accepted: false; message: string };\n\n/** Host-owned storage, picker, policy, resolution, and platform actions. */\nexport type OpenEditorAttachmentRuntime<TSource = unknown> = {\n selectAttachment?: (options?: { signal?: AbortSignal }) =>\n | Promise<OpenEditorAttachmentUploadInput<TSource> | null>\n | OpenEditorAttachmentUploadInput<TSource>\n | null;\n validateAttachment?: (\n input: OpenEditorAttachmentUploadInput<TSource>,\n ) => OpenEditorAttachmentValidationResult | Promise<OpenEditorAttachmentValidationResult>;\n uploadAttachment?: (\n input: OpenEditorAttachmentUploadInput<TSource>,\n callbacks?: OpenEditorAttachmentUploadCallbacks,\n ) => Promise<OpenEditorAttachmentSnapshot>;\n resolveAttachment?: (attachmentId: string, options?: { signal?: AbortSignal }) =>\n Promise<OpenEditorAttachmentSnapshot | null>;\n openAttachment?: (attachment: OpenEditorAttachmentSnapshot) => void | Promise<void>;\n renameAttachment?: (attachmentId: string, name: string) => void | Promise<void>;\n replaceAttachment?: (\n attachmentId: string,\n input: OpenEditorAttachmentUploadInput<TSource>,\n callbacks?: OpenEditorAttachmentUploadCallbacks,\n ) => Promise<OpenEditorAttachmentSnapshot>;\n};\n\nexport type OpenEditorPageSnapshot = {\n pageId: string;\n title: string;\n icon?: string | null;\n href?: string | null;\n};\n\nexport type OpenEditorPageUpdate = {\n title?: string;\n icon?: string | null;\n};\n\n/** Host-owned page identity, persistence, navigation, and metadata lifecycle. */\nexport type OpenEditorPageRuntime = {\n createPage?: (input: { title: string; icon?: string | null }) => Promise<OpenEditorPageSnapshot>;\n resolvePage?: (pageId: string) => Promise<OpenEditorPageSnapshot | null>;\n updatePage: (\n pageId: string,\n update: OpenEditorPageUpdate,\n ) => Promise<OpenEditorPageSnapshot | void> | OpenEditorPageSnapshot | void;\n openPage?: (page: OpenEditorPageSnapshot) => Promise<void> | void;\n};\n\n/** Built-in URL-bearing surfaces rendered from portable document data. */\nexport type OpenEditorUrlContext = \"link\" | \"image\" | \"page\" | \"attachment\";\n\n/**\n * Returns the URL that may be rendered for a context, or `null` to omit the\n * navigation/resource. Policies are pure so the same contract can be shared by\n * React viewers, HTML exporters, and other public renderers.\n */\nexport type OpenEditorUrlPolicy = (\n value: string,\n context: OpenEditorUrlContext,\n) => string | null;\n\nconst OPENEDITOR_URL_SCHEME = /^([a-z][a-z\\d+.-]*):/i;\nconst OPENEDITOR_URL_CONTROL_CHARACTER = /[\\u0000-\\u001f\\u007f]/;\nconst OPENEDITOR_PUBLIC_SCHEMES: Readonly<Record<OpenEditorUrlContext, ReadonlySet<string>>> = {\n link: new Set([\"http\", \"https\", \"mailto\", \"tel\"]),\n image: new Set([\"http\", \"https\"]),\n page: new Set([\"http\", \"https\"]),\n attachment: new Set([\"http\", \"https\"]),\n};\n\n/**\n * Safe default for public rendering. Ordinary relative references (including\n * query strings and fragments) are preserved; explicit schemes are allowlisted\n * per context. Local preview schemes such as `blob:` require a host policy.\n */\nexport const openEditorPublicUrlPolicy: OpenEditorUrlPolicy = (value, context) => {\n const normalized = value.trim();\n if (!normalized || OPENEDITOR_URL_CONTROL_CHARACTER.test(normalized)) return null;\n\n const scheme = OPENEDITOR_URL_SCHEME.exec(normalized)?.[1]?.toLowerCase();\n if (!scheme) return normalized;\n return OPENEDITOR_PUBLIC_SCHEMES[context].has(scheme) ? normalized : null;\n};\n\n/** Explicit trusted-host escape hatch. Never use this for untrusted documents. */\nexport const openEditorUnsafeUrlPolicy: OpenEditorUrlPolicy = (value) => {\n const normalized = value.trim();\n return normalized || null;\n};\n\nexport const createAttachmentSnapshot = (\n attrs: Partial<OpenEditorAttachmentSnapshot> = {},\n): OpenEditorAttachmentSnapshot => ({\n attachmentId: typeof attrs.attachmentId === \"string\" ? attrs.attachmentId : null,\n name: typeof attrs.name === \"string\" ? attrs.name : \"\",\n mimeType: typeof attrs.mimeType === \"string\" ? attrs.mimeType : null,\n size: typeof attrs.size === \"number\" && Number.isFinite(attrs.size) && attrs.size >= 0 ? attrs.size : null,\n url: typeof attrs.url === \"string\" ? attrs.url : null,\n});\n\nexport type OpenEditorFeatureSet = Readonly<Record<OpenEditorFeatureName, boolean>>;\n\n/** Controls which schema-supported blocks may be created by an editor surface. */\nexport type OpenEditorAuthoringCapabilities = {\n enabledBlocks?: readonly string[];\n};\n\nexport const isOpenEditorBlockEnabled = (\n blockName: string,\n capabilities?: OpenEditorAuthoringCapabilities,\n): boolean => capabilities?.enabledBlocks === undefined\n || capabilities.enabledBlocks.includes(blockName);\n\nexport const DEFAULT_CALLOUT_EMOJI = \"💡\";\nexport const DEFAULT_PAGE_EMOJI = \"📄\";\n\nexport const normalizeEmoji = (value: unknown, fallback: string) =>\n typeof value === \"string\" && value.trim() ? value.trim() : fallback;\n\nexport type SerializedEditorState = {\n document: OpenEditorDocument;\n selection?: EditorSelection;\n};\n\nexport type EditorTransaction = {\n before: OpenEditorDocument;\n after: OpenEditorDocument;\n command?: OpenEditorCommand;\n timestamp: string;\n};\n\nexport type OpenEditorCommand =\n | { type: \"setContent\"; document: OpenEditorDocument }\n | { type: \"insertBlock\"; block: string; at?: number; attrs?: ProseMirrorAttrs }\n | { type: \"moveBlock\"; from: number; to: number }\n | { type: \"duplicateBlock\"; index: number }\n | { type: \"deleteBlock\"; index: number }\n | { type: \"setLink\"; href?: string }\n | { type: \"toggleMark\"; mark: OpenEditorMarkName }\n | { type: \"undo\" }\n | { type: \"redo\" }\n | { type: \"setSelection\"; selection: EditorSelection };\n\nexport type EditorCommand = OpenEditorCommand;\n\nexport type OpenEditorEventHandlers = {\n onChange?: (document: OpenEditorDocument) => void;\n onSelectionChange?: (selection: EditorSelection) => void;\n onFocus?: () => void;\n onBlur?: () => void;\n onReady?: (controller: OpenEditorController) => void;\n onCommand?: (command: OpenEditorCommand, transaction: EditorTransaction) => void;\n};\n\nexport type OpenEditorConfig = OpenEditorEventHandlers & {\n initialDocument?: OpenEditorDocument;\n editable?: boolean;\n placeholder?: string;\n enabledBlocks?: readonly string[];\n theme?: Record<string, string | number>;\n};\n\nexport type OpenEditorController = {\n getContent: () => OpenEditorDocument;\n setContent: (document: OpenEditorDocument) => void;\n getSelection: () => EditorSelection;\n execute: (command: OpenEditorCommand) => void;\n};\n\nexport type DocumentValidationIssue = {\n path: string;\n message: string;\n};\n\nexport type DocumentValidationResult = {\n valid: boolean;\n issues: DocumentValidationIssue[];\n};\n\nexport type PlatformSupportIssue = {\n path: string;\n block: string;\n platform: EditorPlatform;\n support: PlatformSupportLevel;\n};\n\nexport type PlatformSupportResult = {\n platform: EditorPlatform;\n document: OpenEditorDocument;\n issues: PlatformSupportIssue[];\n};\n\nexport const OPENEDITOR_BLOCK_ID_ATTR = \"openeditor-id\";\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nconst normalizeMeta = (meta?: OpenEditorDocumentMeta): OpenEditorDocumentMeta | undefined =>\n meta && Object.keys(meta).length ? { ...meta } : undefined;\n\nconst cloneAttrs = (attrs?: ProseMirrorAttrs): ProseMirrorAttrs | undefined =>\n attrs ? { ...attrs } : undefined;\n\nconst cloneMark = (mark: ProseMirrorMark): ProseMirrorMark => ({\n type: mark.type,\n ...(mark.attrs ? { attrs: cloneAttrs(mark.attrs) } : {}),\n});\n\nconst cloneNodeShallow = <T extends ProseMirrorNode>(node: T): T => ({\n ...node,\n ...(node.attrs ? { attrs: cloneAttrs(node.attrs) } : {}),\n ...(node.marks ? { marks: node.marks.map(cloneMark) } : {}),\n});\n\nexport const cloneNode = <T extends ProseMirrorNode>(node: T): T => ({\n ...cloneNodeShallow(node),\n ...(node.content ? { content: node.content.map(cloneNode) } : {}),\n});\n\nexport const createBlockId = (prefix = \"oe\"): string => {\n const random =\n typeof globalThis.crypto?.randomUUID === \"function\"\n ? globalThis.crypto.randomUUID()\n : Math.random().toString(36).slice(2);\n\n return `${prefix}_${random.replaceAll(\"-\", \"\").slice(0, 24)}`;\n};\n\nconst cloneNodeWithIds = (\n node: ProseMirrorNode,\n createId: () => string,\n seenIds: Set<string>,\n): ProseMirrorNode => {\n if (node.type === \"text\") return cloneNode(node);\n const cloned = cloneNodeShallow(node);\n const existingId = getBlockId(cloned);\n let id = existingId && !seenIds.has(existingId) ? existingId : createId();\n while (!id.trim() || seenIds.has(id)) id = createId();\n seenIds.add(id);\n const withId = withBlockId(cloned, id);\n return {\n ...withId,\n ...(node.content\n ? { content: node.content.map((child) => cloneNodeWithIds(child, createId, seenIds)) }\n : {}),\n };\n};\n\nconst createDocumentWithIds = (\n content: ProseMirrorNode[] = [],\n meta?: OpenEditorDocumentMeta,\n createId: () => string = createBlockId,\n): OpenEditorDocument => {\n const normalizedMeta = normalizeMeta(meta);\n const seenIds = new Set<string>();\n return {\n type: \"doc\",\n version: 1,\n content: content.map((node) => cloneNodeWithIds(node, createId, seenIds)) as OpenEditorBlock[],\n ...(normalizedMeta ? { meta: normalizedMeta } : {}),\n };\n};\n\nexport const createDocument = (\n content: ProseMirrorNode[] = [],\n meta?: OpenEditorDocumentMeta,\n): OpenEditorDocument => createDocumentWithIds(content, meta);\n\nexport const createEditorState = (\n document: OpenEditorDocument,\n selection: EditorSelection = { type: \"none\" },\n): SerializedEditorState => ({\n document: normalizeDocument(document),\n selection,\n});\n\nexport const toProseMirrorDocument = (document: OpenEditorDocument): ProseMirrorDocument => ({\n type: \"doc\",\n content: document.content.map(cloneNode),\n});\n\nexport const fromProseMirrorDocument = (\n document: ProseMirrorDocument,\n meta?: OpenEditorDocumentMeta,\n): OpenEditorDocument => createDocument(document.content, meta);\n\nexport const createTextNode = (text: string, marks?: ProseMirrorMark[]): ProseMirrorNode => ({\n type: \"text\",\n text,\n ...(marks?.length ? { marks: marks.map(cloneMark) } : {}),\n});\n\nexport const textBlock = (type: string, text: string, attrs?: ProseMirrorAttrs): OpenEditorBlock => ({\n type,\n ...(attrs ? { attrs: cloneAttrs(attrs) } : {}),\n content: text ? [createTextNode(text)] : [],\n});\n\nexport const createBlockRegistry = (specs: readonly BlockSpec[]): BlockRegistry => {\n const registry = new Map<string, BlockSpec>();\n const nodeTypes = new Map<string, string>();\n\n for (const spec of specs) {\n if (!spec.name.trim()) {\n throw new Error(\"OpenEditor block names must not be empty.\");\n }\n if (registry.has(spec.name)) {\n throw new Error(`Duplicate OpenEditor block name \"${spec.name}\".`);\n }\n\n const nodeType = spec.nodeType ?? spec.name;\n const existing = nodeTypes.get(nodeType);\n if (existing) {\n throw new Error(\n `OpenEditor blocks \"${existing}\" and \"${spec.name}\" both claim node type \"${nodeType}\".`,\n );\n }\n\n registry.set(spec.name, spec);\n nodeTypes.set(nodeType, spec.name);\n }\n\n return registry;\n};\n\nexport const findBlockSpecForNode = (\n registry: BlockRegistry,\n node: ProseMirrorNode,\n): BlockSpec | undefined => {\n for (const spec of registry.values()) {\n if (spec.matchNode?.(node) || (spec.nodeType ?? spec.name) === node.type) {\n return spec;\n }\n }\n\n return undefined;\n};\n\nexport const getBlockId = (node: ProseMirrorNode): string | undefined => {\n const value = node.attrs?.[OPENEDITOR_BLOCK_ID_ATTR];\n return typeof value === \"string\" && value.trim() ? value : undefined;\n};\n\nexport const withBlockId = <T extends ProseMirrorNode>(node: T, id: string): T => ({\n ...node,\n attrs: {\n ...cloneAttrs(node.attrs),\n [OPENEDITOR_BLOCK_ID_ATTR]: id,\n },\n});\n\nexport const ensureBlockIds = (\n document: OpenEditorDocument,\n createId: () => string = createBlockId,\n): OpenEditorDocument => createDocumentWithIds(document.content, document.meta, createId);\n\nexport const findBlockLocation = (\n document: OpenEditorDocument,\n id: string,\n): OpenEditorBlockLocation | null => {\n const visit = (\n nodes: readonly ProseMirrorNode[],\n parentId: string | null,\n path: readonly number[],\n ): OpenEditorBlockLocation | null => {\n for (let index = 0; index < nodes.length; index += 1) {\n const node = nodes[index];\n if (!node) continue;\n const nodeId = getBlockId(node);\n const nodePath = [...path, index];\n if (nodeId === id) {\n return { id, nodeType: node.type, parentId, index, path: nodePath };\n }\n const nested = node.content?.length\n ? visit(node.content, nodeId ?? parentId, nodePath)\n : null;\n if (nested) return nested;\n }\n return null;\n };\n\n return visit(document.content, null, []);\n};\n\nconst normalizeNode = (node: ProseMirrorNode): OpenEditorBlock => {\n if (node.type === \"heading\") {\n const level = typeof node.attrs?.level === \"number\" ? node.attrs.level : 2;\n const content = node.content?.map(normalizeNode);\n\n return {\n ...cloneNode(node),\n attrs: { ...node.attrs, level: Math.min(Math.max(level, 1), 6) },\n ...(content ? { content } : {}),\n };\n }\n\n if (node.type === \"columns\") {\n const content = node.content?.length\n ? node.content.map(normalizeNode)\n : [\n { type: \"column\", content: [textBlock(\"paragraph\", \"\")] },\n { type: \"column\", content: [textBlock(\"paragraph\", \"\")] },\n ];\n\n return {\n ...cloneNode(node),\n attrs: Object.fromEntries(\n Object.entries(node.attrs ?? {}).filter(([name]) => name !== \"count\"),\n ),\n content,\n };\n }\n\n if (node.type === \"column\" && !node.content?.length) {\n return { ...cloneNode(node), content: [textBlock(\"paragraph\", \"\")] };\n }\n\n const content = node.content?.map(normalizeNode);\n return {\n ...cloneNode(node),\n ...(content ? { content } : {}),\n };\n};\n\nexport const normalizeDocument = (document: OpenEditorDocument): OpenEditorDocument =>\n createDocument(document.content.map(normalizeNode), document.meta);\n\nexport const validateDocument = (document: unknown): DocumentValidationResult => {\n const issues: DocumentValidationIssue[] = [];\n const push = (path: string, message: string) => issues.push({ path, message });\n\n const validateNode = (node: unknown, path: string) => {\n if (!isRecord(node)) {\n push(path, \"Node must be an object.\");\n return;\n }\n\n if (typeof node.type !== \"string\" || !node.type) {\n push(`${path}.type`, \"Node type must be a non-empty string.\");\n }\n\n if (\"text\" in node && typeof node.text !== \"string\") {\n push(`${path}.text`, \"Text node content must be a string.\");\n }\n\n if (\"attrs\" in node && node.attrs !== undefined && !isRecord(node.attrs)) {\n push(`${path}.attrs`, \"Node attrs must be an object.\");\n }\n\n if (\"marks\" in node && node.marks !== undefined) {\n if (!Array.isArray(node.marks)) {\n push(`${path}.marks`, \"Marks must be an array.\");\n } else {\n node.marks.forEach((mark, index) => {\n if (!isRecord(mark) || typeof mark.type !== \"string\" || !mark.type) {\n push(`${path}.marks.${index}`, \"Mark must have a non-empty type.\");\n }\n });\n }\n }\n\n if (\"content\" in node && node.content !== undefined) {\n if (!Array.isArray(node.content)) {\n push(`${path}.content`, \"Node content must be an array.\");\n } else {\n node.content.forEach((child, index) => validateNode(child, `${path}.content.${index}`));\n }\n }\n };\n\n if (!isRecord(document)) {\n return {\n valid: false,\n issues: [{ path: \"$\", message: \"Document must be an object.\" }],\n };\n }\n\n if (document.type !== \"doc\") {\n push(\"$.type\", 'Document type must be \"doc\".');\n }\n\n if (document.version !== 1) {\n push(\"$.version\", \"Document version must be 1.\");\n }\n\n if (!Array.isArray(document.content)) {\n push(\"$.content\", \"Document content must be an array.\");\n } else {\n document.content.forEach((node, index) => validateNode(node, `$.content.${index}`));\n }\n\n if (\"meta\" in document && document.meta !== undefined && !isRecord(document.meta)) {\n push(\"$.meta\", \"Document meta must be an object.\");\n }\n\n return {\n valid: issues.length === 0,\n issues,\n };\n};\n\nexport const isOpenEditorDocument = (value: unknown): value is OpenEditorDocument =>\n validateDocument(value).valid;\n\nexport class OpenEditorDocumentParseError extends Error {\n readonly validation: DocumentValidationResult;\n\n constructor(validation: DocumentValidationResult) {\n super(validation.issues.map((issue) => `${issue.path}: ${issue.message}`).join(\"\\n\"));\n this.name = \"OpenEditorDocumentParseError\";\n this.validation = validation;\n }\n}\n\nexport const parseOpenEditorDocument = (\n value: unknown,\n): OpenEditorDocument => {\n const validation = validateDocument(value);\n if (!validation.valid) throw new OpenEditorDocumentParseError(validation);\n return normalizeDocument(value as OpenEditorDocument);\n};\n\n/** Imports unversioned ProseMirror JSON. Versioned values require strict OpenEditor parsing. */\nexport const importProseMirrorDocument = (\n value: unknown,\n meta?: OpenEditorDocumentMeta,\n): OpenEditorDocument => {\n if (isRecord(value) && \"version\" in value) {\n throw new Error(\"Versioned documents must be parsed with parseOpenEditorDocument().\");\n }\n\n const validation = validateDocument(\n isRecord(value) ? { ...value, version: 1 } : value,\n );\n if (!validation.valid) throw new OpenEditorDocumentParseError(validation);\n return fromProseMirrorDocument(value as ProseMirrorDocument, meta);\n};\n\nexport const serializeEditorState = (state: SerializedEditorState): string =>\n JSON.stringify({\n document: normalizeDocument(state.document),\n ...(state.selection ? { selection: state.selection } : {}),\n });\n\nexport const parseEditorState = (\n value: unknown,\n defaultState: SerializedEditorState = createEditorState(createDocument()),\n): SerializedEditorState => {\n let parsed: unknown;\n\n try {\n parsed = typeof value === \"string\" ? JSON.parse(value) : value;\n } catch {\n return defaultState;\n }\n\n if (!isRecord(parsed)) {\n return defaultState;\n }\n\n try {\n return {\n document: parseOpenEditorDocument(parsed.document),\n selection: isRecord(parsed.selection) ? (parsed.selection as EditorSelection) : defaultState.selection,\n };\n } catch {\n return defaultState;\n }\n};\n\nexport const getPlatformDocument = (\n document: OpenEditorDocument,\n registry: BlockRegistry,\n platform: EditorPlatform,\n): OpenEditorDocument => getPlatformSupport(document, registry, platform).document;\n\nexport const getPlatformSupport = (\n document: OpenEditorDocument,\n registry: BlockRegistry,\n platform: EditorPlatform,\n): PlatformSupportResult => {\n const issues: PlatformSupportIssue[] = [];\n\n const mapNode = (node: OpenEditorBlock, path: string): OpenEditorBlock => {\n const spec = findBlockSpecForNode(registry, node);\n const support = spec?.support?.[platform] ?? \"supported\";\n\n if (support !== \"supported\") {\n issues.push({\n path,\n block: spec?.name ?? node.type,\n platform,\n support,\n });\n }\n\n return normalizeNode({\n ...cloneNode(node),\n content: node.content?.map((child, index) => mapNode(child, `${path}.content.${index}`)),\n });\n };\n\n return {\n platform,\n document: createDocument(\n document.content.map((node, index) => mapNode(node, `$.content.${index}`)),\n { ...document.meta, platform },\n ),\n issues,\n };\n};\n\nconst INLINE_NODE_TYPES = new Set([\"text\", \"hardBreak\"]);\n\nexport const getDocumentText = (node: OpenEditorDocument | ProseMirrorNode): string => {\n if (\"text\" in node && typeof node.text === \"string\") {\n return node.text;\n }\n\n const content = \"content\" in node ? node.content : undefined;\n\n if (!content?.length) {\n return \"\";\n }\n\n const isInlineContainer = content.every(\n (child) => INLINE_NODE_TYPES.has(child.type) || child.type === \"link\",\n );\n const joiner = isInlineContainer ? \"\" : \"\\n\";\n return content.map(getDocumentText).filter(Boolean).join(joiner);\n};\n\nexport const applyCommand = (\n document: OpenEditorDocument,\n registry: BlockRegistry,\n command: OpenEditorCommand,\n): OpenEditorDocument => {\n if (command.type === \"setContent\") {\n return normalizeDocument(command.document);\n }\n\n if (command.type === \"setSelection\") {\n return document;\n }\n\n if (command.type === \"moveBlock\") {\n return moveTopLevelBlock(document, command.from, command.to);\n }\n\n if (command.type === \"duplicateBlock\") {\n return duplicateTopLevelBlock(document, command.index);\n }\n\n if (command.type === \"deleteBlock\") {\n return deleteTopLevelBlock(document, command.index);\n }\n\n if (\n command.type === \"setLink\"\n || command.type === \"toggleMark\"\n || command.type === \"undo\"\n || command.type === \"redo\"\n ) {\n return normalizeDocument(document);\n }\n\n const spec = registry.get(command.block);\n if (!spec) {\n throw new Error(`Unknown block \"${command.block}\"`);\n }\n\n const nextContent = [...document.content];\n const index = command.at ?? nextContent.length;\n const defaultNode = spec.defaultNode();\n const node = command.attrs\n ? { ...defaultNode, attrs: { ...defaultNode.attrs, ...command.attrs } }\n : defaultNode;\n\n nextContent.splice(index, 0, node);\n return normalizeDocument(createDocument(nextContent, document.meta));\n};\n\nexport const replaceTopLevelRange = (\n document: OpenEditorDocument,\n start: number,\n length: number,\n replacement: ProseMirrorNode[],\n): OpenEditorDocument =>\n normalizeDocument({\n ...document,\n content: [\n ...document.content.slice(0, start),\n ...replacement.map(cloneNode),\n ...document.content.slice(start + length),\n ],\n });\n\nexport const replaceTopLevelNode = (\n document: OpenEditorDocument,\n index: number,\n replacement: ProseMirrorNode,\n): OpenEditorDocument =>\n normalizeDocument({\n ...document,\n content: document.content.map((node, nodeIndex) => nodeIndex === index ? cloneNode(replacement) : cloneNode(node)),\n });\n\nexport const moveTopLevelBlock = (\n document: OpenEditorDocument,\n from: number,\n to: number,\n): OpenEditorDocument => {\n if (from < 0 || from >= document.content.length || to < 0 || to >= document.content.length || from === to) {\n return normalizeDocument(document);\n }\n\n const nextContent = document.content.map(cloneNode);\n const [item] = nextContent.splice(from, 1);\n if (!item) {\n return normalizeDocument(document);\n }\n\n nextContent.splice(to, 0, item);\n return normalizeDocument({ ...document, content: nextContent });\n};\n\nexport const duplicateTopLevelBlock = (\n document: OpenEditorDocument,\n index: number,\n): OpenEditorDocument => {\n if (index < 0 || index >= document.content.length) {\n return normalizeDocument(document);\n }\n\n const nextContent = document.content.map(cloneNode);\n nextContent.splice(index + 1, 0, cloneNode(document.content[index]));\n return normalizeDocument({ ...document, content: nextContent });\n};\n\nexport const deleteTopLevelBlock = (\n document: OpenEditorDocument,\n index: number,\n emptyBlock: OpenEditorBlock = textBlock(\"paragraph\", \"\"),\n): OpenEditorDocument => {\n if (document.content.length <= 1) {\n return normalizeDocument({ ...document, content: [cloneNode(emptyBlock)] });\n }\n\n if (index < 0 || index >= document.content.length) {\n return normalizeDocument(document);\n }\n\n return normalizeDocument({\n ...document,\n content: document.content.filter((_, currentIndex) => currentIndex !== index).map(cloneNode),\n });\n};\n\nexport const createTransaction = (\n before: OpenEditorDocument,\n after: OpenEditorDocument,\n command?: EditorCommand,\n): EditorTransaction => ({\n before,\n after,\n ...(command ? { command } : {}),\n timestamp: new Date().toISOString(),\n});\n"]}
|