@thomasfosterau/prosekit-utilities 0.0.0 → 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 +446 -1
- package/dist/derive-BtbsOqS7.js +479 -0
- package/dist/derive.d.ts +2 -0
- package/dist/derive.js +1 -0
- package/dist/document-shape-CrKjPIEf.d.ts +195 -0
- package/dist/drizzle.d.ts +76 -0
- package/dist/drizzle.js +95 -0
- package/dist/envelope-DQS7tt8f.js +87 -0
- package/dist/index-DlgceBHe.d.ts +266 -0
- package/dist/index.d.ts +203 -0
- package/dist/index.js +723 -0
- package/dist/prosekit.d.ts +3218 -0
- package/dist/prosekit.js +827 -0
- package/dist/rolldown-runtime-D8jQpDG7.js +12 -0
- package/package.json +66 -6
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import { a as DocumentViolation, c as checkAllowList, d as MarkJSON, f as NodeJSON, i as AllowList, l as defineAllowList, n as DocumentShape, o as allowListFilter, r as defineDocumentShape, s as allowListViolation, t as DocumentGrammarGuard, u as DocumentJSON } from "./document-shape-CrKjPIEf.js";
|
|
2
|
+
/**
|
|
3
|
+
* Extracts plain text from a document, joining the `text` leaves with
|
|
4
|
+
* `options.separator` (default `' '`).
|
|
5
|
+
*
|
|
6
|
+
* Tolerant by design: `null`, `undefined`, a document with no `content`, a
|
|
7
|
+
* stray string or `null` inside `content`, and a `text`-typed node whose
|
|
8
|
+
* `text` is not a string all contribute nothing rather than throwing. The
|
|
9
|
+
* callers are database columns and queue payloads, where a malformed row
|
|
10
|
+
* must degrade to empty text rather than fail a batch.
|
|
11
|
+
*/
|
|
12
|
+
export declare function extractDocumentText(doc: NodeJSON | DocumentJSON | null | undefined, options?: {
|
|
13
|
+
readonly separator?: string | undefined;
|
|
14
|
+
}): string;
|
|
15
|
+
/**
|
|
16
|
+
* Extracts plain text from an inline document, joining the `text` leaves
|
|
17
|
+
* with nothing at all.
|
|
18
|
+
*
|
|
19
|
+
* This is the form a title or other flat field wants: `extractDocumentText`
|
|
20
|
+
* would turn `Rosa` + `canina` (two runs, one styled) into `Rosa canina`
|
|
21
|
+
* with a space that is already in the first run, or into `Rosacanina` with
|
|
22
|
+
* one missing — the `''` join keeps whatever whitespace the author wrote.
|
|
23
|
+
* Recurses into any node that carries `content`, so a wrapping inline node
|
|
24
|
+
* (a sidenote, a mention) still contributes its text.
|
|
25
|
+
*/
|
|
26
|
+
export declare function inlineDocumentText(doc: NodeJSON | DocumentJSON): string;
|
|
27
|
+
/**
|
|
28
|
+
* Rewrites a document's root `type` to `doc`, ready for a ProseMirror
|
|
29
|
+
* schema.
|
|
30
|
+
*
|
|
31
|
+
* Anything that is not already `doc` is treated as an envelope name — the
|
|
32
|
+
* remap does not need to know which one, which is what lets one component
|
|
33
|
+
* serve every shape an application declares.
|
|
34
|
+
*/
|
|
35
|
+
export declare const toEditorDocument: <N extends string>(doc: DocumentJSON<N> | NodeJSON) => NodeJSON;
|
|
36
|
+
/**
|
|
37
|
+
* Rewrites an editor document's root `type` back to the envelope `name`,
|
|
38
|
+
* ready to persist.
|
|
39
|
+
*
|
|
40
|
+
* Curried on the name so a component can bind it once
|
|
41
|
+
* (`const toStored = fromEditorDocument(shape.name)`). A document with no
|
|
42
|
+
* `content` at all becomes an empty one rather than an envelope missing its
|
|
43
|
+
* required field.
|
|
44
|
+
*/
|
|
45
|
+
export declare const fromEditorDocument: <N extends string>(name: N) => (doc: NodeJSON) => DocumentJSON<N>;
|
|
46
|
+
/**
|
|
47
|
+
* What a node serialiser is handed alongside its node: the two recursive
|
|
48
|
+
* passes and the escaping function, so an application's serialiser renders
|
|
49
|
+
* its children exactly as the stock ones do.
|
|
50
|
+
*/
|
|
51
|
+
interface MarkdownContext {
|
|
52
|
+
/** Serialise a run of inline nodes (text with marks, hard breaks, atoms). */
|
|
53
|
+
readonly serialiseInline: (nodes: ReadonlyArray<NodeJSON>) => string;
|
|
54
|
+
/** Serialise a run of block nodes, grouping consecutive list siblings. */
|
|
55
|
+
readonly serialiseBlocks: (nodes: ReadonlyArray<NodeJSON>) => string;
|
|
56
|
+
/** Backslash-escape CommonMark metacharacters in literal text. */
|
|
57
|
+
readonly escape: (text: string) => string;
|
|
58
|
+
}
|
|
59
|
+
/** Renders one block node. Returns `''` to drop the block entirely. */
|
|
60
|
+
type BlockSerialiser = (node: NodeJSON, context: MarkdownContext) => string;
|
|
61
|
+
/** Renders one non-text inline node. Returns `''` to contribute nothing. */
|
|
62
|
+
type InlineSerialiser = (node: NodeJSON, context: MarkdownContext) => string;
|
|
63
|
+
/** Wraps already-rendered text in one mark's Markdown syntax. */
|
|
64
|
+
type MarkSerialiser = (text: string, mark: MarkJSON) => string;
|
|
65
|
+
/** A configured serialiser: one entry point per document shape. */
|
|
66
|
+
interface MarkdownSerialiser {
|
|
67
|
+
/** A block document → multi-line Markdown, trimmed. */
|
|
68
|
+
readonly document: (doc: NodeJSON | DocumentJSON) => string;
|
|
69
|
+
/** An inline document → a single line of Markdown, trimmed. */
|
|
70
|
+
readonly inline: (doc: NodeJSON | DocumentJSON) => string;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Builds a Markdown serialiser.
|
|
74
|
+
*
|
|
75
|
+
* The stock cases — paragraph, heading, blockquote, code block, horizontal
|
|
76
|
+
* rule, image, table, hard break and the five marks with a Markdown form —
|
|
77
|
+
* are built in, along with the flat-list run model and the fallback that
|
|
78
|
+
* emits an unknown node's inline text rather than dropping it. `blocks`,
|
|
79
|
+
* `inlines` and `marks` are merged **over** the stock maps, so an
|
|
80
|
+
* application adds its own nodes (and may replace a stock one) without
|
|
81
|
+
* restating any of this:
|
|
82
|
+
*
|
|
83
|
+
* ```ts
|
|
84
|
+
* const toMarkdown = createMarkdownSerialiser({
|
|
85
|
+
* inlines: { mention: mentionMarkdown },
|
|
86
|
+
* blocks: { figure: figureMarkdown },
|
|
87
|
+
* });
|
|
88
|
+
* ```
|
|
89
|
+
*
|
|
90
|
+
* `list` is the one type a `blocks` entry cannot override: consecutive
|
|
91
|
+
* `list` siblings are one list, so the run — not the node — is the unit of
|
|
92
|
+
* serialisation, and that grouping lives here.
|
|
93
|
+
*/
|
|
94
|
+
export declare function createMarkdownSerialiser(options?: {
|
|
95
|
+
readonly blocks?: Record<string, BlockSerialiser> | undefined;
|
|
96
|
+
readonly inlines?: Record<string, InlineSerialiser> | undefined;
|
|
97
|
+
readonly marks?: Record<string, MarkSerialiser> | undefined;
|
|
98
|
+
}): MarkdownSerialiser;
|
|
99
|
+
/**
|
|
100
|
+
* CommonMark escaping for literal text.
|
|
101
|
+
*
|
|
102
|
+
* @module
|
|
103
|
+
*/
|
|
104
|
+
/**
|
|
105
|
+
* Backslash-escapes the CommonMark inline metacharacters in literal text, so
|
|
106
|
+
* an author's `*` stays an asterisk instead of opening emphasis.
|
|
107
|
+
*
|
|
108
|
+
* Exported because an application's own node serialiser emits literal text
|
|
109
|
+
* too — a mention's `@label`, a caption — and must escape it the same way
|
|
110
|
+
* the stock serialisers do.
|
|
111
|
+
*/
|
|
112
|
+
export declare function escapeMarkdown(text: string): string;
|
|
113
|
+
/**
|
|
114
|
+
* A mention as its `@label`, escaped.
|
|
115
|
+
*
|
|
116
|
+
* The referenced account's id has no Markdown form and is dropped: a
|
|
117
|
+
* mention is a link to something only the application can resolve, so the
|
|
118
|
+
* text is all that survives. The label is escaped like any other literal
|
|
119
|
+
* text, so a display name containing `*` cannot open emphasis.
|
|
120
|
+
*/
|
|
121
|
+
export declare const mentionMarkdown: InlineSerialiser;
|
|
122
|
+
/**
|
|
123
|
+
* A figure as its image line followed by the caption as an italic
|
|
124
|
+
* paragraph — Markdown has no figure element, and this is the form a reader
|
|
125
|
+
* renders closest to one.
|
|
126
|
+
*
|
|
127
|
+
* A figure whose image is dropped (an unsafe `src`) still emits its caption;
|
|
128
|
+
* a figure with no caption emits the image line alone.
|
|
129
|
+
*/
|
|
130
|
+
export declare const figureMarkdown: BlockSerialiser;
|
|
131
|
+
/**
|
|
132
|
+
* A sidenote as a Pandoc inline footnote (`^[note]`).
|
|
133
|
+
*
|
|
134
|
+
* This is the established Markdown form for a reference aside with no
|
|
135
|
+
* separate definition block: it keeps the note where it sits in the prose
|
|
136
|
+
* and renders as a footnote in Pandoc-flavoured pipelines, the closest
|
|
137
|
+
* faithful analogue to a margin note. `^[…]` is a Pandoc extension, not core
|
|
138
|
+
* CommonMark; a plain CommonMark reader shows the bracketed content inline,
|
|
139
|
+
* which still reads as a parenthetical aside.
|
|
140
|
+
*
|
|
141
|
+
* The note holds rich inline content, so its children go through the same
|
|
142
|
+
* inline pass body prose does — `^[…]` legitimately contains inline Markdown
|
|
143
|
+
* (`[t](u)`, `*em*`, `` `code` ``), and literal `[` / `]` in a text run is
|
|
144
|
+
* already backslash-escaped so it cannot close the note early. Any newline
|
|
145
|
+
* (a hard break renders as `\`) is collapsed to a space afterwards: a
|
|
146
|
+
* literal newline would terminate the inline footnote and split the
|
|
147
|
+
* surrounding paragraph.
|
|
148
|
+
*
|
|
149
|
+
* A nested sidenote is flattened to its body first. A grammar restricting a
|
|
150
|
+
* sidenote to `(text | hardBreak)*` rules one out, but a persistence guard
|
|
151
|
+
* checks the node registry rather than content expressions, so a
|
|
152
|
+
* hand-crafted or migrated document can still carry one — and `^[…^[…]…]`
|
|
153
|
+
* has no valid Pandoc rendering, since the inner `]` closes the outer note.
|
|
154
|
+
*/
|
|
155
|
+
export declare const sidenoteMarkdown: InlineSerialiser;
|
|
156
|
+
/**
|
|
157
|
+
* The default serialiser: the shared base grammar and nothing else.
|
|
158
|
+
*
|
|
159
|
+
* An application whose grammar includes an opt-in node builds its own with
|
|
160
|
+
* `createMarkdownSerialiser` rather than reaching for this one, because a
|
|
161
|
+
* node with no serialiser falls back to its inline text — readable, but not
|
|
162
|
+
* a faithful rendering of a figure or a sidenote.
|
|
163
|
+
*/
|
|
164
|
+
export declare const toMarkdown: MarkdownSerialiser;
|
|
165
|
+
/**
|
|
166
|
+
* The safe-URL allow-list shared by every serialiser in this package.
|
|
167
|
+
*
|
|
168
|
+
* Link `href`s and image `src`s are passed through this allow-list before
|
|
169
|
+
* being embedded, so a serialiser never emits a `javascript:` / `data:` /
|
|
170
|
+
* `vbscript:` URI. Single-sourced here so the Markdown serialiser, the HTML
|
|
171
|
+
* serialiser (the ProseKit entry point) and the allow-list write-seam check can never
|
|
172
|
+
* drift apart — the SEC-XSS-001 defence-in-depth both apps this package was
|
|
173
|
+
* extracted from rely on.
|
|
174
|
+
*
|
|
175
|
+
* @module
|
|
176
|
+
*/
|
|
177
|
+
/**
|
|
178
|
+
* The schemes {@link isSafeHref} accepts when the caller names none.
|
|
179
|
+
*
|
|
180
|
+
* Deliberately short: these are the three a rich-text document has a reason
|
|
181
|
+
* to link to. An application that needs `tel:` or a custom scheme passes it
|
|
182
|
+
* in rather than widening the default for everyone.
|
|
183
|
+
*/
|
|
184
|
+
export declare const DEFAULT_SAFE_SCHEMES: ReadonlyArray<string>;
|
|
185
|
+
/**
|
|
186
|
+
* Returns true when `href` is safe to embed as a link target or image
|
|
187
|
+
* source.
|
|
188
|
+
*
|
|
189
|
+
* Allowed: any of `options.schemes` (default `http`, `https`, `mailto`),
|
|
190
|
+
* root-relative paths (`/foo`, but not `//evil.example` or `/\evil.example`,
|
|
191
|
+
* both of which resolve off-origin), and fragment links (`#bar`).
|
|
192
|
+
*
|
|
193
|
+
* The scheme is read off `new URL()` rather than compared as a string
|
|
194
|
+
* prefix, which is what makes the obfuscated forms fail: the WHATWG parser
|
|
195
|
+
* lowercases the scheme and strips leading and inner ASCII whitespace and
|
|
196
|
+
* control characters before reporting it, so `JaVaScRiPt:`, ` javascript:`
|
|
197
|
+
* and `java\tscript:` all normalise to `javascript:` and are rejected. A
|
|
198
|
+
* `startsWith('javascript:')` test would pass all three.
|
|
199
|
+
*/
|
|
200
|
+
export declare function isSafeHref(href: unknown, options?: {
|
|
201
|
+
readonly schemes?: ReadonlyArray<string> | undefined;
|
|
202
|
+
}): href is string;
|
|
203
|
+
export { type AllowList, type BlockSerialiser, type DocumentGrammarGuard, type DocumentJSON, type DocumentShape, DocumentViolation, type InlineSerialiser, type MarkJSON, type MarkSerialiser, type MarkdownContext, type MarkdownSerialiser, type NodeJSON, allowListFilter, allowListViolation, checkAllowList, defineAllowList, defineDocumentShape };
|