svedit 0.11.1 → 0.13.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 (93) hide show
  1. package/README.md +260 -82
  2. package/dist/Command.svelte.d.ts +54 -29
  3. package/dist/Command.svelte.d.ts.map +1 -1
  4. package/dist/Command.svelte.js +286 -283
  5. package/dist/CustomProperty.svelte +3 -5
  6. package/dist/CustomProperty.svelte.d.ts +3 -6
  7. package/dist/CustomProperty.svelte.d.ts.map +1 -1
  8. package/dist/KeyMapper.svelte.d.ts +19 -6
  9. package/dist/KeyMapper.svelte.d.ts.map +1 -1
  10. package/dist/KeyMapper.svelte.js +95 -112
  11. package/dist/Node.svelte +40 -9
  12. package/dist/Node.svelte.d.ts +3 -5
  13. package/dist/Node.svelte.d.ts.map +1 -1
  14. package/dist/NodeArrayProperty.svelte +142 -18
  15. package/dist/NodeArrayProperty.svelte.d.ts +3 -5
  16. package/dist/NodeArrayProperty.svelte.d.ts.map +1 -1
  17. package/dist/NodeCaret.svelte +1 -1
  18. package/dist/NodeCaret.svelte.d.ts +6 -14
  19. package/dist/NodeCaret.svelte.d.ts.map +1 -1
  20. package/dist/NodeGap.svelte +60 -12
  21. package/dist/NodeGap.svelte.d.ts +7 -14
  22. package/dist/NodeGap.svelte.d.ts.map +1 -1
  23. package/dist/NodeGapMarkers.svelte +19 -10
  24. package/dist/NodeGapMarkers.svelte.d.ts +6 -11
  25. package/dist/NodeGapMarkers.svelte.d.ts.map +1 -1
  26. package/dist/NodeSelectionMarkers.svelte +20 -6
  27. package/dist/NodeSelectionMarkers.svelte.d.ts +2 -5
  28. package/dist/NodeSelectionMarkers.svelte.d.ts.map +1 -1
  29. package/dist/Session.svelte.d.ts +85 -116
  30. package/dist/Session.svelte.d.ts.map +1 -1
  31. package/dist/Session.svelte.js +543 -571
  32. package/dist/Svedit.svelte +243 -216
  33. package/dist/Svedit.svelte.d.ts +30 -10
  34. package/dist/Svedit.svelte.d.ts.map +1 -1
  35. package/dist/{AnnotatedTextProperty.svelte → TextProperty.svelte} +71 -56
  36. package/dist/TextProperty.svelte.d.ts +5 -0
  37. package/dist/TextProperty.svelte.d.ts.map +1 -0
  38. package/dist/Transaction.svelte.d.ts +101 -126
  39. package/dist/Transaction.svelte.d.ts.map +1 -1
  40. package/dist/Transaction.svelte.js +843 -827
  41. package/dist/UnknownNode.svelte +4 -3
  42. package/dist/UnknownNode.svelte.d.ts +5 -9
  43. package/dist/UnknownNode.svelte.d.ts.map +1 -1
  44. package/dist/doc_utils.d.ts +109 -122
  45. package/dist/doc_utils.d.ts.map +1 -1
  46. package/dist/doc_utils.js +726 -698
  47. package/dist/index.d.ts +20 -17
  48. package/dist/index.d.ts.map +1 -1
  49. package/dist/index.js +2 -18
  50. package/dist/node_visibility.svelte.d.ts +132 -5
  51. package/dist/node_visibility.svelte.d.ts.map +1 -1
  52. package/dist/node_visibility.svelte.js +535 -642
  53. package/dist/paste_utils.d.ts +11 -43
  54. package/dist/paste_utils.d.ts.map +1 -1
  55. package/dist/paste_utils.js +111 -149
  56. package/dist/transforms.svelte.d.ts +9 -7
  57. package/dist/transforms.svelte.d.ts.map +1 -1
  58. package/dist/transforms.svelte.js +126 -152
  59. package/dist/types.d.ts +329 -291
  60. package/dist/types.d.ts.map +1 -0
  61. package/dist/types.js +1 -0
  62. package/dist/utils.d.ts +79 -95
  63. package/dist/utils.d.ts.map +1 -1
  64. package/dist/utils.js +392 -305
  65. package/package.json +69 -67
  66. package/src/lib/{Command.svelte.js → Command.svelte.ts} +111 -41
  67. package/src/lib/CustomProperty.svelte +3 -5
  68. package/src/lib/{KeyMapper.svelte.js → KeyMapper.svelte.ts} +28 -11
  69. package/src/lib/Node.svelte +40 -9
  70. package/src/lib/NodeArrayProperty.svelte +142 -18
  71. package/src/lib/NodeCaret.svelte +1 -1
  72. package/src/lib/NodeGap.svelte +60 -12
  73. package/src/lib/NodeGapMarkers.svelte +19 -10
  74. package/src/lib/NodeSelectionMarkers.svelte +20 -6
  75. package/src/lib/Session.svelte.ts +656 -0
  76. package/src/lib/Svedit.svelte +243 -216
  77. package/src/lib/{AnnotatedTextProperty.svelte → TextProperty.svelte} +71 -56
  78. package/src/lib/Transaction.svelte.ts +1020 -0
  79. package/src/lib/UnknownNode.svelte +4 -3
  80. package/src/lib/doc_utils.ts +1120 -0
  81. package/src/lib/{index.js → index.ts} +48 -1
  82. package/src/lib/node_visibility.svelte.ts +658 -0
  83. package/src/lib/{paste_utils.js → paste_utils.ts} +51 -59
  84. package/src/lib/{transforms.svelte.js → transforms.svelte.ts} +44 -27
  85. package/src/lib/{types.d.ts → types.ts} +250 -103
  86. package/src/lib/utils.ts +660 -0
  87. package/dist/AnnotatedTextProperty.svelte.d.ts +0 -7
  88. package/dist/AnnotatedTextProperty.svelte.d.ts.map +0 -1
  89. package/src/lib/Session.svelte.js +0 -575
  90. package/src/lib/Transaction.svelte.js +0 -846
  91. package/src/lib/doc_utils.js +0 -807
  92. package/src/lib/node_visibility.svelte.js +0 -718
  93. package/src/lib/utils.js +0 -465
