@openeditor/core 0.0.26 → 0.0.28

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 CHANGED
@@ -2,12 +2,17 @@
2
2
 
3
3
  Canonical SDK contract for OpenEditor documents.
4
4
 
5
- The package exports the portable `OpenEditorAttachmentSnapshot`, opaque/generic `OpenEditorAttachmentUploadInput`, and `OpenEditorAttachmentRuntime` contracts. A web host can use `File` as its generic source; native hosts can use a document-picker asset without introducing platform types here.
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.
6
9
 
7
10
  ## Public surface
8
11
 
9
12
  - `OpenEditorDocument` and related types
10
13
  - document creation, normalization, validation, parsing, and platform support helpers
14
+ - strict `parseOpenEditorDocument` for versioned documents and explicit `importProseMirrorDocument` for unversioned ProseMirror JSON
15
+ - shared authoring capabilities and page metadata runtime contracts
11
16
  - platform-neutral command and transaction helpers
12
17
  - top-level block transforms and text extraction
13
18
 
package/dist/index.d.ts CHANGED
@@ -8,11 +8,6 @@ type ProseMirrorMark = {
8
8
  type: string;
9
9
  attrs?: ProseMirrorAttrs;
10
10
  };
11
- type OpenEditorNodeMeta = {
12
- id?: string;
13
- block?: string;
14
- custom?: Record<string, unknown>;
15
- };
16
11
  type ProseMirrorNode = {
17
12
  type: string;
18
13
  attrs?: ProseMirrorAttrs;
@@ -22,18 +17,26 @@ type ProseMirrorNode = {
22
17
  };
23
18
  type OpenEditorBlock = ProseMirrorNode & {
24
19
  attrs?: ProseMirrorAttrs & {
25
- "data-openeditor-id"?: string;
26
- "data-openeditor-block"?: string;
27
- openeditor?: OpenEditorNodeMeta;
20
+ "openeditor-id"?: string;
28
21
  };
29
22
  };
23
+ /** Stable identity used by commands and interaction adapters. */
24
+ type OpenEditorBlockRef = {
25
+ id: string;
26
+ nodeType: string;
27
+ blockName?: string;
28
+ };
29
+ type OpenEditorBlockLocation = OpenEditorBlockRef & {
30
+ parentId: string | null;
31
+ index: number;
32
+ path: readonly number[];
33
+ };
30
34
  type OpenEditorDocumentMeta = {
31
35
  id?: string;
32
36
  title?: string;
33
37
  source?: string;
34
38
  createdAt?: string;
35
39
  updatedAt?: string;
36
- schemaVersion?: number;
37
40
  platform?: EditorPlatform;
38
41
  custom?: Record<string, unknown>;
39
42
  };
@@ -125,8 +128,33 @@ type OpenEditorAttachmentRuntime<TSource = unknown> = {
125
128
  renameAttachment?: (attachmentId: string, name: string) => void | Promise<void>;
126
129
  replaceAttachment?: (attachmentId: string, input: OpenEditorAttachmentUploadInput<TSource>, callbacks?: OpenEditorAttachmentUploadCallbacks) => Promise<OpenEditorAttachmentSnapshot>;
127
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
+ };
128
151
  declare const createAttachmentSnapshot: (attrs?: Partial<OpenEditorAttachmentSnapshot>) => OpenEditorAttachmentSnapshot;
129
152
  type OpenEditorFeatureSet = Readonly<Record<OpenEditorFeatureName, boolean>>;
153
+ /** Controls which schema-supported blocks may be created by an editor surface. */
154
+ type OpenEditorAuthoringCapabilities = {
155
+ enabledBlocks?: readonly string[];
156
+ };
157
+ declare const isOpenEditorBlockEnabled: (blockName: string, capabilities?: OpenEditorAuthoringCapabilities) => boolean;
130
158
  declare const DEFAULT_CALLOUT_EMOJI = "\uD83D\uDCA1";
131
159
  declare const DEFAULT_PAGE_EMOJI = "\uD83D\uDCC4";
132
160
  declare const normalizeEmoji: (value: unknown, fallback: string) => string;
@@ -168,9 +196,6 @@ type OpenEditorCommand = {
168
196
  type: "undo";
169
197
  } | {
170
198
  type: "redo";
171
- } | {
172
- type: "replaceDocument";
173
- document: OpenEditorDocument;
174
199
  } | {
175
200
  type: "setSelection";
176
201
  selection: EditorSelection;
@@ -185,16 +210,15 @@ type OpenEditorEventHandlers = {
185
210
  onCommand?: (command: OpenEditorCommand, transaction: EditorTransaction) => void;
186
211
  };
187
212
  type OpenEditorConfig = OpenEditorEventHandlers & {
188
- document?: OpenEditorDocument;
213
+ initialDocument?: OpenEditorDocument;
189
214
  editable?: boolean;
190
215
  placeholder?: string;
191
216
  enabledBlocks?: readonly string[];
192
217
  theme?: Record<string, string | number>;
193
- features?: Partial<OpenEditorFeatureSet>;
194
218
  };
195
219
  type OpenEditorController = {
196
- getDocument: () => OpenEditorDocument;
197
- setDocument: (document: OpenEditorDocument) => void;
220
+ getContent: () => OpenEditorDocument;
221
+ setContent: (document: OpenEditorDocument) => void;
198
222
  getSelection: () => EditorSelection;
199
223
  execute: (command: OpenEditorCommand) => void;
200
224
  };
@@ -217,7 +241,9 @@ type PlatformSupportResult = {
217
241
  document: OpenEditorDocument;
218
242
  issues: PlatformSupportIssue[];
219
243
  };
244
+ declare const OPENEDITOR_BLOCK_ID_ATTR = "openeditor-id";
220
245
  declare const cloneNode: <T extends ProseMirrorNode>(node: T) => T;
246
+ declare const createBlockId: (prefix?: string) => string;
221
247
  declare const createDocument: (content?: ProseMirrorNode[], meta?: OpenEditorDocumentMeta) => OpenEditorDocument;
222
248
  declare const createEditorState: (document: OpenEditorDocument, selection?: EditorSelection) => SerializedEditorState;
223
249
  declare const toProseMirrorDocument: (document: OpenEditorDocument) => ProseMirrorDocument;
@@ -226,15 +252,20 @@ declare const createTextNode: (text: string, marks?: ProseMirrorMark[]) => Prose
226
252
  declare const textBlock: (type: string, text: string, attrs?: ProseMirrorAttrs) => OpenEditorBlock;
227
253
  declare const createBlockRegistry: (specs: readonly BlockSpec[]) => BlockRegistry;
228
254
  declare const findBlockSpecForNode: (registry: BlockRegistry, node: ProseMirrorNode) => BlockSpec | undefined;
229
- declare const getNodeMeta: (node: ProseMirrorNode) => OpenEditorNodeMeta | undefined;
230
- declare const withNodeMeta: <T extends ProseMirrorNode>(node: T, meta: OpenEditorNodeMeta) => T;
231
255
  declare const getBlockId: (node: ProseMirrorNode) => string | undefined;
232
- declare const createBlockId: (prefix?: string) => string;
256
+ declare const withBlockId: <T extends ProseMirrorNode>(node: T, id: string) => T;
233
257
  declare const ensureBlockIds: (document: OpenEditorDocument, createId?: () => string) => OpenEditorDocument;
258
+ declare const findBlockLocation: (document: OpenEditorDocument, id: string) => OpenEditorBlockLocation | null;
234
259
  declare const normalizeDocument: (document: OpenEditorDocument) => OpenEditorDocument;
235
260
  declare const validateDocument: (document: unknown) => DocumentValidationResult;
236
261
  declare const isOpenEditorDocument: (value: unknown) => value is OpenEditorDocument;
237
- declare const parseOpenEditorDocument: (value: unknown, defaultDocument?: OpenEditorDocument) => OpenEditorDocument;
262
+ declare class OpenEditorDocumentParseError extends Error {
263
+ readonly validation: DocumentValidationResult;
264
+ constructor(validation: DocumentValidationResult);
265
+ }
266
+ declare const parseOpenEditorDocument: (value: unknown) => OpenEditorDocument;
267
+ /** Imports unversioned ProseMirror JSON. Versioned values require strict OpenEditor parsing. */
268
+ declare const importProseMirrorDocument: (value: unknown, meta?: OpenEditorDocumentMeta) => OpenEditorDocument;
238
269
  declare const serializeEditorState: (state: SerializedEditorState) => string;
239
270
  declare const parseEditorState: (value: unknown, defaultState?: SerializedEditorState) => SerializedEditorState;
240
271
  declare const getPlatformDocument: (document: OpenEditorDocument, registry: BlockRegistry, platform: EditorPlatform) => OpenEditorDocument;
@@ -248,4 +279,4 @@ declare const duplicateTopLevelBlock: (document: OpenEditorDocument, index: numb
248
279
  declare const deleteTopLevelBlock: (document: OpenEditorDocument, index: number, emptyBlock?: OpenEditorBlock) => OpenEditorDocument;
249
280
  declare const createTransaction: (before: OpenEditorDocument, after: OpenEditorDocument, command?: EditorCommand) => EditorTransaction;
250
281
 
251
- 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, type OpenEditorAttachmentRuntime, type OpenEditorAttachmentSnapshot, type OpenEditorAttachmentUploadCallbacks, type OpenEditorAttachmentUploadInput, type OpenEditorAttachmentValidationResult, type OpenEditorBlock, type OpenEditorCommand, type OpenEditorConfig, type OpenEditorController, type OpenEditorDocument, type OpenEditorDocumentMeta, type OpenEditorEventHandlers, type OpenEditorFeatureName, type OpenEditorFeatureSet, type OpenEditorMarkName, type OpenEditorNodeMeta, 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, findBlockSpecForNode, fromProseMirrorDocument, getBlockId, getDocumentText, getNodeMeta, getPlatformDocument, getPlatformSupport, isOpenEditorDocument, moveTopLevelBlock, normalizeDocument, normalizeEmoji, parseEditorState, parseOpenEditorDocument, replaceTopLevelNode, replaceTopLevelRange, serializeEditorState, textBlock, toProseMirrorDocument, validateDocument, withNodeMeta };
282
+ 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 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, parseEditorState, parseOpenEditorDocument, replaceTopLevelNode, replaceTopLevelRange, serializeEditorState, textBlock, toProseMirrorDocument, validateDocument, withBlockId };
package/dist/index.js CHANGED
@@ -6,12 +6,11 @@ var createAttachmentSnapshot = (attrs = {}) => ({
6
6
  size: typeof attrs.size === "number" && Number.isFinite(attrs.size) && attrs.size >= 0 ? attrs.size : null,
7
7
  url: typeof attrs.url === "string" ? attrs.url : null
8
8
  });
9
+ var isOpenEditorBlockEnabled = (blockName, capabilities) => capabilities?.enabledBlocks === void 0 || capabilities.enabledBlocks.includes(blockName);
9
10
  var DEFAULT_CALLOUT_EMOJI = "\u{1F4A1}";
10
11
  var DEFAULT_PAGE_EMOJI = "\u{1F4C4}";
11
12
  var normalizeEmoji = (value, fallback) => typeof value === "string" && value.trim() ? value.trim() : fallback;
12
- var OPENEDITOR_ATTR = "openeditor";
13
- var OPENEDITOR_ID_ATTR = "data-openeditor-id";
14
- var OPENEDITOR_BLOCK_ATTR = "data-openeditor-block";
13
+ var OPENEDITOR_BLOCK_ID_ATTR = "openeditor-id";
15
14
  var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
16
15
  var normalizeMeta = (meta) => meta && Object.keys(meta).length ? { ...meta } : void 0;
17
16
  var cloneAttrs = (attrs) => attrs ? { ...attrs } : void 0;
@@ -19,18 +18,43 @@ var cloneMark = (mark) => ({
19
18
  type: mark.type,
20
19
  ...mark.attrs ? { attrs: cloneAttrs(mark.attrs) } : {}
21
20
  });
22
- var cloneNode = (node) => ({
21
+ var cloneNodeShallow = (node) => ({
23
22
  ...node,
24
23
  ...node.attrs ? { attrs: cloneAttrs(node.attrs) } : {},
25
- ...node.marks ? { marks: node.marks.map(cloneMark) } : {},
26
- ...node.content ? { content: node.content.map(cloneNode) } : {}
24
+ ...node.marks ? { marks: node.marks.map(cloneMark) } : {}
27
25
  });
28
- var createDocument = (content = [], meta) => ({
29
- type: "doc",
30
- version: 1,
31
- content: content.map(cloneNode),
32
- ...normalizeMeta(meta) ? { meta: normalizeMeta(meta) } : {}
26
+ var cloneNode = (node) => ({
27
+ ...cloneNodeShallow(node),
28
+ ...node.content ? { content: node.content.map(cloneNode) } : {}
33
29
  });
30
+ var createBlockId = (prefix = "oe") => {
31
+ const random = typeof globalThis.crypto?.randomUUID === "function" ? globalThis.crypto.randomUUID() : Math.random().toString(36).slice(2);
32
+ return `${prefix}_${random.replaceAll("-", "").slice(0, 24)}`;
33
+ };
34
+ var cloneNodeWithIds = (node, createId, seenIds) => {
35
+ if (node.type === "text") return cloneNode(node);
36
+ const cloned = cloneNodeShallow(node);
37
+ const existingId = getBlockId(cloned);
38
+ let id = existingId && !seenIds.has(existingId) ? existingId : createId();
39
+ while (!id.trim() || seenIds.has(id)) id = createId();
40
+ seenIds.add(id);
41
+ const withId = withBlockId(cloned, id);
42
+ return {
43
+ ...withId,
44
+ ...node.content ? { content: node.content.map((child) => cloneNodeWithIds(child, createId, seenIds)) } : {}
45
+ };
46
+ };
47
+ var createDocumentWithIds = (content = [], meta, createId = createBlockId) => {
48
+ const normalizedMeta = normalizeMeta(meta);
49
+ const seenIds = /* @__PURE__ */ new Set();
50
+ return {
51
+ type: "doc",
52
+ version: 1,
53
+ content: content.map((node) => cloneNodeWithIds(node, createId, seenIds)),
54
+ ...normalizedMeta ? { meta: normalizedMeta } : {}
55
+ };
56
+ };
57
+ var createDocument = (content = [], meta) => createDocumentWithIds(content, meta);
34
58
  var createEditorState = (document, selection = { type: "none" }) => ({
35
59
  document: normalizeDocument(document),
36
60
  selection
@@ -80,50 +104,35 @@ var findBlockSpecForNode = (registry, node) => {
80
104
  }
81
105
  return void 0;
82
106
  };
83
- var getNodeMeta = (node) => {
84
- const attrs = node.attrs;
85
- const nested = attrs?.[OPENEDITOR_ATTR];
86
- const id = attrs?.[OPENEDITOR_ID_ATTR];
87
- const block = attrs?.[OPENEDITOR_BLOCK_ATTR];
88
- if (isRecord(nested)) {
89
- return {
90
- ...nested,
91
- ...typeof id === "string" ? { id } : {},
92
- ...typeof block === "string" ? { block } : {}
93
- };
94
- }
95
- if (typeof id === "string" || typeof block === "string") {
96
- return {
97
- ...typeof id === "string" ? { id } : {},
98
- ...typeof block === "string" ? { block } : {}
99
- };
100
- }
101
- return void 0;
107
+ var getBlockId = (node) => {
108
+ const value = node.attrs?.[OPENEDITOR_BLOCK_ID_ATTR];
109
+ return typeof value === "string" && value.trim() ? value : void 0;
102
110
  };
103
- var withNodeMeta = (node, meta) => {
104
- const attrs = cloneAttrs(node.attrs) ?? {};
105
- const previous = getNodeMeta(node);
106
- const nextMeta = { ...previous, ...meta };
107
- if (nextMeta.id) {
108
- attrs[OPENEDITOR_ID_ATTR] = nextMeta.id;
109
- }
110
- if (nextMeta.block) {
111
- attrs[OPENEDITOR_BLOCK_ATTR] = nextMeta.block;
111
+ var withBlockId = (node, id) => ({
112
+ ...node,
113
+ attrs: {
114
+ ...cloneAttrs(node.attrs),
115
+ [OPENEDITOR_BLOCK_ID_ATTR]: id
112
116
  }
113
- attrs[OPENEDITOR_ATTR] = nextMeta;
114
- return { ...node, attrs };
115
- };
116
- var getBlockId = (node) => getNodeMeta(node)?.id;
117
- var createBlockId = (prefix = "oe") => {
118
- const random = typeof globalThis.crypto?.randomUUID === "function" ? globalThis.crypto.randomUUID() : Math.random().toString(36).slice(2);
119
- return `${prefix}_${random.replaceAll("-", "").slice(0, 24)}`;
117
+ });
118
+ var ensureBlockIds = (document, createId = createBlockId) => createDocumentWithIds(document.content, document.meta, createId);
119
+ var findBlockLocation = (document, id) => {
120
+ const visit = (nodes, parentId, path) => {
121
+ for (let index = 0; index < nodes.length; index += 1) {
122
+ const node = nodes[index];
123
+ if (!node) continue;
124
+ const nodeId = getBlockId(node);
125
+ const nodePath = [...path, index];
126
+ if (nodeId === id) {
127
+ return { id, nodeType: node.type, parentId, index, path: nodePath };
128
+ }
129
+ const nested = node.content?.length ? visit(node.content, nodeId ?? parentId, nodePath) : null;
130
+ if (nested) return nested;
131
+ }
132
+ return null;
133
+ };
134
+ return visit(document.content, null, []);
120
135
  };
121
- var ensureBlockIds = (document, createId = createBlockId) => createDocument(
122
- document.content.map(
123
- (node) => getBlockId(node) ? node : withNodeMeta(node, { id: createId() })
124
- ),
125
- document.meta
126
- );
127
136
  var normalizeNode = (node) => {
128
137
  if (node.type === "heading") {
129
138
  const level = typeof node.attrs?.level === "number" ? node.attrs.level : 2;
@@ -219,14 +228,28 @@ var validateDocument = (document) => {
219
228
  };
220
229
  };
221
230
  var isOpenEditorDocument = (value) => validateDocument(value).valid;
222
- var parseOpenEditorDocument = (value, defaultDocument = createDocument()) => {
223
- if (isOpenEditorDocument(value)) {
224
- return normalizeDocument(value);
231
+ var OpenEditorDocumentParseError = class extends Error {
232
+ validation;
233
+ constructor(validation) {
234
+ super(validation.issues.map((issue) => `${issue.path}: ${issue.message}`).join("\n"));
235
+ this.name = "OpenEditorDocumentParseError";
236
+ this.validation = validation;
225
237
  }
226
- if (isRecord(value) && value.type === "doc" && Array.isArray(value.content)) {
227
- return fromProseMirrorDocument(value, defaultDocument.meta);
238
+ };
239
+ var parseOpenEditorDocument = (value) => {
240
+ const validation = validateDocument(value);
241
+ if (!validation.valid) throw new OpenEditorDocumentParseError(validation);
242
+ return normalizeDocument(value);
243
+ };
244
+ var importProseMirrorDocument = (value, meta) => {
245
+ if (isRecord(value) && "version" in value) {
246
+ throw new Error("Versioned documents must be parsed with parseOpenEditorDocument().");
228
247
  }
229
- return defaultDocument;
248
+ const validation = validateDocument(
249
+ isRecord(value) ? { ...value, version: 1 } : value
250
+ );
251
+ if (!validation.valid) throw new OpenEditorDocumentParseError(validation);
252
+ return fromProseMirrorDocument(value, meta);
230
253
  };
231
254
  var serializeEditorState = (state) => JSON.stringify({
232
255
  document: normalizeDocument(state.document),
@@ -242,10 +265,14 @@ var parseEditorState = (value, defaultState = createEditorState(createDocument()
242
265
  if (!isRecord(parsed)) {
243
266
  return defaultState;
244
267
  }
245
- return {
246
- document: parseOpenEditorDocument(parsed.document, defaultState.document),
247
- selection: isRecord(parsed.selection) ? parsed.selection : defaultState.selection
248
- };
268
+ try {
269
+ return {
270
+ document: parseOpenEditorDocument(parsed.document),
271
+ selection: isRecord(parsed.selection) ? parsed.selection : defaultState.selection
272
+ };
273
+ } catch {
274
+ return defaultState;
275
+ }
249
276
  };
250
277
  var getPlatformDocument = (document, registry, platform) => getPlatformSupport(document, registry, platform).document;
251
278
  var getPlatformSupport = (document, registry, platform) => {
@@ -294,9 +321,6 @@ var applyCommand = (document, registry, command) => {
294
321
  if (command.type === "setContent") {
295
322
  return normalizeDocument(command.document);
296
323
  }
297
- if (command.type === "replaceDocument") {
298
- return normalizeDocument(command.document);
299
- }
300
324
  if (command.type === "setSelection") {
301
325
  return document;
302
326
  }
@@ -374,6 +398,6 @@ var createTransaction = (before, after, command) => ({
374
398
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
375
399
  });
376
400
 
377
- export { DEFAULT_CALLOUT_EMOJI, DEFAULT_PAGE_EMOJI, applyCommand, cloneNode, createAttachmentSnapshot, createBlockId, createBlockRegistry, createDocument, createEditorState, createTextNode, createTransaction, deleteTopLevelBlock, duplicateTopLevelBlock, ensureBlockIds, findBlockSpecForNode, fromProseMirrorDocument, getBlockId, getDocumentText, getNodeMeta, getPlatformDocument, getPlatformSupport, isOpenEditorDocument, moveTopLevelBlock, normalizeDocument, normalizeEmoji, parseEditorState, parseOpenEditorDocument, replaceTopLevelNode, replaceTopLevelRange, serializeEditorState, textBlock, toProseMirrorDocument, validateDocument, withNodeMeta };
401
+ 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, parseEditorState, parseOpenEditorDocument, replaceTopLevelNode, replaceTopLevelRange, serializeEditorState, textBlock, toProseMirrorDocument, validateDocument, withBlockId };
378
402
  //# sourceMappingURL=index.js.map
379
403
  //# 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 OpenEditorNodeMeta = {\n id?: string;\n block?: string;\n custom?: Record<string, unknown>;\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 \"data-openeditor-id\"?: string;\n \"data-openeditor-block\"?: string;\n openeditor?: OpenEditorNodeMeta;\n };\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\nconst OPENEDITOR_ATTR = \"openeditor\";\nconst OPENEDITOR_ID_ATTR = \"data-openeditor-id\";\nconst OPENEDITOR_BLOCK_ATTR = \"data-openeditor-block\";\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\nexport const cloneNode = <T extends ProseMirrorNode>(node: T): T => ({\n ...node,\n ...(node.attrs ? { attrs: cloneAttrs(node.attrs) } : {}),\n ...(node.marks ? { marks: node.marks.map(cloneMark) } : {}),\n ...(node.content ? { content: node.content.map(cloneNode) } : {}),\n});\n\nexport const createDocument = (\n content: ProseMirrorNode[] = [],\n meta?: OpenEditorDocumentMeta,\n): OpenEditorDocument => ({\n type: \"doc\",\n version: 1,\n content: content.map(cloneNode) as OpenEditorBlock[],\n ...(normalizeMeta(meta) ? { meta: normalizeMeta(meta) } : {}),\n});\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 getNodeMeta = (node: ProseMirrorNode): OpenEditorNodeMeta | undefined => {\n const attrs = node.attrs;\n const nested = attrs?.[OPENEDITOR_ATTR];\n const id = attrs?.[OPENEDITOR_ID_ATTR];\n const block = attrs?.[OPENEDITOR_BLOCK_ATTR];\n\n if (isRecord(nested)) {\n return {\n ...nested,\n ...(typeof id === \"string\" ? { id } : {}),\n ...(typeof block === \"string\" ? { block } : {}),\n } as OpenEditorNodeMeta;\n }\n\n if (typeof id === \"string\" || typeof block === \"string\") {\n return {\n ...(typeof id === \"string\" ? { id } : {}),\n ...(typeof block === \"string\" ? { block } : {}),\n };\n }\n\n return undefined;\n};\n\nexport const withNodeMeta = <T extends ProseMirrorNode>(\n node: T,\n meta: OpenEditorNodeMeta,\n): T => {\n const attrs = cloneAttrs(node.attrs) ?? {};\n const previous = getNodeMeta(node);\n const nextMeta = { ...previous, ...meta };\n\n if (nextMeta.id) {\n attrs[OPENEDITOR_ID_ATTR] = nextMeta.id;\n }\n\n if (nextMeta.block) {\n attrs[OPENEDITOR_BLOCK_ATTR] = nextMeta.block;\n }\n\n attrs[OPENEDITOR_ATTR] = nextMeta;\n return { ...node, attrs } as T;\n};\n\nexport const getBlockId = (node: ProseMirrorNode): string | undefined =>\n getNodeMeta(node)?.id;\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\nexport const ensureBlockIds = (\n document: OpenEditorDocument,\n createId: () => string = createBlockId,\n): OpenEditorDocument =>\n createDocument(\n document.content.map((node) =>\n getBlockId(node) ? node : withNodeMeta(node, { id: createId() }),\n ),\n document.meta,\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\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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openeditor/core",
3
- "version": "0.0.26",
3
+ "version": "0.0.28",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "repository": {