svedit 0.6.4 → 0.7.1

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 (66) hide show
  1. package/README.md +117 -45
  2. package/dist/AnnotatedTextProperty.svelte +14 -17
  3. package/dist/AnnotatedTextProperty.svelte.d.ts.map +1 -1
  4. package/dist/Command.svelte.d.ts +3 -3
  5. package/dist/Command.svelte.js +5 -5
  6. package/dist/CustomProperty.svelte +5 -4
  7. package/dist/Node.svelte +29 -14
  8. package/dist/Node.svelte.d.ts.map +1 -1
  9. package/dist/NodeArrayProperty.svelte +29 -9
  10. package/dist/NodeArrayProperty.svelte.d.ts.map +1 -1
  11. package/dist/NodeCaret.svelte +71 -0
  12. package/dist/NodeCaret.svelte.d.ts +27 -0
  13. package/dist/NodeCaret.svelte.d.ts.map +1 -0
  14. package/dist/NodeGap.svelte +249 -0
  15. package/dist/NodeGap.svelte.d.ts +20 -0
  16. package/dist/NodeGap.svelte.d.ts.map +1 -0
  17. package/dist/NodeGapMarkers.svelte +456 -0
  18. package/dist/NodeGapMarkers.svelte.d.ts +12 -0
  19. package/dist/NodeGapMarkers.svelte.d.ts.map +1 -0
  20. package/dist/NodeSelectionMarkers.svelte +49 -0
  21. package/dist/NodeSelectionMarkers.svelte.d.ts +7 -0
  22. package/dist/NodeSelectionMarkers.svelte.d.ts.map +1 -0
  23. package/dist/Session.svelte.d.ts +6 -6
  24. package/dist/Session.svelte.d.ts.map +1 -1
  25. package/dist/Session.svelte.js +13 -69
  26. package/dist/Svedit.svelte +161 -95
  27. package/dist/Svedit.svelte.d.ts.map +1 -1
  28. package/dist/Transaction.svelte.d.ts +1 -1
  29. package/dist/Transaction.svelte.d.ts.map +1 -1
  30. package/dist/Transaction.svelte.js +8 -68
  31. package/dist/doc_utils.d.ts +12 -0
  32. package/dist/doc_utils.d.ts.map +1 -1
  33. package/dist/doc_utils.js +61 -2
  34. package/dist/index.d.ts +4 -0
  35. package/dist/index.js +4 -0
  36. package/dist/node_gap_computation.svelte.d.ts +5 -0
  37. package/dist/node_gap_computation.svelte.d.ts.map +1 -0
  38. package/dist/node_gap_computation.svelte.js +621 -0
  39. package/dist/styles/svedit-colors.css +8 -0
  40. package/dist/transforms.svelte.d.ts +8 -0
  41. package/dist/transforms.svelte.d.ts.map +1 -1
  42. package/dist/transforms.svelte.js +20 -10
  43. package/dist/types.d.ts +56 -68
  44. package/dist/utils.d.ts +0 -3
  45. package/dist/utils.d.ts.map +1 -1
  46. package/dist/utils.js +10 -10
  47. package/package.json +21 -21
  48. package/src/lib/AnnotatedTextProperty.svelte +14 -17
  49. package/src/lib/Command.svelte.js +5 -5
  50. package/src/lib/CustomProperty.svelte +5 -4
  51. package/src/lib/Node.svelte +29 -14
  52. package/src/lib/NodeArrayProperty.svelte +29 -9
  53. package/src/lib/NodeCaret.svelte +71 -0
  54. package/src/lib/NodeGap.svelte +249 -0
  55. package/src/lib/NodeGapMarkers.svelte +456 -0
  56. package/src/lib/NodeSelectionMarkers.svelte +49 -0
  57. package/src/lib/Session.svelte.js +13 -69
  58. package/src/lib/Svedit.svelte +161 -95
  59. package/src/lib/Transaction.svelte.js +8 -68
  60. package/src/lib/doc_utils.js +61 -2
  61. package/src/lib/index.js +4 -0
  62. package/src/lib/node_gap_computation.svelte.js +621 -0
  63. package/src/lib/styles/svedit-colors.css +8 -0
  64. package/src/lib/transforms.svelte.js +20 -10
  65. package/src/lib/types.d.ts +56 -68
  66. package/src/lib/utils.js +10 -10
@@ -18,7 +18,8 @@ import {
18
18
  apply_op,
19
19
  count_references_excluding_deleted,
20
20
  validate_node,
21
- get_active_annotation
21
+ get_active_annotation,
22
+ validate_selection
22
23
  } from './doc_utils.js';
