svedit 0.12.0 → 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.
- package/README.md +33 -21
- package/dist/Command.svelte.d.ts +38 -30
- package/dist/Command.svelte.d.ts.map +1 -1
- package/dist/Command.svelte.js +271 -326
- package/dist/CustomProperty.svelte +3 -5
- package/dist/CustomProperty.svelte.d.ts +3 -6
- package/dist/CustomProperty.svelte.d.ts.map +1 -1
- package/dist/KeyMapper.svelte.d.ts +19 -6
- package/dist/KeyMapper.svelte.d.ts.map +1 -1
- package/dist/KeyMapper.svelte.js +95 -112
- package/dist/Node.svelte +16 -13
- package/dist/Node.svelte.d.ts +3 -5
- package/dist/Node.svelte.d.ts.map +1 -1
- package/dist/NodeArrayProperty.svelte +39 -22
- package/dist/NodeArrayProperty.svelte.d.ts +3 -5
- package/dist/NodeArrayProperty.svelte.d.ts.map +1 -1
- package/dist/NodeCaret.svelte +1 -1
- package/dist/NodeCaret.svelte.d.ts +6 -14
- package/dist/NodeCaret.svelte.d.ts.map +1 -1
- package/dist/NodeGap.svelte +12 -6
- package/dist/NodeGap.svelte.d.ts +7 -14
- package/dist/NodeGap.svelte.d.ts.map +1 -1
- package/dist/NodeGapMarkers.svelte +19 -10
- package/dist/NodeGapMarkers.svelte.d.ts +6 -11
- package/dist/NodeGapMarkers.svelte.d.ts.map +1 -1
- package/dist/NodeSelectionMarkers.svelte +20 -6
- package/dist/NodeSelectionMarkers.svelte.d.ts +2 -5
- package/dist/NodeSelectionMarkers.svelte.d.ts.map +1 -1
- package/dist/Session.svelte.d.ts +81 -129
- package/dist/Session.svelte.d.ts.map +1 -1
- package/dist/Session.svelte.js +542 -648
- package/dist/Svedit.svelte +144 -138
- package/dist/Svedit.svelte.d.ts +30 -10
- package/dist/Svedit.svelte.d.ts.map +1 -1
- package/dist/TextProperty.svelte +32 -18
- package/dist/TextProperty.svelte.d.ts +3 -5
- package/dist/TextProperty.svelte.d.ts.map +1 -1
- package/dist/Transaction.svelte.d.ts +64 -127
- package/dist/Transaction.svelte.d.ts.map +1 -1
- package/dist/Transaction.svelte.js +839 -1001
- package/dist/UnknownNode.svelte +4 -3
- package/dist/UnknownNode.svelte.d.ts +5 -9
- package/dist/UnknownNode.svelte.d.ts.map +1 -1
- package/dist/doc_utils.d.ts +67 -155
- package/dist/doc_utils.d.ts.map +1 -1
- package/dist/doc_utils.js +619 -863
- package/dist/index.d.ts +20 -17
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -17
- package/dist/node_visibility.svelte.d.ts +110 -9
- package/dist/node_visibility.svelte.d.ts.map +1 -1
- package/dist/node_visibility.svelte.js +473 -544
- package/dist/paste_utils.d.ts +11 -44
- package/dist/paste_utils.d.ts.map +1 -1
- package/dist/paste_utils.js +111 -152
- package/dist/transforms.svelte.d.ts +9 -7
- package/dist/transforms.svelte.d.ts.map +1 -1
- package/dist/transforms.svelte.js +125 -150
- package/dist/types.d.ts +277 -309
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +1 -0
- package/dist/utils.d.ts +40 -119
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +346 -473
- package/package.json +69 -70
- package/src/lib/{Command.svelte.js → Command.svelte.ts} +29 -17
- package/src/lib/CustomProperty.svelte +3 -5
- package/src/lib/{KeyMapper.svelte.js → KeyMapper.svelte.ts} +28 -11
- package/src/lib/Node.svelte +16 -13
- package/src/lib/NodeArrayProperty.svelte +39 -22
- package/src/lib/NodeCaret.svelte +1 -1
- package/src/lib/NodeGap.svelte +12 -6
- package/src/lib/NodeGapMarkers.svelte +19 -10
- package/src/lib/NodeSelectionMarkers.svelte +20 -6
- package/src/lib/{Session.svelte.js → Session.svelte.ts} +130 -127
- package/src/lib/Svedit.svelte +144 -138
- package/src/lib/TextProperty.svelte +32 -18
- package/src/lib/{Transaction.svelte.js → Transaction.svelte.ts} +139 -143
- package/src/lib/UnknownNode.svelte +4 -3
- package/src/lib/{doc_utils.js → doc_utils.ts} +247 -206
- package/src/lib/{index.js → index.ts} +47 -0
- package/src/lib/{node_visibility.svelte.js → node_visibility.svelte.ts} +68 -92
- package/src/lib/{paste_utils.js → paste_utils.ts} +47 -58
- package/src/lib/{transforms.svelte.js → transforms.svelte.ts} +39 -21
- package/src/lib/{types.d.ts → types.ts} +143 -66
- package/src/lib/{utils.js → utils.ts} +110 -129
|
@@ -13,6 +13,53 @@ export { default as NodeSelectionMarkers } from './NodeSelectionMarkers.svelte';
|
|
|
13
13
|
export { default as Session } from './Session.svelte.js';
|
|
14
14
|
export { default as Transaction } from './Transaction.svelte.js';
|
|
15
15
|
|
|
16
|
+
// Public types
|
|
17
|
+
export type {
|
|
18
|
+
// Schema definition
|
|
19
|
+
DocumentSchema,
|
|
20
|
+
NodeSchema,
|
|
21
|
+
NodeKind,
|
|
22
|
+
PropertyDefinition,
|
|
23
|
+
PropertyType,
|
|
24
|
+
// Schema-derived node types
|
|
25
|
+
PropertyValue,
|
|
26
|
+
NodeOfType,
|
|
27
|
+
AnyNode,
|
|
28
|
+
NodeMap,
|
|
29
|
+
DynamicRecord,
|
|
30
|
+
SessionConfig,
|
|
31
|
+
CommandRegistry,
|
|
32
|
+
DocumentOperation,
|
|
33
|
+
Inspection,
|
|
34
|
+
// Documents and nodes
|
|
35
|
+
Document,
|
|
36
|
+
DocumentNode,
|
|
37
|
+
DocumentPath,
|
|
38
|
+
NodeId,
|
|
39
|
+
// Values
|
|
40
|
+
Text,
|
|
41
|
+
NodeArray,
|
|
42
|
+
Attachment,
|
|
43
|
+
Mark,
|
|
44
|
+
Annotation,
|
|
45
|
+
// Selections
|
|
46
|
+
Selection,
|
|
47
|
+
TextSelection,
|
|
48
|
+
NodeSelection,
|
|
49
|
+
PropertySelection,
|
|
50
|
+
SelectionRange,
|
|
51
|
+
// Component props and render contexts
|
|
52
|
+
SveditProps,
|
|
53
|
+
SveditContext,
|
|
54
|
+
TextPropertyProps,
|
|
55
|
+
CustomPropertyProps,
|
|
56
|
+
NodeArrayPropertyProps,
|
|
57
|
+
NodeProps,
|
|
58
|
+
NodeArrayAttachmentContext
|
|
59
|
+
} from './types.js';
|
|
60
|
+
export type { SelectedAttachment } from './doc_utils.js';
|
|
61
|
+
export type { Keymap } from './KeyMapper.svelte.js';
|
|
62
|
+
|
|
16
63
|
// Document utilities
|
|
17
64
|
export {
|
|
18
65
|
define_document_schema,
|
|
@@ -120,9 +120,8 @@ class VisibilityRegistry {
|
|
|
120
120
|
* Stable references — once a SvelteSet is created for an array path
|
|
121
121
|
* it survives re-renders so consumers stay subscribed.
|
|
122
122
|
*
|
|
123
|
-
* @type {Map<string, SvelteSet<number>>}
|
|
124
123
|
*/
|
|
125
|
-
#array_indices = new Map();
|
|
124
|
+
#array_indices: Map<string, SvelteSet<number>> = new Map();
|
|
126
125
|
|
|
127
126
|
/**
|
|
128
127
|
* Per-array edge-proximity state. `first` is true when the first
|
|
@@ -138,15 +137,12 @@ class VisibilityRegistry {
|
|
|
138
137
|
* only render when the edge node has actually reached the matching
|
|
139
138
|
* end of its container.
|
|
140
139
|
*
|
|
141
|
-
* @type {SvelteMap<string, { first: boolean, last: boolean }>}
|
|
142
140
|
*/
|
|
143
|
-
edge_map = new SvelteMap();
|
|
141
|
+
edge_map: SvelteMap<string, { first: boolean; last: boolean }> = new SvelteMap();
|
|
144
142
|
|
|
145
|
-
|
|
146
|
-
#io = null;
|
|
143
|
+
#io: IntersectionObserver | null = null;
|
|
147
144
|
|
|
148
|
-
|
|
149
|
-
#view_io = null;
|
|
145
|
+
#view_io: IntersectionObserver | null = null;
|
|
150
146
|
|
|
151
147
|
/**
|
|
152
148
|
* Re-syncs edge state when a registered array's box changes size
|
|
@@ -156,35 +152,31 @@ class VisibilityRegistry {
|
|
|
156
152
|
* change, so neither of the other two triggers would catch them.
|
|
157
153
|
* Writes are change-detected, so redundant firings are no-ops.
|
|
158
154
|
*
|
|
159
|
-
* @type {ResizeObserver | null}
|
|
160
155
|
*/
|
|
161
|
-
#array_ro = null;
|
|
156
|
+
#array_ro: ResizeObserver | null = null;
|
|
162
157
|
|
|
163
158
|
/**
|
|
164
159
|
* Registered node elements and the path each was registered under.
|
|
165
160
|
* The attachment closure carries the path, so a stale data-path
|
|
166
161
|
* attribute can never desync state.
|
|
167
162
|
*
|
|
168
|
-
* @type {Map<HTMLElement, string>}
|
|
169
163
|
*/
|
|
170
|
-
#registered_paths = new Map();
|
|
164
|
+
#registered_paths: Map<HTMLElement, string> = new Map();
|
|
171
165
|
|
|
172
166
|
/**
|
|
173
167
|
* Which element currently owns a node path. Guards unregistration
|
|
174
168
|
* against keyed-update collisions (see module doc).
|
|
175
169
|
*
|
|
176
|
-
* @type {Map<string, HTMLElement>}
|
|
177
170
|
*/
|
|
178
|
-
#path_owners = new Map();
|
|
171
|
+
#path_owners: Map<string, HTMLElement> = new Map();
|
|
179
172
|
|
|
180
|
-
|
|
181
|
-
#near_nodes = new Set();
|
|
173
|
+
#near_nodes: Set<HTMLElement> = new Set();
|
|
182
174
|
|
|
183
|
-
/** Registered node-array container elements.
|
|
184
|
-
#array_els = new Set();
|
|
175
|
+
/** Registered node-array container elements. */
|
|
176
|
+
#array_els: Set<Element> = new Set();
|
|
185
177
|
|
|
186
|
-
/** Which element currently owns an array path.
|
|
187
|
-
#array_owners = new Map();
|
|
178
|
+
/** Which element currently owns an array path. */
|
|
179
|
+
#array_owners: Map<string, Element> = new Map();
|
|
188
180
|
|
|
189
181
|
/**
|
|
190
182
|
* When true, a second IO (rootMargin 0, actual viewport) toggles
|
|
@@ -271,10 +263,8 @@ class VisibilityRegistry {
|
|
|
271
263
|
* the set and reads `.has()` in the same derived never subscribes
|
|
272
264
|
* and never re-evaluates.
|
|
273
265
|
*
|
|
274
|
-
* @param {string} array_path_str
|
|
275
|
-
* @returns {SvelteSet<number>}
|
|
276
266
|
*/
|
|
277
|
-
get_array_indices(array_path_str) {
|
|
267
|
+
get_array_indices(array_path_str: string): SvelteSet<number> {
|
|
278
268
|
let set = this.#array_indices.get(array_path_str);
|
|
279
269
|
if (!set) {
|
|
280
270
|
set = new SvelteSet();
|
|
@@ -291,10 +281,9 @@ class VisibilityRegistry {
|
|
|
291
281
|
* viewport transitions. Re-runs when the element is recreated or
|
|
292
282
|
* its path changes; the teardown unregisters collision-safely.
|
|
293
283
|
*
|
|
294
|
-
* @param {string} path
|
|
295
284
|
*/
|
|
296
|
-
track_node(path) {
|
|
297
|
-
return (
|
|
285
|
+
track_node(path: string) {
|
|
286
|
+
return (el: HTMLElement) => {
|
|
298
287
|
this.#register_node(el, path);
|
|
299
288
|
return () => this.#unregister_node(el, path);
|
|
300
289
|
};
|
|
@@ -305,10 +294,9 @@ class VisibilityRegistry {
|
|
|
305
294
|
* arrays get their edge state synced on mount, on scroll (via the
|
|
306
295
|
* document scroll listener) and after document changes.
|
|
307
296
|
*
|
|
308
|
-
* @param {string} path
|
|
309
297
|
*/
|
|
310
|
-
track_array(path) {
|
|
311
|
-
return (
|
|
298
|
+
track_array(path: string) {
|
|
299
|
+
return (el: Element) => {
|
|
312
300
|
this.start();
|
|
313
301
|
this.#array_els.add(el);
|
|
314
302
|
this.#array_owners.set(path, el);
|
|
@@ -334,9 +322,8 @@ class VisibilityRegistry {
|
|
|
334
322
|
* registry instance. Scopes the document-level scroll listener to
|
|
335
323
|
* this editor without any DOM traversal.
|
|
336
324
|
*
|
|
337
|
-
* @param {Element} el
|
|
338
325
|
*/
|
|
339
|
-
has_array(el) {
|
|
326
|
+
has_array(el: Element): boolean {
|
|
340
327
|
return this.#array_els.has(el);
|
|
341
328
|
}
|
|
342
329
|
|
|
@@ -351,11 +338,7 @@ class VisibilityRegistry {
|
|
|
351
338
|
}
|
|
352
339
|
}
|
|
353
340
|
|
|
354
|
-
|
|
355
|
-
* @param {HTMLElement} el
|
|
356
|
-
* @param {string} path
|
|
357
|
-
*/
|
|
358
|
-
#register_node(el, path) {
|
|
341
|
+
#register_node(el: HTMLElement, path: string): void {
|
|
359
342
|
this.start();
|
|
360
343
|
untrack(() => {
|
|
361
344
|
this.#registered_paths.set(el, path);
|
|
@@ -373,24 +356,20 @@ class VisibilityRegistry {
|
|
|
373
356
|
const vw = window.innerWidth;
|
|
374
357
|
const is_near =
|
|
375
358
|
!this.visibility_culling ||
|
|
376
|
-
(bcr
|
|
377
|
-
bcr
|
|
378
|
-
bcr
|
|
379
|
-
bcr
|
|
359
|
+
(bcr!.bottom > -OVERSCAN_PX &&
|
|
360
|
+
bcr!.top < vh + OVERSCAN_PX &&
|
|
361
|
+
bcr!.right > -OVERSCAN_PX &&
|
|
362
|
+
bcr!.left < vw + OVERSCAN_PX);
|
|
380
363
|
if (is_near) this.#add_near_node(el, path);
|
|
381
364
|
|
|
382
365
|
if (this.view_classes) {
|
|
383
|
-
const in_viewport = bcr
|
|
384
|
-
this.#apply_view_classes(el, in_viewport, bcr
|
|
366
|
+
const in_viewport = bcr!.bottom > 0 && bcr!.top < vh && bcr!.right > 0 && bcr!.left < vw;
|
|
367
|
+
this.#apply_view_classes(el, in_viewport, bcr!, vh);
|
|
385
368
|
}
|
|
386
369
|
});
|
|
387
370
|
}
|
|
388
371
|
|
|
389
|
-
|
|
390
|
-
* @param {HTMLElement} el
|
|
391
|
-
* @param {string} path
|
|
392
|
-
*/
|
|
393
|
-
#unregister_node(el, path) {
|
|
372
|
+
#unregister_node(el: HTMLElement, path: string): void {
|
|
394
373
|
this.#registered_paths.delete(el);
|
|
395
374
|
this.#near_nodes.delete(el);
|
|
396
375
|
this.#io?.unobserve(el);
|
|
@@ -406,21 +385,13 @@ class VisibilityRegistry {
|
|
|
406
385
|
});
|
|
407
386
|
}
|
|
408
387
|
|
|
409
|
-
|
|
410
|
-
* @param {HTMLElement} el
|
|
411
|
-
* @param {string} path
|
|
412
|
-
*/
|
|
413
|
-
#add_near_node(el, path) {
|
|
388
|
+
#add_near_node(el: HTMLElement, path: string): void {
|
|
414
389
|
this.#near_nodes.add(el);
|
|
415
390
|
const split = this.#split_path(path);
|
|
416
391
|
if (split) this.get_array_indices(split.array_path).add(split.index);
|
|
417
392
|
}
|
|
418
393
|
|
|
419
|
-
|
|
420
|
-
* @param {HTMLElement} el
|
|
421
|
-
* @param {string} path
|
|
422
|
-
*/
|
|
423
|
-
#remove_near_node(el, path) {
|
|
394
|
+
#remove_near_node(el: HTMLElement, path: string): void {
|
|
424
395
|
this.#near_nodes.delete(el);
|
|
425
396
|
if (this.#path_owners.get(path) !== el) return;
|
|
426
397
|
const split = this.#split_path(path);
|
|
@@ -445,12 +416,10 @@ class VisibilityRegistry {
|
|
|
445
416
|
* called transitively from $effect contexts without self-
|
|
446
417
|
* invalidation.
|
|
447
418
|
*
|
|
448
|
-
* @param {Element} array_el
|
|
449
|
-
* @returns {boolean}
|
|
450
419
|
*/
|
|
451
|
-
sync_edge_state(array_el) {
|
|
420
|
+
sync_edge_state(array_el: Element): boolean {
|
|
452
421
|
if (!array_el) return false;
|
|
453
|
-
const path =
|
|
422
|
+
const path = (array_el as HTMLElement).dataset.path;
|
|
454
423
|
if (!path) return false;
|
|
455
424
|
|
|
456
425
|
// Check computed overflow BEFORE touching scroll metrics. Reading
|
|
@@ -487,13 +456,12 @@ class VisibilityRegistry {
|
|
|
487
456
|
});
|
|
488
457
|
}
|
|
489
458
|
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
#apply_view_classes(el, in_viewport, bcr, vh) {
|
|
459
|
+
#apply_view_classes(
|
|
460
|
+
el: HTMLElement,
|
|
461
|
+
in_viewport: boolean,
|
|
462
|
+
bcr: DOMRectReadOnly,
|
|
463
|
+
vh: number
|
|
464
|
+
): void {
|
|
497
465
|
const cl = el.classList;
|
|
498
466
|
cl.toggle('in-view', in_viewport);
|
|
499
467
|
if (in_viewport) {
|
|
@@ -508,11 +476,7 @@ class VisibilityRegistry {
|
|
|
508
476
|
}
|
|
509
477
|
}
|
|
510
478
|
|
|
511
|
-
|
|
512
|
-
* @param {string} path
|
|
513
|
-
* @returns {{ array_path: string, index: number } | null}
|
|
514
|
-
*/
|
|
515
|
-
#split_path(path) {
|
|
479
|
+
#split_path(path: string): { array_path: string; index: number } | null {
|
|
516
480
|
const sep = path.lastIndexOf(PATH_SEPARATOR);
|
|
517
481
|
if (sep < 0) return null;
|
|
518
482
|
const index = parseInt(path.slice(sep + PATH_SEPARATOR.length), 10);
|
|
@@ -524,11 +488,10 @@ class VisibilityRegistry {
|
|
|
524
488
|
* Overscan IO callback. Manages the array_indices sets; NodeGap
|
|
525
489
|
* reacts to the map writes and updates .positioned declaratively.
|
|
526
490
|
*
|
|
527
|
-
* @param {IntersectionObserverEntry[]} entries
|
|
528
491
|
*/
|
|
529
|
-
#process_near(entries) {
|
|
492
|
+
#process_near(entries: IntersectionObserverEntry[]): void {
|
|
530
493
|
for (const entry of entries) {
|
|
531
|
-
const el =
|
|
494
|
+
const el = entry.target as HTMLElement;
|
|
532
495
|
const path = this.#registered_paths.get(el);
|
|
533
496
|
if (!path || !el.isConnected) continue;
|
|
534
497
|
|
|
@@ -544,12 +507,11 @@ class VisibilityRegistry {
|
|
|
544
507
|
* Runs on a separate observer with rootMargin 0 so thresholds
|
|
545
508
|
* fire at actual viewport edges, not the overscan boundary.
|
|
546
509
|
*
|
|
547
|
-
* @param {IntersectionObserverEntry[]} entries
|
|
548
510
|
*/
|
|
549
|
-
#process_view(entries) {
|
|
511
|
+
#process_view(entries: IntersectionObserverEntry[]): void {
|
|
550
512
|
const vh = window.innerHeight;
|
|
551
513
|
for (const entry of entries) {
|
|
552
|
-
const el =
|
|
514
|
+
const el = entry.target as HTMLElement;
|
|
553
515
|
if (!this.#registered_paths.has(el) || !el.isConnected) continue;
|
|
554
516
|
this.#apply_view_classes(el, entry.isIntersecting, entry.boundingClientRect, vh);
|
|
555
517
|
}
|
|
@@ -564,9 +526,16 @@ class VisibilityRegistry {
|
|
|
564
526
|
* The IntersectionObservers own viewport changes; document changes
|
|
565
527
|
* only trigger an edge-state re-sync over the registered arrays.
|
|
566
528
|
*
|
|
567
|
-
* @param
|
|
529
|
+
* @param svedit - Svedit context (session, editable)
|
|
568
530
|
*/
|
|
569
|
-
export function create_node_visibility(svedit
|
|
531
|
+
export function create_node_visibility(svedit: {
|
|
532
|
+
session: {
|
|
533
|
+
config?: { view_classes?: boolean; visibility_culling?: boolean };
|
|
534
|
+
doc: unknown;
|
|
535
|
+
};
|
|
536
|
+
editable: boolean;
|
|
537
|
+
visibility_registry?: VisibilityRegistryApi;
|
|
538
|
+
}): void {
|
|
570
539
|
const registry = new VisibilityRegistry();
|
|
571
540
|
registry.view_classes = svedit.session?.config?.view_classes !== false;
|
|
572
541
|
registry.visibility_culling = svedit.session?.config?.visibility_culling !== false;
|
|
@@ -587,9 +556,8 @@ export function create_node_visibility(svedit) {
|
|
|
587
556
|
* coalesces array scrolls into one RAF that reads only scrollLeft /
|
|
588
557
|
* scrollWidth / clientWidth — no per-node BCRs.
|
|
589
558
|
*/
|
|
590
|
-
/** @type {Set<Element>} */
|
|
591
559
|
// eslint-disable-next-line svelte/prefer-svelte-reactivity -- Non-reactive RAF queue.
|
|
592
|
-
const pending_scroll_arrays = new Set();
|
|
560
|
+
const pending_scroll_arrays: Set<Element> = new Set();
|
|
593
561
|
let scroll_raf = 0;
|
|
594
562
|
function flush_scroll_sync() {
|
|
595
563
|
scroll_raf = 0;
|
|
@@ -598,9 +566,8 @@ export function create_node_visibility(svedit) {
|
|
|
598
566
|
}
|
|
599
567
|
pending_scroll_arrays.clear();
|
|
600
568
|
}
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
const target = /** @type {Element | null} */ (event.target);
|
|
569
|
+
function on_scroll(event: Event) {
|
|
570
|
+
const target = event.target as Element | null;
|
|
604
571
|
const arr = target?.closest?.('[data-type="node_array"]');
|
|
605
572
|
if (!arr || !registry.has_array(arr)) return;
|
|
606
573
|
pending_scroll_arrays.add(arr);
|
|
@@ -636,6 +603,13 @@ export function create_node_visibility(svedit) {
|
|
|
636
603
|
});
|
|
637
604
|
}
|
|
638
605
|
|
|
606
|
+
export type VisibilityRegistryApi = {
|
|
607
|
+
edge_map: SvelteMap<string, { first: boolean; last: boolean }>;
|
|
608
|
+
get_array_indices(array_path_str: string): SvelteSet<number>;
|
|
609
|
+
track_node(path: string): (el: HTMLElement) => () => void;
|
|
610
|
+
track_array(path: string): (el: Element) => () => void;
|
|
611
|
+
};
|
|
612
|
+
|
|
639
613
|
/**
|
|
640
614
|
* Pure visibility check for a gap's `.positioned` class. NodeGap calls
|
|
641
615
|
* this from a $derived, so the `near.has()` reads are tracked at
|
|
@@ -648,13 +622,15 @@ export function create_node_visibility(svedit) {
|
|
|
648
622
|
* $derived (see the note there): membership reads on a set created
|
|
649
623
|
* within the same derived are not tracked by Svelte.
|
|
650
624
|
*
|
|
651
|
-
* @param
|
|
652
|
-
* @param {{ first: boolean, last: boolean } | undefined} edge_state
|
|
653
|
-
* @param {number} offset
|
|
654
|
-
* @param {boolean} is_last
|
|
655
|
-
* @param {boolean} empty
|
|
625
|
+
* @param near - near child indices of the array
|
|
656
626
|
*/
|
|
657
|
-
export function should_position_gap(
|
|
627
|
+
export function should_position_gap(
|
|
628
|
+
near: SvelteSet<number>,
|
|
629
|
+
edge_state: { first: boolean; last: boolean } | undefined,
|
|
630
|
+
offset: number,
|
|
631
|
+
is_last: boolean,
|
|
632
|
+
empty: boolean
|
|
633
|
+
): boolean {
|
|
658
634
|
if (!near) return false;
|
|
659
635
|
|
|
660
636
|
if (empty) {
|
|
@@ -1,12 +1,23 @@
|
|
|
1
|
-
|
|
2
|
-
* @import { DocumentSchema } from './types.d.ts'
|
|
3
|
-
*/
|
|
1
|
+
import type { Text, DocumentNode, DocumentSchema } from './types.js';
|
|
4
2
|
|
|
5
|
-
|
|
3
|
+
function is_record(value: unknown): value is Record<string, unknown> {
|
|
4
|
+
return typeof value === 'object' && value !== null;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
function is_text(value: unknown): value is Text {
|
|
8
|
+
return (
|
|
9
|
+
is_record(value) &&
|
|
10
|
+
typeof value.content === 'string' &&
|
|
11
|
+
Array.isArray(value.marks) &&
|
|
12
|
+
Array.isArray(value.annotations)
|
|
13
|
+
);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function normalize_line_endings(text: string): string {
|
|
6
17
|
return text.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
|
|
7
18
|
}
|
|
8
19
|
|
|
9
|
-
export function dedent_plain_text(plain_text) {
|
|
20
|
+
export function dedent_plain_text(plain_text: string): string {
|
|
10
21
|
const lines = normalize_line_endings(plain_text).split('\n');
|
|
11
22
|
if (lines.length < 2) return plain_text;
|
|
12
23
|
|
|
@@ -42,23 +53,21 @@ export function dedent_plain_text(plain_text) {
|
|
|
42
53
|
.join('\n');
|
|
43
54
|
}
|
|
44
55
|
|
|
45
|
-
export function split_plain_text_paragraphs(plain_text) {
|
|
56
|
+
export function split_plain_text_paragraphs(plain_text: string): string[] {
|
|
46
57
|
return normalize_line_endings(plain_text)
|
|
47
58
|
.split(/\n{2,}/)
|
|
48
59
|
.map((fragment) => fragment.trim())
|
|
49
60
|
.filter(Boolean);
|
|
50
61
|
}
|
|
51
62
|
|
|
52
|
-
export function normalize_plain_text_for_single_line_property(plain_text) {
|
|
63
|
+
export function normalize_plain_text_for_single_line_property(plain_text: string): string {
|
|
53
64
|
return normalize_line_endings(plain_text).replace(/\s*\n+\s*/g, ' ');
|
|
54
65
|
}
|
|
55
66
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
*/
|
|
61
|
-
export function get_text_property_name(node_type, schema) {
|
|
67
|
+
export function get_text_property_name(
|
|
68
|
+
node_type: string | null | undefined,
|
|
69
|
+
schema: DocumentSchema
|
|
70
|
+
): string | null {
|
|
62
71
|
if (!node_type) return null;
|
|
63
72
|
const node_schema = schema[node_type];
|
|
64
73
|
if (!node_schema || node_schema.kind !== 'text') return null;
|
|
@@ -70,75 +79,55 @@ export function get_text_property_name(node_type, schema) {
|
|
|
70
79
|
);
|
|
71
80
|
}
|
|
72
81
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
* @param {DocumentSchema} schema
|
|
76
|
-
* @returns {{ content: string, marks: any[], annotations: any[] } | null}
|
|
77
|
-
*/
|
|
78
|
-
export function get_text_content(node, schema) {
|
|
79
|
-
if (!node || typeof node !== 'object') return null;
|
|
80
|
-
|
|
81
|
-
const is_text_value = (value) =>
|
|
82
|
-
value &&
|
|
83
|
-
typeof value.content === 'string' &&
|
|
84
|
-
Array.isArray(value.marks) &&
|
|
85
|
-
Array.isArray(value.annotations);
|
|
82
|
+
export function get_text_content(node: unknown, schema: DocumentSchema): Text | null {
|
|
83
|
+
if (!is_record(node)) return null;
|
|
86
84
|
|
|
87
|
-
const
|
|
88
|
-
|
|
85
|
+
const node_type = typeof node.type === 'string' ? node.type : null;
|
|
86
|
+
const text_property_name = get_text_property_name(node_type, schema);
|
|
87
|
+
if (text_property_name && is_text(node[text_property_name])) {
|
|
89
88
|
return node[text_property_name];
|
|
90
89
|
}
|
|
91
90
|
|
|
92
|
-
if (
|
|
91
|
+
if (is_text(node.content)) {
|
|
93
92
|
return node.content;
|
|
94
93
|
}
|
|
95
94
|
|
|
96
95
|
return null;
|
|
97
96
|
}
|
|
98
97
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
* @returns {boolean}
|
|
103
|
-
*/
|
|
104
|
-
export function is_text_like_node_payload(node, schema) {
|
|
105
|
-
if (!node || typeof node !== 'object') return false;
|
|
106
|
-
if (schema[node.type]?.kind === 'text') return true;
|
|
98
|
+
export function is_text_like_node_payload(node: unknown, schema: DocumentSchema): boolean {
|
|
99
|
+
if (!is_record(node)) return false;
|
|
100
|
+
if (typeof node.type === 'string' && schema[node.type]?.kind === 'text') return true;
|
|
107
101
|
return !!get_text_content(node, schema);
|
|
108
102
|
}
|
|
109
103
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
*/
|
|
115
|
-
export function get_default_text_node(node_array_property_definition, schema) {
|
|
104
|
+
export function get_default_text_node(
|
|
105
|
+
node_array_property_definition: unknown,
|
|
106
|
+
schema: DocumentSchema
|
|
107
|
+
): string | null {
|
|
116
108
|
if (
|
|
117
|
-
node_array_property_definition
|
|
109
|
+
!is_record(node_array_property_definition) ||
|
|
110
|
+
node_array_property_definition.type !== 'node_array' ||
|
|
118
111
|
!Array.isArray(node_array_property_definition.node_types)
|
|
119
112
|
) {
|
|
120
113
|
return null;
|
|
121
114
|
}
|
|
122
115
|
|
|
123
116
|
const default_node_type = node_array_property_definition.default_node_type;
|
|
124
|
-
if (default_node_type && schema[default_node_type]?.kind === 'text') {
|
|
117
|
+
if (typeof default_node_type === 'string' && schema[default_node_type]?.kind === 'text') {
|
|
125
118
|
return default_node_type;
|
|
126
119
|
}
|
|
127
120
|
|
|
128
|
-
return (
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
) || null
|
|
132
|
-
);
|
|
121
|
+
return (node_array_property_definition.node_types.find(
|
|
122
|
+
(node_type: unknown) => typeof node_type === 'string' && schema[node_type]?.kind === 'text'
|
|
123
|
+
) || null) as string | null;
|
|
133
124
|
}
|
|
134
125
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
*/
|
|
141
|
-
export function create_plain_text_nodes_payload(paragraph_fragments, node_type, schema) {
|
|
126
|
+
export function create_plain_text_nodes_payload(
|
|
127
|
+
paragraph_fragments: string[],
|
|
128
|
+
node_type: string | null | undefined,
|
|
129
|
+
schema: DocumentSchema
|
|
130
|
+
): { main_nodes: string[]; nodes: Record<string, DocumentNode> } | null {
|
|
142
131
|
if (!Array.isArray(paragraph_fragments) || paragraph_fragments.length === 0 || !node_type) {
|
|
143
132
|
return null;
|
|
144
133
|
}
|
|
@@ -146,7 +135,7 @@ export function create_plain_text_nodes_payload(paragraph_fragments, node_type,
|
|
|
146
135
|
const text_property_name = get_text_property_name(node_type, schema);
|
|
147
136
|
if (!text_property_name) return null;
|
|
148
137
|
|
|
149
|
-
const payload = {
|
|
138
|
+
const payload: { main_nodes: string[]; nodes: Record<string, DocumentNode> } = {
|
|
150
139
|
main_nodes: [],
|
|
151
140
|
nodes: {}
|
|
152
141
|
};
|