svedit 0.11.1 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/README.md +230 -64
  2. package/dist/Command.svelte.d.ts +21 -4
  3. package/dist/Command.svelte.d.ts.map +1 -1
  4. package/dist/Command.svelte.js +85 -27
  5. package/dist/Node.svelte +29 -1
  6. package/dist/Node.svelte.d.ts.map +1 -1
  7. package/dist/NodeArrayProperty.svelte +119 -12
  8. package/dist/NodeArrayProperty.svelte.d.ts.map +1 -1
  9. package/dist/NodeGap.svelte +48 -6
  10. package/dist/NodeGap.svelte.d.ts.map +1 -1
  11. package/dist/Session.svelte.d.ts +31 -14
  12. package/dist/Session.svelte.d.ts.map +1 -1
  13. package/dist/Session.svelte.js +155 -77
  14. package/dist/Svedit.svelte +110 -89
  15. package/dist/Svedit.svelte.d.ts.map +1 -1
  16. package/dist/{AnnotatedTextProperty.svelte → TextProperty.svelte} +45 -44
  17. package/dist/TextProperty.svelte.d.ts +7 -0
  18. package/dist/TextProperty.svelte.d.ts.map +1 -0
  19. package/dist/Transaction.svelte.d.ts +78 -40
  20. package/dist/Transaction.svelte.d.ts.map +1 -1
  21. package/dist/Transaction.svelte.js +412 -234
  22. package/dist/doc_utils.d.ts +96 -21
  23. package/dist/doc_utils.d.ts.map +1 -1
  24. package/dist/doc_utils.js +440 -168
  25. package/dist/index.d.ts +1 -1
  26. package/dist/index.js +1 -1
  27. package/dist/node_visibility.svelte.d.ts +30 -4
  28. package/dist/node_visibility.svelte.d.ts.map +1 -1
  29. package/dist/node_visibility.svelte.js +327 -363
  30. package/dist/paste_utils.d.ts +3 -2
  31. package/dist/paste_utils.d.ts.map +1 -1
  32. package/dist/paste_utils.js +16 -13
  33. package/dist/transforms.svelte.d.ts.map +1 -1
  34. package/dist/transforms.svelte.js +5 -6
  35. package/dist/types.d.ts +112 -42
  36. package/dist/utils.d.ts +75 -12
  37. package/dist/utils.d.ts.map +1 -1
  38. package/dist/utils.js +292 -78
  39. package/package.json +4 -1
  40. package/src/lib/Command.svelte.js +85 -27
  41. package/src/lib/Node.svelte +29 -1
  42. package/src/lib/NodeArrayProperty.svelte +119 -12
  43. package/src/lib/NodeGap.svelte +48 -6
  44. package/src/lib/Session.svelte.js +155 -77
  45. package/src/lib/Svedit.svelte +110 -89
  46. package/src/lib/{AnnotatedTextProperty.svelte → TextProperty.svelte} +45 -44
  47. package/src/lib/Transaction.svelte.js +412 -234
  48. package/src/lib/doc_utils.js +440 -168
  49. package/src/lib/index.js +1 -1
  50. package/src/lib/node_visibility.svelte.js +327 -363
  51. package/src/lib/paste_utils.js +16 -13
  52. package/src/lib/transforms.svelte.js +5 -6
  53. package/src/lib/types.d.ts +112 -42
  54. package/src/lib/utils.js +292 -78
  55. package/dist/AnnotatedTextProperty.svelte.d.ts +0 -7
  56. package/dist/AnnotatedTextProperty.svelte.d.ts.map +0 -1