@@ -1,12 +1,32 @@
1
- export default Svedit;
2
- type Svedit = {
3
- $on?(type: string, callback: (e: any) => void): () => void;
4
- $set?(props: Partial<SveditProps>): void;
5
- } & {
6
- focus_canvas: () => void;
1
+ import './styles/svedit-colors.css';
2
+ import './styles/svedit-animations.css';
3
+ import type { DocumentSchema, SveditProps } from './types.js';
4
+ declare function $$render<S extends DocumentSchema>(): {
5
+ props: SveditProps<S>;
6
+ exports: {
7
+ focus_canvas: () => void;
8
+ };
9
+ bindings: "editable";
10
+ slots: {};
11
+ events: {};
7
12
  };
8
- declare const Svedit: import("svelte").Component<SveditProps, {
9
- focus_canvas: () => void;
10
- }, "editable">;
11
- import type { SveditProps } from './types.d.ts';
13
+ declare class __sveltets_Render<S extends DocumentSchema> {
14
+ props(): ReturnType<typeof $$render<S>>['props'];
15
+ events(): ReturnType<typeof $$render<S>>['events'];
16
+ slots(): ReturnType<typeof $$render<S>>['slots'];
17
+ bindings(): "editable";
18
+ exports(): {
19
+ focus_canvas: () => void;
20
+ };
21
+ }
22
+ interface $$IsomorphicComponent {
23
+ new <S extends DocumentSchema>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<S>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<S>['props']>, ReturnType<__sveltets_Render<S>['events']>, ReturnType<__sveltets_Render<S>['slots']>> & {
24
+ $$bindings?: ReturnType<__sveltets_Render<S>['bindings']>;
25
+ } & ReturnType<__sveltets_Render<S>['exports']>;
26
+ <S extends DocumentSchema>(internal: unknown, props: ReturnType<__sveltets_Render<S>['props']> & {}): ReturnType<__sveltets_Render<S>['exports']>;
27
+ z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
28
+ }
29
+ declare const Svedit: $$IsomorphicComponent;
30
+ type Svedit<S extends DocumentSchema> = InstanceType<typeof Svedit<S>>;
31
+ export default Svedit;
12
32
  //# sourceMappingURL=Svedit.svelte.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Svedit.svelte.d.ts","sourceRoot":"","sources":["../src/lib/Svedit.svelte.js"],"names":[],"mappings":";;;;;;;AA0mDA;;eAAqD;iCA9jD1C,cAAc"}
1
+ {"version":3,"file":"Svedit.svelte.d.ts","sourceRoot":"","sources":["../src/lib/Svedit.svelte.ts"],"names":[],"mappings":"AAyBA,OAAO,4BAA4B,CAAC;AACpC,OAAO,gCAAgC,CAAC;AAExC,OAAO,KAAK,EACV,cAAc,EACd,WAAW,EASX,MAAM,YAAY,CAAC;AAGrB,iBAAS,QAAQ,CAAC,CAAC,SAAS,cAAc;WA8lDb,WAAW,CAAC,CAAC,CAAC;aAAwB;QAAE,YAAY,aAAqB;KAAE;;;;EAAuE;AAC/K,cAAM,iBAAiB,CAAC,CAAC,SAAS,cAAc;IAC5C,KAAK,IAAI,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IAChD,MAAM,IAAI,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;IAClD,KAAK,IAAI,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IAChD,QAAQ;IACR,OAAO;;;CACV;AAED,UAAU,qBAAqB;IAC3B,KAAK,CAAC,SAAS,cAAc,EAAE,OAAO,EAAE,OAAO,QAAQ,EAAE,2BAA2B,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,QAAQ,EAAE,eAAe,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG;QAAE,UAAU,CAAC,EAAE,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAA;KAAE,GAAG,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;IACnZ,CAAC,CAAC,SAAS,cAAc,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,GAAG,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;IAClJ,YAAY,CAAC,EAAE,UAAU,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;CACjE;AACD,QAAA,MAAM,MAAM,EAAE,qBAAmC,CAAC;AAChC,KAAK,MAAM,CAAC,CAAC,SAAS,cAAc,IAAI,YAAY,CAAC,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;AACzE,eAAe,MAAM,CAAC"}
@@ -1,19 +1,32 @@
1
- <script>
1
+ <script lang="ts">
2
2
  import { getContext } from 'svelte';
3
3
  import {
4
4
  char_slice,
5
5
  get_char_length,
6
6
  paths_equal,
7
7
  serialize_path,
8
- get_selection_range
8
+ get_selection_range,
9
+ calculate_fragment_ranges
9
10
  } from './utils.js';
10
11
 
11
- /** @import { AnnotatedTextPropertyProps, Annotation, Fragment, SelectionRange } from './types.d.ts'; */
12
-
13
- const svedit = getContext('svedit');
14
-
15
- /** @type {AnnotatedTextPropertyProps} */
16
- let { path, class: css_class, placeholder = '', tag = 'div', style = '', ...rest } = $props();
12
+ import type {
13
+ TextPropertyProps,
14
+ Mark,
15
+ Fragment,
16
+ SelectionRange,
17
+ SveditContext
18
+ } from './types.js';
19
+
20
+ const svedit = getContext<SveditContext>('svedit');
21
+
22
+ let {
23
+ path,
24
+ class: css_class,
25
+ placeholder = '',
26
+ tag = 'div',
27
+ style = '',
28
+ ...rest
29
+ }: TextPropertyProps = $props();
17
30
 
18
31
  let path_str = $derived(serialize_path(path));
19
32
 
@@ -23,16 +36,20 @@
23
36
  );
