svedit 0.11.0 → 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.
- package/README.md +230 -64
- package/dist/Command.svelte.d.ts +21 -5
- package/dist/Command.svelte.d.ts.map +1 -1
- package/dist/Command.svelte.js +86 -30
- package/dist/KeyMapper.svelte.d.ts.map +1 -1
- package/dist/KeyMapper.svelte.js +18 -6
- package/dist/Node.svelte +29 -1
- package/dist/Node.svelte.d.ts.map +1 -1
- package/dist/NodeArrayProperty.svelte +119 -12
- package/dist/NodeArrayProperty.svelte.d.ts.map +1 -1
- package/dist/NodeGap.svelte +48 -6
- package/dist/NodeGap.svelte.d.ts.map +1 -1
- package/dist/Session.svelte.d.ts +31 -14
- package/dist/Session.svelte.d.ts.map +1 -1
- package/dist/Session.svelte.js +155 -77
- package/dist/Svedit.svelte +110 -89
- package/dist/Svedit.svelte.d.ts.map +1 -1
- package/dist/{AnnotatedTextProperty.svelte → TextProperty.svelte} +45 -44
- package/dist/TextProperty.svelte.d.ts +7 -0
- package/dist/TextProperty.svelte.d.ts.map +1 -0
- package/dist/Transaction.svelte.d.ts +78 -40
- package/dist/Transaction.svelte.d.ts.map +1 -1
- package/dist/Transaction.svelte.js +412 -234
- package/dist/doc_utils.d.ts +96 -21
- package/dist/doc_utils.d.ts.map +1 -1
- package/dist/doc_utils.js +440 -168
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/node_visibility.svelte.d.ts +30 -4
- package/dist/node_visibility.svelte.d.ts.map +1 -1
- package/dist/node_visibility.svelte.js +327 -363
- package/dist/paste_utils.d.ts +3 -2
- package/dist/paste_utils.d.ts.map +1 -1
- package/dist/paste_utils.js +16 -13
- package/dist/transforms.svelte.d.ts.map +1 -1
- package/dist/transforms.svelte.js +5 -6
- package/dist/types.d.ts +112 -42
- package/dist/utils.d.ts +89 -13
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +320 -85
- package/package.json +4 -1
- package/src/lib/Command.svelte.js +86 -30
- package/src/lib/KeyMapper.svelte.js +18 -6
- package/src/lib/Node.svelte +29 -1
- package/src/lib/NodeArrayProperty.svelte +119 -12
- package/src/lib/NodeGap.svelte +48 -6
- package/src/lib/Session.svelte.js +155 -77
- package/src/lib/Svedit.svelte +110 -89
- package/src/lib/{AnnotatedTextProperty.svelte → TextProperty.svelte} +45 -44
- package/src/lib/Transaction.svelte.js +412 -234
- package/src/lib/doc_utils.js +440 -168
- package/src/lib/index.js +1 -1
- package/src/lib/node_visibility.svelte.js +327 -363
- package/src/lib/paste_utils.js +16 -13
- package/src/lib/transforms.svelte.js +5 -6
- package/src/lib/types.d.ts +112 -42
- package/src/lib/utils.js +320 -85
- package/dist/AnnotatedTextProperty.svelte.d.ts +0 -7
- package/dist/AnnotatedTextProperty.svelte.d.ts.map +0 -1
package/dist/paste_utils.d.ts
CHANGED
|
@@ -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 {{
|
|
17
|
+
* @returns {{ content: string, marks: any[], annotations: any[] } | null}
|
|
18
18
|
*/
|
|
19
19
|
export function get_text_content(node: any, schema: DocumentSchema): {
|
|
20
|
-
|
|
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,
|
|
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"}
|
package/dist/paste_utils.js
CHANGED
|
@@ -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 === '
|
|
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 === '
|
|
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 {{
|
|
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 (
|
|
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(
|
|
129
|
-
|
|
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
|
-
|
|
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,
|
|
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 {
|
|
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] =
|
|
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.
|
|
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 =
|
|
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.
|
|
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 = '
|
|
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
|
-
// | '
|
|
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 '
|
|
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
|
|
150
|
+
* A property that stores text with optional marks and annotations and required allow_newlines setting.
|
|
151
151
|
*/
|
|
152
|
-
export type
|
|
153
|
-
type: '
|
|
154
|
-
|
|
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
|
|
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
|
-
|
|
|
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
|
|
278
|
-
* Use define_document_schema to also check that content is the only
|
|
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:
|
|
283
|
+
content: TextProperty;
|
|
284
284
|
} & Record<string, PropertyDefinition>;
|
|
285
285
|
};
|
|
286
286
|
|
|
287
|
-
export type
|
|
288
|
-
[PropertyName in keyof Properties]: Properties[PropertyName] extends { type: '
|
|
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 =
|
|
298
|
-
'Text node schemas must define a "content" property of type
|
|
299
|
-
>;
|
|
297
|
+
export type TextNodeMissingContentError =
|
|
298
|
+
TextNodeSchemaError<'Text node schemas must define a "content" property of type text.'>;
|
|
300
299
|
|
|
301
|
-
export type
|
|
302
|
-
|
|
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:
|
|
312
|
-
? Exclude<
|
|
309
|
+
: Properties extends { content: TextProperty }
|
|
310
|
+
? Exclude<TextPropertyNames<Properties>, 'content'> extends infer ExtraProperties
|
|
313
311
|
? [ExtraProperties] extends [never]
|
|
314
312
|
? Schema
|
|
315
|
-
:
|
|
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
|
|
364
|
+
* Props for the TextProperty component
|
|
367
365
|
*/
|
|
368
|
-
export type
|
|
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
|
-
*
|
|
448
|
+
* A range with an attached payload node, used for both marks and annotations.
|
|
447
449
|
*/
|
|
448
|
-
export type
|
|
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
|
-
*
|
|
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
|
-
|
|
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
|
|
512
|
+
* Represents a mark fragment in annotated text content
|
|
472
513
|
*/
|
|
473
|
-
export type
|
|
474
|
-
type: '
|
|
475
|
-
/** NodeId that has
|
|
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
|
|
518
|
+
/** The text content of the mark */
|
|
478
519
|
content: string;
|
|
479
|
-
/** Index of the
|
|
480
|
-
|
|
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 |
|
|
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
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Detect if the
|
|
2
|
+
* Detect if the virtual keyboard is likely visible.
|
|
3
|
+
*
|
|
4
|
+
* This is a heuristic based on the visual viewport becoming smaller than the
|
|
5
|
+
* layout viewport.
|
|
6
|
+
*
|
|
7
|
+
* @returns {boolean} true if the virtual keyboard is likely active, false otherwise
|
|
8
|
+
*/
|
|
9
|
+
export function is_virtual_keyboard_active(): boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Detect if the current browser is likely on a mobile device.
|
|
12
|
+
*
|
|
13
|
+
* This uses the user agent only so touch-capable laptops are not treated as
|
|
14
|
+
* mobile browsers.
|
|
15
|
+
*
|
|
3
16
|
* @returns {boolean} true if mobile browser, false otherwise
|
|
4
17
|
*/
|
|
5
18
|
export function is_mobile_browser(): boolean;
|
|
@@ -88,37 +101,38 @@ export function char_to_utf16_offset(str: string, char_offset: number): number;
|
|
|
88
101
|
/**
|
|
89
102
|
* Splits an annotated text at the specified character position.
|
|
90
103
|
*
|
|
91
|
-
*
|
|
92
|
-
* 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.
|
|
93
106
|
*
|
|
94
|
-
* @param {AnnotatedText}
|
|
107
|
+
* @param {AnnotatedText} text_value - Annotated text object
|
|
95
108
|
* @param {number} at_position - Character position where to split (0-based)
|
|
96
109
|
* @returns {[AnnotatedText, AnnotatedText]} Tuple of [left_part, right_part]
|
|
97
110
|
*
|
|
98
111
|
* @example
|
|
99
|
-
*
|
|
112
|
+
* split_text({content: "Hello world", marks: [{start_offset: 6, end_offset: 11, node_id: "strong"}], annotations: []}, 8)
|
|
100
113
|
* // Returns:
|
|
101
114
|
* // [
|
|
102
|
-
* // {
|
|
103
|
-
* // {
|
|
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: []}
|
|
104
117
|
* // ]
|
|
105
118
|
*/
|
|
106
|
-
export function
|
|
119
|
+
export function split_text(text_value: AnnotatedText, at_position: number): [AnnotatedText, AnnotatedText];
|
|
107
120
|
/**
|
|
108
121
|
* Joins two annotated texts into a single annotated text.
|
|
109
122
|
*
|
|
110
|
-
*
|
|
111
|
-
* of the first text. Adjacent
|
|
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.
|
|
112
126
|
*
|
|
113
127
|
* @param {AnnotatedText} first_text - First annotated text object
|
|
114
128
|
* @param {AnnotatedText} second_text - Second annotated text object
|
|
115
129
|
* @returns {AnnotatedText} Combined annotated text object
|
|
116
130
|
*
|
|
117
131
|
* @example
|
|
118
|
-
*
|
|
119
|
-
* // Returns: {
|
|
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: []}
|
|
120
134
|
*/
|
|
121
|
-
export function
|
|
135
|
+
export function join_text(first_text: AnnotatedText, second_text: AnnotatedText): AnnotatedText;
|
|
122
136
|
/**
|
|
123
137
|
* Convert snake_case string to PascalCase
|
|
124
138
|
*
|
|
@@ -180,6 +194,18 @@ export function deserialize_path(serialized_path: string): Array<string | number
|
|
|
180
194
|
* @returns {boolean}
|
|
181
195
|
*/
|
|
182
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[];
|
|
183
209
|
export function traverse(node_id: any, schema: any, nodes: any): any[];
|
|
184
210
|
/**
|
|
185
211
|
* Extracts the normalized range from a text or node selection.
|
|
@@ -189,6 +215,56 @@ export function traverse(node_id: any, schema: any, nodes: any): any[];
|
|
|
189
215
|
*/
|
|
190
216
|
export function get_selection_range(selection?: Selection): SelectionRange | null;
|
|
191
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
|
+
}>;
|
|
192
268
|
export const PATH_SEPARATOR: "__";
|
|
193
269
|
import type { AnnotatedText } from './types.d.ts';
|
|
194
270
|
import type { Selection } from './types.d.ts';
|
package/dist/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/lib/utils.js"],"names":[],"mappings":"AAMA
|
|
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"}
|