@quillmark/svelte 0.27.0 → 0.28.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/NOTICE +4 -4
- package/README.md +26 -8
- package/THEMING.md +10 -8
- package/dist/core/address.d.ts +35 -64
- package/dist/core/address.js +35 -55
- package/dist/core/bloom.d.ts +4 -10
- package/dist/core/bloom.js +14 -27
- package/dist/core/codec/blocks.d.ts +41 -43
- package/dist/core/codec/blocks.js +97 -130
- package/dist/core/codec/code.d.ts +7 -10
- package/dist/core/codec/code.js +37 -46
- package/dist/core/codec/decode.d.ts +19 -23
- package/dist/core/codec/decode.js +76 -111
- package/dist/core/codec/encode.d.ts +11 -15
- package/dist/core/codec/encode.js +60 -67
- package/dist/core/codec/field.d.ts +62 -95
- package/dist/core/codec/field.js +107 -179
- package/dist/core/codec/islands.d.ts +33 -41
- package/dist/core/codec/islands.js +76 -86
- package/dist/core/codec/lists.d.ts +17 -26
- package/dist/core/codec/lists.js +117 -157
- package/dist/core/codec/marks.d.ts +4 -3
- package/dist/core/codec/marks.js +8 -3
- package/dist/core/codec/prose.css +84 -46
- package/dist/core/codec/schema.d.ts +18 -23
- package/dist/core/codec/schema.js +84 -76
- package/dist/core/codec/slash.d.ts +42 -48
- package/dist/core/codec/slash.js +0 -0
- package/dist/core/codec/table-copy.d.ts +4 -3
- package/dist/core/codec/table-copy.js +25 -7
- package/dist/core/codec/table-view.d.ts +12 -12
- package/dist/core/codec/table-view.js +460 -383
- package/dist/core/codec/table.d.ts +94 -61
- package/dist/core/codec/table.js +331 -83
- package/dist/core/codec/tasks.d.ts +6 -0
- package/dist/core/codec/tasks.js +30 -3
- package/dist/core/errors.d.ts +15 -30
- package/dist/core/errors.js +2 -6
- package/dist/core/index.js +7 -12
- package/dist/core/lifecycle.d.ts +7 -16
- package/dist/core/lifecycle.js +10 -21
- package/dist/core/rebind.svelte.d.ts +10 -20
- package/dist/core/rebind.svelte.js +15 -27
- package/dist/core/rungs.d.ts +14 -11
- package/dist/core/rungs.js +17 -19
- package/dist/core/teardown.d.ts +4 -6
- package/dist/core/teardown.js +7 -10
- package/dist/core/theme.css +74 -54
- package/dist/index.js +3 -8
- package/dist/preset/app.css +3 -1
- package/dist/preset/index.css +6 -8
- package/dist/preset/recipes.css +12 -15
- package/dist/preset/scale.css +18 -17
- package/dist/preset/shell.css +10 -0
- package/dist/preview/bridge.d.ts +18 -22
- package/dist/preview/bridge.js +29 -58
- package/dist/preview/controller.d.ts +21 -29
- package/dist/preview/controller.js +14 -39
- package/dist/preview/geometry.d.ts +13 -34
- package/dist/preview/geometry.js +13 -34
- package/dist/preview/index.js +4 -16
- package/dist/preview/paint.d.ts +3 -3
- package/dist/preview/paint.js +28 -68
- package/dist/preview/strings.d.ts +1 -1
- package/dist/preview/strings.js +2 -14
- package/dist/preview/zoom.d.ts +18 -23
- package/dist/preview/zoom.js +28 -27
- package/dist/visual/ArrayField.svelte +77 -16
- package/dist/visual/BooleanField.svelte +27 -14
- package/dist/visual/Card.svelte +61 -48
- package/dist/visual/CardControls.svelte +5 -11
- package/dist/visual/DateField.svelte +20 -4
- package/dist/visual/EnumField.svelte +3 -0
- package/dist/visual/FieldHint.svelte +2 -1
- package/dist/visual/FormatPopover.svelte +82 -15
- package/dist/visual/FormatPopover.svelte.d.ts +4 -0
- package/dist/visual/MatrixAdd.svelte +30 -12
- package/dist/visual/MatrixField.svelte +24 -16
- package/dist/visual/NumberField.svelte +7 -0
- package/dist/visual/ObjectField.svelte +4 -4
- package/dist/visual/ProseField.svelte +0 -5
- package/dist/visual/TipsCard.svelte +11 -10
- package/dist/visual/VariantField.svelte +3 -1
- package/dist/visual/VisualEditorInner.svelte +19 -3
- package/dist/visual/controls.css +7 -2
- package/dist/visual/fonts.d.ts +18 -0
- package/dist/visual/fonts.js +59 -0
- package/dist/visual/icons/nodes.d.ts +0 -5
- package/dist/visual/icons/nodes.js +0 -4
- package/dist/visual/props.d.ts +14 -1
- package/dist/visual/strings.d.ts +7 -0
- package/dist/visual/strings.js +5 -2
- package/dist/visual/structure.d.ts +43 -87
- package/dist/visual/structure.js +42 -83
- package/package.json +2 -2
|
@@ -1,35 +1,28 @@
|
|
|
1
|
-
// Islands: the `U+FFFC` slot + `ContentIsland` entry ↔ a PM leaf node. Every slot sits
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
// verbatim.
|
|
1
|
+
// Islands: the `U+FFFC` slot + `ContentIsland` entry ↔ a PM leaf node. Every slot sits in a `para`
|
|
2
|
+
// line; the island's type says which node it is, a `table` a block alone on its line and every
|
|
3
|
+
// other type inline. The node carries `id`, `islandType` and `props` verbatim.
|
|
5
4
|
//
|
|
6
|
-
//
|
|
7
|
-
// `
|
|
8
|
-
// `
|
|
9
|
-
// reads it rather than hand-rolling a shape. `type` is a closed set, so a
|
|
10
|
-
// discriminant check narrows it; `props` still crosses the DOM as opaque JSON,
|
|
11
|
-
// which is what §`tablePropsOfNode` guards.
|
|
5
|
+
// `ContentIsland.props` is the typed union at the boundary (DOCUMENT_MODEL §Stability seams), so a
|
|
6
|
+
// discriminant check narrows it; `props` still crosses the DOM as opaque JSON, which
|
|
7
|
+
// §`tablePropsOfNode` guards.
|
|
12
8
|
import { Fragment, Slice } from 'prosemirror-model';
|
|
13
9
|
import { Plugin } from 'prosemirror-state';
|
|
14
10
|
import { storableUrl } from './urls.js';
|
|
15
11
|
/** The `U+FFFC` object-replacement char that occupies one island slot in `text`. */
|
|
16
12
|
export const ISLAND_SLOT = '';
|
|
17
|
-
// The three island node attributes carry the content entry verbatim: `id` is the
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
//
|
|
21
|
-
// supplied at every `create`.
|
|
13
|
+
// The three island node attributes carry the content entry verbatim: `id` is the stable identity
|
|
14
|
+
// (rebases like an anchor), `islandType` the discriminator, `props` the payload preserved
|
|
15
|
+
// byte-for-byte. `islandType` and `props` declare no default: a node standing for an island holds
|
|
16
|
+
// one.
|
|
22
17
|
const islandAttrs = {
|
|
23
18
|
id: { default: '' },
|
|
24
19
|
islandType: {},
|
|
25
20
|
props: {}
|
|
26
21
|
};
|
|
27
|
-
// All three attributes cross the DOM
|
|
28
|
-
// through `toDOM`/`parseDOM` (CODEC §"Markdown at the edges")
|
|
29
|
-
//
|
|
30
|
-
//
|
|
31
|
-
// what the rule requires: an island is a leaf, so a rule reading a tag someone else
|
|
32
|
-
// chose would swallow that element's whole subtree.
|
|
22
|
+
// All three attributes cross the DOM, since a copy and a paste inside one body run the document
|
|
23
|
+
// through `toDOM`/`parseDOM` (CODEC §"Markdown at the edges") and an island's tags alone say only
|
|
24
|
+
// `[table]`. `props` crosses as JSON. The names are `data-qm-*`, and the id is required: an island
|
|
25
|
+
// is a leaf, so a rule reading someone else's tag would swallow that element's whole subtree.
|
|
33
26
|
/** The DOM an island node writes and reads back, for either spec. */
|
|
34
27
|
function islandDOM(node) {
|
|
35
28
|
return {
|
|
@@ -38,11 +31,12 @@ function islandDOM(node) {
|
|
|
38
31
|
'data-qm-island-props': JSON.stringify(node.attrs.props ?? null)
|
|
39
32
|
};
|
|
40
33
|
}
|
|
41
|
-
/**
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
34
|
+
/**
|
|
35
|
+
* The island types the content model names, each with whether its markup is a block (deciding the
|
|
36
|
+
* node its slot decodes to) and whether a leaf edits it. A `Record` over the boundary's union, so a
|
|
37
|
+
* member added upstream is a missing key here. A footnote and an equation are read, not edited
|
|
38
|
+
* (CODEC §Decode): a leaf holding one is held.
|
|
39
|
+
*/
|
|
46
40
|
const ISLANDS = {
|
|
47
41
|
table: { block: true, edited: true },
|
|
48
42
|
image: { block: false, edited: true },
|
|
@@ -57,12 +51,12 @@ export function isBlockIsland(type) {
|
|
|
57
51
|
export function isEditedIsland(type) {
|
|
58
52
|
return ISLANDS[type].edited;
|
|
59
53
|
}
|
|
60
|
-
/**
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
|
|
54
|
+
/**
|
|
55
|
+
* An island node's attributes off that DOM, or `false` where the id is absent or the type is one no
|
|
56
|
+
* leaf edits (an unknown name, a footnote, an equation), so the element's text arrives as text. A
|
|
57
|
+
* `props` that is not the JSON written above reads as `null`, one of the wrong shape `undefined` at
|
|
58
|
+
* its reader (§`tablePropsOfNode`): the entry survives as an island of its type.
|
|
59
|
+
*/
|
|
66
60
|
function islandAttrsFromDOM(el) {
|
|
67
61
|
const id = el.getAttribute('data-qm-island-id');
|
|
68
62
|
// Asserted off an untrusted attribute and checked against the set on the next line.
|
|
@@ -79,16 +73,17 @@ function islandAttrsFromDOM(el) {
|
|
|
79
73
|
}
|
|
80
74
|
return { id, islandType: type, props: storableProps(type, props) };
|
|
81
75
|
}
|
|
82
|
-
/**
|
|
83
|
-
*
|
|
84
|
-
*
|
|
76
|
+
/**
|
|
77
|
+
* `props` with the one key the authored lane refuses made storable: an `image`'s `url` carrying a
|
|
78
|
+
* line ending, which `IslandOp` and `overwrite` throw on.
|
|
79
|
+
*/
|
|
85
80
|
function storableProps(type, props) {
|
|
86
81
|
if (type !== 'image' || typeof props !== 'object' || props === null)
|
|
87
82
|
return props;
|
|
88
83
|
const url = props.url;
|
|
89
84
|
return typeof url === 'string' ? { ...props, url: storableUrl(url) } : props;
|
|
90
85
|
}
|
|
91
|
-
/** Block island node (a table): a `U+FFFC` slot alone on its `para` line. Atom
|
|
86
|
+
/** Block island node (a table): a `U+FFFC` slot alone on its `para` line. Atom. */
|
|
92
87
|
export const islandBlockSpec = {
|
|
93
88
|
group: 'block',
|
|
94
89
|
atom: true,
|
|
@@ -97,8 +92,7 @@ export const islandBlockSpec = {
|
|
|
97
92
|
parseDOM: [{ tag: 'div[data-qm-island]', getAttrs: (el) => islandAttrsFromDOM(el) }],
|
|
98
93
|
toDOM: (node) => ['div', islandDOM(node), `[${node.attrs.islandType || 'island'}]`]
|
|
99
94
|
};
|
|
100
|
-
/** Inline island node (an image, a footnote, an equation): a `U+FFFC` slot inside a
|
|
101
|
-
* `para` line. */
|
|
95
|
+
/** Inline island node (an image, a footnote, an equation): a `U+FFFC` slot inside a `para` line. */
|
|
102
96
|
export const islandInlineSpec = {
|
|
103
97
|
group: 'inline',
|
|
104
98
|
inline: true,
|
|
@@ -108,9 +102,10 @@ export const islandInlineSpec = {
|
|
|
108
102
|
parseDOM: [{ tag: 'span[data-qm-island]', getAttrs: (el) => islandAttrsFromDOM(el) }],
|
|
109
103
|
toDOM: inlineIslandDOM
|
|
110
104
|
};
|
|
111
|
-
/**
|
|
112
|
-
*
|
|
113
|
-
*
|
|
105
|
+
/**
|
|
106
|
+
* An inline island's DOM: a footnote its reference mark (number drawn by `prose.css`, note as
|
|
107
|
+
* title), an equation its TeX between dollars, an image its tag.
|
|
108
|
+
*/
|
|
114
109
|
function inlineIslandDOM(node) {
|
|
115
110
|
const attrs = node.attrs;
|
|
116
111
|
const dom = islandDOM(node);
|
|
@@ -123,11 +118,12 @@ function inlineIslandDOM(node) {
|
|
|
123
118
|
}
|
|
124
119
|
return ['span', dom, `[${attrs.islandType || 'island'}]`];
|
|
125
120
|
}
|
|
126
|
-
/**
|
|
127
|
-
*
|
|
128
|
-
*
|
|
129
|
-
*
|
|
130
|
-
*
|
|
121
|
+
/**
|
|
122
|
+
* Build a content island entry from a PM island node's attrs. The cast pairs a closed `type` with a
|
|
123
|
+
* `props` that crossed the DOM as opaque JSON. The store is lenient about a table's shape, so a
|
|
124
|
+
* payload the arm does not hold is stored, and `undefined` at its reader draws the placeholder
|
|
125
|
+
* (§`tablePropsOfNode`).
|
|
126
|
+
*/
|
|
131
127
|
export function islandEntryFromNode(attrs) {
|
|
132
128
|
return {
|
|
133
129
|
id: attrs.id,
|
|
@@ -135,9 +131,10 @@ export function islandEntryFromNode(attrs) {
|
|
|
135
131
|
props: attrs.props
|
|
136
132
|
};
|
|
137
133
|
}
|
|
138
|
-
/**
|
|
139
|
-
*
|
|
140
|
-
*
|
|
134
|
+
/**
|
|
135
|
+
* The `TableProps` shape over a value that reached the node off the DOM: the rectangle every reader
|
|
136
|
+
* indexes (`table.ts`), down to the `text` a row's emptiness is read off.
|
|
137
|
+
*/
|
|
141
138
|
function isTableProps(props) {
|
|
142
139
|
if (typeof props !== 'object' || props === null)
|
|
143
140
|
return false;
|
|
@@ -146,32 +143,30 @@ function isTableProps(props) {
|
|
|
146
143
|
v.every((c) => typeof c === 'object' && c !== null && typeof c.text === 'string');
|
|
147
144
|
return (cells(header) && Array.isArray(aligns) && Array.isArray(rows) && rows.every((row) => cells(row)));
|
|
148
145
|
}
|
|
149
|
-
/**
|
|
150
|
-
*
|
|
151
|
-
*
|
|
152
|
-
*
|
|
153
|
-
|
|
146
|
+
/**
|
|
147
|
+
* A node's `TableProps`, or `undefined` for any other island and for a payload of the wrong shape:
|
|
148
|
+
* the boundary's guard, so a `props` that crossed the DOM is read once here. Every caller draws the
|
|
149
|
+
* placeholder for `undefined` (`table-view.ts` §`render`).
|
|
150
|
+
*/
|
|
154
151
|
export function tablePropsOfNode(node) {
|
|
155
152
|
const attrs = node.attrs;
|
|
156
153
|
return attrs.islandType === 'table' && isTableProps(attrs.props) ? attrs.props : undefined;
|
|
157
154
|
}
|
|
158
155
|
/**
|
|
159
|
-
* A minter over one document: the positional `isl-{n}` sequence continued past the
|
|
160
|
-
*
|
|
161
|
-
*
|
|
162
|
-
*
|
|
163
|
-
* counter over the projection in hand — never a UUID, never a clock reading, and never a
|
|
164
|
-
* re-numbering of the ids already there, which are identities.
|
|
156
|
+
* A minter over one document: the positional `isl-{n}` sequence continued past the highest id the
|
|
157
|
+
* field holds, so a caller placing several islands keeps one minter. A minted id is part of the
|
|
158
|
+
* document's canonical bytes (CODEC §Islands): a counter over the projection in hand, never a UUID
|
|
159
|
+
* or clock reading, and never a re-numbering of existing ids.
|
|
165
160
|
*
|
|
166
|
-
* Reads the PM doc rather than
|
|
167
|
-
*
|
|
168
|
-
* a stale content could collide with one the same transaction places.
|
|
161
|
+
* Reads the PM doc rather than stored content because that is what the caller holds and the commit
|
|
162
|
+
* will project; a stale content could collide with an id the same transaction places.
|
|
169
163
|
*/
|
|
170
164
|
export function islandMinter(doc) {
|
|
171
165
|
return islandState(doc).mint;
|
|
172
166
|
}
|
|
173
|
-
/**
|
|
174
|
-
*
|
|
167
|
+
/**
|
|
168
|
+
* The ids a document holds and the minter continuing past them, off one sweep for the paste pass.
|
|
169
|
+
*/
|
|
175
170
|
function islandState(doc) {
|
|
176
171
|
const held = new Set();
|
|
177
172
|
let next = 0;
|
|
@@ -187,20 +182,19 @@ function islandState(doc) {
|
|
|
187
182
|
});
|
|
188
183
|
return { held, mint: () => `isl-${next++}` };
|
|
189
184
|
}
|
|
190
|
-
/** The next island id for a field: one draw from {@link islandMinter}
|
|
191
|
-
* command placing exactly one island wants. */
|
|
185
|
+
/** The next island id for a field: one draw from {@link islandMinter}. */
|
|
192
186
|
export function mintIslandId(doc) {
|
|
193
187
|
return islandMinter(doc)();
|
|
194
188
|
}
|
|
195
|
-
/** Either island node: the test the sweep and the paste pass share
|
|
196
|
-
* shape is one arm rather than two. */
|
|
189
|
+
/** Either island node: the test the sweep and the paste pass share. */
|
|
197
190
|
function isIsland(node) {
|
|
198
191
|
return node.type.name === 'island_block' || node.type.name === 'island_inline';
|
|
199
192
|
}
|
|
200
|
-
/**
|
|
201
|
-
*
|
|
202
|
-
*
|
|
203
|
-
*
|
|
193
|
+
/**
|
|
194
|
+
* `fragment` with every island whose id is empty or already `taken` minted afresh, or `null` where
|
|
195
|
+
* none was, so an untouched paste stays the slice it arrived as. Every surviving id joins the set,
|
|
196
|
+
* so a slice carrying one id twice comes apart in the same pass.
|
|
197
|
+
*/
|
|
204
198
|
function remintIslands(fragment, taken, mint) {
|
|
205
199
|
const out = [];
|
|
206
200
|
let changed = false;
|
|
@@ -224,22 +218,18 @@ function remintIslands(fragment, taken, mint) {
|
|
|
224
218
|
return changed ? Fragment.fromArray(out) : null;
|
|
225
219
|
}
|
|
226
220
|
/**
|
|
227
|
-
* The paste's island pass: an id the field already holds is re-minted on the way in, and
|
|
228
|
-
*
|
|
229
|
-
* its first.
|
|
221
|
+
* The paste's island pass: an id the field already holds is re-minted on the way in, and an island
|
|
222
|
+
* arriving with none (a table read off foreign markup, `table-paste.ts`) takes its first.
|
|
230
223
|
*
|
|
231
|
-
*
|
|
232
|
-
*
|
|
233
|
-
*
|
|
234
|
-
* collides with nothing and keeps the identity it had.
|
|
224
|
+
* Ids are unique across the field, so two islands wearing one is a projection the store has no
|
|
225
|
+
* shape for. That arrives by a copy or a paste from a second field; a cut pasted back collides with
|
|
226
|
+
* nothing and keeps its identity.
|
|
235
227
|
*
|
|
236
|
-
* The test is the document as it stands,
|
|
237
|
-
*
|
|
238
|
-
*
|
|
239
|
-
* duplicate would cost the whole field.
|
|
228
|
+
* The test is the document as it stands, so a drag moving a selection over an island sees the
|
|
229
|
+
* original still there and mints a fresh id for the arrival, which costs nothing next to a
|
|
230
|
+
* duplicate.
|
|
240
231
|
*
|
|
241
|
-
* A plugin prop rather than a view option:
|
|
242
|
-
* which nodes carry an identity is the codec's to know.
|
|
232
|
+
* A plugin prop rather than a view option: which nodes carry an identity is the codec's to know.
|
|
243
233
|
*/
|
|
244
234
|
export function islandPastePlugin() {
|
|
245
235
|
return new Plugin({
|
|
@@ -1,34 +1,25 @@
|
|
|
1
1
|
import type { Schema } from 'prosemirror-model';
|
|
2
2
|
import type { Command } from 'prosemirror-state';
|
|
3
3
|
/**
|
|
4
|
-
* The list bindings for a block-schema leaf: `{}` for the one-line and plain
|
|
5
|
-
*
|
|
4
|
+
* The list bindings for a block-schema leaf: `{}` for the one-line and plain schemas, which declare
|
|
5
|
+
* no list nodes.
|
|
6
6
|
*
|
|
7
|
-
* `Tab` / `Shift-Tab` hold the list link of the body's Tab chain
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* (`
|
|
7
|
+
* `Tab` / `Shift-Tab` hold the list link of the body's Tab chain; surfaces owning Tab more locally
|
|
8
|
+
* prepend a link in `keymap.ts` (`prose/canon/VISUAL_EDITOR.md` §Chrome). `Tab` sinks an unnumbered
|
|
9
|
+
* line alone into a sub-list, any other line its whole item, and a block right after a list into
|
|
10
|
+
* the list's last item. `Mod-Shift-7` / `Mod-Shift-8` are the list toggle (`list-toggle.ts`).
|
|
11
|
+
* `Mod-Enter` ticks the task item around the caret (`toggleTask`).
|
|
12
12
|
*
|
|
13
|
-
* `
|
|
14
|
-
*
|
|
13
|
+
* `Enter` is a chain in precedence order: the empty line above an unnumbered one, an empty top-level
|
|
14
|
+
* middle item out of the list, the marker back on an empty continuation line, `splitListItem` (`splitTaskItem` for
|
|
15
|
+
* tasks), then `liftListItem`. The split link splits a non-empty item, and on an empty last item
|
|
16
|
+
* either splits the wrapping item (a nested one, so Enter lifts one level) or bails so the last
|
|
17
|
+
* link lifts a top-level one to a paragraph.
|
|
15
18
|
*
|
|
16
|
-
* `
|
|
17
|
-
* and a block
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* (`splitTaskItem`, which leaves a task item's new half an open task), then
|
|
22
|
-
* `liftListItem`. The split link carries two behaviors of its own: it splits a
|
|
23
|
-
* non-empty item, and on an empty last item it either splits the wrapping item (a
|
|
24
|
-
* nested one, so Enter lifts exactly one level) or bails so the last link lifts a
|
|
25
|
-
* top-level one out to a paragraph. `Backspace` takes an item's marker off at its
|
|
26
|
-
* start, a top-level continuation line out to full width, and joins a block onto the
|
|
27
|
-
* list it stands after, and both keys over a selection spanning blocks join the lists
|
|
28
|
-
* the delete leaves touching. `Delete` is the marker off at the seam below with the two lines
|
|
29
|
-
* joined, never the line out: a forward delete edits the line after the caret, not its
|
|
30
|
-
* indent. An empty line is neither key's here:
|
|
31
|
-
* the block link takes it ahead of this chain (`blocks.ts`), the caret's own line
|
|
32
|
-
* being a nearer fact than the boundary under it.
|
|
19
|
+
* `Backspace` takes an item's marker off at its start, a top-level continuation line out to full
|
|
20
|
+
* width, and joins a block onto the list it follows; over a selection spanning blocks both keys
|
|
21
|
+
* join the lists the delete leaves touching. `Delete` is the marker off at the seam below with the
|
|
22
|
+
* two lines joined, never the line out. An empty line is neither key's here: the block link takes
|
|
23
|
+
* it first (`blocks.ts`).
|
|
33
24
|
*/
|
|
34
25
|
export declare function listKeymap(schema: Schema): Record<string, Command>;
|