23
24
 
24
25
  /**
@@ -145,7 +146,7 @@ export default class Transaction {
145
146
  }
146
147
 
147
148
  /**
148
- * Returns the annotation object that is currently "under the cursor".
149
+ * Returns the annotation object that is currently "under the caret".
149
150
  * NOTE: Annotations in Svedit are exclusive, so there can only be one active_annotation
150
151
  *
151
152
  * @param {string} [annotation_type] Optional annotation type to filter by
@@ -336,6 +337,7 @@ export default class Transaction {
336
337
  const previous_value = this.get(id);
337
338
  if (!previous_value) {
338
339
  console.warn(`Deletion of node ${id} skipped, as it does not exist.`);
340
+ return this;
339
341
  }
340
342
  // Get nodes referenced by this node BEFORE deleting it.
341
343
  const referenced_nodes = this.get_referenced_nodes(id);
@@ -343,9 +345,7 @@ export default class Transaction {
343
345
  this.ops.push(op);
344
346
  this.inverse_ops.push(['create', previous_value]);
345
347
  this._apply_op(op);
346
- // Check if the nodes that were referenced by the deleted node are now orphaned
347
- // NOTE: We don't do this yet, because we still have some manual child node removal code
348
- // that causes errors. But we should soon implement this only here.
348
+ // Cascade delete any nodes that are now orphaned after removing this node
349
349
  this._cascade_delete_unreferenced_nodes(referenced_nodes);
350
350
  return this;
351
351
  }
@@ -371,50 +371,7 @@ export default class Transaction {
371
371
  * @private
372
372
  */
373
373
  _validate_selection(selection) {
374
- if (!selection) return;
375
-
376
- const selection_type = selection.type;
377
- if (!['node', 'text', 'property'].includes(selection_type)) {
378
- throw new Error(`Invalid selection type: ${selection_type}`);
379
- }
380
-
381
- if (selection_type === 'node') {
382
- const node_array = this.get(selection.path);
383
-
384
- if (!Array.isArray(node_array)) {
385
- throw new Error('Node selection path must point to a node_array');
386
- }
387
-
388
- const max_offset = node_array.length;
389
- if (selection.anchor_offset < 0 || selection.anchor_offset > max_offset) {
390
- throw new Error(
391
- `Node selection anchor_offset (${selection.anchor_offset}) is out of bounds. Max is ${max_offset}.`
392
- );
393
- }
394
- if (selection.focus_offset < 0 || selection.focus_offset > max_offset) {
395
- throw new Error(
396
- `Node selection focus_offset (${selection.focus_offset}) is out of bounds. Max is ${max_offset}.`
397
- );
398
- }
399
- } else if (selection_type === 'text') {
400
- const annotated_text = this.get(selection.path);
401
-
402
- if (!annotated_text || typeof annotated_text.text !== 'string') {
403
- throw new Error('Text selection path must point to annotated_text');
404
- }
405
-
406
- const char_length = get_char_length(annotated_text.text);
407
- if (selection.anchor_offset < 0 || selection.anchor_offset > char_length) {
408
- throw new Error(
409
- `Text selection anchor_offset (${selection.anchor_offset}) is out of bounds. Max is ${char_length}.`
410
- );
411
- }
412
- if (selection.focus_offset < 0 || selection.focus_offset > char_length) {
413
- throw new Error(
414
- `Text selection focus_offset (${selection.focus_offset}) is out of bounds. Max is ${char_length}.`
415
- );
416
- }
417
- }
374
+ validate_selection(selection, this);
418
375
  }
419
376
 