@@ -14,10 +14,11 @@ export function get_text_property_name(node_type: string | null | undefined, sch
14
14
  /**
15
15
  * @param {any} node
16
16
  * @param {DocumentSchema} schema
17
- * @returns {{ text: string, annotations: any[] } | null}
17
+ * @returns {{ content: string, marks: any[], annotations: any[] } | null}
18
18
  */
19
19
  export function get_text_content(node: any, schema: DocumentSchema): {
20
- text: string;
20
+ content: string;
21
+ marks: any[];
21
22
  annotations: any[];
22
23
  } | null;
23
24
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"paste_utils.d.ts","sourceRoot":"","sources":["../src/lib/paste_utils.js"],"names":[],"mappings":"AAAA;;GAEG;AAEH,uDAEC;AAED,wDAkCC;AAED,kEAKC;AAED,oFAEC;AAED;;;;GAIG;AACH,kDAJW,MAAM,GAAG,IAAI,GAAG,SAAS,UACzB,cAAc,GACZ,MAAM,GAAG,IAAI,CAYzB;AAED;;;;GAIG;AACH,uCAJW,GAAG,UACH,cAAc,GACZ;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,GAAG,EAAE,CAAA;CAAE,GAAG,IAAI,CAoBvD;AAED;;;;GAIG;AACH,gDAJW,GAAG,UACH,cAAc,GACZ,OAAO,CAMnB;AAED;;;;GAIG;AACH,sEAJW,GAAG,UACH,cAAc,GACZ,MAAM,GAAG,IAAI,CAmBzB;AAED;;;;;GAKG;AACH,qEALW,MAAM,EAAE,aACR,MAAM,GAAG,IAAI,GAAG,SAAS,UACzB,cAAc,GACZ;IAAE,UAAU,EAAE,MAAM,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;CAAE,GAAG,IAAI,CA8BvE;oCArKkC,cAAc"}
1
+ {"version":3,"file":"paste_utils.d.ts","sourceRoot":"","sources":["../src/lib/paste_utils.js"],"names":[],"mappings":"AAAA;;GAEG;AAEH,uDAEC;AAED,wDAkCC;AAED,kEAKC;AAED,oFAEC;AAED;;;;GAIG;AACH,kDAJW,MAAM,GAAG,IAAI,GAAG,SAAS,UACzB,cAAc,GACZ,MAAM,GAAG,IAAI,CAYzB;AAED;;;;GAIG;AACH,uCAJW,GAAG,UACH,cAAc,GACZ;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,GAAG,EAAE,CAAC;IAAC,WAAW,EAAE,GAAG,EAAE,CAAA;CAAE,GAAG,IAAI,CAqBxE;AAED;;;;GAIG;AACH,gDAJW,GAAG,UACH,cAAc,GACZ,OAAO,CAMnB;AAED;;;;GAIG;AACH,sEAJW,GAAG,UACH,cAAc,GACZ,MAAM,GAAG,IAAI,CAoBzB;AAED;;;;;GAKG;AACH,qEALW,MAAM,EAAE,aACR,MAAM,GAAG,IAAI,GAAG,SAAS,UACzB,cAAc,GACZ;IAAE,UAAU,EAAE,MAAM,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;CAAE,GAAG,IAAI,CA+BvE;oCAxKkC,cAAc"}
@@ -62,10 +62,10 @@ export function get_text_property_name(node_type, schema) {
62
62
  if (!node_type) return null;
63
63
  const node_schema = schema[node_type];
64
64
  if (!node_schema || node_schema.kind !== 'text') return null;
65
- if (node_schema.properties?.content?.type === 'annotated_text') return 'content';
65
+ if (node_schema.properties?.content?.type === 'text') return 'content';
66
66
  return (
67
67
  Object.entries(node_schema.properties).find(([, property_definition]) => {
68
- return property_definition.type === 'annotated_text';
68
+ return property_definition.type === 'text';
69
69
  })?.[0] || null
70
70
  );
71
71
  }
