@charcuterie/ui 3.0.0 → 3.2.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 +10 -0
- package/dist/Badge/Badge.d.ts +33 -3
- package/dist/Badge/Badge.d.ts.map +1 -1
- package/dist/Badge/Badge.js +20 -2
- package/dist/Badge/Badge.js.map +1 -1
- package/dist/Board/Board.d.ts +119 -0
- package/dist/Board/Board.d.ts.map +1 -0
- package/dist/Board/Board.js +165 -0
- package/dist/Board/Board.js.map +1 -0
- package/dist/Board/BoardCard.d.ts +120 -0
- package/dist/Board/BoardCard.d.ts.map +1 -0
- package/dist/Board/BoardCard.js +77 -0
- package/dist/Board/BoardCard.js.map +1 -0
- package/dist/Board/BoardLaneList.d.ts +103 -0
- package/dist/Board/BoardLaneList.d.ts.map +1 -0
- package/dist/Board/BoardLaneList.js +69 -0
- package/dist/Board/BoardLaneList.js.map +1 -0
- package/dist/Board/boardMove.d.ts +116 -0
- package/dist/Board/boardMove.d.ts.map +1 -0
- package/dist/Board/boardMove.js +116 -0
- package/dist/Board/boardMove.js.map +1 -0
- package/dist/Board/useBoardDrag.d.ts +44 -0
- package/dist/Board/useBoardDrag.d.ts.map +1 -0
- package/dist/Board/useBoardDrag.js +237 -0
- package/dist/Board/useBoardDrag.js.map +1 -0
- package/dist/Checkbox/Checkbox.d.ts.map +1 -1
- package/dist/Checkbox/Checkbox.js +15 -4
- package/dist/Checkbox/Checkbox.js.map +1 -1
- package/dist/DataTable/DataTable.d.ts +159 -0
- package/dist/DataTable/DataTable.d.ts.map +1 -0
- package/dist/DataTable/DataTable.js +197 -0
- package/dist/DataTable/DataTable.js.map +1 -0
- package/dist/DatePicker/DateGrid.d.ts +79 -0
- package/dist/DatePicker/DateGrid.d.ts.map +1 -0
- package/dist/DatePicker/DateGrid.js +220 -0
- package/dist/DatePicker/DateGrid.js.map +1 -0
- package/dist/DatePicker/DatePicker.d.ts +138 -0
- package/dist/DatePicker/DatePicker.d.ts.map +1 -0
- package/dist/DatePicker/DatePicker.js +384 -0
- package/dist/DatePicker/DatePicker.js.map +1 -0
- package/dist/DatePicker/datePresets.d.ts +29 -0
- package/dist/DatePicker/datePresets.d.ts.map +1 -0
- package/dist/DatePicker/datePresets.js +28 -0
- package/dist/DatePicker/datePresets.js.map +1 -0
- package/dist/DatePicker/parseDateInput.d.ts +106 -0
- package/dist/DatePicker/parseDateInput.d.ts.map +1 -0
- package/dist/DatePicker/parseDateInput.js +419 -0
- package/dist/DatePicker/parseDateInput.js.map +1 -0
- package/dist/DatePicker/plainDate.d.ts +167 -0
- package/dist/DatePicker/plainDate.d.ts.map +1 -0
- package/dist/DatePicker/plainDate.js +272 -0
- package/dist/DatePicker/plainDate.js.map +1 -0
- package/dist/Dialog/Dialog.d.ts +12 -2
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +2 -2
- package/dist/Dialog/Dialog.js.map +1 -1
- package/dist/MarkdownEditor/MarkdownEditor.d.ts +147 -0
- package/dist/MarkdownEditor/MarkdownEditor.d.ts.map +1 -0
- package/dist/MarkdownEditor/MarkdownEditor.js +492 -0
- package/dist/MarkdownEditor/MarkdownEditor.js.map +1 -0
- package/dist/MarkdownEditor/markdownCommands.d.ts +202 -0
- package/dist/MarkdownEditor/markdownCommands.d.ts.map +1 -0
- package/dist/MarkdownEditor/markdownCommands.js +379 -0
- package/dist/MarkdownEditor/markdownCommands.js.map +1 -0
- package/dist/MarkdownEditor/markdownSpans.d.ts +92 -0
- package/dist/MarkdownEditor/markdownSpans.d.ts.map +1 -0
- package/dist/MarkdownEditor/markdownSpans.js +303 -0
- package/dist/MarkdownEditor/markdownSpans.js.map +1 -0
- package/dist/Modal/Modal.d.ts +6 -2
- package/dist/Modal/Modal.d.ts.map +1 -1
- package/dist/Modal/Modal.js +1 -1
- package/dist/Modal/Modal.js.map +1 -1
- package/dist/Overlay/OverlayPanel.d.ts +13 -2
- package/dist/Overlay/OverlayPanel.d.ts.map +1 -1
- package/dist/Overlay/OverlayPanel.js +5 -1
- package/dist/Overlay/OverlayPanel.js.map +1 -1
- package/dist/categoricalStyles.d.ts +53 -0
- package/dist/categoricalStyles.d.ts.map +1 -0
- package/dist/categoricalStyles.js +195 -0
- package/dist/categoricalStyles.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/Badge/Badge.mdx +46 -0
- package/src/Badge/Badge.stories.tsx +98 -4
- package/src/Badge/Badge.test.tsx +157 -2
- package/src/Badge/Badge.tsx +49 -3
- package/src/Board/Board.mdx +199 -0
- package/src/Board/Board.stories.tsx +707 -0
- package/src/Board/Board.test.tsx +310 -0
- package/src/Board/Board.tsx +333 -0
- package/src/Board/BoardCard.tsx +290 -0
- package/src/Board/BoardLaneList.tsx +275 -0
- package/src/Board/boardMove.test.ts +213 -0
- package/src/Board/boardMove.ts +225 -0
- package/src/Board/useBoardDrag.ts +413 -0
- package/src/Checkbox/Checkbox.tsx +34 -3
- package/src/DataTable/DataTable.mdx +123 -0
- package/src/DataTable/DataTable.stories.tsx +411 -0
- package/src/DataTable/DataTable.test.tsx +386 -0
- package/src/DataTable/DataTable.tsx +497 -0
- package/src/DatePicker/DateGrid.tsx +467 -0
- package/src/DatePicker/DatePicker.mdx +170 -0
- package/src/DatePicker/DatePicker.stories.tsx +268 -0
- package/src/DatePicker/DatePicker.test.tsx +455 -0
- package/src/DatePicker/DatePicker.tsx +852 -0
- package/src/DatePicker/datePresets.ts +34 -0
- package/src/DatePicker/parseDateInput.test.ts +187 -0
- package/src/DatePicker/parseDateInput.ts +629 -0
- package/src/DatePicker/plainDate.test.ts +375 -0
- package/src/DatePicker/plainDate.ts +465 -0
- package/src/Dialog/Dialog.stories.tsx +48 -0
- package/src/Dialog/Dialog.test.tsx +30 -0
- package/src/Dialog/Dialog.tsx +13 -1
- package/src/MarkdownEditor/MarkdownEditor.mdx +189 -0
- package/src/MarkdownEditor/MarkdownEditor.stories.tsx +267 -0
- package/src/MarkdownEditor/MarkdownEditor.test.tsx +627 -0
- package/src/MarkdownEditor/MarkdownEditor.tsx +862 -0
- package/src/MarkdownEditor/markdownCommands.test.ts +384 -0
- package/src/MarkdownEditor/markdownCommands.ts +566 -0
- package/src/MarkdownEditor/markdownSpans.test.ts +217 -0
- package/src/MarkdownEditor/markdownSpans.ts +458 -0
- package/src/Modal/Modal.tsx +7 -1
- package/src/Overlay/OverlayPanel.tsx +17 -1
- package/src/argTypes.storyHelpers.ts +39 -0
- package/src/categoricalStyles.ts +244 -0
- package/src/index.ts +89 -0
- package/src/sourceRules.test.ts +52 -1
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Every edit the editor can make, as pure text-in / text-out.
|
|
3
|
+
*
|
|
4
|
+
* Nothing here touches the DOM, so the whole formatting grammar —
|
|
5
|
+
* what Ctrl+B does to a selection that already has asterisks
|
|
6
|
+
* outside it, what Enter does at the end of an empty list item,
|
|
7
|
+
* how an ordered list renumbers when you promote three paragraphs
|
|
8
|
+
* — is a Node test rather than a browser one. That split is not
|
|
9
|
+
* tidiness: the browser suite is where the expensive tests live,
|
|
10
|
+
* and this is the half with all the edge cases.
|
|
11
|
+
*
|
|
12
|
+
* ### Everything is `{ selectionEnd, selectionStart, text }`
|
|
13
|
+
*
|
|
14
|
+
* The same three fields a `<textarea>` exposes, in and out. A
|
|
15
|
+
* command takes the state the control is in and returns the state
|
|
16
|
+
* it should be in, and the component's only job is to get from one
|
|
17
|
+
* to the other without breaking undo.
|
|
18
|
+
*
|
|
19
|
+
* ### And that is what `getMinimalEdit` is for
|
|
20
|
+
*
|
|
21
|
+
* Writing `textarea.value = next` — or handing a controlled React
|
|
22
|
+
* `value` a new string — **erases the browser's undo stack**. Ctrl+Z
|
|
23
|
+
* after a toolbar click then jumps past everything the user typed,
|
|
24
|
+
* or does nothing at all. The fix is to express the change as a
|
|
25
|
+
* *replacement of a range*, select that range, and let the browser
|
|
26
|
+
* apply it through its own editing pipeline
|
|
27
|
+
* (`document.execCommand("insertText", …)`, which is deprecated and
|
|
28
|
+
* is still the only API that appends to the native undo stack).
|
|
29
|
+
*
|
|
30
|
+
* So commands return whole strings, because that is the easy thing
|
|
31
|
+
* to reason about and to test, and `getMinimalEdit` turns the pair
|
|
32
|
+
* back into the range replacement the DOM wants. A bold toggle
|
|
33
|
+
* becomes one undo step covering four characters instead of a
|
|
34
|
+
* document-sized one.
|
|
35
|
+
*
|
|
36
|
+
* ### No HTML, anywhere
|
|
37
|
+
*
|
|
38
|
+
* Every function here returns markdown. There is no serialiser, no
|
|
39
|
+
* intermediate document model, and no HTML string — which is the
|
|
40
|
+
* mechanical reason `<b>` cannot reach the stored value: nothing in
|
|
41
|
+
* this file can produce one, and the surface these run against is a
|
|
42
|
+
* `<textarea>`, which takes `text/plain` off the clipboard and
|
|
43
|
+
* nothing else.
|
|
44
|
+
*/
|
|
45
|
+
export type MarkdownSelection = {
|
|
46
|
+
selectionEnd: number;
|
|
47
|
+
selectionStart: number;
|
|
48
|
+
text: string;
|
|
49
|
+
};
|
|
50
|
+
export type MarkdownLinePrefix = {
|
|
51
|
+
/**
|
|
52
|
+
* Matches a line that **already is** this kind, which is what
|
|
53
|
+
* decides whether the toggle adds or removes.
|
|
54
|
+
*/
|
|
55
|
+
pattern: RegExp;
|
|
56
|
+
/**
|
|
57
|
+
* What to take off before adding — wider than `pattern`, and the
|
|
58
|
+
* two genuinely differ. A task list *detects* `- [ ] `, because a
|
|
59
|
+
* plain bullet is not a task; but it *strips* the bare `- ` too,
|
|
60
|
+
* so toggling a task on an existing bullet replaces the marker
|
|
61
|
+
* instead of producing `- - [ ] `. Collapsing these into one
|
|
62
|
+
* regex is how that bug gets written.
|
|
63
|
+
*/
|
|
64
|
+
stripPattern: RegExp;
|
|
65
|
+
/**
|
|
66
|
+
* The prefix to add, given the line's zero-based position inside
|
|
67
|
+
* the selection. Ordered lists are the only kind that uses the
|
|
68
|
+
* argument, and it is why this is a function.
|
|
69
|
+
*/
|
|
70
|
+
toPrefix: (indexInSelection: number) => string;
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* The prefixes the toolbar and the shortcuts drive, written out
|
|
74
|
+
* rather than derived.
|
|
75
|
+
*
|
|
76
|
+
* `task` deliberately matches a plain bullet's prefix *plus* the
|
|
77
|
+
* checkbox, so toggling a task on an existing `- item` replaces the
|
|
78
|
+
* bullet rather than nesting one inside the other.
|
|
79
|
+
*/
|
|
80
|
+
export declare const MARKDOWN_LINE_PREFIXES: {
|
|
81
|
+
readonly blockquote: {
|
|
82
|
+
readonly pattern: RegExp;
|
|
83
|
+
readonly stripPattern: RegExp;
|
|
84
|
+
readonly toPrefix: () => string;
|
|
85
|
+
};
|
|
86
|
+
readonly bulletList: {
|
|
87
|
+
readonly pattern: RegExp;
|
|
88
|
+
readonly stripPattern: RegExp;
|
|
89
|
+
readonly toPrefix: () => string;
|
|
90
|
+
};
|
|
91
|
+
readonly orderedList: {
|
|
92
|
+
readonly pattern: RegExp;
|
|
93
|
+
readonly stripPattern: RegExp;
|
|
94
|
+
readonly toPrefix: (indexInSelection: number) => string;
|
|
95
|
+
};
|
|
96
|
+
readonly taskList: {
|
|
97
|
+
readonly pattern: RegExp;
|
|
98
|
+
readonly stripPattern: RegExp;
|
|
99
|
+
readonly toPrefix: () => string;
|
|
100
|
+
};
|
|
101
|
+
};
|
|
102
|
+
/** The character range of the whole lines a selection touches. */
|
|
103
|
+
export declare const getLineRange: ({ selectionEnd, selectionStart, text, }: MarkdownSelection) => {
|
|
104
|
+
end: number;
|
|
105
|
+
start: number;
|
|
106
|
+
};
|
|
107
|
+
/** Type text over the selection, as if it had been typed. */
|
|
108
|
+
export declare const insertText: ({ selectionEnd, selectionStart, text }: MarkdownSelection, insertion: string) => MarkdownSelection;
|
|
109
|
+
/**
|
|
110
|
+
* Wrap or unwrap a selection in `**`, `_`, `` ` `` or `~~`.
|
|
111
|
+
*
|
|
112
|
+
* Three cases, and the middle one is the one hand-rolled editors
|
|
113
|
+
* miss: the markers may be **outside** the selection. Double-click
|
|
114
|
+
* a word inside `**bold**` and the browser selects `bold`, not
|
|
115
|
+
* `**bold**`, so a naive implementation adds a second pair and
|
|
116
|
+
* produces `****bold****`. Looking just past both ends first is
|
|
117
|
+
* what makes Ctrl+B genuinely a toggle.
|
|
118
|
+
*/
|
|
119
|
+
export declare const toggleInlineMarker: ({ selectionEnd, selectionStart, text }: MarkdownSelection, marker: string) => MarkdownSelection;
|
|
120
|
+
/**
|
|
121
|
+
* Add or remove a line prefix across every line the selection
|
|
122
|
+
* touches.
|
|
123
|
+
*
|
|
124
|
+
* Removal wins when **every** line already has the prefix, which is
|
|
125
|
+
* the behaviour that makes the toolbar button a toggle rather than
|
|
126
|
+
* a one-way trip. A mixed block — two bullets and a paragraph —
|
|
127
|
+
* gets the prefix added to all three, because the alternative is a
|
|
128
|
+
* button whose effect depends on invisible state.
|
|
129
|
+
*/
|
|
130
|
+
export declare const toggleLinePrefix: (state: MarkdownSelection, { pattern, stripPattern, toPrefix }: MarkdownLinePrefix) => MarkdownSelection;
|
|
131
|
+
/**
|
|
132
|
+
* `#` … `######`, and pressing the same level twice removes it.
|
|
133
|
+
*
|
|
134
|
+
* A heading replaces any heading already on the line rather than
|
|
135
|
+
* stacking, so H2-then-H3 is H3 and not `## ### `.
|
|
136
|
+
*/
|
|
137
|
+
export declare const toggleHeading: (state: MarkdownSelection, level: number) => MarkdownSelection;
|
|
138
|
+
/**
|
|
139
|
+
* Markdown-safe ``.
|
|
140
|
+
*
|
|
141
|
+
* The alt text is escaped rather than stripped — a filename with a
|
|
142
|
+
* bracket in it is legal, and silently deleting characters out of
|
|
143
|
+
* somebody's caption is worse than the escape being visible. The
|
|
144
|
+
* destination goes inside angle brackets when it contains anything
|
|
145
|
+
* that would end the destination early, which is the CommonMark
|
|
146
|
+
* spelling for "this whole thing is the URL".
|
|
147
|
+
*/
|
|
148
|
+
export declare const toMarkdownImage: ({ alt, url, }: {
|
|
149
|
+
alt?: string;
|
|
150
|
+
url: string;
|
|
151
|
+
}) => string;
|
|
152
|
+
/** Insert an image at the caret, replacing any selection. */
|
|
153
|
+
export declare const insertImage: (state: MarkdownSelection, image: {
|
|
154
|
+
alt?: string;
|
|
155
|
+
url: string;
|
|
156
|
+
}) => MarkdownSelection;
|
|
157
|
+
/**
|
|
158
|
+
* `[selected](url)`, with the caret parked in the destination when
|
|
159
|
+
* there is nothing to put there yet — which is the only reason this
|
|
160
|
+
* is not `toggleInlineMarker` with a funny marker.
|
|
161
|
+
*/
|
|
162
|
+
export declare const insertLink: (state: MarkdownSelection, url?: string) => MarkdownSelection;
|
|
163
|
+
/**
|
|
164
|
+
* What Enter should do inside a list, a task list or a blockquote —
|
|
165
|
+
* or `null` when it should do the ordinary thing and the component
|
|
166
|
+
* must not call `preventDefault`.
|
|
167
|
+
*
|
|
168
|
+
* Two behaviours, and the second is the one people notice when it
|
|
169
|
+
* is missing: continuing the marker onto the next line, and
|
|
170
|
+
* **clearing** it when the item is empty. Without the second, an
|
|
171
|
+
* empty bullet is a trap — every Enter makes another empty bullet
|
|
172
|
+
* and the only way out is Backspace.
|
|
173
|
+
*
|
|
174
|
+
* Returning `null` rather than the unchanged state is deliberate.
|
|
175
|
+
* A plain Enter has to fall through to the browser so it lands on
|
|
176
|
+
* the native undo stack as a normal typing step.
|
|
177
|
+
*/
|
|
178
|
+
export declare const continueList: ({ selectionEnd, selectionStart, text, }: MarkdownSelection) => MarkdownSelection | null;
|
|
179
|
+
/** Two spaces onto every line the selection touches. */
|
|
180
|
+
export declare const indentLines: (state: MarkdownSelection) => MarkdownSelection;
|
|
181
|
+
/** Up to two spaces, or one tab, off every line. */
|
|
182
|
+
export declare const outdentLines: (state: MarkdownSelection) => MarkdownSelection;
|
|
183
|
+
/**
|
|
184
|
+
* The smallest range replacement that turns `before` into `after`.
|
|
185
|
+
*
|
|
186
|
+
* Whole-string commands are easy to write and easy to test; whole
|
|
187
|
+
* string *assignments* destroy undo. This closes the gap between
|
|
188
|
+
* the two by finding the common prefix and the common suffix and
|
|
189
|
+
* reporting only what is left, so a bold toggle on one word is one
|
|
190
|
+
* four-character edit and one undo step — not a document-sized one
|
|
191
|
+
* that swallows the paragraph the user typed before it.
|
|
192
|
+
*
|
|
193
|
+
* The prefix scan runs first and the suffix scan is bounded by what
|
|
194
|
+
* it left, so the two can never overlap on a repetitive string
|
|
195
|
+
* (`aaaa` → `aaaaa` reports an insert, not a negative range).
|
|
196
|
+
*/
|
|
197
|
+
export declare const getMinimalEdit: (before: string, after: string) => {
|
|
198
|
+
end: number;
|
|
199
|
+
start: number;
|
|
200
|
+
text: string;
|
|
201
|
+
};
|
|
202
|
+
//# sourceMappingURL=markdownCommands.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdownCommands.d.ts","sourceRoot":"","sources":["../../src/MarkdownEditor/markdownCommands.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAEH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,YAAY,EAAE,MAAM,CAAA;IACpB,cAAc,EAAE,MAAM,CAAA;IACtB,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED,MAAM,MAAM,kBAAkB,GAAG;IAC/B;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAA;IACf;;;;;;;OAOG;IACH,YAAY,EAAE,MAAM,CAAA;IACpB;;;;OAIG;IACH,QAAQ,EAAE,CAAC,gBAAgB,EAAE,MAAM,KAAK,MAAM,CAAA;CAC/C,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;8CAcF,MAAM;;;;;;;CAQgB,CAAA;AAevD,kEAAkE;AAClE,eAAO,MAAM,YAAY,GAAI,yCAI1B,iBAAiB,KAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAUlD,CAAA;AAsBD,6DAA6D;AAC7D,eAAO,MAAM,UAAU,GACrB,wCAAwC,iBAAiB,EACzD,WAAW,MAAM,KAChB,iBAQC,CAAA;AAEJ;;;;;;;;;GASG;AACH,eAAO,MAAM,kBAAkB,GAC7B,wCAAwC,iBAAiB,EACzD,QAAQ,MAAM,KACb,iBAyDF,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,gBAAgB,GAC3B,OAAO,iBAAiB,EACxB,qCAAqC,kBAAkB,KACtD,iBA+BF,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,aAAa,GACxB,OAAO,iBAAiB,EACxB,OAAO,MAAM,KACZ,iBA+BF,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe,GAAI,eAG7B;IACD,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,MAAM,CAAA;CACZ,KAAG,MAYH,CAAA;AAED,6DAA6D;AAC7D,eAAO,MAAM,WAAW,GACtB,OAAO,iBAAiB,EACxB,OAAO;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,KACnC,iBACwC,CAAA;AAE3C;;;;GAIG;AACH,eAAO,MAAM,UAAU,GACrB,OAAO,iBAAiB,EACxB,YAAQ,KACP,iBAmBF,CAAA;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,YAAY,GAAI,yCAI1B,iBAAiB,KAAG,iBAAiB,GAAG,IA0D1C,CAAA;AAID,wDAAwD;AACxD,eAAO,MAAM,WAAW,GACtB,OAAO,iBAAiB,KACvB,iBAiBF,CAAA;AAED,oDAAoD;AACpD,eAAO,MAAM,YAAY,GACvB,OAAO,iBAAiB,KACvB,iBAiBF,CAAA;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,cAAc,GACzB,QAAQ,MAAM,EACd,OAAO,MAAM,KACZ;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CA2B5C,CAAA"}
|
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Every edit the editor can make, as pure text-in / text-out.
|
|
3
|
+
*
|
|
4
|
+
* Nothing here touches the DOM, so the whole formatting grammar —
|
|
5
|
+
* what Ctrl+B does to a selection that already has asterisks
|
|
6
|
+
* outside it, what Enter does at the end of an empty list item,
|
|
7
|
+
* how an ordered list renumbers when you promote three paragraphs
|
|
8
|
+
* — is a Node test rather than a browser one. That split is not
|
|
9
|
+
* tidiness: the browser suite is where the expensive tests live,
|
|
10
|
+
* and this is the half with all the edge cases.
|
|
11
|
+
*
|
|
12
|
+
* ### Everything is `{ selectionEnd, selectionStart, text }`
|
|
13
|
+
*
|
|
14
|
+
* The same three fields a `<textarea>` exposes, in and out. A
|
|
15
|
+
* command takes the state the control is in and returns the state
|
|
16
|
+
* it should be in, and the component's only job is to get from one
|
|
17
|
+
* to the other without breaking undo.
|
|
18
|
+
*
|
|
19
|
+
* ### And that is what `getMinimalEdit` is for
|
|
20
|
+
*
|
|
21
|
+
* Writing `textarea.value = next` — or handing a controlled React
|
|
22
|
+
* `value` a new string — **erases the browser's undo stack**. Ctrl+Z
|
|
23
|
+
* after a toolbar click then jumps past everything the user typed,
|
|
24
|
+
* or does nothing at all. The fix is to express the change as a
|
|
25
|
+
* *replacement of a range*, select that range, and let the browser
|
|
26
|
+
* apply it through its own editing pipeline
|
|
27
|
+
* (`document.execCommand("insertText", …)`, which is deprecated and
|
|
28
|
+
* is still the only API that appends to the native undo stack).
|
|
29
|
+
*
|
|
30
|
+
* So commands return whole strings, because that is the easy thing
|
|
31
|
+
* to reason about and to test, and `getMinimalEdit` turns the pair
|
|
32
|
+
* back into the range replacement the DOM wants. A bold toggle
|
|
33
|
+
* becomes one undo step covering four characters instead of a
|
|
34
|
+
* document-sized one.
|
|
35
|
+
*
|
|
36
|
+
* ### No HTML, anywhere
|
|
37
|
+
*
|
|
38
|
+
* Every function here returns markdown. There is no serialiser, no
|
|
39
|
+
* intermediate document model, and no HTML string — which is the
|
|
40
|
+
* mechanical reason `<b>` cannot reach the stored value: nothing in
|
|
41
|
+
* this file can produce one, and the surface these run against is a
|
|
42
|
+
* `<textarea>`, which takes `text/plain` off the clipboard and
|
|
43
|
+
* nothing else.
|
|
44
|
+
*/
|
|
45
|
+
/**
|
|
46
|
+
* The prefixes the toolbar and the shortcuts drive, written out
|
|
47
|
+
* rather than derived.
|
|
48
|
+
*
|
|
49
|
+
* `task` deliberately matches a plain bullet's prefix *plus* the
|
|
50
|
+
* checkbox, so toggling a task on an existing `- item` replaces the
|
|
51
|
+
* bullet rather than nesting one inside the other.
|
|
52
|
+
*/
|
|
53
|
+
export const MARKDOWN_LINE_PREFIXES = {
|
|
54
|
+
blockquote: {
|
|
55
|
+
pattern: /^>[ \t]?/,
|
|
56
|
+
stripPattern: /^>[ \t]?/,
|
|
57
|
+
toPrefix: () => "> ",
|
|
58
|
+
},
|
|
59
|
+
bulletList: {
|
|
60
|
+
pattern: /^[-*+][ \t]+(?:\[[ xX]\][ \t]*)?/,
|
|
61
|
+
stripPattern: /^[-*+][ \t]+(?:\[[ xX]\][ \t]*)?/,
|
|
62
|
+
toPrefix: () => "- ",
|
|
63
|
+
},
|
|
64
|
+
orderedList: {
|
|
65
|
+
pattern: /^\d{1,9}[.)][ \t]+/,
|
|
66
|
+
stripPattern: /^\d{1,9}[.)][ \t]+/,
|
|
67
|
+
toPrefix: (indexInSelection) => `${indexInSelection + 1}. `,
|
|
68
|
+
},
|
|
69
|
+
taskList: {
|
|
70
|
+
pattern: /^[-*+][ \t]+\[[ xX]\][ \t]*/,
|
|
71
|
+
stripPattern: /^[-*+][ \t]+(?:\[[ xX]\][ \t]*)?/,
|
|
72
|
+
toPrefix: () => "- [ ] ",
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
const INDENT_PATTERN = /^[ \t]*/;
|
|
76
|
+
const HEADING_PATTERN = /^#{1,6}[ \t]+/;
|
|
77
|
+
/**
|
|
78
|
+
* A continuable line: an ordered item, a bullet, a task, or a
|
|
79
|
+
* blockquote — with its indent, its marker, its optional checkbox
|
|
80
|
+
* and whatever came after them, captured separately so Enter can
|
|
81
|
+
* rebuild the marker without the content.
|
|
82
|
+
*/
|
|
83
|
+
const CONTINUABLE_PATTERN = /^([ \t]*)(?:(\d{1,9})([.)])[ \t]+|([-*+])[ \t]+|(>[ \t]?))(\[[ xX]\][ \t]*)?(.*)$/;
|
|
84
|
+
/** The character range of the whole lines a selection touches. */
|
|
85
|
+
export const getLineRange = ({ selectionEnd, selectionStart, text, }) => {
|
|
86
|
+
const start = text.lastIndexOf("\n", selectionStart - 1) + 1;
|
|
87
|
+
const nextNewline = text.indexOf("\n", selectionEnd);
|
|
88
|
+
return {
|
|
89
|
+
end: nextNewline === -1 ? text.length : nextNewline,
|
|
90
|
+
start,
|
|
91
|
+
};
|
|
92
|
+
};
|
|
93
|
+
const replaceRange = ({ end, insertion, selectionEnd, selectionStart, start, text, }) => ({
|
|
94
|
+
selectionEnd,
|
|
95
|
+
selectionStart,
|
|
96
|
+
text: text.slice(0, start) + insertion + text.slice(end),
|
|
97
|
+
});
|
|
98
|
+
/** Type text over the selection, as if it had been typed. */
|
|
99
|
+
export const insertText = ({ selectionEnd, selectionStart, text }, insertion) => replaceRange({
|
|
100
|
+
end: selectionEnd,
|
|
101
|
+
insertion,
|
|
102
|
+
selectionEnd: selectionStart + insertion.length,
|
|
103
|
+
selectionStart: selectionStart + insertion.length,
|
|
104
|
+
start: selectionStart,
|
|
105
|
+
text,
|
|
106
|
+
});
|
|
107
|
+
/**
|
|
108
|
+
* Wrap or unwrap a selection in `**`, `_`, `` ` `` or `~~`.
|
|
109
|
+
*
|
|
110
|
+
* Three cases, and the middle one is the one hand-rolled editors
|
|
111
|
+
* miss: the markers may be **outside** the selection. Double-click
|
|
112
|
+
* a word inside `**bold**` and the browser selects `bold`, not
|
|
113
|
+
* `**bold**`, so a naive implementation adds a second pair and
|
|
114
|
+
* produces `****bold****`. Looking just past both ends first is
|
|
115
|
+
* what makes Ctrl+B genuinely a toggle.
|
|
116
|
+
*/
|
|
117
|
+
export const toggleInlineMarker = ({ selectionEnd, selectionStart, text }, marker) => {
|
|
118
|
+
const selected = text.slice(selectionStart, selectionEnd);
|
|
119
|
+
if (selected.length >= marker.length * 2 &&
|
|
120
|
+
selected.startsWith(marker) &&
|
|
121
|
+
selected.endsWith(marker)) {
|
|
122
|
+
const stripped = selected.slice(marker.length, selected.length - marker.length);
|
|
123
|
+
return replaceRange({
|
|
124
|
+
end: selectionEnd,
|
|
125
|
+
insertion: stripped,
|
|
126
|
+
selectionEnd: selectionStart + stripped.length,
|
|
127
|
+
selectionStart,
|
|
128
|
+
start: selectionStart,
|
|
129
|
+
text,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
const isWrappedOutside = text.slice(selectionStart - marker.length, selectionStart) === marker &&
|
|
133
|
+
text.slice(selectionEnd, selectionEnd + marker.length) === marker;
|
|
134
|
+
if (isWrappedOutside) {
|
|
135
|
+
return replaceRange({
|
|
136
|
+
end: selectionEnd + marker.length,
|
|
137
|
+
insertion: selected,
|
|
138
|
+
selectionEnd: selectionStart - marker.length + selected.length,
|
|
139
|
+
selectionStart: selectionStart - marker.length,
|
|
140
|
+
start: selectionStart - marker.length,
|
|
141
|
+
text,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
return replaceRange({
|
|
145
|
+
end: selectionEnd,
|
|
146
|
+
insertion: `${marker}${selected}${marker}`,
|
|
147
|
+
// The caret lands *inside* the new pair when nothing was
|
|
148
|
+
// selected, so Ctrl+B then typing works the way it does in
|
|
149
|
+
// every other editor.
|
|
150
|
+
selectionEnd: selectionStart + marker.length + selected.length,
|
|
151
|
+
selectionStart: selectionStart + marker.length,
|
|
152
|
+
start: selectionStart,
|
|
153
|
+
text,
|
|
154
|
+
});
|
|
155
|
+
};
|
|
156
|
+
/**
|
|
157
|
+
* Add or remove a line prefix across every line the selection
|
|
158
|
+
* touches.
|
|
159
|
+
*
|
|
160
|
+
* Removal wins when **every** line already has the prefix, which is
|
|
161
|
+
* the behaviour that makes the toolbar button a toggle rather than
|
|
162
|
+
* a one-way trip. A mixed block — two bullets and a paragraph —
|
|
163
|
+
* gets the prefix added to all three, because the alternative is a
|
|
164
|
+
* button whose effect depends on invisible state.
|
|
165
|
+
*/
|
|
166
|
+
export const toggleLinePrefix = (state, { pattern, stripPattern, toPrefix }) => {
|
|
167
|
+
const { end, start } = getLineRange(state);
|
|
168
|
+
const lines = state.text.slice(start, end).split("\n");
|
|
169
|
+
const hasPrefixEverywhere = lines.every((line) => pattern.test(line.replace(INDENT_PATTERN, "")));
|
|
170
|
+
const nextLines = lines.map((line, indexInSelection) => {
|
|
171
|
+
const indent = INDENT_PATTERN.exec(line)?.[0] ?? "";
|
|
172
|
+
const body = line.slice(indent.length);
|
|
173
|
+
const stripped = body.replace(stripPattern, "");
|
|
174
|
+
return hasPrefixEverywhere
|
|
175
|
+
? `${indent}${stripped}`
|
|
176
|
+
: `${indent}${toPrefix(indexInSelection)}${stripped}`;
|
|
177
|
+
});
|
|
178
|
+
const insertion = nextLines.join("\n");
|
|
179
|
+
return replaceRange({
|
|
180
|
+
end,
|
|
181
|
+
insertion,
|
|
182
|
+
selectionEnd: start + insertion.length,
|
|
183
|
+
selectionStart: start,
|
|
184
|
+
start,
|
|
185
|
+
text: state.text,
|
|
186
|
+
});
|
|
187
|
+
};
|
|
188
|
+
/**
|
|
189
|
+
* `#` … `######`, and pressing the same level twice removes it.
|
|
190
|
+
*
|
|
191
|
+
* A heading replaces any heading already on the line rather than
|
|
192
|
+
* stacking, so H2-then-H3 is H3 and not `## ### `.
|
|
193
|
+
*/
|
|
194
|
+
export const toggleHeading = (state, level) => {
|
|
195
|
+
const { end, start } = getLineRange(state);
|
|
196
|
+
const wanted = `${"#".repeat(level)} `;
|
|
197
|
+
const insertion = state.text
|
|
198
|
+
.slice(start, end)
|
|
199
|
+
.split("\n")
|
|
200
|
+
.map((line) => {
|
|
201
|
+
const indent = INDENT_PATTERN.exec(line)?.[0] ?? "";
|
|
202
|
+
const body = line.slice(indent.length);
|
|
203
|
+
const existing = HEADING_PATTERN.exec(body)?.[0];
|
|
204
|
+
const stripped = body.replace(HEADING_PATTERN, "");
|
|
205
|
+
return existing?.trimEnd() === wanted.trimEnd()
|
|
206
|
+
? `${indent}${stripped}`
|
|
207
|
+
: `${indent}${wanted}${stripped}`;
|
|
208
|
+
})
|
|
209
|
+
.join("\n");
|
|
210
|
+
return replaceRange({
|
|
211
|
+
end,
|
|
212
|
+
insertion,
|
|
213
|
+
selectionEnd: start + insertion.length,
|
|
214
|
+
selectionStart: start,
|
|
215
|
+
start,
|
|
216
|
+
text: state.text,
|
|
217
|
+
});
|
|
218
|
+
};
|
|
219
|
+
/**
|
|
220
|
+
* Markdown-safe ``.
|
|
221
|
+
*
|
|
222
|
+
* The alt text is escaped rather than stripped — a filename with a
|
|
223
|
+
* bracket in it is legal, and silently deleting characters out of
|
|
224
|
+
* somebody's caption is worse than the escape being visible. The
|
|
225
|
+
* destination goes inside angle brackets when it contains anything
|
|
226
|
+
* that would end the destination early, which is the CommonMark
|
|
227
|
+
* spelling for "this whole thing is the URL".
|
|
228
|
+
*/
|
|
229
|
+
export const toMarkdownImage = ({ alt = "", url, }) => {
|
|
230
|
+
const safeAlt = alt
|
|
231
|
+
.replace(/[\r\n]+/g, " ")
|
|
232
|
+
.replace(/([\\[\]])/g, "\\$1");
|
|
233
|
+
const flatUrl = url.replace(/[\r\n]+/g, "");
|
|
234
|
+
const safeUrl = /[\s()<>]/.test(flatUrl)
|
|
235
|
+
? `<${flatUrl.replace(/([<>])/g, "\\$1")}>`
|
|
236
|
+
: flatUrl;
|
|
237
|
+
return ``;
|
|
238
|
+
};
|
|
239
|
+
/** Insert an image at the caret, replacing any selection. */
|
|
240
|
+
export const insertImage = (state, image) => insertText(state, toMarkdownImage(image));
|
|
241
|
+
/**
|
|
242
|
+
* `[selected](url)`, with the caret parked in the destination when
|
|
243
|
+
* there is nothing to put there yet — which is the only reason this
|
|
244
|
+
* is not `toggleInlineMarker` with a funny marker.
|
|
245
|
+
*/
|
|
246
|
+
export const insertLink = (state, url = "") => {
|
|
247
|
+
const selected = state.text.slice(state.selectionStart, state.selectionEnd);
|
|
248
|
+
const insertion = `[${selected}](${url})`;
|
|
249
|
+
const destinationStart = state.selectionStart + selected.length + 3;
|
|
250
|
+
return replaceRange({
|
|
251
|
+
end: state.selectionEnd,
|
|
252
|
+
insertion,
|
|
253
|
+
selectionEnd: destinationStart + url.length,
|
|
254
|
+
selectionStart: destinationStart,
|
|
255
|
+
start: state.selectionStart,
|
|
256
|
+
text: state.text,
|
|
257
|
+
});
|
|
258
|
+
};
|
|
259
|
+
/**
|
|
260
|
+
* What Enter should do inside a list, a task list or a blockquote —
|
|
261
|
+
* or `null` when it should do the ordinary thing and the component
|
|
262
|
+
* must not call `preventDefault`.
|
|
263
|
+
*
|
|
264
|
+
* Two behaviours, and the second is the one people notice when it
|
|
265
|
+
* is missing: continuing the marker onto the next line, and
|
|
266
|
+
* **clearing** it when the item is empty. Without the second, an
|
|
267
|
+
* empty bullet is a trap — every Enter makes another empty bullet
|
|
268
|
+
* and the only way out is Backspace.
|
|
269
|
+
*
|
|
270
|
+
* Returning `null` rather than the unchanged state is deliberate.
|
|
271
|
+
* A plain Enter has to fall through to the browser so it lands on
|
|
272
|
+
* the native undo stack as a normal typing step.
|
|
273
|
+
*/
|
|
274
|
+
export const continueList = ({ selectionEnd, selectionStart, text, }) => {
|
|
275
|
+
if (selectionStart !== selectionEnd) {
|
|
276
|
+
return null;
|
|
277
|
+
}
|
|
278
|
+
const lineStart = text.lastIndexOf("\n", selectionStart - 1) + 1;
|
|
279
|
+
const line = text.slice(lineStart, selectionStart);
|
|
280
|
+
const match = CONTINUABLE_PATTERN.exec(line);
|
|
281
|
+
if (!match) {
|
|
282
|
+
return null;
|
|
283
|
+
}
|
|
284
|
+
const [, indent = "", orderedNumber, orderedDelimiter, bullet, quote, checkbox, content = "",] = match;
|
|
285
|
+
if (content === "") {
|
|
286
|
+
// An empty item: clear the marker instead of making another
|
|
287
|
+
// one. The line becomes its own indent, and the caret sits at
|
|
288
|
+
// the end of it.
|
|
289
|
+
return replaceRange({
|
|
290
|
+
end: selectionStart,
|
|
291
|
+
insertion: indent,
|
|
292
|
+
selectionEnd: lineStart + indent.length,
|
|
293
|
+
selectionStart: lineStart + indent.length,
|
|
294
|
+
start: lineStart,
|
|
295
|
+
text,
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
const nextMarker = orderedNumber === undefined
|
|
299
|
+
? `${bullet ?? quote ?? ""}${quote === undefined ? " " : ""}`
|
|
300
|
+
: `${Number(orderedNumber) + 1}${orderedDelimiter ?? "."} `;
|
|
301
|
+
const insertion = `\n${indent}${nextMarker}${checkbox === undefined ? "" : "[ ] "}`;
|
|
302
|
+
return replaceRange({
|
|
303
|
+
end: selectionEnd,
|
|
304
|
+
insertion,
|
|
305
|
+
selectionEnd: selectionStart + insertion.length,
|
|
306
|
+
selectionStart: selectionStart + insertion.length,
|
|
307
|
+
start: selectionStart,
|
|
308
|
+
text,
|
|
309
|
+
});
|
|
310
|
+
};
|
|
311
|
+
const INDENT_UNIT = " ";
|
|
312
|
+
/** Two spaces onto every line the selection touches. */
|
|
313
|
+
export const indentLines = (state) => {
|
|
314
|
+
const { end, start } = getLineRange(state);
|
|
315
|
+
const insertion = state.text
|
|
316
|
+
.slice(start, end)
|
|
317
|
+
.split("\n")
|
|
318
|
+
.map((line) => `${INDENT_UNIT}${line}`)
|
|
319
|
+
.join("\n");
|
|
320
|
+
return replaceRange({
|
|
321
|
+
end,
|
|
322
|
+
insertion,
|
|
323
|
+
selectionEnd: start + insertion.length,
|
|
324
|
+
selectionStart: start,
|
|
325
|
+
start,
|
|
326
|
+
text: state.text,
|
|
327
|
+
});
|
|
328
|
+
};
|
|
329
|
+
/** Up to two spaces, or one tab, off every line. */
|
|
330
|
+
export const outdentLines = (state) => {
|
|
331
|
+
const { end, start } = getLineRange(state);
|
|
332
|
+
const insertion = state.text
|
|
333
|
+
.slice(start, end)
|
|
334
|
+
.split("\n")
|
|
335
|
+
.map((line) => line.replace(/^(?: {1,2}|\t)/, ""))
|
|
336
|
+
.join("\n");
|
|
337
|
+
return replaceRange({
|
|
338
|
+
end,
|
|
339
|
+
insertion,
|
|
340
|
+
selectionEnd: start + insertion.length,
|
|
341
|
+
selectionStart: start,
|
|
342
|
+
start,
|
|
343
|
+
text: state.text,
|
|
344
|
+
});
|
|
345
|
+
};
|
|
346
|
+
/**
|
|
347
|
+
* The smallest range replacement that turns `before` into `after`.
|
|
348
|
+
*
|
|
349
|
+
* Whole-string commands are easy to write and easy to test; whole
|
|
350
|
+
* string *assignments* destroy undo. This closes the gap between
|
|
351
|
+
* the two by finding the common prefix and the common suffix and
|
|
352
|
+
* reporting only what is left, so a bold toggle on one word is one
|
|
353
|
+
* four-character edit and one undo step — not a document-sized one
|
|
354
|
+
* that swallows the paragraph the user typed before it.
|
|
355
|
+
*
|
|
356
|
+
* The prefix scan runs first and the suffix scan is bounded by what
|
|
357
|
+
* it left, so the two can never overlap on a repetitive string
|
|
358
|
+
* (`aaaa` → `aaaaa` reports an insert, not a negative range).
|
|
359
|
+
*/
|
|
360
|
+
export const getMinimalEdit = (before, after) => {
|
|
361
|
+
const shortest = Math.min(before.length, after.length);
|
|
362
|
+
let start = 0;
|
|
363
|
+
while (start < shortest &&
|
|
364
|
+
before[start] === after[start]) {
|
|
365
|
+
start += 1;
|
|
366
|
+
}
|
|
367
|
+
let suffix = 0;
|
|
368
|
+
while (suffix < shortest - start &&
|
|
369
|
+
before[before.length - 1 - suffix] ===
|
|
370
|
+
after[after.length - 1 - suffix]) {
|
|
371
|
+
suffix += 1;
|
|
372
|
+
}
|
|
373
|
+
return {
|
|
374
|
+
end: before.length - suffix,
|
|
375
|
+
start,
|
|
376
|
+
text: after.slice(start, after.length - suffix),
|
|
377
|
+
};
|
|
378
|
+
};
|
|
379
|
+
//# sourceMappingURL=markdownCommands.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdownCommands.js","sourceRoot":"","sources":["../../src/MarkdownEditor/markdownCommands.ts"],"names":[],"mappings":"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"}
|