@crewlethq/ui 0.29.0 → 0.31.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.
Files changed (51) hide show
  1. package/README.md +28 -3
  2. package/dist/ArtifactBar/ArtifactBar.d.ts +13 -1
  3. package/dist/ArtifactBar/index.js +1 -1
  4. package/dist/{ArtifactBar-IBWB5POL.css → ArtifactBar-MLMJHWY6.css} +7 -0
  5. package/dist/ArtifactCover/index.js +2 -2
  6. package/dist/CommentThread/index.js +2 -2
  7. package/dist/DataView/index.js +2 -2
  8. package/dist/Document/Document.d.ts +8 -1
  9. package/dist/Document/index.js +1 -1
  10. package/dist/{Document-PQGXJHB7.css → Document-G3YTZIUL.css} +71 -0
  11. package/dist/EditingStatus/EditingStatus.d.ts +25 -0
  12. package/dist/EditingStatus/index.d.ts +3 -0
  13. package/dist/EditingStatus/index.js +2 -0
  14. package/dist/EditingStatus-NFADEPSX.css +53 -0
  15. package/dist/Editor-YZ7KG2RD.js +2099 -0
  16. package/dist/Markdown/grammar.d.ts +170 -0
  17. package/dist/Markdown/index.d.ts +2 -0
  18. package/dist/Markdown/index.js +1 -0
  19. package/dist/RichEditor/Editor.d.ts +17 -0
  20. package/dist/RichEditor/RichEditor.d.ts +26 -0
  21. package/dist/RichEditor/codec.d.ts +78 -0
  22. package/dist/RichEditor/commands.d.ts +89 -0
  23. package/dist/RichEditor/index.d.ts +4 -0
  24. package/dist/RichEditor/index.js +8 -0
  25. package/dist/RichEditor/keys.d.ts +16 -0
  26. package/dist/RichEditor/nodeviews.d.ts +60 -0
  27. package/dist/RichEditor/paste.d.ts +47 -0
  28. package/dist/RichEditor/plugins.d.ts +49 -0
  29. package/dist/RichEditor/roundtrip.d.ts +14 -0
  30. package/dist/RichEditor/schema.d.ts +23 -0
  31. package/dist/RichEditor/types.d.ts +140 -0
  32. package/dist/RichEditor-NPD2KAPS.css +419 -0
  33. package/dist/RichEditorMarkdown/index.d.ts +1 -0
  34. package/dist/RichEditorMarkdown/index.js +3 -0
  35. package/dist/chunk-3DPIU2Q7.js +28 -0
  36. package/dist/{chunk-XALUCIG5.js → chunk-6AH2XJ3Q.js} +1 -1
  37. package/dist/chunk-A4E5YLXO.js +85 -0
  38. package/dist/{chunk-FKULOLKG.js → chunk-GR55WT4R.js} +1 -1
  39. package/dist/chunk-IDBHX5SR.js +12 -0
  40. package/dist/{chunk-WI6K5M5X.js → chunk-M3LUNN7F.js} +1 -1
  41. package/dist/{chunk-QMBP23BL.js → chunk-P4BOXB6E.js} +17 -1
  42. package/dist/chunk-SKOYC2CF.js +288 -0
  43. package/dist/chunk-VOX3YRFO.js +76 -0
  44. package/dist/chunk-YFW4MTK4.js +749 -0
  45. package/dist/generated/index.d.ts +4 -0
  46. package/dist/generated/index.js +50 -44
  47. package/dist/index.js +50 -44
  48. package/dist/styles.css +558 -2
  49. package/package.json +13 -3
  50. package/dist/{chunk-IFNQKWUO.js → chunk-OC46246T.js} +0 -0
  51. package/dist/{chunk-RODMM35O.js → chunk-UVJ5FF5V.js} +1 -1