420
377
  /**
@@ -653,7 +610,7 @@ export default class Transaction {
653
610
  insert_nodes(node_ids) {
654
611
  if (this.selection.type !== 'node') return this;
655
612
 
656
- // Unless cursor is collapsed, delete the selected nodes as a first step
613
+ // Unless caret is collapsed, delete the selected nodes as a first step
657
614
  if (this.selection.anchor_offset !== this.selection.focus_offset) {
658
615
  this.delete_selection();
659
616
  }
@@ -661,14 +618,7 @@ export default class Transaction {
661
618
  const path = this.selection.path;
662
619
  const node_array = [...this.get(path)];
663
620
 
664
- // Get the start and end indices for the selection
665
621
  let start = Math.min(this.selection.anchor_offset, this.selection.focus_offset);
666
- let end = Math.max(this.selection.anchor_offset, this.selection.focus_offset);
667
-
668
- if (start !== end) {
669
- // Remove the selected nodes from the node_array
670
- node_array.splice(start, end - start);
671
- }
672
622
 
673
623
  // Insert the new nodes
674
624
  node_array.splice(start, 0, ...node_ids);
@@ -744,16 +694,6 @@ export default class Transaction {
744
694
  node_id
745
695
  };
746
696
  }
747
-
748
- // Insertion point is inside the annotation - extend the annotation
749
- if (annotation_start < range.start_offset && annotation_end > range.start_offset) {
750
- return {
751
- start_offset: annotation_start,
752
- end_offset: annotation_end + delta,
753
- node_id
754
- };
755
- }
756
-
757
697
  return annotation;
758
698
  });
759
699
 
@@ -771,7 +711,7 @@ export default class Transaction {
771
711
  this.selection = new_selection;
772
712
 
773
713
  // Now we apply annotations if there are any, but only if there's no active annotation
774
- // at the current collapsed cursor
714
+ // at the current collapsed caret
775
715
  if (!this.active_annotation() && annotations.length > 0) {
776
716
  const new_annotations = annotations
777
717
  .map((annotation) => {
@@ -114,6 +114,18 @@ export function get_active_annotation(schema: DocumentSchema, doc: Document, sel
114
114
  * @returns {number} The number of references excluding deleted nodes
115
115
  */
116
116
  export function count_references_excluding_deleted(schema: DocumentSchema, doc: Document, target_node_id: NodeId, nodes_to_delete: Record<NodeId, boolean>): number;
117
+ /**
118
+ * Validates a selection against the current document state.
119
+ * Works with any object that implements get() and inspect() (Session or Transaction).
120
+ *
121
+ * @param {Selection} selection - The selection to validate
122
+ * @param {{ get: Function, inspect: Function }} session_or_transaction - A Session or Transaction instance
123
+ * @throws {Error} Throws if the selection is invalid
124
+ */
125
+ export function validate_selection(selection: Selection, session_or_transaction: {
126
+ get: Function;
127
+ inspect: Function;
128
+ }): void;
117
129
  import type { NodeSchema } from './types';
118
130
  import type { PrimitiveType } from './types';
119
131
  import type { NodeProperty } from './types';
