svedit 0.12.0 → 0.14.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 +35 -22
- 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 +2 -2
- 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 +36 -14
- package/dist/NodeGapMarkers.svelte.d.ts +6 -11
- package/dist/NodeGapMarkers.svelte.d.ts.map +1 -1
- package/dist/NodeSelectionMarkers.svelte +21 -7
- 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 +146 -140
- package/dist/Svedit.svelte.d.ts +30 -10
- package/dist/Svedit.svelte.d.ts.map +1 -1
- package/dist/TextProperty.svelte +37 -23
- 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/styles/svedit-colors.css +8 -5
- 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 +294 -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 +70 -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 +2 -2
- package/src/lib/NodeGap.svelte +12 -6
- package/src/lib/NodeGapMarkers.svelte +36 -14
- package/src/lib/NodeSelectionMarkers.svelte +21 -7
- package/src/lib/{Session.svelte.js → Session.svelte.ts} +130 -127
- package/src/lib/Svedit.svelte +146 -140
- package/src/lib/TextProperty.svelte +37 -23
- 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} +48 -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/styles/svedit-colors.css +8 -5
- package/src/lib/{transforms.svelte.js → transforms.svelte.ts} +39 -21
- package/src/lib/{types.d.ts → types.ts} +161 -66
- package/src/lib/{utils.js → utils.ts} +110 -129
|
@@ -1,20 +1,33 @@
|
|
|
1
1
|
import { split_text, join_text, get_char_length } from './utils.js';
|
|
2
2
|
import { get_default_node_type } from './doc_utils.js';
|
|
3
|
+
import type Transaction from './Transaction.svelte.js';
|
|
4
|
+
import type {
|
|
5
|
+
DocumentNode,
|
|
6
|
+
DocumentPath,
|
|
7
|
+
NodeArrayProperty,
|
|
8
|
+
NodeProperty,
|
|
9
|
+
Selection,
|
|
10
|
+
TextSelection
|
|
11
|
+
} from './types.js';
|
|
3
12
|
|
|
4
13
|
/**
|
|
5
14
|
* Set multiple properties on a node via a transaction.
|
|
6
15
|
*
|
|
7
|
-
* @param
|
|
8
|
-
* @param
|
|
9
|
-
* @param
|
|
16
|
+
* @param tr - The transaction
|
|
17
|
+
* @param path - Path to the node
|
|
18
|
+
* @param properties - Key/value pairs to set
|
|
10
19
|
*/
|
|
11
|
-
export function set_properties(
|
|
20
|
+
export function set_properties(
|
|
21
|
+
tr: Transaction,
|
|
22
|
+
path: DocumentPath,
|
|
23
|
+
properties: Record<string, unknown>
|
|
24
|
+
): void {
|
|
12
25
|
for (const [key, value] of Object.entries(properties)) {
|
|
13
26
|
tr.set([...path, key], value);
|
|
14
27
|
}
|
|
15
28
|
}
|
|
16
29
|
|
|
17
|
-
export function break_text_node(tr) {
|
|
30
|
+
export function break_text_node(tr: Transaction): boolean {
|
|
18
31
|
// Keep a reference of the original selection (before any transforms are applied)
|
|
19
32
|
const selection = tr.selection;
|
|
20
33
|
// First we need to ensure we have a text selection
|
|
@@ -28,7 +41,7 @@ export function break_text_node(tr) {
|
|
|
28
41
|
if (tr.kind(node) !== 'text') return false;
|
|
29
42
|
const is_inside_node_array = tr.inspect(selection.path.slice(0, -2))?.type === 'node_array';
|
|
30
43
|
if (!is_inside_node_array) return false; // Do nothing if we're not inside a node_array
|
|
31
|
-
const node_array_prop = selection.path.at(-3);
|
|
44
|
+
const node_array_prop = String(selection.path.at(-3));
|
|
32
45
|
// Get the node that owns the node_array property (e.g. a page.body)
|
|
33
46
|
const node_array_node = tr.get(selection.path.slice(0, -3));
|
|
34
47
|
|
|
@@ -37,23 +50,26 @@ export function break_text_node(tr) {
|
|
|
37
50
|
tr.delete_selection();
|
|
38
51
|
}
|
|
39
52
|
|
|
40
|
-
|
|
53
|
+
// After delete_selection the selection is still a (collapsed) text selection
|
|
54
|
+
const split_at_position = (tr.selection as TextSelection).anchor_offset;
|
|
41
55
|
const content = tr.get(selection.path);
|
|
42
56
|
const [left_text, right_text] = split_text(content, split_at_position);
|
|
43
57
|
|
|
44
58
|
tr.set([node.id, 'content'], left_text);
|
|
45
59
|
|
|
46
|
-
const node_insert_position = {
|
|
60
|
+
const node_insert_position: Selection = {
|
|
47
61
|
type: 'node',
|
|
48
62
|
path: tr.selection.path.slice(0, -2),
|
|
49
|
-
anchor_offset:
|
|
50
|
-
focus_offset:
|
|
63
|
+
anchor_offset: (tr.selection.path.at(-2) as number) + 1,
|
|
64
|
+
focus_offset: (tr.selection.path.at(-2) as number) + 1
|
|
51
65
|
};
|
|
52
66
|
|
|
53
67
|
// TODO: Only use default_node_type when caret is at the end of
|
|
54
68
|
const node_array_property_definition =
|
|
55
69
|
tr.schema[node_array_node.type].properties[node_array_prop];
|
|
56
|
-
const target_node_type = get_default_node_type(
|
|
70
|
+
const target_node_type = get_default_node_type(
|
|
71
|
+
node_array_property_definition as NodeProperty | NodeArrayProperty
|
|
72
|
+
);
|
|
57
73
|
|
|
58
74
|
if (!target_node_type) {
|
|
59
75
|
console.warn(
|
|
@@ -68,7 +84,7 @@ export function break_text_node(tr) {
|
|
|
68
84
|
return true;
|
|
69
85
|
}
|
|
70
86
|
|
|
71
|
-
export function join_text_node(tr) {
|
|
87
|
+
export function join_text_node(tr: Transaction): boolean {
|
|
72
88
|
// Keep a reference of the original selection (before any transforms are applied)
|
|
73
89
|
const selection = tr.selection;
|
|
74
90
|
// First we need to ensure we have a text selection
|
|
@@ -79,16 +95,16 @@ export function join_text_node(tr) {
|
|
|
79
95
|
const is_inside_node_array = tr.inspect(selection.path.slice(0, -2))?.type === 'node_array';
|
|
80
96
|
if (!is_inside_node_array) return false; // Do nothing if we're not inside a node_array
|
|
81
97
|
|
|
82
|
-
const node_index =
|
|
98
|
+
const node_index = tr.selection.path.at(-2) as number;
|
|
83
99
|
|
|
84
100
|
// Determine if we can join with the previous node
|
|
85
101
|
let can_join = false;
|
|
86
|
-
let predecessor_node = null;
|
|
102
|
+
let predecessor_node: DocumentNode | null = null;
|
|
87
103
|
|
|
88
104
|
if (node_index > 0) {
|
|
89
105
|
const previous_text_path = [...tr.selection.path.slice(0, -2), node_index - 1];
|
|
90
106
|
predecessor_node = tr.get(previous_text_path);
|
|
91
|
-
can_join = tr.kind(predecessor_node) === 'text';
|
|
107
|
+
can_join = predecessor_node !== null && tr.kind(predecessor_node) === 'text';
|
|
92
108
|
}
|
|
93
109
|
|
|
94
110
|
// Special behavior: if we can't join and current node is empty, delete it
|
|
@@ -104,7 +120,7 @@ export function join_text_node(tr) {
|
|
|
104
120
|
}
|
|
105
121
|
|
|
106
122
|
// If we can't join for any reason, return false
|
|
107
|
-
if (!can_join) {
|
|
123
|
+
if (!can_join || !predecessor_node) {
|
|
108
124
|
return false;
|
|
109
125
|
}
|
|
110
126
|
|
|
@@ -138,7 +154,7 @@ export function join_text_node(tr) {
|
|
|
138
154
|
return true;
|
|
139
155
|
}
|
|
140
156
|
|
|
141
|
-
export function insert_default_node(tr) {
|
|
157
|
+
export function insert_default_node(tr: Transaction): boolean {
|
|
142
158
|
const selection = tr.selection;
|
|
143
159
|
|
|
144
160
|
// Only work with collapsed node selections
|
|
@@ -148,15 +164,17 @@ export function insert_default_node(tr) {
|
|
|
148
164
|
|
|
149
165
|
const path = selection.path;
|
|
150
166
|
const node_array_node = tr.get(path.slice(0, -1));
|
|
151
|
-
const property_name = path.at(-1);
|
|
167
|
+
const property_name = String(path.at(-1));
|
|
152
168
|
|
|
153
169
|
// Get the definition for this property
|
|
154
170
|
const property_definition = tr.schema[node_array_node.type].properties[property_name];
|
|
155
|
-
const default_type = get_default_node_type(
|
|
171
|
+
const default_type = get_default_node_type(
|
|
172
|
+
property_definition as NodeProperty | NodeArrayProperty
|
|
173
|
+
);
|
|
156
174
|
|
|
157
175
|
// Use the inserter function if available
|
|
158
|
-
if (tr.config?.inserters?.[default_type]) {
|
|
159
|
-
tr.config.inserters[default_type](tr);
|
|
176
|
+
if (tr.config?.inserters?.[default_type as string]) {
|
|
177
|
+
tr.config.inserters[default_type as string](tr);
|
|
160
178
|
return true;
|
|
161
179
|
} else {
|
|
162
180
|
throw new Error(`No inserter function available for default node type '${default_type}'`);
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type Session from './Session.svelte.js';
|
|
2
|
-
import type
|
|
2
|
+
import type { VisibilityRegistryApi } from './node_visibility.svelte.js';
|
|
3
3
|
|
|
4
4
|
// ===== SVELTE TYPE IMPORTS =====
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Import Svelte's Snippet type for properly typing children in components
|
|
8
8
|
*/
|
|
9
|
-
import type {
|
|
9
|
+
import type { Snippet } from 'svelte';
|
|
10
10
|
|
|
11
11
|
// ===== SELECTION TYPE DEFINITIONS =====
|
|
12
12
|
|
|
@@ -19,6 +19,13 @@ import type { Component, Snippet } from 'svelte';
|
|
|
19
19
|
*/
|
|
20
20
|
export type NodeId = string;
|
|
21
21
|
|
|
22
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
23
|
+
export type DynamicRecord = Record<string, any>;
|
|
24
|
+
export type SessionConfig = DynamicRecord;
|
|
25
|
+
export type CommandRegistry = DynamicRecord;
|
|
26
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
27
|
+
export type DocumentOperation = [string, ...any[]];
|
|
28
|
+
|
|
22
29
|
/**
|
|
23
30
|
* Array of IDs, property names (strings), or indexes (integers) that identify a node or property in the document.
|
|
24
31
|
* String segments must follow the same path segment rules as NodeId.
|
|
@@ -98,54 +105,82 @@ export type PrimitiveType = ScalarType | ArrayType | RichType;
|
|
|
98
105
|
*/
|
|
99
106
|
export type PropertyType = PrimitiveType | ReferenceType;
|
|
100
107
|
|
|
101
|
-
//
|
|
102
|
-
// e.g. `session.get('image')` auto-completes the node's properties based on
|
|
103
|
-
// the schema definition. The types below are a starting point for that.
|
|
104
|
-
//
|
|
105
|
-
// export type DocumentSchemaPrimitive =
|
|
106
|
-
// | 'string'
|
|
107
|
-
// | 'number'
|
|
108
|
-
// | 'boolean'
|
|
109
|
-
// | 'integer'
|
|
110
|
-
// | 'datetime'
|
|
111
|
-
// | 'string_array'
|
|
112
|
-
// | 'number_array'
|
|
113
|
-
// | 'boolean_array'
|
|
114
|
-
// | 'integer_array'
|
|
115
|
-
// | 'text'
|
|
116
|
-
// | 'node'
|
|
117
|
-
// | 'node_array';
|
|
118
|
-
//
|
|
119
|
-
// export type DocumentSchemaValueToJs<T> = T extends 'string'
|
|
120
|
-
// ? string
|
|
121
|
-
// : T extends 'number'
|
|
122
|
-
// ? number
|
|
123
|
-
// : T extends 'boolean'
|
|
124
|
-
// ? boolean
|
|
125
|
-
// : T extends 'integer'
|
|
126
|
-
// ? number
|
|
127
|
-
// : T extends 'datetime'
|
|
128
|
-
// ? string
|
|
129
|
-
// : T extends 'string_array'
|
|
130
|
-
// ? Array<string>
|
|
131
|
-
// : T extends 'number_array'
|
|
132
|
-
// ? Array<number>
|
|
133
|
-
// : T extends 'boolean_array'
|
|
134
|
-
// ? Array<boolean>
|
|
135
|
-
// : T extends 'integer_array'
|
|
136
|
-
// ? Array<number>
|
|
137
|
-
// : T extends 'text'
|
|
138
|
-
// ? AnnotatedText
|
|
139
|
-
// : T extends 'node'
|
|
140
|
-
// ? string
|
|
141
|
-
// : T extends 'node_array'
|
|
142
|
-
// ? Array<string>
|
|
143
|
-
// : never;
|
|
144
|
-
//
|
|
145
|
-
// export type DocumentNodeToJs<S extends NodeSchema> = { id: string; type: string } & {
|
|
146
|
-
// [K in keyof S['properties']]: DocumentSchemaValueToJs<S['properties'][K]['type']>;
|
|
147
|
-
// };
|
|
108
|
+
// ===== SCHEMA-DERIVED NODE TYPES =====
|
|
148
109
|
|
|
110
|
+
/**
|
|
111
|
+
* Maps a schema property definition to the runtime value type it stores.
|
|
112
|
+
*/
|
|
113
|
+
export type PropertyValue<P extends PropertyDefinition> = P extends {
|
|
114
|
+
type: 'string';
|
|
115
|
+
values: readonly (infer Value extends string)[];
|
|
116
|
+
}
|
|
117
|
+
? Value
|
|
118
|
+
: P extends { type: 'string' }
|
|
119
|
+
? string
|
|
120
|
+
: P extends { type: 'number' }
|
|
121
|
+
? number
|
|
122
|
+
: P extends { type: 'integer' }
|
|
123
|
+
? number
|
|
124
|
+
: P extends { type: 'boolean' }
|
|
125
|
+
? boolean
|
|
126
|
+
: P extends { type: 'datetime' }
|
|
127
|
+
? string
|
|
128
|
+
: P extends { type: 'string_array' }
|
|
129
|
+
? string[]
|
|
130
|
+
: P extends { type: 'number_array' }
|
|
131
|
+
? number[]
|
|
132
|
+
: P extends { type: 'integer_array' }
|
|
133
|
+
? number[]
|
|
134
|
+
: P extends { type: 'boolean_array' }
|
|
135
|
+
? boolean[]
|
|
136
|
+
: P extends { type: 'text' }
|
|
137
|
+
? Text
|
|
138
|
+
: P extends { type: 'node' }
|
|
139
|
+
? NodeId
|
|
140
|
+
: P extends { type: 'node_array' }
|
|
141
|
+
? NodeArray
|
|
142
|
+
: never;
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* The runtime shape of a node of a specific type, derived from the schema.
|
|
146
|
+
*
|
|
147
|
+
* Falls back to the untyped DocumentNode when the schema is not a concrete
|
|
148
|
+
* schema literal (e.g. the DocumentSchema default of Session).
|
|
149
|
+
*/
|
|
150
|
+
export type NodeOfType<S extends DocumentSchema, T extends keyof S> = string extends keyof S
|
|
151
|
+
? DocumentNode
|
|
152
|
+
: {
|
|
153
|
+
id: NodeId;
|
|
154
|
+
type: T;
|
|
155
|
+
} & {
|
|
156
|
+
[K in keyof S[T]['properties']]: PropertyValue<S[T]['properties'][K]>;
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Discriminated union of all node types in a schema. Narrow with
|
|
161
|
+
* `node.type === '...'` to get exact property types.
|
|
162
|
+
*
|
|
163
|
+
* Falls back to the untyped DocumentNode when the schema is not a concrete
|
|
164
|
+
* schema literal (e.g. the DocumentSchema default of Session).
|
|
165
|
+
*/
|
|
166
|
+
export type AnyNode<S extends DocumentSchema> = string extends keyof S
|
|
167
|
+
? DocumentNode
|
|
168
|
+
: {
|
|
169
|
+
[T in keyof S]: NodeOfType<S, T>;
|
|
170
|
+
}[keyof S];
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Convenience map from node type name to its runtime node shape,
|
|
174
|
+
* e.g. `NodeMap<typeof document_schema>['story']`.
|
|
175
|
+
*/
|
|
176
|
+
export type NodeMap<S extends DocumentSchema> = {
|
|
177
|
+
[T in keyof S]: NodeOfType<S, T>;
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Assert that a node is of the given type. Narrows the static type and
|
|
182
|
+
* checks at runtime — for call sites that know what they expect.
|
|
183
|
+
*/
|
|
149
184
|
/**
|
|
150
185
|
* A property that stores text with optional marks and annotations and required allow_newlines setting.
|
|
151
186
|
*/
|
|
@@ -162,6 +197,7 @@ export type TextProperty = {
|
|
|
162
197
|
export type StringProperty = {
|
|
163
198
|
type: 'string';
|
|
164
199
|
default?: string;
|
|
200
|
+
values?: readonly string[];
|
|
165
201
|
};
|
|
166
202
|
|
|
167
203
|
/**
|
|
@@ -186,6 +222,8 @@ export type BooleanProperty = {
|
|
|
186
222
|
export type IntegerProperty = {
|
|
187
223
|
type: 'integer';
|
|
188
224
|
default?: number;
|
|
225
|
+
min?: number;
|
|
226
|
+
max?: number;
|
|
189
227
|
};
|
|
190
228
|
|
|
191
229
|
/**
|
|
@@ -346,6 +384,13 @@ export type DocumentSchema = Record<string, NodeSchema>;
|
|
|
346
384
|
export type DocumentNode = {
|
|
347
385
|
id: string;
|
|
348
386
|
type: string;
|
|
387
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
388
|
+
[key: string]: any;
|
|
389
|
+
};
|
|
390
|
+
|
|
391
|
+
export type Inspection = {
|
|
392
|
+
kind: 'property' | 'node';
|
|
393
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
349
394
|
[key: string]: any;
|
|
350
395
|
};
|
|
351
396
|
|
|
@@ -360,6 +405,13 @@ export type Document = {
|
|
|
360
405
|
};
|
|
361
406
|
};
|
|
362
407
|
|
|
408
|
+
/** Converts a document node to HTML, with access to recursive exporters. */
|
|
409
|
+
export type NodeHtmlExporter<S extends DocumentSchema = DocumentSchema> = (
|
|
410
|
+
node: DocumentNode,
|
|
411
|
+
session: Session<S>,
|
|
412
|
+
html_exporters: Record<string, NodeHtmlExporter<S>>
|
|
413
|
+
) => string;
|
|
414
|
+
|
|
363
415
|
/**
|
|
364
416
|
* Props for the TextProperty component
|
|
365
417
|
*/
|
|
@@ -373,7 +425,7 @@ export type TextPropertyProps = {
|
|
|
373
425
|
/** A placeholder to be rendered for empty content */
|
|
374
426
|
placeholder?: string;
|
|
375
427
|
/** Rest props to spread onto the rendered element (e.g. href, target, etc.) */
|
|
376
|
-
[key: string]:
|
|
428
|
+
[key: string]: unknown;
|
|
377
429
|
};
|
|
378
430
|
|
|
379
431
|
/**
|
|
@@ -389,7 +441,7 @@ export type CustomPropertyProps = {
|
|
|
389
441
|
/** The content of the custom property (e.g. an image) */
|
|
390
442
|
children: Snippet;
|
|
391
443
|
/** Rest props to spread onto the rendered element */
|
|
392
|
-
[key: string]:
|
|
444
|
+
[key: string]: unknown;
|
|
393
445
|
};
|
|
394
446
|
|
|
395
447
|
/**
|
|
@@ -403,7 +455,25 @@ export type NodeArrayPropertyProps = {
|
|
|
403
455
|
/** The `class` attribute on the container element */
|
|
404
456
|
class?: string;
|
|
405
457
|
/** Rest props to spread onto the rendered element (e.g. href, target, etc.) */
|
|
406
|
-
[key: string]:
|
|
458
|
+
[key: string]: unknown;
|
|
459
|
+
};
|
|
460
|
+
|
|
461
|
+
/**
|
|
462
|
+
* Props passed to the consumer's `system_components.node_gap_tools`
|
|
463
|
+
* component. It renders inside the active node gap marker (the one carrying
|
|
464
|
+
* the caret), so it inherits the `--row` orientation variable and
|
|
465
|
+
* appears/disappears together with the caret. The marker has
|
|
466
|
+
* pointer-events: none — interactive tools must set pointer-events: auto.
|
|
467
|
+
*/
|
|
468
|
+
export type NodeGapToolsProps = {
|
|
469
|
+
/** The full path to the node_array the gap belongs to */
|
|
470
|
+
path: DocumentPath;
|
|
471
|
+
/** The insertion offset of the gap (0..count) */
|
|
472
|
+
offset: number;
|
|
473
|
+
/** True for the gap before the first node */
|
|
474
|
+
is_first: boolean;
|
|
475
|
+
/** True for the gap after the last node */
|
|
476
|
+
is_last: boolean;
|
|
407
477
|
};
|
|
408
478
|
|
|
409
479
|
/**
|
|
@@ -423,15 +493,15 @@ export type NodeProps = {
|
|
|
423
493
|
/** The type-specific content of the node */
|
|
424
494
|
children: Snippet;
|
|
425
495
|
/** Rest props to spread onto the rendered element (e.g. href, target, etc.) */
|
|
426
|
-
[key: string]:
|
|
496
|
+
[key: string]: unknown;
|
|
427
497
|
};
|
|
428
498
|
|
|
429
499
|
/**
|
|
430
500
|
* Props for the Svedit component
|
|
431
501
|
*/
|
|
432
|
-
export type SveditProps = {
|
|
433
|
-
/** The session instance */
|
|
434
|
-
session: Session
|
|
502
|
+
export type SveditProps<S extends DocumentSchema = DocumentSchema> = {
|
|
503
|
+
/** The schema-typed session instance */
|
|
504
|
+
session: Session<S>;
|
|
435
505
|
/** Determines wether the document should be editable or read-only. */
|
|
436
506
|
editable?: boolean;
|
|
437
507
|
/** The path to the root element (e.g. ['page_1']) */
|
|
@@ -444,6 +514,24 @@ export type SveditProps = {
|
|
|
444
514
|
spellcheck?: 'true' | 'false';
|
|
445
515
|
};
|
|
446
516
|
|
|
517
|
+
/**
|
|
518
|
+
* Context provided by the Svedit component to commands and descendant components.
|
|
519
|
+
*/
|
|
520
|
+
export type SveditContext<S extends DocumentSchema = DocumentSchema> = {
|
|
521
|
+
session: Session<S>;
|
|
522
|
+
editable: boolean;
|
|
523
|
+
is_composing: boolean;
|
|
524
|
+
canvas_el: HTMLElement | undefined;
|
|
525
|
+
canvas_focused: boolean;
|
|
526
|
+
focus_canvas: () => void;
|
|
527
|
+
visibility_registry?: VisibilityRegistryApi;
|
|
528
|
+
};
|
|
529
|
+
|
|
530
|
+
/** Internal descendant context after Svedit's visibility registry is installed. */
|
|
531
|
+
export type SveditRenderContext<S extends DocumentSchema = DocumentSchema> = SveditContext<S> & {
|
|
532
|
+
visibility_registry: VisibilityRegistryApi;
|
|
533
|
+
};
|
|
534
|
+
|
|
447
535
|
/**
|
|
448
536
|
* A range with an attached payload node, used for both marks and annotations.
|
|
449
537
|
*/
|
|
@@ -468,23 +556,23 @@ export type Annotation = Attachment;
|
|
|
468
556
|
/**
|
|
469
557
|
* Represents text content with marks and annotations.
|
|
470
558
|
*/
|
|
471
|
-
export type
|
|
559
|
+
export type Text = {
|
|
472
560
|
content: string;
|
|
473
561
|
marks: Array<Mark>;
|
|
474
562
|
annotations: Array<Annotation>;
|
|
475
563
|
};
|
|
476
564
|
|
|
477
565
|
/**
|
|
478
|
-
* Represents
|
|
566
|
+
* Represents a node array with nodes, marks and annotations.
|
|
479
567
|
*/
|
|
480
|
-
export type
|
|
568
|
+
export type NodeArray = {
|
|
481
569
|
nodes: Array<NodeId>;
|
|
482
570
|
marks: Array<Mark>;
|
|
483
571
|
annotations: Array<Annotation>;
|
|
484
572
|
};
|
|
485
573
|
|
|
486
574
|
/**
|
|
487
|
-
* Attachment context passed to a node rendered inside
|
|
575
|
+
* Attachment context passed to a node rendered inside a node array.
|
|
488
576
|
* It is the flattened mark or annotation attachment, enriched with the resolved
|
|
489
577
|
* payload node, its index in the parent attachment array, and this child node's
|
|
490
578
|
* position in the attachment range.
|
|
@@ -500,8 +588,15 @@ export type NodeArrayAttachmentContext = {
|
|
|
500
588
|
is_end: boolean;
|
|
501
589
|
};
|
|
502
590
|
|
|
591
|
+
/** Internal context shared by a node array and its rendered child nodes. */
|
|
592
|
+
export type NodeArrayRenderContext = {
|
|
593
|
+
length: number;
|
|
594
|
+
mark_for: (node_index: number) => NodeArrayAttachmentContext | null;
|
|
595
|
+
annotations_for: (node_index: number) => NodeArrayAttachmentContext[];
|
|
596
|
+
};
|
|
597
|
+
|
|
503
598
|
/**
|
|
504
|
-
* Represents a selection highlight fragment for
|
|
599
|
+
* Represents a selection highlight fragment for unmarked text selections
|
|
505
600
|
*/
|
|
506
601
|
export type SelectionHighlightFragment = {
|
|
507
602
|
type: 'selection_highlight';
|
|
@@ -509,12 +604,12 @@ export type SelectionHighlightFragment = {
|
|
|
509
604
|
};
|
|
510
605
|
|
|
511
606
|
/**
|
|
512
|
-
* Represents a mark fragment in
|
|
607
|
+
* Represents a mark fragment in text content
|
|
513
608
|
*/
|
|
514
609
|
export type MarkFragment = {
|
|
515
610
|
type: 'mark';
|
|
516
611
|
/** NodeId that has mark type and details */
|
|
517
|
-
node:
|
|
612
|
+
node: DocumentNode;
|
|
518
613
|
/** The text content of the mark */
|
|
519
614
|
content: string;
|
|
520
615
|
/** Index of the mark in the original array */
|
|
@@ -522,7 +617,7 @@ export type MarkFragment = {
|
|
|
522
617
|
};
|
|
523
618
|
|
|
524
619
|
/**
|
|
525
|
-
* Represents a fragment of
|
|
620
|
+
* Represents a fragment of text content
|
|
526
621
|
*/
|
|
527
622
|
export type Fragment = string | MarkFragment | SelectionHighlightFragment;
|
|
528
623
|
|
|
@@ -541,7 +636,7 @@ export type NodeArrayPlainFragment = {
|
|
|
541
636
|
export type NodeArrayMarkFragment = {
|
|
542
637
|
type: 'mark';
|
|
543
638
|
/** NodeId that has mark type and details */
|
|
544
|
-
node:
|
|
639
|
+
node: DocumentNode;
|
|
545
640
|
/** The nodes wrapped by the mark */
|
|
546
641
|
nodes: Array<NodeId>;
|
|
547
642
|
/** Start index in the original nodes array */
|
|
@@ -551,6 +646,6 @@ export type NodeArrayMarkFragment = {
|
|
|
551
646
|
};
|
|
552
647
|
|
|
553
648
|
/**
|
|
554
|
-
* Represents a fragment of
|
|
649
|
+
* Represents a fragment of node array content
|
|
555
650
|
*/
|
|
556
651
|
export type NodeArrayFragment = NodeArrayPlainFragment | NodeArrayMarkFragment;
|