@tarhnama/core 0.1.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/LICENSE +21 -0
- package/README.md +16 -0
- package/dist/code-tokens.d.ts +39 -0
- package/dist/code-tokens.d.ts.map +1 -0
- package/dist/code-tokens.js +189 -0
- package/dist/code-tokens.js.map +1 -0
- package/dist/context-menu.d.ts +59 -0
- package/dist/context-menu.d.ts.map +1 -0
- package/dist/context-menu.js +69 -0
- package/dist/context-menu.js.map +1 -0
- package/dist/features.d.ts +114 -0
- package/dist/features.d.ts.map +1 -0
- package/dist/features.js +128 -0
- package/dist/features.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/nested.d.ts +66 -0
- package/dist/nested.d.ts.map +1 -0
- package/dist/nested.js +194 -0
- package/dist/nested.js.map +1 -0
- package/dist/ops.d.ts +120 -0
- package/dist/ops.d.ts.map +1 -0
- package/dist/ops.js +333 -0
- package/dist/ops.js.map +1 -0
- package/dist/shortcuts.d.ts +90 -0
- package/dist/shortcuts.d.ts.map +1 -0
- package/dist/shortcuts.js +179 -0
- package/dist/shortcuts.js.map +1 -0
- package/dist/spine.d.ts +92 -0
- package/dist/spine.d.ts.map +1 -0
- package/dist/spine.js +213 -0
- package/dist/spine.js.map +1 -0
- package/dist/styles.d.ts +63 -0
- package/dist/styles.d.ts.map +1 -0
- package/dist/styles.js +169 -0
- package/dist/styles.js.map +1 -0
- package/dist/tree.d.ts +70 -0
- package/dist/tree.d.ts.map +1 -0
- package/dist/tree.js +190 -0
- package/dist/tree.js.map +1 -0
- package/dist/types.d.ts +239 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +47 -0
- package/dist/types.js.map +1 -0
- package/package.json +52 -0
- package/src/code-tokens.ts +236 -0
- package/src/context-menu.ts +139 -0
- package/src/features.ts +173 -0
- package/src/index.ts +58 -0
- package/src/nested.ts +271 -0
- package/src/ops.ts +341 -0
- package/src/shortcuts.ts +280 -0
- package/src/spine.ts +214 -0
- package/src/styles.ts +201 -0
- package/src/tree.ts +189 -0
- package/src/types.ts +275 -0
package/dist/ops.js
ADDED
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
import { BODY, MAX_LEVEL, } from './types.js';
|
|
2
|
+
import { ancestors, buildIndex, isLocked, prevHeading, subtreeRange } from './tree.js';
|
|
3
|
+
/**
|
|
4
|
+
* Structural operations. All are pure: they take a flat list and return a new one,
|
|
5
|
+
* sharing unchanged blocks by reference so downstream memoization works.
|
|
6
|
+
*
|
|
7
|
+
* The defining rule of this module: an operation on a heading applies to its whole
|
|
8
|
+
* SUBTREE. Indenting a heading and leaving its children behind — the bug in the
|
|
9
|
+
* earlier Tiptap scaffold — produces an orphaned document.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Can `i` be indented?
|
|
13
|
+
*
|
|
14
|
+
* The rule prevents skipped levels: a heading may go one deeper than the nearest
|
|
15
|
+
* preceding heading, never more. Without this you can indent from level 1 straight
|
|
16
|
+
* to level 3 and create a block with no representable parent.
|
|
17
|
+
*
|
|
18
|
+
* Body text has no level, so indenting it is meaningless — use `setLevel` to promote
|
|
19
|
+
* body text into a heading instead.
|
|
20
|
+
*/
|
|
21
|
+
export function canIndent(blocks, i) {
|
|
22
|
+
const block = blocks[i];
|
|
23
|
+
if (!block || block.level === BODY)
|
|
24
|
+
return false;
|
|
25
|
+
// A locked block's position is fixed. Checked here rather than in `indent` so the UI
|
|
26
|
+
// can grey the control out instead of offering an action that silently does nothing.
|
|
27
|
+
if (isLocked(blocks, buildIndex(blocks), i))
|
|
28
|
+
return false;
|
|
29
|
+
const prev = prevHeading(blocks, i);
|
|
30
|
+
if (prev === -1)
|
|
31
|
+
return false; // first heading in the document: nothing to nest under
|
|
32
|
+
if (block.level > blocks[prev].level)
|
|
33
|
+
return false; // already a child of prev
|
|
34
|
+
// The deepest descendant must still fit within MAX_LEVEL after the shift.
|
|
35
|
+
const index = buildIndex(blocks);
|
|
36
|
+
const end = index.subtreeEnd[i];
|
|
37
|
+
for (let j = i; j < end; j++) {
|
|
38
|
+
const l = blocks[j].level;
|
|
39
|
+
if (l !== BODY && l + 1 > MAX_LEVEL)
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
export function indent(blocks, i) {
|
|
45
|
+
if (!canIndent(blocks, i))
|
|
46
|
+
return blocks;
|
|
47
|
+
return shiftSubtree(blocks, i, +1);
|
|
48
|
+
}
|
|
49
|
+
/** Level 1 cannot outdent — there is nothing above it. Body text has no level. */
|
|
50
|
+
export function canOutdent(blocks, i) {
|
|
51
|
+
const block = blocks[i];
|
|
52
|
+
if (!block || block.level < 2)
|
|
53
|
+
return false;
|
|
54
|
+
return !isLocked(blocks, buildIndex(blocks), i);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Outdent a heading and its subtree.
|
|
58
|
+
*
|
|
59
|
+
* Pleasant property of the flat model: the following siblings that were at the
|
|
60
|
+
* outdented block's old level automatically become its children, which is exactly
|
|
61
|
+
* what Workflowy and Word's outline view do — no extra code needed.
|
|
62
|
+
*/
|
|
63
|
+
export function outdent(blocks, i) {
|
|
64
|
+
if (!canOutdent(blocks, i))
|
|
65
|
+
return blocks;
|
|
66
|
+
return shiftSubtree(blocks, i, -1);
|
|
67
|
+
}
|
|
68
|
+
function shiftSubtree(blocks, i, delta) {
|
|
69
|
+
const index = buildIndex(blocks);
|
|
70
|
+
const end = index.subtreeEnd[i];
|
|
71
|
+
const next = blocks.slice();
|
|
72
|
+
for (let j = i; j < end; j++) {
|
|
73
|
+
const b = blocks[j];
|
|
74
|
+
if (b.level === BODY)
|
|
75
|
+
continue; // body text has no level to shift
|
|
76
|
+
next[j] = { ...b, level: (b.level + delta) };
|
|
77
|
+
}
|
|
78
|
+
return next;
|
|
79
|
+
}
|
|
80
|
+
/** Set a block's level directly — used to promote body text to a heading and back. */
|
|
81
|
+
export function canSetLevel(blocks, i) {
|
|
82
|
+
return !!blocks[i] && !isLocked(blocks, buildIndex(blocks), i);
|
|
83
|
+
}
|
|
84
|
+
export function setLevel(blocks, i, level) {
|
|
85
|
+
if (!canSetLevel(blocks, i))
|
|
86
|
+
return blocks;
|
|
87
|
+
const block = blocks[i];
|
|
88
|
+
if (!block || block.level === level)
|
|
89
|
+
return blocks;
|
|
90
|
+
const next = blocks.slice();
|
|
91
|
+
next[i] = { ...block, level };
|
|
92
|
+
return next;
|
|
93
|
+
}
|
|
94
|
+
export function toggleCollapse(blocks, i) {
|
|
95
|
+
const block = blocks[i];
|
|
96
|
+
if (!block)
|
|
97
|
+
return blocks;
|
|
98
|
+
const next = blocks.slice();
|
|
99
|
+
next[i] = { ...block, collapsed: !block.collapsed };
|
|
100
|
+
return next;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Expand every collapsed ancestor of a block, so it can actually be reached.
|
|
104
|
+
*
|
|
105
|
+
* Needed wherever the app navigates to a block the user did not click: a search result, a
|
|
106
|
+
* cross-document link, a backlink. A collapsed subtree is ABSENT from the DOM, not hidden,
|
|
107
|
+
* so scrolling to it finds nothing and the jump silently does nothing at all — which reads
|
|
108
|
+
* as a broken feature rather than as "that match is folded away".
|
|
109
|
+
*
|
|
110
|
+
* Only ancestors are touched. The block's own collapse state is left alone: revealing a
|
|
111
|
+
* heading should not also unfold everything beneath it.
|
|
112
|
+
*
|
|
113
|
+
* Returns the SAME list when nothing was collapsed.
|
|
114
|
+
*/
|
|
115
|
+
export function expandAncestors(blocks, blockId) {
|
|
116
|
+
const at = blocks.findIndex((block) => block.id === blockId);
|
|
117
|
+
if (at === -1)
|
|
118
|
+
return blocks;
|
|
119
|
+
const index = buildIndex(blocks);
|
|
120
|
+
const toOpen = new Set(ancestors(index, at).filter((i) => blocks[i]?.collapsed === true));
|
|
121
|
+
if (toOpen.size === 0)
|
|
122
|
+
return blocks;
|
|
123
|
+
return blocks.map((block, i) => (toOpen.has(i) ? { ...block, collapsed: false } : block));
|
|
124
|
+
}
|
|
125
|
+
export function setDirection(blocks, i, dir) {
|
|
126
|
+
const block = blocks[i];
|
|
127
|
+
if (!block || block.dir === dir)
|
|
128
|
+
return blocks;
|
|
129
|
+
const next = blocks.slice();
|
|
130
|
+
next[i] = { ...block, dir };
|
|
131
|
+
return next;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Move the subtree rooted at `from` so it begins at document position `to`.
|
|
135
|
+
*
|
|
136
|
+
* `to` is interpreted against the ORIGINAL list. Moving a subtree into itself is a
|
|
137
|
+
* no-op rather than an error, because drag-and-drop will attempt it constantly.
|
|
138
|
+
*/
|
|
139
|
+
/**
|
|
140
|
+
* Can the subtree at `from` be moved to `to`?
|
|
141
|
+
*
|
|
142
|
+
* Both ends matter: a locked subtree cannot be dragged away, and nothing may be dropped
|
|
143
|
+
* INTO a locked one. Checking only the source is the easy mistake — it lets a reader
|
|
144
|
+
* append into a chapter they are not allowed to change.
|
|
145
|
+
*/
|
|
146
|
+
export function canMoveSubtree(blocks, from, to) {
|
|
147
|
+
const index = buildIndex(blocks);
|
|
148
|
+
if (!blocks[from])
|
|
149
|
+
return false;
|
|
150
|
+
if (isLocked(blocks, index, from))
|
|
151
|
+
return false;
|
|
152
|
+
// A drop lands BETWEEN blocks, so the block before the insertion point is checked as
|
|
153
|
+
// well: landing just after a locked heading would place the block inside its subtree.
|
|
154
|
+
const before = to - 1;
|
|
155
|
+
if (before >= 0 && before < blocks.length && isLocked(blocks, index, before)) {
|
|
156
|
+
const [, end] = subtreeRange(index, before);
|
|
157
|
+
if (to < end)
|
|
158
|
+
return false;
|
|
159
|
+
}
|
|
160
|
+
if (to < blocks.length && isLocked(blocks, index, to))
|
|
161
|
+
return false;
|
|
162
|
+
return true;
|
|
163
|
+
}
|
|
164
|
+
export function moveSubtree(blocks, from, to) {
|
|
165
|
+
const index = buildIndex(blocks);
|
|
166
|
+
const end = index.subtreeEnd[from];
|
|
167
|
+
if (to >= from && to <= end)
|
|
168
|
+
return blocks; // dropping inside itself
|
|
169
|
+
if (!canMoveSubtree(blocks, from, to))
|
|
170
|
+
return blocks;
|
|
171
|
+
const slice = blocks.slice(from, end);
|
|
172
|
+
const rest = [...blocks.slice(0, from), ...blocks.slice(end)];
|
|
173
|
+
const insertAt = to > from ? to - (end - from) : to;
|
|
174
|
+
return [...rest.slice(0, insertAt), ...slice, ...rest.slice(insertAt)];
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Repair skipped levels — the import path for real Word documents, which jump from
|
|
178
|
+
* H1 to H3 constantly.
|
|
179
|
+
*
|
|
180
|
+
* Each heading is clamped to at most one deeper than the preceding heading, and the
|
|
181
|
+
* first heading is clamped to 1. Body text is untouched.
|
|
182
|
+
*/
|
|
183
|
+
export function normalizeLevels(blocks) {
|
|
184
|
+
let changed = false;
|
|
185
|
+
const next = blocks.slice();
|
|
186
|
+
let prevLevel = 0;
|
|
187
|
+
for (let i = 0; i < blocks.length; i++) {
|
|
188
|
+
const b = blocks[i];
|
|
189
|
+
if (b.level === BODY)
|
|
190
|
+
continue;
|
|
191
|
+
const max = (prevLevel + 1);
|
|
192
|
+
const level = b.level > max ? max : b.level;
|
|
193
|
+
if (level !== b.level) {
|
|
194
|
+
next[i] = { ...b, level };
|
|
195
|
+
changed = true;
|
|
196
|
+
}
|
|
197
|
+
prevLevel = level;
|
|
198
|
+
}
|
|
199
|
+
return changed ? next : blocks;
|
|
200
|
+
}
|
|
201
|
+
/** True when no heading is more than one level deeper than the one before it. */
|
|
202
|
+
export function isNormalized(blocks) {
|
|
203
|
+
let prevLevel = 0;
|
|
204
|
+
for (const b of blocks) {
|
|
205
|
+
if (b.level === BODY)
|
|
206
|
+
continue;
|
|
207
|
+
if (b.level > prevLevel + 1)
|
|
208
|
+
return false;
|
|
209
|
+
prevLevel = b.level;
|
|
210
|
+
}
|
|
211
|
+
return true;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Lock or unlock a block. Locking a heading makes its whole subtree read-only by
|
|
215
|
+
* derivation — only the heading itself carries the flag.
|
|
216
|
+
*/
|
|
217
|
+
export function setLocked(blocks, i, locked) {
|
|
218
|
+
const block = blocks[i];
|
|
219
|
+
if (!block || (block.locked ?? false) === locked)
|
|
220
|
+
return blocks;
|
|
221
|
+
const out = [...blocks];
|
|
222
|
+
// Unlocking REMOVES the flag rather than setting it to `false`, so a document that
|
|
223
|
+
// never used locking serializes exactly as it did before the feature existed.
|
|
224
|
+
out[i] = locked ? { ...block, locked: true } : stripLocked(block);
|
|
225
|
+
return out;
|
|
226
|
+
}
|
|
227
|
+
function stripLocked(block) {
|
|
228
|
+
const { locked: _locked, ...rest } = block;
|
|
229
|
+
return rest;
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* The previous sibling of the block at `i`, or -1.
|
|
233
|
+
*
|
|
234
|
+
* A sibling is the nearest preceding block at the SAME level that shares a parent — which
|
|
235
|
+
* for this model means: walking backwards, the first block at that level, stopping if a
|
|
236
|
+
* shallower one appears first, because that is the parent and the run has ended.
|
|
237
|
+
*/
|
|
238
|
+
function previousSibling(blocks, i) {
|
|
239
|
+
const level = blocks[i]?.level;
|
|
240
|
+
if (level === undefined)
|
|
241
|
+
return -1;
|
|
242
|
+
for (let j = i - 1; j >= 0; j--) {
|
|
243
|
+
const other = blocks[j]?.level;
|
|
244
|
+
if (other === undefined)
|
|
245
|
+
continue;
|
|
246
|
+
if (other === level)
|
|
247
|
+
return j;
|
|
248
|
+
// Body text (level 0) sits under headings and never terminates a heading's run, but a
|
|
249
|
+
// heading shallower than us IS our parent and there is no earlier sibling under it.
|
|
250
|
+
if (other !== BODY && other < level)
|
|
251
|
+
return -1;
|
|
252
|
+
if (level === BODY && other !== BODY)
|
|
253
|
+
return -1;
|
|
254
|
+
}
|
|
255
|
+
return -1;
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Move a node before its previous sibling, subtree and all.
|
|
259
|
+
*
|
|
260
|
+
* "Up" is **a sibling**, not a row. A heading with forty blocks under it must jump the
|
|
261
|
+
* whole of its neighbour's subtree; swapping single rows would tear both apart, and the
|
|
262
|
+
* design's درخت menu calls this "move node" for that reason.
|
|
263
|
+
*
|
|
264
|
+
* A first sibling does not move. The tempting alternative — promote it above its parent —
|
|
265
|
+
* changes the node's LEVEL as a side effect of a move, and a command that quietly does two
|
|
266
|
+
* things is one users stop trusting. Indent and outdent are how a level changes.
|
|
267
|
+
*/
|
|
268
|
+
export function moveBlockUp(blocks, blockId) {
|
|
269
|
+
const at = blocks.findIndex((block) => block.id === blockId);
|
|
270
|
+
if (at === -1)
|
|
271
|
+
return blocks;
|
|
272
|
+
const target = previousSibling(blocks, at);
|
|
273
|
+
if (target === -1)
|
|
274
|
+
return blocks;
|
|
275
|
+
return moveSubtree(blocks, at, target);
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Move a node after its next sibling, subtree and all.
|
|
279
|
+
*
|
|
280
|
+
* The target is the END of the sibling's subtree, in ORIGINAL indices — `moveSubtree`
|
|
281
|
+
* interprets `to` against the list it was given and does the shift arithmetic itself.
|
|
282
|
+
* Pre-adjusting by the moved subtree's size (the obvious defensive move) lands the target
|
|
283
|
+
* back inside the node being moved, where `moveSubtree`'s "dropping inside itself" guard
|
|
284
|
+
* correctly refuses it and the command silently does nothing.
|
|
285
|
+
*/
|
|
286
|
+
export function moveBlockDown(blocks, blockId) {
|
|
287
|
+
const at = blocks.findIndex((block) => block.id === blockId);
|
|
288
|
+
if (at === -1)
|
|
289
|
+
return blocks;
|
|
290
|
+
const index = buildIndex(blocks);
|
|
291
|
+
const [, end] = subtreeRange(index, at);
|
|
292
|
+
if (end >= blocks.length)
|
|
293
|
+
return blocks;
|
|
294
|
+
const level = blocks[at]?.level;
|
|
295
|
+
const nextLevel = blocks[end]?.level;
|
|
296
|
+
if (level === undefined || nextLevel === undefined)
|
|
297
|
+
return blocks;
|
|
298
|
+
// The block after our subtree is only a SIBLING if it is at our level; anything
|
|
299
|
+
// shallower is the end of our parent's run and there is nothing left to swap with.
|
|
300
|
+
if (nextLevel !== level)
|
|
301
|
+
return blocks;
|
|
302
|
+
const [, siblingEnd] = subtreeRange(index, end);
|
|
303
|
+
return moveSubtree(blocks, at, siblingEnd);
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* The level this heading skipped over, or `null`.
|
|
307
|
+
*
|
|
308
|
+
* `isNormalized` answers "does this document skip anywhere", which is enough to enable a
|
|
309
|
+
* repair command and useless for showing the reader WHERE. Frame 1a puts an amber
|
|
310
|
+
* «سطح ۳ جا افتاده» chip on the offending heading, so the question has to be asked of a
|
|
311
|
+
* single block.
|
|
312
|
+
*
|
|
313
|
+
* Returns the FIRST missing level, not the deepest. When 2 → 4 skips only 3 that is the
|
|
314
|
+
* same answer either way, but 1 → 4 skips both 2 and 3, and 2 is the one to add first —
|
|
315
|
+
* naming 3 would send someone to fix the wrong end of the gap.
|
|
316
|
+
*
|
|
317
|
+
* Body text is never an answer and never breaks the chain: level 0 is not a hierarchy
|
|
318
|
+
* level, it belongs to the nearest preceding heading, and a paragraph between two headings
|
|
319
|
+
* does not make the second one a skip.
|
|
320
|
+
*/
|
|
321
|
+
export function skippedLevelAt(blocks, i) {
|
|
322
|
+
const block = blocks[i];
|
|
323
|
+
if (!block || block.level === BODY)
|
|
324
|
+
return null;
|
|
325
|
+
const prev = prevHeading(blocks, i);
|
|
326
|
+
// A document that opens below level 1 has no representable parent for its first heading.
|
|
327
|
+
const parentLevel = prev === -1 ? 0 : (blocks[prev]?.level ?? 0);
|
|
328
|
+
// Going back up, or one step down, is never a skip.
|
|
329
|
+
if (block.level <= parentLevel + 1)
|
|
330
|
+
return null;
|
|
331
|
+
return (parentLevel + 1);
|
|
332
|
+
}
|
|
333
|
+
//# sourceMappingURL=ops.js.map
|
package/dist/ops.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ops.js","sourceRoot":"","sources":["../src/ops.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { type OutlineFeatureName, type OutlineFeatures } from './features.js';
|
|
2
|
+
/**
|
|
3
|
+
* The keyboard shortcuts, as DATA.
|
|
4
|
+
*
|
|
5
|
+
* A hard-coded `addKeyboardShortcuts` in the editor extension has three problems, and each
|
|
6
|
+
* one lands on a different person:
|
|
7
|
+
*
|
|
8
|
+
* 1. A host cannot CHANGE it. Every embedder inherits `Tab` and `Mod-.` whether those
|
|
9
|
+
* collide with their own application or not — and `Tab` in particular is the web's
|
|
10
|
+
* focus key, so an editor that eats it is one a keyboard user cannot leave.
|
|
11
|
+
* 2. A host cannot READ it. Rendering a shortcuts sheet means retyping the list by hand,
|
|
12
|
+
* and the copy drifts from the bindings the moment either changes.
|
|
13
|
+
* 3. Nobody can turn it off, per binding or at all.
|
|
14
|
+
*
|
|
15
|
+
* So the table is plain serializable data — no closures, no editor reference — and the
|
|
16
|
+
* Tiptap extension is generated from it. A settings screen can render it, store it, diff
|
|
17
|
+
* it and hand back an override map.
|
|
18
|
+
*/
|
|
19
|
+
/** The commands a shortcut can be bound to. Names, not functions — see the note above. */
|
|
20
|
+
export type ShortcutCommand = 'indent' | 'outdent' | 'setLevel1' | 'setLevel2' | 'setLevel3' | 'setLevel4' | 'setLevel5' | 'setLevel6' | 'setBodyText' | 'toggleCollapse' | 'collapseSiblings' | 'insertZwnj' | 'undo' | 'redo' | 'bold' | 'italic' | 'underline' | 'strike' | 'moveUp' | 'moveDown';
|
|
21
|
+
export interface ShortcutBinding {
|
|
22
|
+
readonly command: ShortcutCommand;
|
|
23
|
+
/** ProseMirror's spelling: `Mod-` is ⌘ on Apple and Ctrl elsewhere. */
|
|
24
|
+
readonly key: string;
|
|
25
|
+
/** For grouping in a help sheet. */
|
|
26
|
+
readonly group: 'structure' | 'collapse' | 'formatting' | 'editing' | 'persian';
|
|
27
|
+
/**
|
|
28
|
+
* The feature this binding belongs to, if any.
|
|
29
|
+
*
|
|
30
|
+
* Lets `features={{ collapse: false }}` drop `Mod-.` without the host having to know
|
|
31
|
+
* which key that was. A binding with no feature is structural and always survives —
|
|
32
|
+
* indent and outdent ARE the outline, not a feature of it.
|
|
33
|
+
*/
|
|
34
|
+
readonly feature?: OutlineFeatureName;
|
|
35
|
+
/** Shown in a help sheet. English; a host translates via its own label pack. */
|
|
36
|
+
readonly description: string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* The defaults.
|
|
40
|
+
*
|
|
41
|
+
* `Mod-1…6` rather than 1…9: levels 7–9 exist in the model because Word documents contain
|
|
42
|
+
* them, but no keyboard has a comfortable ninth digit and the ladder covers the rest.
|
|
43
|
+
*/
|
|
44
|
+
export declare const DEFAULT_SHORTCUTS: readonly ShortcutBinding[];
|
|
45
|
+
export interface ShortcutOptions {
|
|
46
|
+
/** `false` binds nothing at all. */
|
|
47
|
+
readonly enabled?: boolean;
|
|
48
|
+
/**
|
|
49
|
+
* Rebind (`'Mod-Shift-c'`) or unbind (`null`) by command name.
|
|
50
|
+
*
|
|
51
|
+
* By command rather than by key, because the host knows what they want to move, not
|
|
52
|
+
* what it is currently bound to — and the current binding is exactly the thing they
|
|
53
|
+
* would have to keep in sync by hand.
|
|
54
|
+
*/
|
|
55
|
+
readonly overrides?: Readonly<Partial<Record<ShortcutCommand, string | null>>>;
|
|
56
|
+
/** Bindings whose feature is off are dropped. */
|
|
57
|
+
readonly features?: Partial<OutlineFeatures> | readonly OutlineFeatureName[];
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Apply a host's overrides and feature set to the default table.
|
|
61
|
+
*
|
|
62
|
+
* Collisions THROW. Letting a rebinding silently win means the losing command stops
|
|
63
|
+
* working with nothing logged, discoverable only by someone trying it and wondering what
|
|
64
|
+
* broke — and by then the override is somewhere in the host's configuration, far from the
|
|
65
|
+
* symptom.
|
|
66
|
+
*/
|
|
67
|
+
export declare function resolveShortcuts(options?: ShortcutOptions): readonly ShortcutBinding[];
|
|
68
|
+
export interface ShortcutGroup {
|
|
69
|
+
readonly group: ShortcutBinding['group'];
|
|
70
|
+
readonly bindings: readonly ShortcutBinding[];
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Group the live bindings for display.
|
|
74
|
+
*
|
|
75
|
+
* The order is fixed rather than derived from the data: a sheet that reshuffles between
|
|
76
|
+
* openings cannot be learned, and learning it is the only reason it exists.
|
|
77
|
+
*/
|
|
78
|
+
export declare function shortcutsFor(bindings: readonly ShortcutBinding[]): readonly ShortcutGroup[];
|
|
79
|
+
/** Which glyph set to render. Callers pass their own platform check. */
|
|
80
|
+
export type ShortcutPlatform = 'apple' | 'other';
|
|
81
|
+
/**
|
|
82
|
+
* A binding as a person reads it.
|
|
83
|
+
*
|
|
84
|
+
* `Mod` is ProseMirror's platform-agnostic spelling and must never reach a user: nobody
|
|
85
|
+
* has a Mod key. Apple users read glyphs with no separator, everyone else reads words
|
|
86
|
+
* joined by `+`, and getting that backwards is one of the small things that makes software
|
|
87
|
+
* feel foreign.
|
|
88
|
+
*/
|
|
89
|
+
export declare function formatShortcut(key: string, platform: ShortcutPlatform): string;
|
|
90
|
+
//# sourceMappingURL=shortcuts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shortcuts.d.ts","sourceRoot":"","sources":["../src/shortcuts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,kBAAkB,EAAE,KAAK,eAAe,EAAE,MAAM,eAAe,CAAC;AAE/F;;;;;;;;;;;;;;;;GAgBG;AAEH,0FAA0F;AAC1F,MAAM,MAAM,eAAe,GACvB,QAAQ,GACR,SAAS,GACT,WAAW,GACX,WAAW,GACX,WAAW,GACX,WAAW,GACX,WAAW,GACX,WAAW,GACX,aAAa,GACb,gBAAgB,GAChB,kBAAkB,GAClB,YAAY,GACZ,MAAM,GACN,MAAM,GACN,MAAM,GACN,QAAQ,GACR,WAAW,GACX,QAAQ,GACR,QAAQ,GACR,UAAU,CAAC;AAEf,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;IAClC,uEAAuE;IACvE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,oCAAoC;IACpC,QAAQ,CAAC,KAAK,EAAE,WAAW,GAAG,UAAU,GAAG,YAAY,GAAG,SAAS,GAAG,SAAS,CAAC;IAChF;;;;;;OAMG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,kBAAkB,CAAC;IACtC,gFAAgF;IAChF,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,EAAE,SAAS,eAAe,EA4EvD,CAAC;AAIF,MAAM,WAAW,eAAe;IAC9B,oCAAoC;IACpC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B;;;;;;OAMG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IAC/E,iDAAiD;IACjD,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,GAAG,SAAS,kBAAkB,EAAE,CAAC;CAC9E;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,CAAC,EAAE,eAAe,GAAG,SAAS,eAAe,EAAE,CA6CtF;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC;IACzC,QAAQ,CAAC,QAAQ,EAAE,SAAS,eAAe,EAAE,CAAC;CAC/C;AAWD;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,SAAS,eAAe,EAAE,GAAG,SAAS,aAAa,EAAE,CAK3F;AAED,wEAAwE;AACxE,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,OAAO,CAAC;AAgBjD;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,gBAAgB,GAAG,MAAM,CAU9E"}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { resolveFeatures } from './features.js';
|
|
2
|
+
/**
|
|
3
|
+
* The defaults.
|
|
4
|
+
*
|
|
5
|
+
* `Mod-1…6` rather than 1…9: levels 7–9 exist in the model because Word documents contain
|
|
6
|
+
* them, but no keyboard has a comfortable ninth digit and the ladder covers the rest.
|
|
7
|
+
*/
|
|
8
|
+
export const DEFAULT_SHORTCUTS = [
|
|
9
|
+
{ command: 'indent', key: 'Tab', group: 'structure', description: 'Indent block' },
|
|
10
|
+
{ command: 'outdent', key: 'Shift-Tab', group: 'structure', description: 'Outdent block' },
|
|
11
|
+
{ command: 'setLevel1', key: 'Mod-1', group: 'structure', description: 'Heading 1' },
|
|
12
|
+
{ command: 'setLevel2', key: 'Mod-2', group: 'structure', description: 'Heading 2' },
|
|
13
|
+
{ command: 'setLevel3', key: 'Mod-3', group: 'structure', description: 'Heading 3' },
|
|
14
|
+
{ command: 'setLevel4', key: 'Mod-4', group: 'structure', description: 'Heading 4' },
|
|
15
|
+
{ command: 'setLevel5', key: 'Mod-5', group: 'structure', description: 'Heading 5' },
|
|
16
|
+
{ command: 'setLevel6', key: 'Mod-6', group: 'structure', description: 'Heading 6' },
|
|
17
|
+
{ command: 'setBodyText', key: 'Mod-0', group: 'structure', description: 'Body text' },
|
|
18
|
+
{ command: 'moveUp', key: 'Alt-ArrowUp', group: 'structure', description: 'Move block up' },
|
|
19
|
+
{ command: 'moveDown', key: 'Alt-ArrowDown', group: 'structure', description: 'Move block down' },
|
|
20
|
+
{
|
|
21
|
+
command: 'toggleCollapse',
|
|
22
|
+
key: 'Mod-.',
|
|
23
|
+
group: 'collapse',
|
|
24
|
+
feature: 'collapse',
|
|
25
|
+
description: 'Collapse or expand this node',
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
command: 'collapseSiblings',
|
|
29
|
+
key: 'Mod-Shift-.',
|
|
30
|
+
group: 'collapse',
|
|
31
|
+
feature: 'collapse',
|
|
32
|
+
description: 'Collapse every sibling at this level',
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
command: 'bold',
|
|
36
|
+
key: 'Mod-b',
|
|
37
|
+
group: 'formatting',
|
|
38
|
+
feature: 'formatting',
|
|
39
|
+
description: 'Bold',
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
command: 'italic',
|
|
43
|
+
key: 'Mod-i',
|
|
44
|
+
group: 'formatting',
|
|
45
|
+
feature: 'formatting',
|
|
46
|
+
description: 'Italic',
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
command: 'underline',
|
|
50
|
+
key: 'Mod-u',
|
|
51
|
+
group: 'formatting',
|
|
52
|
+
feature: 'formatting',
|
|
53
|
+
description: 'Underline',
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
command: 'strike',
|
|
57
|
+
key: 'Mod-Shift-x',
|
|
58
|
+
group: 'formatting',
|
|
59
|
+
feature: 'formatting',
|
|
60
|
+
description: 'Strikethrough',
|
|
61
|
+
},
|
|
62
|
+
{ command: 'undo', key: 'Mod-z', group: 'editing', feature: 'history', description: 'Undo' },
|
|
63
|
+
{
|
|
64
|
+
command: 'redo',
|
|
65
|
+
key: 'Mod-Shift-z',
|
|
66
|
+
group: 'editing',
|
|
67
|
+
feature: 'history',
|
|
68
|
+
description: 'Redo',
|
|
69
|
+
},
|
|
70
|
+
/**
|
|
71
|
+
* نیمفاصله. Not a convenience: this is how Persian compound words are written at all —
|
|
72
|
+
* میشود, نمیتوان, دانشآموزان — and an editor without it cannot be used for real Persian.
|
|
73
|
+
*/
|
|
74
|
+
{
|
|
75
|
+
command: 'insertZwnj',
|
|
76
|
+
key: 'Shift-Space',
|
|
77
|
+
group: 'persian',
|
|
78
|
+
description: 'Half-space (ZWNJ)',
|
|
79
|
+
},
|
|
80
|
+
];
|
|
81
|
+
const COMMANDS = new Set(DEFAULT_SHORTCUTS.map((b) => b.command));
|
|
82
|
+
/**
|
|
83
|
+
* Apply a host's overrides and feature set to the default table.
|
|
84
|
+
*
|
|
85
|
+
* Collisions THROW. Letting a rebinding silently win means the losing command stops
|
|
86
|
+
* working with nothing logged, discoverable only by someone trying it and wondering what
|
|
87
|
+
* broke — and by then the override is somewhere in the host's configuration, far from the
|
|
88
|
+
* symptom.
|
|
89
|
+
*/
|
|
90
|
+
export function resolveShortcuts(options) {
|
|
91
|
+
if (options?.enabled === false)
|
|
92
|
+
return [];
|
|
93
|
+
const features = resolveFeatures(options?.features);
|
|
94
|
+
const overrides = options?.overrides ?? {};
|
|
95
|
+
for (const name of Object.keys(overrides)) {
|
|
96
|
+
if (!COMMANDS.has(name)) {
|
|
97
|
+
throw new Error(`Unknown shortcut command ${JSON.stringify(name)}. Known: ${[...COMMANDS].join(', ')}.`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
const resolved = [];
|
|
101
|
+
for (const binding of DEFAULT_SHORTCUTS) {
|
|
102
|
+
if (binding.feature !== undefined && !features[binding.feature])
|
|
103
|
+
continue;
|
|
104
|
+
const override = Object.hasOwn(overrides, binding.command)
|
|
105
|
+
? overrides[binding.command]
|
|
106
|
+
: undefined;
|
|
107
|
+
// An explicit null unbinds; `undefined` means the host said nothing about it.
|
|
108
|
+
if (override === null)
|
|
109
|
+
continue;
|
|
110
|
+
resolved.push(override === undefined ? binding : { ...binding, key: override });
|
|
111
|
+
}
|
|
112
|
+
/*
|
|
113
|
+
* Collisions are checked AFTER every override is applied, not while applying them, so
|
|
114
|
+
* that swapping two commands works in a single call. Checking as we go would reject
|
|
115
|
+
* `{ indent: null, toggleCollapse: 'Tab' }` depending on table order, which is a rule
|
|
116
|
+
* nobody could predict.
|
|
117
|
+
*/
|
|
118
|
+
const seen = new Map();
|
|
119
|
+
for (const binding of resolved) {
|
|
120
|
+
const previous = seen.get(binding.key);
|
|
121
|
+
if (previous !== undefined) {
|
|
122
|
+
throw new Error(`Shortcut collision on ${binding.key}: ${previous} and ${binding.command}. ` +
|
|
123
|
+
`Unbind one with { ${previous}: null }.`);
|
|
124
|
+
}
|
|
125
|
+
seen.set(binding.key, binding.command);
|
|
126
|
+
}
|
|
127
|
+
return resolved;
|
|
128
|
+
}
|
|
129
|
+
/** Stable group order for a help sheet — structure first, because it is the product. */
|
|
130
|
+
const GROUP_ORDER = [
|
|
131
|
+
'structure',
|
|
132
|
+
'collapse',
|
|
133
|
+
'formatting',
|
|
134
|
+
'editing',
|
|
135
|
+
'persian',
|
|
136
|
+
];
|
|
137
|
+
/**
|
|
138
|
+
* Group the live bindings for display.
|
|
139
|
+
*
|
|
140
|
+
* The order is fixed rather than derived from the data: a sheet that reshuffles between
|
|
141
|
+
* openings cannot be learned, and learning it is the only reason it exists.
|
|
142
|
+
*/
|
|
143
|
+
export function shortcutsFor(bindings) {
|
|
144
|
+
return GROUP_ORDER.map((group) => ({
|
|
145
|
+
group,
|
|
146
|
+
bindings: bindings.filter((binding) => binding.group === group),
|
|
147
|
+
})).filter((entry) => entry.bindings.length > 0);
|
|
148
|
+
}
|
|
149
|
+
const APPLE_GLYPHS = {
|
|
150
|
+
Mod: '⌘',
|
|
151
|
+
Shift: '⇧',
|
|
152
|
+
Alt: '⌥',
|
|
153
|
+
Ctrl: '⌃',
|
|
154
|
+
};
|
|
155
|
+
const ARROWS = {
|
|
156
|
+
ArrowUp: '↑',
|
|
157
|
+
ArrowDown: '↓',
|
|
158
|
+
ArrowLeft: '←',
|
|
159
|
+
ArrowRight: '→',
|
|
160
|
+
};
|
|
161
|
+
/**
|
|
162
|
+
* A binding as a person reads it.
|
|
163
|
+
*
|
|
164
|
+
* `Mod` is ProseMirror's platform-agnostic spelling and must never reach a user: nobody
|
|
165
|
+
* has a Mod key. Apple users read glyphs with no separator, everyone else reads words
|
|
166
|
+
* joined by `+`, and getting that backwards is one of the small things that makes software
|
|
167
|
+
* feel foreign.
|
|
168
|
+
*/
|
|
169
|
+
export function formatShortcut(key, platform) {
|
|
170
|
+
const parts = key.split('-');
|
|
171
|
+
const last = parts.pop() ?? '';
|
|
172
|
+
// A single letter is shown capitalised — `Mod-b` is written ⌘B on every key cap.
|
|
173
|
+
const final = ARROWS[last] ?? (last.length === 1 ? last.toUpperCase() : last);
|
|
174
|
+
if (platform === 'apple') {
|
|
175
|
+
return parts.map((part) => APPLE_GLYPHS[part] ?? part).join('') + final;
|
|
176
|
+
}
|
|
177
|
+
return [...parts.map((part) => (part === 'Mod' ? 'Ctrl' : part)), final].join('+');
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=shortcuts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shortcuts.js","sourceRoot":"","sources":["../src/shortcuts.ts"],"names":[],"mappings":"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"}
|