@@ -1 +1 @@
1
- {"version":3,"file":"doc_utils.d.ts","sourceRoot":"","sources":["../src/lib/doc_utils.js"],"names":[],"mappings":"AAWA;;;;;;;GAOG;AACH,uCAJ0C,CAAC,SAA7B,MAAM,CAAC,MAAM,EAAE,UAAU,CAAE,UAC9B,CAAC,GACC,CAAC,CAIb;AAED;;;;GAIG;AACH,wCAHW,MAAM,GACJ,IAAI,IAAI,aAAa,CAejC;AAED;;;;GAIG;AACH,2DAHW,YAAY,GAAG,iBAAiB,GAC9B,MAAM,GAAG,IAAI,CAWzB;AAED;;;;GAIG;AACH,0DAHW,cAAc,QAmBxB;AAgDD;;;;;;GAMG;AACH,oCALW,GAAG,UACH,cAAc,cACd,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,QA6D7B;AAED;;;;;;;GAOG;AACH,4BALW,cAAc,OACd,QAAQ,QACR,YAAY,GAAC,MAAM,GACjB,GAAG,CA4Ef;AAED;;;;;;;GAOG;AACH,sCALW,MAAM,QACN,MAAM,YACN,MAAM,GACJ,MAAM,CAclB;AAED;;;;;;GAMG;AACH,6BAJW,MAAM,QACN,GAAG,GACD,OAAO,GAAC,MAAM,GAAC,YAAY,CAIvC;AAED;;;;;;;GAOG;AACH,gCALW,cAAc,OACd,QAAQ,QACR,YAAY,GACV;IAAC,IAAI,EAAE,UAAU,GAAC,MAAM,CAAC;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CAAC,CAoBzD;AAED;;;;;;;GAOG;AACH,8BAJW,QAAQ,cAEN,QAAQ,CAkCpB;AAED;;;;;;;GAOG;AACH,yCALW,cAAc,OACd,QAAQ,WACR,MAAM,GACJ,MAAM,CAoBlB;AAED;;;;;;;;;;;;;GAaG;AACH,8CANW,cAAc,OACd,QAAQ,cACR,SAAS,oBACT,MAAM,GACJ,UAAU,GAAG,IAAI,CAwB7B;AAED;;;;;;;;GAQG;AACH,2DANW,cAAc,OACd,QAAQ,kBACR,MAAM,mBACN,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACrB,MAAM,CA0BlB;gCA3dqJ,SAAS;mCAAT,SAAS;kCAAT,SAAS;uCAAT,SAAS;oCAAT,SAAS;8BAAT,SAAS;kCAAT,SAAS;4BAAT,SAAS;+BAAT,SAAS;gCAAT,SAAS"}
1
+ {"version":3,"file":"doc_utils.d.ts","sourceRoot":"","sources":["../src/lib/doc_utils.js"],"names":[],"mappings":"AAWA;;;;;;;GAOG;AACH,uCAJ0C,CAAC,SAA7B,MAAM,CAAC,MAAM,EAAE,UAAU,CAAE,UAC9B,CAAC,GACC,CAAC,CAIb;AAED;;;;GAIG;AACH,wCAHW,MAAM,GACJ,IAAI,IAAI,aAAa,CAejC;AAED;;;;GAIG;AACH,2DAHW,YAAY,GAAG,iBAAiB,GAC9B,MAAM,GAAG,IAAI,CAWzB;AAED;;;;GAIG;AACH,0DAHW,cAAc,QAmBxB;AAgDD;;;;;;GAMG;AACH,oCALW,GAAG,UACH,cAAc,cACd,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,QA6D7B;AAED;;;;;;;GAOG;AACH,4BALW,cAAc,OACd,QAAQ,QACR,YAAY,GAAC,MAAM,GACjB,GAAG,CA4Ef;AAED;;;;;;;GAOG;AACH,sCALW,MAAM,QACN,MAAM,YACN,MAAM,GACJ,MAAM,CAclB;AAED;;;;;;GAMG;AACH,6BAJW,MAAM,QACN,GAAG,GACD,OAAO,GAAC,MAAM,GAAC,YAAY,CAIvC;AAED;;;;;;;GAOG;AACH,gCALW,cAAc,OACd,QAAQ,QACR,YAAY,GACV;IAAC,IAAI,EAAE,UAAU,GAAC,MAAM,CAAC;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CAAC,CAoBzD;AAED;;;;;;;GAOG;AACH,8BAJW,QAAQ,cAEN,QAAQ,CAkCpB;AAED;;;;;;;GAOG;AACH,yCALW,cAAc,OACd,QAAQ,WACR,MAAM,GACJ,MAAM,CAoBlB;AAED;;;;;;;;;;;;;GAaG;AACH,8CANW,cAAc,OACd,QAAQ,cACR,SAAS,oBACT,MAAM,GACJ,UAAU,GAAG,IAAI,CAwB7B;AAED;;;;;;;;GAQG;AACH,2DANW,cAAc,OACd,QAAQ,kBACR,MAAM,mBACN,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACrB,MAAM,CA0BlB;AAED;;;;;;;GAOG;AACH,8CAJW,SAAS,0BACT;IAAE,GAAG,WAAW;IAAC,OAAO,WAAU;CAAE,QAoD9C;gCAthBqJ,SAAS;mCAAT,SAAS;kCAAT,SAAS;uCAAT,SAAS;oCAAT,SAAS;8BAAT,SAAS;kCAAT,SAAS;4BAAT,SAAS;+BAAT,SAAS;gCAAT,SAAS"}
package/dist/doc_utils.js CHANGED
@@ -7,7 +7,7 @@
7
7
  * @import { NodeId, DocumentPath, PrimitiveType, NodeProperty, NodeArrayProperty, NodeSchema, DocumentSchema, Selection, Annotation, Document } from './types'
8
8
  */
9
9
 
10
- import { get_selection_range } from './utils.js';
10
+ import { get_selection_range, get_char_length } from './utils.js';
11
11
 
12
12
  /**
13
13
  * Identity function — keeps schema at runtime & makes IDE infer types.
@@ -119,7 +119,7 @@ function validate_primitive_value(type, value) {
119
119
  }
120
120
 
121
121
  /**
122
- * @param {String} id
122
+ * @param {string} id
123
123
  * @returns {boolean}
124
124
  */