@@ -73,22 +73,23 @@ export function get_text_property_name(node_type, schema) {
73
73
  /**
74
74
  * @param {any} node
75
75
  * @param {DocumentSchema} schema
76
- * @returns {{ text: string, annotations: any[] } | null}
76
+ * @returns {{ content: string, marks: any[], annotations: any[] } | null}
77
77
  */
78
78
  export function get_text_content(node, schema) {
79
79
  if (!node || typeof node !== 'object') return null;
80
80
 
81
+ const is_text_value = (value) =>
82
+ value &&
83
+ typeof value.content === 'string' &&
84
+ Array.isArray(value.marks) &&
85
+ Array.isArray(value.annotations);
86
+
81
87
  const text_property_name = get_text_property_name(node.type, schema);
82
- if (
83
- text_property_name &&
84
- node[text_property_name] &&
85
- typeof node[text_property_name].text === 'string' &&
86
- Array.isArray(node[text_property_name].annotations)
87
- ) {
88
+ if (text_property_name && is_text_value(node[text_property_name])) {
88
89
  return node[text_property_name];
89
90
  }
90
91
 
91
- if (node.content && typeof node.content.text === 'string' && Array.isArray(node.content.annotations)) {
92
+ if (is_text_value(node.content)) {
92
93
  return node.content;
93
94
  }
94
95
 
@@ -125,8 +126,9 @@ export function get_default_text_node(node_array_property_definition, schema) {
125
126
  }
126
127
 
127
128
  return (
128
- node_array_property_definition.node_types.find((node_type) => schema[node_type]?.kind === 'text') ||
129
- null
129
+ node_array_property_definition.node_types.find(
130
+ (node_type) => schema[node_type]?.kind === 'text'
131
+ ) || null
130
132
  );
131
133
  }
132
134
 
@@ -156,7 +158,8 @@ export function create_plain_text_nodes_payload(paragraph_fragments, node_type,
156
158
  id: node_id,
157
159
  type: node_type,
158
160
  [text_property_name]: {
159
- text: fragment,
161
+ content: fragment,
162
+ marks: [],
160
163
  annotations: []
161
164
  }
162
165
  };
@@ -1 +1 @@
1
- {"version":3,"file":"transforms.svelte.d.ts","sourceRoot":"","sources":["../src/lib/transforms.svelte.js"],"names":[],"mappings":"AAGA;;;;;;GAMG;AACH,mCAJW,MAAM,2BAEN,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,QAM7B;AAED,kDAqDC;AAED,iDAoEC;AAED,sDAuBC"}
1
+ {"version":3,"file":"transforms.svelte.d.ts","sourceRoot":"","sources":["../src/lib/transforms.svelte.js"],"names":[],"mappings":"AAGA;;;;;;GAMG;AACH,mCAJW,MAAM,2BAEN,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,QAM7B;AAED,kDAoDC;AAED,iDAoEC;AAED,sDAuBC"}
@@ -1,4 +1,4 @@
1
- import { split_annotated_text, join_annotated_text, get_char_length } from './utils.js';
1
+ import { split_text, join_text, get_char_length } from './utils.js';
2
2
  import { get_default_node_type } from './doc_utils.js';
3
3
 
4
4
  /**
@@ -32,7 +32,6 @@ export function break_text_node(tr) {
32
32
  // Get the node that owns the node_array property (e.g. a page.body)
33
33
  const node_array_node = tr.get(selection.path.slice(0, -3));
34
34
 
35
-
36
35
  // Delete selection unless collapsed
37
36
  if (selection.anchor_offset !== selection.focus_offset) {
38
37
  tr.delete_selection();
@@ -40,7 +39,7 @@ export function break_text_node(tr) {
40
39
 
41
40
  const split_at_position = tr.selection.anchor_offset;
42
41
  const content = tr.get(selection.path);
43
- const [left_text, right_text] = split_annotated_text(content, split_at_position);
42
+ const [left_text, right_text] = split_text(content, split_at_position);
44
43
 
45
44
  tr.set([node.id, 'content'], left_text);
46
45
 
@@ -93,7 +92,7 @@ export function join_text_node(tr) {
93
92
  }
94
93
 
95
94
  // Special behavior: if we can't join and current node is empty, delete it
96
- if (!can_join && node.content.text === '') {
95
+ if (!can_join && node.content.content === '') {
97
96
  tr.set_selection({
98
97
  type: 'node',
99
98
  path: tr.selection.path.slice(0, -2),
@@ -111,10 +110,10 @@ export function join_text_node(tr) {
111
110
 
112
111
  // Normal joining logic - both nodes are text nodes
113
112
  const previous_text_path = [...tr.selection.path.slice(0, -2), node_index - 1];
114
- const joined_text = join_annotated_text(predecessor_node.content, node.content);
113
+ const joined_text = join_text(predecessor_node.content, node.content);
115
114
 
116
115
  // Calculate caret position based on original predecessor content length
117
- const caret_position = get_char_length(predecessor_node.content.text);
116
+ const caret_position = get_char_length(predecessor_node.content.content);
118
117
 
119
118
  // First set the joined content on the predecessor node (preserves annotations)
120
119
  tr.set([predecessor_node.id, 'content'], joined_text);
package/dist/types.d.ts CHANGED
@@ -81,7 +81,7 @@ export type ArrayType = 'string_array' | 'number_array' | 'boolean_array' | 'int
81
81
  /**
82
82
  * Special types for rich content.
83
83
  */
84
- export type RichType = 'annotated_text';
84
+ export type RichType = 'text';
85
85
 
86
86
  /**
87
87
  * Node reference types for linking to other nodes.
@@ -112,7 +112,7 @@ export type PropertyType = PrimitiveType | ReferenceType;
112
112
  // | 'number_array'
113
113
  // | 'boolean_array'
114
114
  // | 'integer_array'
115
- // | 'annotated_text'
115
+ // | 'text'
116
116
  // | 'node'
117
117
  // | 'node_array';
118
118
  //
@@ -134,7 +134,7 @@ export type PropertyType = PrimitiveType | ReferenceType;
134
134
  // ? Array<boolean>
135
135
  // : T extends 'integer_array'
136
136
  // ? Array<number>
137
- // : T extends 'annotated_text'
137
+ // : T extends 'text'
138
138
  // ? AnnotatedText
139
139
  // : T extends 'node'
140
140
  // ? string
@@ -147,11 +147,12 @@ export type PropertyType = PrimitiveType | ReferenceType;
147
147
  // };
148
148
 
149
149
  /**
150
- * A property that stores an annotated text with required allow_newlines setting.
150
+ * A property that stores text with optional marks and annotations and required allow_newlines setting.
151
151
  */
152
- export type AnnotatedTextProperty = {
153
- type: 'annotated_text';
154
- node_types?: string[];
152
+ export type TextProperty = {
153
+ type: 'text';
154
+ mark_types?: string[];
155
+ annotation_types?: string[];
155
156
  allow_newlines: boolean;
156
157
  };
157
158
 
@@ -228,7 +229,7 @@ export type IntegerArrayProperty = {
228
229
  };
229
230
 
230
231
  /**
231
- * A property that stores a primitive value (excluding annotated_text).
232
+ * A property that stores a primitive value (excluding text).
232
233
  */
233
234
  export type PrimitiveProperty =
234
235
  | StringProperty
@@ -256,6 +257,8 @@ export type NodeProperty = {
256
257
  export type NodeArrayProperty = {
257
258
  type: 'node_array';
258
259
  node_types: string[];
260
+ mark_types?: string[];
261
+ annotation_types?: string[];
259
262
  default_node_type?: string;
260
263
  };
261
264
 
@@ -263,29 +266,26 @@ export type NodeArrayProperty = {
263
266
  * Union type for all possible property definitions.
264
267
  */
265
268
  export type PropertyDefinition =
266
- | PrimitiveProperty
267
- | AnnotatedTextProperty
268
- | NodeProperty
269
- | NodeArrayProperty;
269
+ PrimitiveProperty | TextProperty | NodeProperty | NodeArrayProperty;
270
270
 
271
271
  /**
272
272
  * Node kind values for different types of content nodes
273
273
  */
274
- export type NodeKind = 'document' | 'block' | 'text' | 'annotation';
274
+ export type NodeKind = 'document' | 'block' | 'text' | 'mark' | 'annotation';
275
275
 
276
276
  /**
277
- * Schema for text nodes - must have a content property of type annotated_text.
278
- * Use define_document_schema to also check that content is the only annotated_text property.
277
+ * Schema for text nodes - must have a content property of type text.
278
+ * Use define_document_schema to also check that content is the only text property.
279
279
  */
280
280
  export type TextNodeSchema = {
281
281
  kind: 'text';
282
282
  properties: {
283
- content: AnnotatedTextProperty;
283
+ content: TextProperty;
284
284
  } & Record<string, PropertyDefinition>;
285
285
  };
286
286
 
287
- export type AnnotatedTextPropertyNames<Properties> = {
288
- [PropertyName in keyof Properties]: Properties[PropertyName] extends { type: 'annotated_text' }
287
+ export type TextPropertyNames<Properties> = {
288
+ [PropertyName in keyof Properties]: Properties[PropertyName] extends { type: 'text' }
289
289
  ? PropertyName
290
290
  : never;
291
291
  }[keyof Properties];
@@ -294,13 +294,11 @@ export type TextNodeSchemaError<Message extends string> = {
294
294
  [SchemaError in `Svedit schema error: ${Message}`]: never;
295
295
  };
296
296
 
297
- export type TextNodeMissingContentError = TextNodeSchemaError<
298
- 'Text node schemas must define a "content" property of type annotated_text.'
299
- >;
297
+ export type TextNodeMissingContentError =
298
+ TextNodeSchemaError<'Text node schemas must define a "content" property of type text.'>;
300
299
 
301
- export type TextNodeExtraAnnotatedTextError<ExtraProperty extends string> = TextNodeSchemaError<
302
- `Text node schemas must not define annotated_text property "${ExtraProperty}". Use "content" as the only annotated_text property.`
303
- >;
300
+ export type TextNodeExtraTextPropertyError<ExtraProperty extends string> =
301
+ TextNodeSchemaError<`Text node schemas must not define text property "${ExtraProperty}". Use "content" as the only text property.`>;
304
302
 
305
303
  export type ValidateTextNodeSchema<Schema> = Schema extends {
306
304
  kind: 'text';
@@ -308,11 +306,11 @@ export type ValidateTextNodeSchema<Schema> = Schema extends {
308
306
  }
309
307
  ? string extends keyof Properties
310
308
  ? Schema
311
- : Properties extends { content: AnnotatedTextProperty }
312
- ? Exclude<AnnotatedTextPropertyNames<Properties>, 'content'> extends infer ExtraProperties
309
+ : Properties extends { content: TextProperty }
310
+ ? Exclude<TextPropertyNames<Properties>, 'content'> extends infer ExtraProperties
313
311
  ? [ExtraProperties] extends [never]
314
312
  ? Schema
315
- : TextNodeExtraAnnotatedTextError<Extract<ExtraProperties, string>>
313
+ : TextNodeExtraTextPropertyError<Extract<ExtraProperties, string>>
316
314
  : never
317
315
  : TextNodeMissingContentError
318
316
  : Schema;
@@ -325,7 +323,7 @@ export type ValidateDocumentSchema<Schema extends Record<string, NodeSchema>> =
325
323
  * Schema for non-text nodes
326
324
  */
327
325
  export type NonTextNodeSchema = {
328
- kind: 'document' | 'block' | 'annotation';
326
+ kind: 'document' | 'block' | 'mark' | 'annotation';
329
327
  properties: Record<string, PropertyDefinition>;
330
328
  };
331
329
 
@@ -363,9 +361,9 @@ export type Document = {
363
361
  };
364
362
 
365
363
  /**
366
- * Props for the AnnotatedTextProperty component
364
+ * Props for the TextProperty component
367
365
  */
368
- export type AnnotatedTextPropertyProps = {
366
+ export type TextPropertyProps = {
369
367
  /** The full path to the property */
370
368
  path: DocumentPath;
371
369
  /** Optional custom HTML tag */
@@ -414,6 +412,10 @@ export type NodeArrayPropertyProps = {
414
412
  export type NodeProps = {
415
413
  /** The full path to the node */
416
414
  path: DocumentPath;
415
+ /** The single node-array mark wrapping this node, if any */
416
+ mark?: NodeArrayAttachmentContext | null;
417
+ /** All node-array annotations covering this node */
418
+ annotations?: Array<NodeArrayAttachmentContext>;
417
419
  /** Optional custom HTML tag */
418
420
  tag?: string;
419
421
  /** Optional string of CSS classes */
@@ -443,22 +445,61 @@ export type SveditProps = {
443
445
  };
444
446
 
445
447
  /**
446
- * Represents an annotation in an annotated string
448
+ * A range with an attached payload node, used for both marks and annotations.
447
449
  */
448
- export type Annotation = {
450
+ export type Attachment = {
449
451
  start_offset: number;
450
452
  end_offset: number;
451
453
  node_id: NodeId;
452
454
  };
453
455
 
454
456
  /**
455
- * Represents an annotated text with text and annotations
457
+ * A content-level range (e.g. strong, emphasis, link, section).
458
+ * Marks are mutually exclusive within a property and render in-place.
459
+ */
460
+ export type Mark = Attachment;
461
+
462
+ /**
463
+ * A metadata/overlay range (e.g. comment, marker).
464
+ * Annotations may overlap and are data-only.
465
+ */
466
+ export type Annotation = Attachment;
467
+
468
+ /**
469
+ * Represents text content with marks and annotations.
456
470
  */
457
471
  export type AnnotatedText = {
458
- text: string;
472
+ content: string;
473
+ marks: Array<Mark>;
459
474
  annotations: Array<Annotation>;
460
475
  };
461
476
 
477
+ /**
478
+ * Represents an annotated node array with nodes, marks and annotations
479
+ */
480
+ export type AnnotatedNodeArray = {
481
+ nodes: Array<NodeId>;
482
+ marks: Array<Mark>;
483
+ annotations: Array<Annotation>;
484
+ };
485
+
486
+ /**
487
+ * Attachment context passed to a node rendered inside an annotated node array.
488
+ * It is the flattened mark or annotation attachment, enriched with the resolved
489
+ * payload node, its index in the parent attachment array, and this child node's
490
+ * position in the attachment range.
491
+ */
492
+ export type NodeArrayAttachmentContext = {
493
+ start_offset: number;
494
+ end_offset: number;
495
+ node_id: NodeId;
496
+ index: number;
497
+ node: DocumentNode;
498
+ is_start: boolean;
499
+ is_middle: boolean;
500
+ is_end: boolean;
501
+ };
502
+
462
503
  /**
463
504
  * Represents a selection highlight fragment for non-annotated text selections
464
505
  */
@@ -468,19 +509,48 @@ export type SelectionHighlightFragment = {
468
509
  };
469
510
 
470
511
  /**
471
- * Represents an annotation fragment in annotated text content
512
+ * Represents a mark fragment in annotated text content
472
513
  */
473
- export type AnnotationFragment = {
474
- type: 'annotation';
475
- /** NodeId that has annotation type and details */
514
+ export type MarkFragment = {
515
+ type: 'mark';
516
+ /** NodeId that has mark type and details */
476
517
  node: any;
477
- /** The text content of the annotation */
518
+ /** The text content of the mark */
478
519
  content: string;
479
- /** Index of the annotation in the original array */
480
- annotation_index: number;
520
+ /** Index of the mark in the original array */
521
+ mark_index: number;
481
522
  };
482
523
 
483
524
  /**
484
525
  * Represents a fragment of annotated text content
485
526
  */
486
- export type Fragment = string | AnnotationFragment | SelectionHighlightFragment;
527
+ export type Fragment = string | MarkFragment | SelectionHighlightFragment;
528
+
529
+ /**
530
+ * Represents a node array fragment for plain nodes
531
+ */
532
+ export type NodeArrayPlainFragment = {
533
+ type: 'nodes';
534
+ nodes: Array<NodeId>;
535
+ start_index: number;
536
+ };
537
+
538
+ /**
539
+ * Represents a mark fragment in node array content
540
+ */
541
+ export type NodeArrayMarkFragment = {
542
+ type: 'mark';
543
+ /** NodeId that has mark type and details */
544
+ node: any;
545
+ /** The nodes wrapped by the mark */
546
+ nodes: Array<NodeId>;
547
+ /** Start index in the original nodes array */
548
+ start_index: number;
549
+ /** Index of the mark in the original array */
550
+ mark_index: number;
551
+ };
552
+
553
+ /**
554
+ * Represents a fragment of annotated node array content
555
+ */
556
+ export type NodeArrayFragment = NodeArrayPlainFragment | NodeArrayMarkFragment;
package/dist/utils.d.ts CHANGED
@@ -101,37 +101,38 @@ export function char_to_utf16_offset(str: string, char_offset: number): number;
101
101
  /**
102
102
  * Splits an annotated text at the specified character position.
103
103
  *
104
- * Annotations that span the split point will be divided appropriately,
105
- * with offsets adjusted for each resulting part.
104
+ * Marks and annotations that span the split point will be divided
105
+ * appropriately, with offsets adjusted for each resulting part.
106
106
  *
107
- * @param {AnnotatedText} text_with_annotations - Annotated text object
107
+ * @param {AnnotatedText} text_value - Annotated text object
108
108
  * @param {number} at_position - Character position where to split (0-based)
109
109
  * @returns {[AnnotatedText, AnnotatedText]} Tuple of [left_part, right_part]
110
110
  *
111
111
  * @example
112
- * split_annotated_text({text: "Hello world", annotations: [{start_offset: 6, end_offset: 11, node_id: "strong"}]}, 8)
112
+ * split_text({content: "Hello world", marks: [{start_offset: 6, end_offset: 11, node_id: "strong"}], annotations: []}, 8)
113
113
  * // Returns:
114
114
  * // [
115
- * // {text: "Hello wo", annotations: [{start_offset: 6, end_offset: 8, node_id: "strong"}]},
116
- * // {text: "rld", annotations: [{start_offset: 0, end_offset: 3, node_id: "strong"}]}
115
+ * // {content: "Hello wo", marks: [{start_offset: 6, end_offset: 8, node_id: "strong"}], annotations: []},
116
+ * // {content: "rld", marks: [{start_offset: 0, end_offset: 3, node_id: "strong"}], annotations: []}
117
117
  * // ]
118
118
  */
119
- export function split_annotated_text(text_with_annotations: AnnotatedText, at_position: number): [AnnotatedText, AnnotatedText];
119
+ export function split_text(text_value: AnnotatedText, at_position: number): [AnnotatedText, AnnotatedText];
120
120
  /**
121
121
  * Joins two annotated texts into a single annotated text.
122
122
  *
123
- * Annotations from the second text will have their offsets shifted by the length
124
- * of the first text. Adjacent annotations of the same type and data will be merged.
123
+ * Marks and annotations from the second text will have their offsets shifted
124
+ * by the length of the first text. Adjacent ranges referencing the same node
125
+ * will be merged.
125
126
  *
126
127
  * @param {AnnotatedText} first_text - First annotated text object
127
128
  * @param {AnnotatedText} second_text - Second annotated text object
128
129
  * @returns {AnnotatedText} Combined annotated text object
129
130
  *
130
131
  * @example
131
- * join_annotated_text({text: "Hello wo", annotations: [{start_offset: 6, end_offset: 8, node_id: "strong"}]}, {text: "rld", annotations: [{start_offset: 0, end_offset: 3, node_id: "strong"}]})
132
- * // Returns: {text: "Hello world", annotations: [{start_offset: 6, end_offset: 11, node_id: "strong"}]}
132
+ * join_text({content: "Hello wo", marks: [{start_offset: 6, end_offset: 8, node_id: "strong"}], annotations: []}, {content: "rld", marks: [{start_offset: 0, end_offset: 3, node_id: "strong"}], annotations: []})
133
+ * // Returns: {content: "Hello world", marks: [{start_offset: 6, end_offset: 11, node_id: "strong"}], annotations: []}
133
134
  */
134
- export function join_annotated_text(first_text: AnnotatedText, second_text: AnnotatedText): AnnotatedText;
135
+ export function join_text(first_text: AnnotatedText, second_text: AnnotatedText): AnnotatedText;
135
136
  /**
136
137
  * Convert snake_case string to PascalCase
137
138
  *
@@ -193,6 +194,18 @@ export function deserialize_path(serialized_path: string): Array<string | number
193
194
  * @returns {boolean}
194
195
  */
195
196
  export function paths_equal(a: Array<string | number>, b: Array<string | number>): boolean;
197
+ /**
198
+ * Like traverse, but returns only node ids in depth-first order and never
199
+ * clones nodes. Use this when only the reachable id set is needed (e.g.
200
+ * reference bookkeeping) — traverse() deep-clones every visited node,
201
+ * which is wasteful for id-only consumers.
202
+ *
203
+ * @param {string} node_id - The ID of the node to start traversing from
204
+ * @param {object} schema - The document schema
205
+ * @param {Record<string, any>} nodes - All document nodes
206
+ * @returns {string[]} Node ids in depth-first order (entry point last)
207
+ */
208
+ export function traverse_ids(node_id: string, schema: object, nodes: Record<string, any>): string[];
196
209
  export function traverse(node_id: any, schema: any, nodes: any): any[];
197
210
  /**
198
211
  * Extracts the normalized range from a text or node selection.
@@ -202,6 +215,56 @@ export function traverse(node_id: any, schema: any, nodes: any): any[];
202
215
  */
203
216
  export function get_selection_range(selection?: Selection): SelectionRange | null;
204
217
  export function is_selection_collapsed(selection: any): boolean;
218
+ /**
219
+ * Adjust ranges (marks or annotations) after deleting a sequence range.
220
+ *
221
+ * Works for both annotated text (character offsets) and annotated node arrays
222
+ * (node offsets).
223
+ *
224
+ * @param {Array<import('./types.d.ts').Attachment>} ranges
225
+ * @param {number} start
226
+ * @param {number} end
227
+ * @returns {{ranges: Array<import('./types.d.ts').Attachment>, removed_node_ids: string[]}}
228
+ */
229
+ export function adjust_ranges_for_deletion(ranges: Array<import("./types.d.ts").Attachment>, start: number, end: number): {
230
+ ranges: Array<import("./types.d.ts").Attachment>;
231
+ removed_node_ids: string[];
232
+ };
233
+ /**
234
+ * Adjust ranges (marks or annotations) after inserting into a sequence.
235
+ *
236
+ * Insertion inside a range extends it. Insertion exactly at either edge
237
+ * stays outside the range.
238
+ *
239
+ * @param {Array<import('./types.d.ts').Attachment>} ranges
240
+ * @param {number} offset
241
+ * @param {number} length
242
+ * @returns {Array<import('./types.d.ts').Attachment>}
243
+ */
244
+ export function adjust_ranges_for_insertion(ranges: Array<import("./types.d.ts").Attachment>, offset: number, length: number): Array<import("./types.d.ts").Attachment>;
245
+ /**
246
+ * Check whether ranges are non-empty and mutually exclusive.
247
+ *
248
+ * @param {Array<import('./types.d.ts').Attachment>} ranges
249
+ * @param {number} [length]
250
+ * @returns {boolean}
251
+ */
252
+ export function are_ranges_exclusive(ranges: Array<import("./types.d.ts").Attachment>, length?: number): boolean;
253
+ /**
254
+ * Calculates abstract fragment ranges from a length and marks.
255
+ *
256
+ * @param {number} length - Length of the sequence (e.g. text length or array length)
257
+ * @param {Array<import('./types.d.ts').Mark>} marks - Array of marks
258
+ * @param {import('./types.d.ts').SelectionRange} [selection_highlight_range] - Optional selection highlight range
259
+ * @returns {Array<{type: 'content' | 'mark' | 'selection_highlight', start_offset: number, end_offset: number, mark_index?: number, node_id?: string}>}
260
+ */
261
+ export function calculate_fragment_ranges(length: number, marks: Array<import("./types.d.ts").Mark>, selection_highlight_range?: import("./types.d.ts").SelectionRange): Array<{
262
+ type: "content" | "mark" | "selection_highlight";
263
+ start_offset: number;
264
+ end_offset: number;
265
+ mark_index?: number;
266
+ node_id?: string;
267
+ }>;
205
268
  export const PATH_SEPARATOR: "__";
206
269
  import type { AnnotatedText } from './types.d.ts';
207
270
  import type { Selection } from './types.d.ts';
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/lib/utils.js"],"names":[],"mappings":"AAMA;;;;;;;GAOG;AACH,8CAFa,OAAO,CAanB;AAED;;;;;;;GAOG;AACH,qCAFa,OAAO,CASnB;AAGD;;;GAGG;AACH,6CAFa,OAAO,CAUnB;AAED;;;;;;;;;;;;;GAaG;AACH,qCARW,MAAM,GACJ,MAAM,CASlB;AAGD;;;;;;;;;;;;;;GAcG;AACH,iCATW,MAAM,SACN,MAAM,GACJ,MAAM,CAUlB;AAED;;;;;;;;;;;;;;GAcG;AACH,gCATW,MAAM,SACN,MAAM,QACN,MAAM,GACJ,MAAM,CAYlB;AAED;;;;;;;;;;;;;GAaG;AACH,0CARW,MAAM,gBACN,MAAM,GACJ,MAAM,CAmBlB;AAED;;;;;;;;;;;;;GAaG;AACH,0CARW,MAAM,eACN,MAAM,GACJ,MAAM,CAelB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,4DAZW,aAAa,eACb,MAAM,GACJ,CAAC,aAAa,EAAE,aAAa,CAAC,CA6C1C;AAED;;;;;;;;;;;;;GAaG;AACH,gDARW,aAAa,eACb,aAAa,GACX,aAAa,CA4CzB;AAED;;;;;;;;GAQG;AACH,qCANW,MAAM,GACJ,MAAM,CAUlB;AAMD;;;;;;;;;GASG;AACH,sDAHW,MAAM,GACJ,OAAO,CAQnB;AAED;;;;;;GAMG;AACH,oDAJW,MAAM,UACN,MAAM,GACJ,IAAI,CAQhB;AAED;;;;;;;;;;;;GAYG;AACH,qCANW,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,GACpB,MAAM,CAmBlB;AAED;;;;;;;;GAQG;AACH,kDANW,MAAM,GACJ,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CAuBlC;AAED;;;;;;GAMG;AACH,+BAJW,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,KACtB,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,GACpB,OAAO,CAKnB;AAED,uEAgCC;AAED;;;;;GAKG;AACH,gDAHW,SAAS,GACP,cAAc,GAAG,IAAI,CAWjC;AAED,gEAMC;AApKD,6BAA8B,IAAI,CAAC;mCA3SsC,cAAc;+BAAd,cAAc;oCAAd,cAAc"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/lib/utils.js"],"names":[],"mappings":"AAMA;;;;;;;GAOG;AACH,8CAFa,OAAO,CAanB;AAED;;;;;;;GAOG;AACH,qCAFa,OAAO,CASnB;AAGD;;;GAGG;AACH,6CAFa,OAAO,CAUnB;AAED;;;;;;;;;;;;;GAaG;AACH,qCARW,MAAM,GACJ,MAAM,CASlB;AAGD;;;;;;;;;;;;;;GAcG;AACH,iCATW,MAAM,SACN,MAAM,GACJ,MAAM,CAUlB;AAED;;;;;;;;;;;;;;GAcG;AACH,gCATW,MAAM,SACN,MAAM,QACN,MAAM,GACJ,MAAM,CAYlB;AAED;;;;;;;;;;;;;GAaG;AACH,0CARW,MAAM,gBACN,MAAM,GACJ,MAAM,CAmBlB;AAED;;;;;;;;;;;;;GAaG;AACH,0CARW,MAAM,eACN,MAAM,GACJ,MAAM,CAelB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,uCAZW,aAAa,eACb,MAAM,GACJ,CAAC,aAAa,EAAE,aAAa,CAAC,CAuC1C;AAED;;;;;;;;;;;;;;GAcG;AACH,sCARW,aAAa,eACb,aAAa,GACX,aAAa,CAgDzB;AAED;;;;;;;;GAQG;AACH,qCANW,MAAM,GACJ,MAAM,CAUlB;AAMD;;;;;;;;;GASG;AACH,sDAHW,MAAM,GACJ,OAAO,CAQnB;AAED;;;;;;GAMG;AACH,oDAJW,MAAM,UACN,MAAM,GACJ,IAAI,CAQhB;AAED;;;;;;;;;;;;GAYG;AACH,qCANW,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,GACpB,MAAM,CAmBlB;AAED;;;;;;;;GAQG;AACH,kDANW,MAAM,GACJ,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CAuBlC;AAED;;;;;;GAMG;AACH,+BAJW,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,KACtB,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,GACpB,OAAO,CAKnB;AAED;;;;;;;;;;GAUG;AACH,sCALW,MAAM,UACN,MAAM,SACN,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GACjB,MAAM,EAAE,CAkCpB;AAED,uEAsCC;AAED;;;;;GAKG;AACH,gDAHW,SAAS,GACP,cAAc,GAAG,IAAI,CAWjC;AAED,gEAMC;AAED;;;;;;;;;;GAUG;AACH,mDALW,KAAK,CAAC,OAAO,cAAc,EAAE,UAAU,CAAC,SACxC,MAAM,OACN,MAAM,GACJ;IAAC,MAAM,EAAE,KAAK,CAAC,OAAO,cAAc,EAAE,UAAU,CAAC,CAAC;IAAC,gBAAgB,EAAE,MAAM,EAAE,CAAA;CAAC,CAkC1F;AAED;;;;;;;;;;GAUG;AACH,oDALW,KAAK,CAAC,OAAO,cAAc,EAAE,UAAU,CAAC,UACxC,MAAM,UACN,MAAM,GACJ,KAAK,CAAC,OAAO,cAAc,EAAE,UAAU,CAAC,CAsBpD;AAED;;;;;;GAMG;AACH,6CAJW,KAAK,CAAC,OAAO,cAAc,EAAE,UAAU,CAAC,WACxC,MAAM,GACJ,OAAO,CAgBnB;AAED;;;;;;;GAOG;AACH,kDALW,MAAM,SACN,KAAK,CAAC,OAAO,cAAc,EAAE,IAAI,CAAC,8BAClC,OAAO,cAAc,EAAE,cAAc,GACnC,KAAK,CAAC;IAAC,IAAI,EAAE,SAAS,GAAG,MAAM,GAAG,qBAAqB,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAC,CAAC,CAuDtJ;AA3XD,6BAA8B,IAAI,CAAC;mCA1SwD,cAAc;+BAAd,cAAc;oCAAd,cAAc"}