24
37
  });
25
38
 
26
- let plain_text = $derived(svedit.session.get(path).text);
27
- let is_empty = $derived(
28
- get_char_length(plain_text) === 0 && !(svedit.is_composing && is_focused)
29
- );
39
+ let plain_text = $derived(svedit.session.get(path).content);
40
+ // A string has zero grapheme clusters iff it has zero code units, so a
41
+ // plain length check avoids a full Intl.Segmenter pass (this derived
42
+ // re-runs for every text property on every document change).
43
+ let is_empty = $derived(plain_text.length === 0 && !(svedit.is_composing && is_focused));
30
44
 
31
- let is_collapsed = $derived(
32
- is_focused && svedit.session.selection?.anchor_offset == svedit.session.selection?.focus_offset
33
- );
45
+ let is_collapsed = $derived.by(() => {
46
+ const selection = svedit.session.selection;
47
+ return (
48
+ is_focused && selection?.type === 'text' && selection.anchor_offset === selection.focus_offset
49
+ );
50
+ });
34
51
 
35
- // Get selection highlight range if not inside an annotation
52
+ // Get selection highlight range if it does not touch marks.
36
53
  // Only render selection highlight when canvas is NOT focused.
37
54
  // This avoids DOM mutations (splitting text nodes for highlight spans)
38
55
  // while the user is actively selecting, which would cause selection
@@ -41,7 +58,7 @@
41
58
  if (svedit.canvas_focused) return null;
42
59
  if (is_collapsed) return null;
43
60
  if (!is_focused) return null;
44
- if (svedit.session.active_annotation()) return null;
61
+ if (svedit.session.selected_marks.length > 0) return null;
45
62
  const sel = svedit.session.selection;
46
63
  if (!sel || sel.type !== 'text') return null;
47
64
  return get_selection_range(sel);
@@ -49,61 +66,57 @@
49
66
 
50
67
  let fragments = $derived(
51
68
  get_fragments(
52
- svedit.session.get(path).text,
53
- svedit.session.get(path).annotations,
69
+ svedit.session.get(path).content,
70
+ svedit.session.get(path).marks,
54
71
  selection_highlight_range
55
72
  )
56
73
  );
57
74
 
58
75
  /**
59
- * Converts text with annotations into renderable fragments for display.
60
- * @param {string} text - The plain text content
61
- * @param {Array<Annotation>} annotations - Array of annotations
62
- * @param {SelectionRange} [selection_highlight_range] - Optional selection highlight range
63
- * @returns {Array<Fragment>} Array of fragments
76
+ * Converts text with marks into renderable fragments for display.
77
+ * Annotations never fragment the text; they are data-only.
64
78
  */