125
125
  function is_id_valid(id) {
@@ -480,3 +480,62 @@ export function count_references_excluding_deleted(schema, doc, target_node_id,
480
480
 
481
481
  return count;
482
482
  }
483
+
484
+ /**
485
+ * Validates a selection against the current document state.
486
+ * Works with any object that implements get() and inspect() (Session or Transaction).
487
+ *
488
+ * @param {Selection} selection - The selection to validate
489
+ * @param {{ get: Function, inspect: Function }} session_or_transaction - A Session or Transaction instance
490
+ * @throws {Error} Throws if the selection is invalid
491
+ */
492
+ export function validate_selection(selection, session_or_transaction) {
493
+ if (!selection) return;
494
+
495
+ const selection_type = selection.type;
496
+ if (!['node', 'text', 'property'].includes(selection_type)) {
497
+ throw new Error(`Invalid selection type: ${selection_type}`);
498
+ }
499
+
500
+ if (selection_type === 'node') {
501
+ const node_array = session_or_transaction.get(selection.path);
502
+
503
+ if (!Array.isArray(node_array)) {
504
+ throw new Error('Node selection path must point to a node_array');
505
+ }
506
+
507
+ const max_offset = node_array.length;
508
+ if (selection.anchor_offset < 0 || selection.anchor_offset > max_offset) {
509
+ throw new Error(
510
+ `Node selection anchor_offset (${selection.anchor_offset}) is out of bounds. Max is ${max_offset}.`
511
+ );
512
+ }
513
+ if (selection.focus_offset < 0 || selection.focus_offset > max_offset) {
514
+ throw new Error(
515
+ `Node selection focus_offset (${selection.focus_offset}) is out of bounds. Max is ${max_offset}.`
516
+ );
517
+ }
518
+ } else if (selection_type === 'text') {
519
+ const annotated_text = session_or_transaction.get(selection.path);
520
+
521
+ if (!annotated_text || typeof annotated_text.text !== 'string') {
522
+ throw new Error('Text selection path must point to annotated_text');
523
+ }
524
+
525
+ const char_length = get_char_length(annotated_text.text);
526
+ if (selection.anchor_offset < 0 || selection.anchor_offset > char_length) {
527
+ throw new Error(
528
+ `Text selection anchor_offset (${selection.anchor_offset}) is out of bounds. Max is ${char_length}.`
529
+ );
530
+ }
531
+ if (selection.focus_offset < 0 || selection.focus_offset > char_length) {
532
+ throw new Error(
533
+ `Text selection focus_offset (${selection.focus_offset}) is out of bounds. Max is ${char_length}.`
534
+ );
535
+ }
536
+ } else if (selection_type === 'property') {
537
+ if (!session_or_transaction.inspect(selection.path)) {
538
+ throw new Error(`Property selection path not found: ${selection.path.join('.')}`);
539
+ }
540
+ }
541
+ }
package/dist/index.d.ts CHANGED
@@ -3,6 +3,10 @@ export { default as AnnotatedTextProperty } from "./AnnotatedTextProperty.svelte
3
3
  export { default as CustomProperty } from "./CustomProperty.svelte";
4
4
  export { default as Node } from "./Node.svelte";
5
5
  export { default as NodeArrayProperty } from "./NodeArrayProperty.svelte";
6
+ export { default as NodeGap } from "./NodeGap.svelte";
7
+ export { default as NodeGapMarkers } from "./NodeGapMarkers.svelte";
8
+ export { default as NodeCaret } from "./NodeCaret.svelte";
9
+ export { default as NodeSelectionMarkers } from "./NodeSelectionMarkers.svelte";
6
10
  export { default as Session } from "./Session.svelte.js";
7
11
  export { default as Transaction } from "./Transaction.svelte.js";
8
12
  export { default as Command } from "./Command.svelte.js";
package/dist/index.js CHANGED
@@ -4,6 +4,10 @@ export { default as AnnotatedTextProperty } from './AnnotatedTextProperty.svelte
4
4
  export { default as CustomProperty } from './CustomProperty.svelte';
5
5
  export { default as Node } from './Node.svelte';
6
6
  export { default as NodeArrayProperty } from './NodeArrayProperty.svelte';
7
+ export { default as NodeGap } from './NodeGap.svelte';
8
+ export { default as NodeGapMarkers } from './NodeGapMarkers.svelte';
9
+ export { default as NodeCaret } from './NodeCaret.svelte';
10
+ export { default as NodeSelectionMarkers } from './NodeSelectionMarkers.svelte';
7
11
 
8
12
  // Core classes and utilities
9
13
  export { default as Session } from './Session.svelte.js';
@@ -0,0 +1,5 @@
1
+ /**
2
+ * @param {object} svedit - Svedit context (session, editable, doc, schema, etc.)
3
+ */
4
+ export function create_gap_computation(svedit: object): void;
5
+ //# sourceMappingURL=node_gap_computation.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node_gap_computation.svelte.d.ts","sourceRoot":"","sources":["../src/lib/node_gap_computation.svelte.js"],"names":[],"mappings":"AAkWA;;GAEG;AACH,+CAFW,MAAM,QAyQhB"}