@@ -0,0 +1,170 @@
1
+ /**
2
+ * The Markdown grammar every Crewlet surface reads and writes: a CommonMark
3
+ * subset, parsed into blocks and inline matches and never into markup.
4
+ *
5
+ * ONE GRAMMAR FOR READING AND EDITING. An application renders these blocks
6
+ * with its own renderer (which elements, which link schemes, where a picture
7
+ * is fetched from are decisions about its own content), and `RichEditor`
8
+ * builds its document from the same blocks. A page that reads one way and
9
+ * edits another is a page whose author cannot trust what they see, and two
10
+ * copies of a grammar drift the first time somebody fixes one of them.
11
+ *
12
+ * NOTHING HERE PRODUCES MARKUP. The parser answers plain objects and strings,
13
+ * so a renderer that builds elements from them never parses HTML, which is
14
+ * what lets a consumer enforce Trusted Types with no policy at all.
15
+ *
16
+ * WHAT IT READS: ATX headings, paragraphs, emphasis and strong, strikethrough,
17
+ * inline code, fenced code, links, images, autolinks, backslash escapes,
18
+ * bullet and ordered lists (nested), task list items, block quotes, callouts
19
+ * (`> [!NOTE]`, GitHub's alert syntax), tables, thematic breaks and hard line
20
+ * breaks.
21
+ *
22
+ * WHAT IT DELIBERATELY DOES NOT: raw HTML (read as its own text, never
23
+ * parsed), reference links, footnotes, bare autolink literals, setext
24
+ * headings and indented code. Each is a shape these documents do not use, and
25
+ * every one of them is a place a parser grows a branch nobody exercises.
26
+ */
27
+ export type MarkdownAlign = 'left' | 'center' | 'right';
28
+ /**
29
+ * A callout's tone, by GitHub's alert names: `> [!NOTE]`, `> [!TIP]`,
30
+ * `> [!IMPORTANT]`, `> [!WARNING]` and `> [!CAUTION]`. The syntax is
31
+ * GitHub's so a page reads as a callout on GitHub too, and anywhere else it
32
+ * degrades to a quote whose first line names its tone.
33
+ */
34
+ export type MarkdownCalloutTone = 'note' | 'tip' | 'important' | 'warning' | 'caution';
35
+ export declare const MARKDOWN_CALLOUT_TONES: readonly MarkdownCalloutTone[];
36
+ /**
37
+ * Each tone's name as a reader sees it, on the callout's own label line: the
38
+ * one set of words a renderer and the editor both draw.
39
+ */
40
+ export declare const MARKDOWN_CALLOUT_NAMES: Readonly<Record<MarkdownCalloutTone, string>>;
41
+ /** One parsed block. */
42
+ export type MarkdownBlock = {
43
+ kind: 'heading';
44
+ level: number;
45
+ text: string;
46
+ } | {
47
+ kind: 'paragraph';
48
+ text: string;
49
+ } | {
50
+ kind: 'code';
51
+ lang: string;
52
+ text: string;
53
+ fence: MarkdownFence;
54
+ } | {
55
+ kind: 'quote';
56
+ blocks: MarkdownBlock[];
57
+ } | {
58
+ kind: 'callout';
59
+ tone: MarkdownCalloutTone;
60
+ blocks: MarkdownBlock[];
61
+ } | {
62
+ kind: 'list';
63
+ ordered: boolean;
64
+ start: number;
65
+ /** The bullet character (`-`, `*`, `+`) or the ordered delimiter (`.`, `)`). */
66
+ marker: string;
67
+ /** Whether a blank line separates any two of its items. */
68
+ loose: boolean;
69
+ items: MarkdownListItem[];
70
+ } | {
71
+ kind: 'table';
72
+ head: string[];
73
+ align: MarkdownAlign[];
74
+ rows: string[][];
75
+ } | {
76
+ kind: 'rule';
77
+ };
78
+ export type MarkdownFence = '```' | '~~~';
79
+ export interface MarkdownListItem {
80
+ /** null when the item is not a task item, which is not "unticked". */
81
+ checked: boolean | null;
82
+ blocks: MarkdownBlock[];
83
+ }
84
+ /** A top-level block and the source lines it was read from, `[start, end)`. */
85
+ export interface MarkdownSpan {
86
+ block: MarkdownBlock;
87
+ start: number;
88
+ end: number;
89
+ }
90
+ /**
91
+ * Whether a href may be followed at all, and in what form: `http:`, `https:`,
92
+ * `mailto:` and an application's own `#/` routes. Anything else is null.
93
+ *
94
+ * In-app routes (`#/work/ENG-1`) are allowed because they are how a page
95
+ * points at the company's own objects and they cannot leave the application.
96
+ * Everything else must carry an allowed scheme, including, deliberately, a
97
+ * bare `/path` or `guide.html`, which would resolve against whatever origin
98
+ * serves the page and mean nothing to a reader.
99
+ */
100
+ export declare function safeHref(raw: string): string | null;
101
+ /** Whether `line` closes a fence opened with `marker`. */
102
+ export declare function markdownClosesFence(line: string, marker: MarkdownFence): boolean;
103
+ /** The fence `line` opens, with its info string, or null when it opens none. */
104
+ export declare function markdownFenceOf(line: string): {
105
+ marker: MarkdownFence;
106
+ lang: string;
107
+ } | null;
108
+ /** The ATX heading `line` is, or null. Closing hashes are decoration, not content. */
109
+ export declare function markdownHeadingOf(line: string): {
110
+ level: number;
111
+ title: string;
112
+ } | null;
113
+ /** A document's lines, every line ending normalised to `\n`. */
114
+ export declare function markdownLines(source: string): string[];
115
+ /** Split a document into blocks. Pure, and the only thing that reads lines. */
116
+ export declare function parseMarkdown(source: string): MarkdownBlock[];
117
+ /**
118
+ * Split a document into its top-level blocks AND the lines each was read
119
+ * from, for an editor that keeps the source of every block it did not change.
120
+ */
121
+ export declare function parseMarkdownSpans(source: string): {
122
+ lines: string[];
123
+ spans: MarkdownSpan[];
124
+ };
125
+ /** What one inline construct captured, by name. */
126
+ export interface MarkdownInlineGroups {
127
+ /** An escaped ASCII punctuation character, without its backslash. */
128
+ esc?: string;
129
+ tick?: string;
130
+ code?: string;
131
+ alt?: string;
132
+ src?: string;
133
+ srcTitle?: string;
134
+ label?: string;
135
+ href?: string;
136
+ hrefTitle?: string;
137
+ auto?: string;
138
+ strong?: string;
139
+ strongUnder?: string;
140
+ em?: string;
141
+ emUnder?: string;
142
+ del?: string;
143
+ }
144
+ /** One inline construct: where it starts and ends in the text, and what it captured. */
145
+ export interface MarkdownInlineMatch {
146
+ index: number;
147
+ end: number;
148
+ groups: MarkdownInlineGroups;
149
+ }
150
+ /**
151
+ * Every inline construct of `text`, in order: THE ONE WALK every reader of
152
+ * inline Markdown takes, so a renderer, a text flattener and an editor can
153
+ * never disagree about where a construct begins.
154
+ *
155
+ * A fresh pattern per walk: the walk is re-entered for a construct's own
156
+ * content before the outer one has finished, and a shared `g` pattern carries
157
+ * its position in `lastIndex`.
158
+ */
159
+ export declare function markdownInline(text: string): Generator<MarkdownInlineMatch>;
160
+ /**
161
+ * A code span's content as it reads: ONE leading and one trailing space go,
162
+ * which is how CommonMark lets a span start with a backtick of its own.
163
+ */
164
+ export declare function markdownCodeText(code: string): string;
165
+ /**
166
+ * The splits a run of text breaks at: two trailing spaces or a backslash
167
+ * before a newline is a HARD break; every other newline is soft. With
168
+ * `hard`, every newline is a break and the two markers are consumed with it.
169
+ */
170
+ export declare function markdownBreaks(text: string, hard?: boolean): string[];
@@ -0,0 +1,2 @@
1
+ export { MARKDOWN_CALLOUT_NAMES, MARKDOWN_CALLOUT_TONES, markdownBreaks, markdownClosesFence, markdownCodeText, markdownFenceOf, markdownHeadingOf, markdownInline, markdownLines, parseMarkdown, parseMarkdownSpans, safeHref, } from './grammar.js';
2
+ export type { MarkdownAlign, MarkdownBlock, MarkdownCalloutTone, MarkdownFence, MarkdownInlineGroups, MarkdownInlineMatch, MarkdownListItem, MarkdownSpan, } from './grammar.js';
@@ -0,0 +1 @@
1
+ export { MARKDOWN_CALLOUT_NAMES, MARKDOWN_CALLOUT_TONES, markdownBreaks, markdownClosesFence, markdownCodeText, markdownFenceOf, markdownHeadingOf, markdownInline, markdownLines, parseMarkdown, parseMarkdownSpans, safeHref } from '../chunk-SKOYC2CF.js';
@@ -0,0 +1,17 @@
1
+ /**
2
+ * The editor itself: ProseMirror, drawn as the document it edits, with the
3
+ * slash menu, the selection toolbar, the link and picture panels and the
4
+ * table bar around it. Loaded lazily by `RichEditor`, so nothing here is
5
+ * fetched until somebody edits.
6
+ */
7
+ import { EditorView } from 'prosemirror-view';
8
+ import { type RichEditorHandle, type RichEditorProps } from './types.js';
9
+ /**
10
+ * The engine's handle: the public one, and the view itself for this
11
+ * package's own suites, which drive ProseMirror where jsdom has no layout to
12
+ * drive a browser's input through.
13
+ */
14
+ export interface EditorHandle extends RichEditorHandle {
15
+ view(): EditorView | null;
16
+ }
17
+ export declare const Editor: import("react").ForwardRefExoticComponent<RichEditorProps & import("react").RefAttributes<EditorHandle>>;
@@ -0,0 +1,26 @@
1
+ /**
2
+ * `RichEditor`: Markdown edited in place, as the document it reads as.
3
+ *
4
+ * # Loaded when somebody edits
5
+ *
6
+ * The editor is ProseMirror and everything around it, which is more than a
7
+ * reader of a page needs, so this component is a SHELL: it fetches the engine
8
+ * (`Editor.tsx`) with `import()` the first time one is drawn, and a bundler
9
+ * splits that into a chunk of its own. While the chunk loads the shell draws
10
+ * the caller's `fallback` (the body as it reads, so nothing moves) or a
11
+ * skeleton.
12
+ *
13
+ * A LOAD THAT FAILED IS FORGOTTEN, so the next attempt asks the server again
14
+ * rather than replaying the failure for the life of the page: the usual
15
+ * cause is a deploy that renamed the chunk while the page was open, and the
16
+ * other is one dropped request, which a retry fixes.
17
+ */
18
+ import { type RefAttributes } from 'react';
19
+ import { type RichEditorHandle, type RichEditorProps } from './types.js';
20
+ /**
21
+ * Fetch the editor's code ahead of the first edit, on a press that is about
22
+ * to open one. It settles once the code is there, or once fetching it has
23
+ * failed, which the editor itself then says where it is drawn.
24
+ */
25
+ export declare function preloadRichEditor(): Promise<void>;
26
+ export declare const RichEditor: import("react").ForwardRefExoticComponent<RichEditorProps & RefAttributes<RichEditorHandle>>;
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Markdown in, Markdown out: the editor's document read from a body, and the
3
+ * body written back from the document.
4
+ *
5
+ * # A save with no edit changes nothing, by construction
6
+ *
7
+ * Storage is Markdown, and the bytes are the record: a Knowledge page is
8
+ * merged line by line against somebody else's save, and a doc's version is a
9
+ * patch of the lines that moved. An editor that wrote every body back in its
10
+ * own canonical spelling would turn opening a page and pressing Save into a
11
+ * rewrite of every line, and every concurrent save into a conflict.
12
+ *
13
+ * So the document REMEMBERS THE SOURCE OF EVERY TOP-LEVEL BLOCK it read
14
+ * ([LoadedMarkdown]). ProseMirror shares every node a transaction did not
15
+ * touch, so a block nobody edited is the very node that was read, and it is
16
+ * written back as the lines it came from, with the blank lines that stood
17
+ * between it and its neighbour. A block an edit replaced is looked up by
18
+ * value too, so a change that was undone writes back its original lines.
19
+ * Only a block that really changed is written in the canonical spelling
20
+ * below, and it keeps the markers it was read with.
21
+ *
22
+ * # A changed block is checked before it is written
23
+ *
24
+ * The canonical spelling is read back through the same grammar and compared
25
+ * with what the writer sees ([signature]); a spelling that would read
26
+ * differently (an asterisk that would open emphasis, a `_` inside a word that
27
+ * cannot close one) is written again with plainer markers and then with every
28
+ * punctuation character escaped. What the editor shows is what the next
29
+ * reader sees.
30
+ */
31
+ import { type Node as PMNode } from 'prosemirror-model';
32
+ /** One top-level block as it was read: its lines, and what stood before it. */
33
+ interface SourceBlock {
34
+ index: number;
35
+ node: PMNode;
36
+ text: string;
37
+ /** The text between the previous block's last line and this block's first. */
38
+ sep: string;
39
+ }
40
+ /** A document and the source it was read from. */
41
+ export interface LoadedMarkdown {
42
+ doc: PMNode;
43
+ source: MarkdownSource;
44
+ }
45
+ /** What a document remembers of the body it was read from. */
46
+ export interface MarkdownSource {
47
+ original: string;
48
+ doc: PMNode;
49
+ lead: string;
50
+ trail: string;
51
+ blocks: SourceBlock[];
52
+ byNode: WeakMap<PMNode, SourceBlock>;
53
+ /** Whether every line of the original ends in CRLF, which a changed body keeps. */
54
+ crlf: boolean;
55
+ }
56
+ /** Read a Markdown body into the editor's document. */
57
+ export declare function readMarkdown(markdown: string): LoadedMarkdown;
58
+ /**
59
+ * The body a document is saved as.
60
+ *
61
+ * With the source it was read from, every block nobody changed is written as
62
+ * the lines it was read from; a document nobody changed at all is the source,
63
+ * byte for byte, line endings included.
64
+ */
65
+ export declare function writeMarkdown(doc: PMNode, source?: MarkdownSource): string;
66
+ /**
67
+ * One block in the canonical spelling, checked: the first spelling that reads
68
+ * back as what the writer sees, or the plainest when none does.
69
+ */
70
+ export declare function writeBlock(node: PMNode): string;
71
+ /**
72
+ * What a block SAYS: its structure and the attributes a reader sees, and its
73
+ * text character by character with the marks each carries. The spelling (a
74
+ * `*` or a `_`, a fence's marker, whether a space sat inside the strong or
75
+ * after it) is not part of it, because the reader cannot see it either.
76
+ */
77
+ export declare function signature(node: PMNode): string;
78
+ export {};
@@ -0,0 +1,89 @@
1
+ /**
2
+ * What the editor can do to a document, as ProseMirror commands: each takes a
3
+ * state and, given a dispatch, applies itself, and without one answers
4
+ * whether it could. The slash menu, the selection toolbar, the shortcuts and
5
+ * the table bar all call these, so a block is made one way whichever of them
6
+ * made it.
7
+ */
8
+ import { type Mark, type MarkType, type Node as PMNode } from 'prosemirror-model';
9
+ import { type Command, type EditorState } from 'prosemirror-state';
10
+ import type { MarkdownAlign, MarkdownCalloutTone } from '../Markdown/index.js';
11
+ /** Whether a mark is on across the selection, or stored for the next keystroke. */
12
+ export declare function markActive(state: EditorState, type: MarkType): boolean;
13
+ /** The heading level the selection sits in, or 0 for any other block. */
14
+ export declare function headingLevel(state: EditorState): number;
15
+ /** Whether the selection is inside a code block, where no formatting applies. */
16
+ export declare function inCode(state: EditorState): boolean;
17
+ export declare const toggleStrong: Command;
18
+ export declare const toggleEm: Command;
19
+ export declare const toggleStrike: Command;
20
+ export declare const toggleCode: Command;
21
+ /** The link the selection is on: its whole range, and the mark. */
22
+ export declare function linkAt(state: EditorState): {
23
+ from: number;
24
+ to: number;
25
+ mark: Mark;
26
+ } | null;
27
+ /**
28
+ * Link the selection to `href`, or the link the caret is on; with nothing
29
+ * selected and no link under the caret, insert `text` linked.
30
+ */
31
+ export declare function setLink(href: string, text?: string): Command;
32
+ /** Remove the link under the caret or across the selection. */
33
+ export declare const removeLink: Command;
34
+ /** A heading of `level`, or back to a paragraph when the block already is one. */
35
+ export declare function toggleHeading(level: number): Command;
36
+ export declare const setParagraph: Command;
37
+ export declare function setCodeBlock(lang?: string): Command;
38
+ export declare const wrapQuote: Command;
39
+ export declare function wrapCallout(tone?: MarkdownCalloutTone): Command;
40
+ export type ListKind = 'bullet' | 'ordered' | 'task';
41
+ /**
42
+ * Make the selection a list of `kind`. In a list of that kind already, the
43
+ * items come out of it; in a list of another kind, the list changes kind.
44
+ */
45
+ export declare function setList(kind: ListKind): Command;
46
+ /** Enter in a list item: a new item, a task when this one is a task. */
47
+ export declare const splitItem: Command;
48
+ /** Tick or untick the task item at `pos`. */
49
+ export declare function toggleTask(pos: number): Command;
50
+ export declare const insertRule: Command;
51
+ export declare function insertImage(src: string, alt: string): Command;
52
+ /** The table the caret is in, and the cell. */
53
+ export interface TableAt {
54
+ table: PMNode;
55
+ pos: number;
56
+ row: number;
57
+ col: number;
58
+ }
59
+ export declare function tableAt(state: EditorState): TableAt | null;
60
+ /** A table of `rows` by `cols`, header included, with the caret in its first cell. */
61
+ export declare function insertTable(rows?: number, cols?: number): Command;
62
+ export declare const addRowBefore: Command;
63
+ export declare const addRowAfter: Command;
64
+ export declare const addColumnBefore: Command;
65
+ export declare const addColumnAfter: Command;
66
+ export declare const deleteRow: Command;
67
+ export declare const deleteColumn: Command;
68
+ export declare const deleteTable: Command;
69
+ export declare function alignColumn(align: MarkdownAlign): Command;
70
+ /** The alignment of the column the caret is in. */
71
+ export declare function columnAlign(state: EditorState): MarkdownAlign | null;
72
+ /**
73
+ * Tab and Shift-Tab between cells, and Enter to the cell below: past the last
74
+ * cell (or the last row, for Enter) a row is added, as a spreadsheet does.
75
+ */
76
+ export declare function moveCell(direction: 'next' | 'previous' | 'down'): Command;
77
+ /**
78
+ * Enter on the third blank line at the end of a code block leaves it: the
79
+ * two blank lines go, and a paragraph opens after the block.
80
+ */
81
+ export declare const exitCodeOnBlankLines: Command;
82
+ /** Enter after ```` ```lang ```` in a paragraph opens a code block in that language. */
83
+ export declare const fenceToCode: Command;
84
+ /** Select a whole node: an image the writer clicked, a rule. */
85
+ export declare function selectNode(pos: number): Command;
86
+ export declare function setCalloutTone(pos: number, tone: MarkdownCalloutTone): Command;
87
+ export declare function setCodeLanguage(pos: number, lang: string): Command;
88
+ /** Take the callout or quote at `pos` away, keeping what it holds. */
89
+ export declare function unwrapAt(pos: number): Command;
@@ -0,0 +1,4 @@
1
+ import './RichEditor.css';
2
+ export { RichEditor, preloadRichEditor } from './RichEditor.js';
3
+ export { RICH_EDITOR_LABELS, richEditorLabels } from './types.js';
4
+ export type { RichEditorBlock, RichEditorCommand, RichEditorHandle, RichEditorLabelOverrides, RichEditorLabels, RichEditorPanelApi, RichEditorProps, } from './types.js';
@@ -0,0 +1,8 @@
1
+ export { RichEditor, preloadRichEditor } from '../chunk-VOX3YRFO.js';
2
+ export { RICH_EDITOR_LABELS, richEditorLabels } from '../chunk-A4E5YLXO.js';
3
+ import '../chunk-W5J7R5EB.js';
4
+ import '../chunk-SKOYC2CF.js';
5
+ import '../chunk-SVSCLHHI.js';
6
+ import '../chunk-OG6CL3EB.js';
7
+ import '../chunk-BZFWDIV6.js';
8
+ import '../chunk-ODEQTPFM.js';
@@ -0,0 +1,16 @@
1
+ /**
2
+ * The keyboard: Markdown typed as Markdown becomes the block or the format it
3
+ * spells (`# `, `- `, `1. `, `[ ] `, `> `, ```` ``` ````, `---`, `**bold**`),
4
+ * and the shortcuts every editor shares.
5
+ *
6
+ * AN INPUT RULE IS UNDONE BY BACKSPACE: a writer who meant a literal `# ` or
7
+ * `**` presses it once right after, and has the characters they typed.
8
+ */
9
+ import { type Plugin } from 'prosemirror-state';
10
+ export declare function buildInputRules(): Plugin;
11
+ export interface KeyHooks {
12
+ submit: () => boolean;
13
+ link: () => boolean;
14
+ toolbar: () => boolean;
15
+ }
16
+ export declare function buildKeymap(hooks: KeyHooks): Plugin[];
@@ -0,0 +1,60 @@
1
+ /**
2
+ * The blocks that draw more than their element while they are edited: a code
3
+ * block's language, a callout's tone, a task's box, a picture's file, a
4
+ * table's scroller.
5
+ *
6
+ * Each is the element shape the reader's renderer emits, so `Document` sets it
7
+ * the same way, plus a CONTROL SLOT that is not part of the content
8
+ * (`contenteditable="false"`). The editor draws its React controls into those
9
+ * slots through portals ([SlotStore]), so a code block's language field is a
10
+ * design system field rather than markup built here.
11
+ */
12
+ import type { Node as PMNode } from 'prosemirror-model';
13
+ import type { EditorView, NodeView } from 'prosemirror-view';
14
+ /** A control slot a node view opened, for the editor to draw into. */
15
+ export interface Slot {
16
+ kind: 'code' | 'callout';
17
+ element: HTMLElement;
18
+ node: PMNode;
19
+ getPos: () => number | undefined;
20
+ }
21
+ /** The open slots, which the editor subscribes to and draws portals into. */
22
+ export declare class SlotStore {
23
+ private slots;
24
+ private listeners;
25
+ private snapshot;
26
+ add(slot: Slot): void;
27
+ remove(slot: Slot): void;
28
+ changed(): void;
29
+ subscribe: (listener: () => void) => (() => void);
30
+ get: () => Slot[];
31
+ private emit;
32
+ }
33
+ export declare function codeBlockView(store: SlotStore): (node: PMNode, _view: EditorView, getPos: () => number | undefined) => NodeView;
34
+ export declare function calloutView(store: SlotStore): (node: PMNode, _view: EditorView, getPos: () => number | undefined) => NodeView;
35
+ /**
36
+ * A list item, and a task item's box. The box is the same native checkbox
37
+ * the reader's renderer draws, and here it can be pressed: a press ticks the
38
+ * task without moving the caret.
39
+ */
40
+ export declare function listItemView(labels: () => {
41
+ done: string;
42
+ notDone: string;
43
+ }): (node: PMNode, view: EditorView, getPos: () => number | undefined) => NodeView;
44
+ /** A table inside the scroller the reader's renderer wraps it in. */
45
+ export declare function tableView(node: PMNode): NodeView;
46
+ /** How a picture's address is shown: a doc's are files of its version. */
47
+ export type ImageResolver = (src: string) => string | null;
48
+ /**
49
+ * A picture, shown from where the application says (a doc's file, through an
50
+ * object URL) or, without a resolver, from an address a reader may follow.
51
+ * One it cannot show reads as its alt text, as it does to a reader.
52
+ */
53
+ export declare class ImageViews {
54
+ private resolve;
55
+ private views;
56
+ constructor(resolve: () => ImageResolver | undefined);
57
+ /** Paint every picture again, when what the resolver can answer has changed. */
58
+ refresh(): void;
59
+ view: (node: PMNode) => NodeView;
60
+ }
@@ -0,0 +1,47 @@
1
+ /**
2
+ * What a paste or a drop becomes: Markdown, HTML or plain text, read into the
3
+ * editor's document WITHOUT EVER PARSING MARKUP THROUGH A SINK.
4
+ *
5
+ * # Why HTML is tokenized here
6
+ *
7
+ * ProseMirror reads pasted HTML by assigning it to `innerHTML` on a detached
8
+ * document, behind a pass-through Trusted Types policy it creates for itself.
9
+ * A page that enforces Trusted Types with `trusted-types 'none'` allows no
10
+ * policy at all, so that path throws; and a pass-through policy, where one is
11
+ * allowed, is exactly the hole Trusted Types exists to close. So the editor
12
+ * takes the paste and the drop itself (`handleDOMEvents`), and reads HTML
13
+ * with the small tokenizer below, which builds elements one by one in an
14
+ * inert document (`createElement`, `setAttribute` and `createTextNode`, none
15
+ * of them a sink), keeping only the elements and attributes the editor has a
16
+ * meaning for. ProseMirror's own `DOMParser` then reads that tree, so every
17
+ * rule about what an element becomes is the schema's.
18
+ *
19
+ * NOTHING IN THE TREE LOADS ANYTHING: it lives in a document with no browsing
20
+ * context, a picture's address is kept in `data-src` rather than `src`, and a
21
+ * link whose scheme is not allowed is dropped to its text.
22
+ */
23
+ import { Slice, type ResolvedPos } from 'prosemirror-model';
24
+ /**
25
+ * The paste as an element tree in an inert document, kept to what the
26
+ * editor understands. Unclosed `p`, `li`, `tr`, `td` and `th` close where a
27
+ * browser would close them, which is how real clipboard HTML is written.
28
+ */
29
+ export declare function htmlTree(html: string, doc?: Document): HTMLElement;
30
+ /** A slice of the editor's document from pasted HTML. */
31
+ export declare function htmlSlice(html: string, $context: ResolvedPos): Slice;
32
+ /**
33
+ * Whether plain text is written in Markdown: a block's syntax at a line's
34
+ * start, or a span's (strong, a link, a code span) anywhere. Text with
35
+ * neither is pasted line by line, as it was written.
36
+ */
37
+ export declare function looksLikeMarkdown(text: string): boolean;
38
+ /** A slice from Markdown text. */
39
+ export declare function markdownSlice(text: string): Slice;
40
+ /** A slice from plain text: one paragraph per line. */
41
+ export declare function textSlice(text: string): Slice;
42
+ /**
43
+ * Whether clipboard HTML carries structure worth keeping. A code editor puts
44
+ * its text on the clipboard as HTML too, every line a styled `div`, and
45
+ * reading that as HTML would lose the Markdown the text was written in.
46
+ */
47
+ export declare function richHtml(html: string, types: readonly string[]): boolean;
@@ -0,0 +1,49 @@
1
+ /**
2
+ * The editor's plugins: the slash trigger, the placeholder, and the clipboard.
3
+ */
4
+ import { Slice, type Node as PMNode } from 'prosemirror-model';
5
+ import { Plugin, PluginKey } from 'prosemirror-state';
6
+ /** Where the slash the writer typed is, and what they have typed after it. */
7
+ export interface SlashState {
8
+ open: boolean;
9
+ /** The position of the `/`. */
10
+ from: number;
11
+ query: string;
12
+ }
13
+ export declare const slashKey: PluginKey<SlashState>;
14
+ /**
15
+ * The slash trigger: a `/` typed at the start of a line or after a space
16
+ * opens the block menu, and the menu follows what is typed after it until
17
+ * the caret leaves, a space ends the word, or Escape closes it.
18
+ *
19
+ * ONLY A TYPED SLASH OPENS IT. A caret moved into an address that holds one
20
+ * (`https://…`) is not asking for a block.
21
+ */
22
+ export declare function slashPlugin(keys: {
23
+ current: ((event: KeyboardEvent) => boolean) | null;
24
+ }): Plugin<SlashState>;
25
+ export declare const focusKey: PluginKey<boolean>;
26
+ /** Whether the editor has focus, kept as state so a decoration can follow it. */
27
+ export declare const focusPlugin: Plugin<boolean>;
28
+ /**
29
+ * The words an empty editor shows, and the hint an empty line shows while the
30
+ * caret is on it. Both are a decoration's attribute drawn by the stylesheet,
31
+ * never text in the document, so neither can be saved.
32
+ */
33
+ export declare function placeholderPlugin(text: () => {
34
+ empty: string;
35
+ line: string;
36
+ }): Plugin;
37
+ /** A slice's content as Markdown, for a paste into anything that reads text. */
38
+ export declare function sliceMarkdown(slice: Slice): string;
39
+ /**
40
+ * The clipboard, taken whole: copy writes Markdown as the text a plain field
41
+ * receives, and paste and drop read Markdown, HTML and text through
42
+ * `paste.ts` rather than through ProseMirror's own HTML path, which assigns
43
+ * markup to `innerHTML` and cannot run under Trusted Types.
44
+ */
45
+ export declare function clipboardPlugin(shift: {
46
+ current: boolean;
47
+ }): Plugin;
48
+ /** Whether a document is the single empty paragraph an empty body reads as. */
49
+ export declare function isEmptyDoc(doc: PMNode): boolean;
@@ -0,0 +1,14 @@
1
+ /**
2
+ * The editor's Markdown round trip, as plain functions: what a load and a
3
+ * save with no edit write, and the spelling a changed block is written in.
4
+ * An application holds its own bodies to them (a Knowledge page's fixtures, a
5
+ * doc's), so a body the editor would rewrite is found by a test rather than
6
+ * by somebody's diff.
7
+ *
8
+ * Importing these brings the document model with them; the editor's shell
9
+ * does not, so a screen that only draws `RichEditor` pays for neither.
10
+ */
11
+ /** The body a load and a save with no edit write: the body itself, byte for byte. */
12
+ export declare function roundTripMarkdown(markdown: string): string;
13
+ /** The body as the editor writes it when every block has changed. */
14
+ export declare function canonicalMarkdown(markdown: string): string;
@@ -0,0 +1,23 @@
1
+ /**
2
+ * The document model `RichEditor` edits: exactly what the Markdown grammar
3
+ * (`../Markdown`) reads, and nothing it cannot write back.
4
+ *
5
+ * EVERY NODE DRAWS WHAT THE READER SEES. The editor's DOM is the element shape
6
+ * an application's renderer emits for the same block (an `h2` for a `#`
7
+ * heading, a list item whose first child is a checkbox, a table inside a
8
+ * scrolling wrapper), inside `Document`, so the page looks the same while it
9
+ * is edited as when it is read, and one stylesheet sets both.
10
+ *
11
+ * A NODE CARRIES THE SPELLING IT WAS READ WITH (a bullet's character, a
12
+ * fence's marker, emphasis by `*` or `_`), so a block somebody edits is
13
+ * written back in the hand it was written in rather than in the editor's.
14
+ *
15
+ * NO STYLE ATTRIBUTE IS EVER WRITTEN. A strict Content-Security-Policy refuses
16
+ * `style-src 'unsafe-inline'`, which covers a `style` attribute set through
17
+ * `setAttribute`, so a cell's alignment is a data attribute the stylesheet
18
+ * reads.
19
+ */
20
+ import { Schema } from 'prosemirror-model';
21
+ /** A heading's element: a body's `#` is an `h2`, because the page's title is its `h1`. */
22
+ export declare function headingTag(level: number): string;
23
+ export declare const schema: Schema<"blockquote" | "table" | "image" | "text" | "heading" | "doc" | "paragraph" | "callout" | "code_block" | "horizontal_rule" | "bullet_list" | "ordered_list" | "list_item" | "table_row" | "table_header" | "table_cell" | "hard_break", "code" | "em" | "link" | "strong" | "strike">;