65
- function get_fragments(text, annotations, selection_highlight_range) {
66
- /** @type {Array<Fragment>} */
67
- let fragments = [];
68
- let last_index = 0;
79
+ function get_fragments(
80
+ text: string,
81
+ marks: Array<Mark>,
82
+ selection_highlight_range?: SelectionRange | null
83
+ ): Array<Fragment> {
84
+ // Fast path: no marks and no selection highlight means the whole text
85
+ // is a single content fragment. This runs for EVERY text property on
86
+ // EVERY document change, so skipping the two full Intl.Segmenter passes
87
+ // (get_char_length + char_slice over the whole text) matters at scale.
88
+ if (marks.length === 0 && !selection_highlight_range) {
89
+ return text.length > 0 ? [text] : [];
90
+ }
69
91
 
70
- // Merge annotations with selection highlight and sort by start offset
71
- const ranges = [
72
- ...annotations,
73
- ...(selection_highlight_range ? [selection_highlight_range] : [])
74
- ].sort((a, b) => a.start_offset - b.start_offset);
92
+ const ranges = calculate_fragment_ranges(
93
+ get_char_length(text),
94
+ marks,
95
+ selection_highlight_range
96
+ );
97
+ const fragments: Array<Fragment> = [];
75
98
 
76
99
  for (const range of ranges) {
77
- // Add text before this range
78
- if (range.start_offset > last_index) {
79
- fragments.push(char_slice(text, last_index, range.start_offset));
80
- }
81
-
82
100
  const content = char_slice(text, range.start_offset, range.end_offset);
83
101
 
84
- if ('node_id' in range) {
102
+ if (range.type === 'mark') {
85
103
  const node = svedit.session.get(range.node_id);
86
- if (!node) throw new Error(`Node not found for annotation ${range.node_id}`);
104
+ if (!node) throw new Error(`Node not found for mark ${range.node_id}`);
87
105
 
88
106
  fragments.push({
89
- type: 'annotation',
107
+ type: 'mark',
90
108
  node,
91
109
  content,
92
- annotation_index: annotations.indexOf(/** @type {Annotation} */ (range))
110
+ mark_index: range.mark_index!
93
111
  });
94
- } else {
112
+ } else if (range.type === 'selection_highlight') {
95
113
  fragments.push({
96
114
  type: 'selection_highlight',
97
115
  content
98
116
  });
117
+ } else {
118
+ fragments.push(content);
99
119
  }
100
-
101
- last_index = range.end_offset;
102
- }
103
-
104
- // Add any remaining text
105
- if (last_index < get_char_length(text)) {
106
- fragments.push(char_slice(text, last_index));
107
120
  }
108
121
 
109
122
  return fragments;
@@ -130,12 +143,14 @@
130
143
  {#if typeof fragment === 'string'}{fragment}{:else if fragment.type === 'selection_highlight'}<span
131
144
  class="selection-highlight"
132
145
  style="anchor-name: --selection-highlight;">{fragment.content}</span
133
- >{:else if fragment.type === 'annotation'}
134
- {@const AnnotationComponent = svedit.session.config.node_components[fragment.node.type]}
135
- <AnnotationComponent
136
- path={[...path, 'annotations', fragment.annotation_index, 'node_id']}
137
- content={fragment.content}
138
- />
146
+ >{:else if fragment.type === 'mark'}
147
+ {@const MarkComponent = svedit.session.config.node_components[fragment.node.type]}
148
+ {#if MarkComponent}
149
+ <MarkComponent
150
+ path={[...path, 'marks', fragment.mark_index, 'node_id']}
151
+ content={fragment.content}
152
+ />
153
+ {:else}<span class="mark-{fragment.node.type}">{fragment.content}</span>{/if}
139
154
  {/if}
140
155
  {/each}<!--
141
156
  -->{#if !is_focused || !is_empty}<br />{/if}
@@ -0,0 +1,5 @@
1
+ import type { TextPropertyProps } from './types.js';
2
+ declare const TextProperty: import("svelte").Component<TextPropertyProps, {}, "">;
3
+ type TextProperty = ReturnType<typeof TextProperty>;
4
+ export default TextProperty;
5
+ //# sourceMappingURL=TextProperty.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TextProperty.svelte.d.ts","sourceRoot":"","sources":["../src/lib/TextProperty.svelte.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EACV,iBAAiB,EAKjB,MAAM,YAAY,CAAC;AAsIrB,QAAA,MAAM,YAAY,uDAAwC,CAAC;AAC3D,KAAK,YAAY,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;AACpD,eAAe,YAAY,CAAC"}
@@ -1,3 +1,5 @@
1
+ import type { SelectedAttachment } from './doc_utils.js';
2
+ import type { NodeId, NodeKind, Selection, Document, DocumentSchema, DocumentNode, DocumentPath, Mark, Annotation, DocumentOperation, DynamicRecord, Inspection, SessionConfig } from './types.js';
1
3
  /**
2
4
  * Transaction class for managing atomic document operations with undo/redo support.
3
5
  *
@@ -14,110 +16,81 @@
14
16
  * ```
15
17
  */
16
18
  export default class Transaction {
17
- /**
18
- * Creates a new Transaction with the given state.
19
- *
20
- * @param {DocumentSchema} schema - The document schema
21
- * @param {Document} doc - The document state {document_id, nodes}
22
- * @param {Selection | null} selection - The current selection
23
- * @param {object} config - The document config (including generate_id)
24
- */
25
- constructor(schema: DocumentSchema, doc: Document, selection: Selection | null, config: object);
26
19
  schema: DocumentSchema;
27
- /** @type {object} */
28
- doc: object;
29
- /** @type {Selection} */
20
+ doc: Document;
30
21
  selection: Selection;
31
- config: any;
32
- /** @type {Record<string, any>[]} */
33
- ops: Record<string, any>[];
34
- /** @type {Record<string, any>[]} */
35
- inverse_ops: Record<string, any>[];
36
- selection_before: Selection;
37
- /** @type {NodeId[]} */
22
+ config: SessionConfig;
23
+ ops: DocumentOperation[];
24
+ inverse_ops: DocumentOperation[];
25
+ selection_before: Selection | null;
38
26
  created_node_ids: NodeId[];
39
- /** @type {NodeId[]} */
40
27
  modified_node_ids: NodeId[];
41
- /** @type {NodeId[]} */
42
28
  deleted_node_ids: NodeId[];
29
+ changed_node_types: boolean;
30
+ /**
31
+ * Creates a new Transaction with the given state.
32
+ *
33
+ * @param schema - The document schema
34
+ * @param doc - The document state {document_id, nodes}
35
+ * @param selection - The current selection
36
+ * @param config - The document config (including generate_id)
37
+ */
38
+ constructor(schema: DocumentSchema, doc: Document, selection: Selection | null, config: SessionConfig);
43
39
  /**
44
40
  * Gets a value from the document at the specified path.
45
41
  *
46
- * @param {DocumentPath|string} path - The path to the value in the document, or a string node ID
47
- * @returns {any} The value at the specified path
42
+ * @param path - The path to the value in the document, or a string node ID
43
+ * @returns The value at the specified path
48
44
  */
49
45
  get(path: DocumentPath | string): any;
50
46
  /**
51
47
  * Gets the type of a property from the schema.
52
- *
53
- * @param {string} type - The node type
54
- * @param {string} property - The property name
55
- * @returns {string} The property type
56
48
  */
57
49
  property_type(type: string, property: string): string;
58
50
  /**
59
- * Determines the kind of a node ('block', 'text', or 'annotation').
60
- *
61
- * @param {any} node - The node to check
62
- * @returns {'block'|'text'|'annotation'} The node kind
51
+ * Determines the kind of a node ('document', 'block', 'text', 'mark', or 'annotation').
63
52
  */
64
- kind(node: any): "block" | "text" | "annotation";
53
+ kind(node: DocumentNode): NodeKind;
65
54
  /**
66
55
  * Inspects a path to get metadata about the value at that location.
67
- *
68
- * @param {DocumentPath} path - The path to inspect
69
- * @returns {{kind: 'property'|'node', [key: string]: any}} Metadata about the path
70
56
  */
71
- inspect(path: DocumentPath): {
72
- kind: "property" | "node";
73
- [key: string]: any;
74
- };
57
+ inspect(path: DocumentPath): Inspection;
75
58
  /**
76
59
  * Generates a new unique ID using the config's generate_id function.
77
- *
78
- * @returns {string} A new unique ID
79
60
  */
80
61
  generate_id(): string;
81
62
  /**
82
63
  * Validates a node against the document schema.
83
64
  *
84
- * @param {any} node - The node to validate
85
65
  * @throws {Error} Throws if the node is invalid
86
66
  */
87
- validate_node(node: any): void;
67
+ validate_node(node: DocumentNode): void;
88
68
  /**
89
69
  * Gets all nodes referenced by a given node (recursively).
90
- *
91
- * @param {NodeId} node_id - The node ID to get references for
92
- * @returns {NodeId[]} Array of referenced node IDs
93
70
  */
94
71
  get_referenced_nodes(node_id: NodeId): NodeId[];
72
+ /**
73
+ * Gets the available mark types for the current selection.
74
+ */
75
+ get available_mark_types(): string[];
95
76
  /**
96
77
  * Gets the available annotation types for the current selection.
97
- *
98
- * @returns {string[]} Array of available annotation type names
99
78
  */
100
79
  get available_annotation_types(): string[];
101
80
  /**
102
- * Returns the annotation object that is currently "under the caret".
103
- * NOTE: Annotations in Svedit are exclusive, so there can only be one active_annotation
104
- *
105
- * @param {string} [annotation_type] Optional annotation type to filter by
106
- * @returns {Annotation|null}
81
+ * Returns marks touched by the current selection.
107
82
  */
108
- active_annotation(annotation_type?: string): Annotation | null;
83
+ get selected_marks(): SelectedAttachment[];
84
+ get active_mark(): SelectedAttachment | null;
109
85
  /**
110
- * Applies an operation to the document (internal).
111
- *
112
- * @param {Array} op - The operation to apply
113
- * @private
86
+ * Returns annotations touched by the current selection.
114
87
  */
115
- private _apply_op;
88
+ get selected_annotations(): SelectedAttachment[];
89
+ get active_annotation(): SelectedAttachment | null;
116
90
  /**
117
- * @param {NodeId[]} node_ids
118
- * @param {NodeId} node_id
119
- * @private
91
+ * Applies an operation to the document (internal).
120
92
  */
93
+ private _apply_op;
121
94
  private _track_node_id;
122
95
  /**
123
96
  * Sets a property of a node to a new value.
@@ -125,26 +98,26 @@ export default class Transaction {
125
98
  * This is the core operation for modifying document properties. It records
126
99
  * both the forward operation and its inverse for undo support.
127
100
  *
128
- * @param {DocumentPath} path - Array path to the property (e.g., ["node_1", "title"])
129
- * @param {any} value - The new value to set
130
- * @returns {Transaction} This transaction instance for method chaining
101
+ * @param path - Array path to the property (e.g., ["node_1", "title"])
102
+ * @param value - The new value to set
103
+ * @returns This transaction instance for method chaining
131
104
  *
132
105
  * @example
133
106
  * ```js
134
107
  * tr.set(["list_1", "list_items"], [1, 2, 3]);
135
- * tr.set(["page_1", "body", "0", "description"], {text: "Hello world", annotations: []});
108
+ * tr.set(["page_1", "body", "0", "description"], {content: "Hello world", marks: [], annotations: []});
136
109
  * ```
137
110
  */
138
- set(path: DocumentPath, value: any): Transaction;
139
- build(node_id: any, nodes: any): any;
111
+ set(path: DocumentPath, value: any): this;
112
+ build(node_id: NodeId, nodes: Record<string, DocumentNode>): NodeId;
140
113
  /**
141
114
  * Creates a new node in the document.
142
115
  *
143
116
  * The node must have a valid id and must not already exist in the document.
144
117
  * Omitted properties with schema defaults are filled before validation.
145
118
  *
146
- * @param {any} node - The node object to create (must include id, type, and required properties)
147
- * @returns {Transaction} This transaction instance for method chaining
119
+ * @param node - The node object to create (must include id, type, and required properties)
120
+ * @returns This transaction instance for method chaining
148
121
  * @throws {Error} If the node ID is invalid or if the node already exists
149
122
  *
150
123
  * @example
@@ -156,7 +129,7 @@ export default class Transaction {
156
129
  * });
157
130
  * ```
158
131
  */
159
- create(node: any): Transaction;
132
+ create(node: DocumentNode): this;
160
133
  /**
161
134
  * Deletes a node from the document by its ID.
162
135
  *
@@ -164,57 +137,74 @@ export default class Transaction {
164
137
  *
165
138
  * NOTE: This is a force-delete and intentionally does NOT check whether
166
139
  * the node is still referenced from elsewhere — callers (e.g.
167
- * `annotate_text`) sometimes need to remove a node while a stale
140
+ * `toggle_mark`) sometimes need to remove a node while a stale
168
141
  * reference to it still exists in the property they are about to update.
169
142
  * For ref-count-aware cleanup, see how `set` calls
170
143
  * `_cascade_delete_unreferenced_nodes`.
171
144
  *
172
- * @param {any} id - The ID of the node to delete
173
- * @returns {Transaction} This transaction instance for method chaining
145
+ * @param id - The ID of the node to delete
146
+ * @returns This transaction instance for method chaining
174
147
  *
175
148
  * @example
176
149
  * ```js
177
150
  * tr.delete('node_123');
178
151
  * ```
179
152
  */
180
- delete(id: any): Transaction;
153
+ delete(id: NodeId): this;
181
154
  /**
182
155
  * Sets the document selection.
183
156
  *
184
- * @param {Selection} selection - The new selection object
185
- * @returns {Transaction} This transaction instance for method chaining
157
+ * @param selection - The new selection object
158
+ * @returns This transaction instance for method chaining
186
159
  * @throws {Error} Throws if the selection is invalid or out of bounds
187
160
  */
188
- set_selection(selection: Selection): Transaction;
161
+ set_selection(selection: Selection): this;
189
162
  /**
190
163
  * Validates a selection against the current document state.
191
164
  *
192
- * @param {Selection} selection - The selection to validate
193
165
  * @throws {Error} Throws if the selection is invalid
194
- * @private
195
166
  */
196
167
  private _validate_selection;
197
168
  /**
198
- * Adds, updates, or removes text annotations in the current selection.
169
+ * Toggles a mark on the current text or node selection.
199
170
  *
200
- * Handles various annotation scenarios including adding new annotations,
201
- * updating existing ones (especially for links), and removing annotations
202
- * when conflicting types are applied.
171
+ * Marks are mutually exclusive. Whole marks are toggled, removed, or
172
+ * switched; ranges are never truncated or expanded by this command.
203
173
  *
204
- * @param {any} annotation_type - The type of annotation (e.g., 'link', 'bold', 'italic')
205
- * @param {any} annotation_properties - Additional data for the annotation (e.g., href for links)
206
- * @returns {Transaction} This transaction instance for method chaining
174
+ * @param mark_type - The type of mark (e.g., 'link', 'strong', 'emphasis')
175
+ * @param mark_properties - Additional data for the mark (e.g., href for links)
176
+ * @returns This transaction instance for method chaining
207
177
  *
208
178
  * @example
209
179
  * ```js
210
- * // Add a link annotation
211
- * tr.annotate_text('link', { href: 'https://example.com' });
180
+ * // Add a link mark
181
+ * tr.toggle_mark('link', { href: 'https://example.com' });
212
182
  *
213
183
  * // Add emphasis
214
- * tr.annotate_text('emphasis', {});
184
+ * tr.toggle_mark('emphasis', {});
215
185
  * ```
216
186
  */
217
- annotate_text(annotation_type: any, annotation_properties: any): Transaction;
187
+ toggle_mark(mark_type: string, mark_properties?: DynamicRecord): this;
188
+ /**
189
+ * Toggles an annotation on the current text or node selection.
190
+ *
191
+ * Annotations only compete with touched annotations of the same type:
192
+ * touched same-type annotations are removed, otherwise a new annotation is
193
+ * created. Marks and other annotation types never block a toggle, and
194
+ * same-type annotations may still overlap when created through lower-level
195
+ * APIs.
196
+ *
197
+ * @param annotation_type - The type of annotation (e.g., 'comment', 'marker')
198
+ * @param annotation_properties - Additional data for the annotation
199
+ * @returns This transaction instance for method chaining
200
+ *
201
+ * @example
202
+ * ```js
203
+ * // Add a comment annotation
204
+ * tr.toggle_annotation('comment', { text: 'Please review' });
205
+ * ```
206
+ */
207
+ toggle_annotation(annotation_type: string, annotation_properties?: DynamicRecord): this;
218
208
  /**
219
209
  * Deletes the currently selected text, node, or property.
220
210
  *
@@ -224,34 +214,38 @@ export default class Transaction {
224
214
  * - For collapsed selections: Deletes the previous character/node (backward) or next character/node (forward)
225
215
  * - For property selections: Delegates to the config's handle_property_deletion hook
226
216
  *
227
- * @param {'backward' | 'forward'} [direction] - Direction of deletion for collapsed selections
228
- * @returns {Transaction} This transaction instance for method chaining
217
+ * @param direction - Direction of deletion for collapsed selections
218
+ * @returns This transaction instance for method chaining
229
219
  */
230
- delete_selection(direction?: "backward" | "forward"): Transaction;
220
+ delete_selection(direction?: 'backward' | 'forward'): this;
231
221
  /**
232
222
  * Inserts nodes at the current node selection position.
233
223
  *
234
224
  * If the selection is expanded (not collapsed), first deletes the selected nodes
235
225
  * before inserting the new ones.
236
226
  *
237
- * @param {NodeId[]} node_ids - Array of node IDs to insert
238
- * @returns {Transaction} This transaction instance for method chaining
227
+ * @param node_ids - Array of node IDs to insert
228
+ * @param marks - Selection-relative marks to restore
229
+ * @param annotations - Selection-relative annotations to restore
230
+ * @param nodes - Node graph for restored marks and annotations
231
+ * @returns This transaction instance for method chaining
239
232
  */
240
- insert_nodes(node_ids: NodeId[]): Transaction;
233
+ insert_nodes(node_ids: NodeId[], marks?: Array<Mark>, annotations?: Array<Annotation>, nodes?: Record<NodeId, DocumentNode>): this;
241
234
  /**
242
235
  * Inserts text at the current text selection position.
243
236
  *
244
- * Handles annotation adjustments when text is inserted, including:
245
- * - Expanding annotations that contain the insertion point
246
- * - Shifting annotations that come after the insertion point
247
- * - Optionally applying new annotations to the inserted text
237
+ * Handles mark and annotation adjustments when text is inserted, including:
238
+ * - Expanding ranges that contain the insertion point
239
+ * - Shifting ranges that come after the insertion point
240
+ * - Optionally applying new marks and annotations to the inserted text
248
241
  *
249
- * @param {string} replaced_text - The text to insert
250
- * @param {Array} [annotations] - Optional annotations to apply to the inserted text
251
- * @param {object} [nodes] - Optional node definitions for annotation nodes
252
- * @returns {Transaction} This transaction instance for method chaining
242
+ * @param replaced_text - The text to insert
243
+ * @param marks - Optional marks to apply to the inserted text
244
+ * @param annotations - Optional annotations to apply to the inserted text
245
+ * @param nodes - Optional node definitions for mark and annotation nodes
246
+ * @returns This transaction instance for method chaining
253
247
  */
254
- insert_text(replaced_text: string, annotations?: any[], nodes?: object): Transaction;
248
+ insert_text(replaced_text: string, marks?: Array<Mark>, annotations?: Array<Annotation>, nodes?: Record<NodeId, DocumentNode>): this;
255
249
  /**
256
250
  * Recursively deletes nodes that are no longer referenced in the document.
257
251
  *
@@ -259,27 +253,8 @@ export default class Transaction {
259
253
  * references are removed. Uses reference counting to determine which
260
254
  * nodes are safe to delete.
261
255
  *
262
- * @param {NodeId[]} potentially_orphaned_nodes - Array of node IDs to check
263
- * @private
256
+ * @param potentially_orphaned_nodes - Array of node IDs to check
264
257
  */
265
258
  private _cascade_delete_unreferenced_nodes;
266
- /**
267
- * Counts references to a node, excluding nodes that have been marked for deletion.
268
- *
269
- * This is used during cascade deletion to accurately count remaining references
270
- * as nodes are being deleted.
271
- *
272
- * @param {NodeId} target_node_id - The node ID to count references for
273
- * @param {Record<NodeId, boolean>} nodes_to_delete - Nodes already marked for deletion
274
- * @returns {number} The number of references to the target node
275
- * @private
276
- */
277
- private _count_references_excluding_deleted;
278
259
  }
279
- import type { DocumentSchema } from './types.d.js';
280
- import type { Selection } from './types.d.js';
281
- import type { NodeId } from './types.d.js';
282
- import type { DocumentPath } from './types.d.js';
283
- import type { Annotation } from './types.d.js';
284
- import type { Document } from './types.d.js';
285
260
  //# sourceMappingURL=Transaction.svelte.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Transaction.svelte.d.ts","sourceRoot":"","sources":["../src/lib/Transaction.svelte.js"],"names":[],"mappings":"AA0BA;;;;;;;;;;;;;;GAcG;AACH;IACC;;;;;;;OAOG;IACH,oBALW,cAAc,OACd,QAAQ,aACR,SAAS,GAAG,IAAI,UAChB,MAAM,EAuBhB;IApBA,uBAAoB;IACpB,qBAAqB;IACrB,KADW,MAAM,CACH;IACd,wBAAwB;IACxB,WADW,SAAS,CACM;IAC1B,YAAoB;IAEpB,oCAAoC;IACpC,KADW,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,CACnB;IACb,oCAAoC;IACpC,aADW,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,CACX;IAErB,4BAAiC;IAEjC,uBAAuB;IACvB,kBADW,MAAM,EAAE,CACO;IAC1B,uBAAuB;IACvB,mBADW,MAAM,EAAE,CACQ;IAC3B,uBAAuB;IACvB,kBADW,MAAM,EAAE,CACO;IAG3B;;;;;OAKG;IACH,UAHW,YAAY,GAAC,MAAM,GACjB,GAAG,CAIf;IAED;;;;;;OAMG;IACH,oBAJW,MAAM,YACN,MAAM,GACJ,MAAM,CAIlB;IAED;;;;;OAKG;IACH,WAHW,GAAG,GACD,OAAO,GAAC,MAAM,GAAC,YAAY,CAIvC;IAED;;;;;OAKG;IACH,cAHW,YAAY,GACV;QAAC,IAAI,EAAE,UAAU,GAAC,MAAM,CAAC;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KAAC,CAIzD;IAED;;;;OAIG;IACH,eAFa,MAAM,CAIlB;IAED;;;;;OAKG;IACH,oBAHW,GAAG,QAKb;IAGD;;;;;OAKG;IACH,8BAHW,MAAM,GACJ,MAAM,EAAE,CAKpB;IAED;;;;OAIG;IACH,kCAFa,MAAM,EAAE,CAOpB;IAED;;;;;;OAMG;IACH,oCAHW,MAAM,GACJ,UAAU,GAAC,IAAI,CAI3B;IAED;;;;;OAKG;IACH,kBAEC;IAED;;;;OAIG;IACH,uBAEC;IAED;;;;;;;;;;;;;;;OAeG;IACH,UAVW,YAAY,SACZ,GAAG,GACD,WAAW,CA8DvB;IAKD,qCAkCC;IAED;;;;;;;;;;;;;;;;;;OAkBG;IACH,aAbW,GAAG,GACD,WAAW,CA4BvB;IAED;;;;;;;;;;;;;;;;;;;OAmBG;IACH,WARW,GAAG,GACD,WAAW,CAuBvB;IAED;;;;;;OAMG;IACH,yBAJW,SAAS,GACP,WAAW,CAOvB;IAED;;;;;;OAMG;IACH,4BAEC;IAED;;;;;;;;;;;;;;;;;;;OAmBG;IACH,+BAbW,GAAG,yBACH,GAAG,GACD,WAAW,CA+EvB;IAED;;;;;;;;;;;OAWG;IACH,6BAHW,UAAU,GAAG,SAAS,GACpB,WAAW,CA8IvB;IAED;;;;;;;;OAQG;IACH,uBAHW,MAAM,EAAE,GACN,WAAW,CA2BvB;IAED;;;;;;;;;;;;OAYG;IACH,2BALW,MAAM,+BAEN,MAAM,GACJ,WAAW,CA2FvB;IAED;;;;;;;;;OASG;IACH,2CAiCC;IAED;;;;;;;;;;OAUG;IACH,4CAOC;CACD;oCA50ByF,cAAc;+BAAd,cAAc;4BAAd,cAAc;kCAAd,cAAc;gCAAd,cAAc;8BAAd,cAAc"}
1
+ {"version":3,"file":"Transaction.svelte.d.ts","sourceRoot":"","sources":["../src/lib/Transaction.svelte.ts"],"names":[],"mappings":"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"}