@mikedown/core 0.1.0 → 0.3.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/CHANGELOG.md +20 -0
- package/README.md +183 -3
- package/dist/ai/engines-page.d.ts +130 -0
- package/dist/ai/engines-page.js +10 -0
- package/dist/ai/engines-page.js.map +1 -0
- package/dist/ai/index.d.ts +1531 -0
- package/dist/ai/index.js +395 -0
- package/dist/ai/index.js.map +1 -0
- package/dist/ai-ui-C7ENTWWU.js +3370 -0
- package/dist/ai-ui-C7ENTWWU.js.map +1 -0
- package/dist/chunk-7A5HEPLK.js +4910 -0
- package/dist/chunk-7A5HEPLK.js.map +1 -0
- package/dist/chunk-GWCRPPCX.js +18 -0
- package/dist/chunk-GWCRPPCX.js.map +1 -0
- package/dist/chunk-JZWKEBCI.js +3899 -0
- package/dist/chunk-JZWKEBCI.js.map +1 -0
- package/dist/chunk-L4FO63DF.js +113 -0
- package/dist/chunk-L4FO63DF.js.map +1 -0
- package/dist/chunk-LXZG7IKN.js +39 -0
- package/dist/chunk-LXZG7IKN.js.map +1 -0
- package/dist/chunk-QDVY7WW6.js +165 -0
- package/dist/chunk-QDVY7WW6.js.map +1 -0
- package/dist/chunk-QWKT57TR.js +62 -0
- package/dist/chunk-QWKT57TR.js.map +1 -0
- package/dist/chunk-TSP7BAV3.js +22 -0
- package/dist/chunk-TSP7BAV3.js.map +1 -0
- package/dist/index.d.ts +62 -441
- package/dist/index.js +6871 -1247
- package/dist/index.js.map +1 -1
- package/dist/schema-DYzxkuSb.d.ts +46 -0
- package/dist/shared/anchoring.js +4 -16
- package/dist/shared/anchoring.js.map +1 -1
- package/dist/shared/imagePaste.js +3 -57
- package/dist/shared/imagePaste.js.map +1 -1
- package/dist/shared/sha1.js +3 -57
- package/dist/shared/sha1.js.map +1 -1
- package/dist/shared/wordCount.js +4 -12
- package/dist/shared/wordCount.js.map +1 -1
- package/dist/styles.css +3700 -94
- package/dist/types-CgEeIUhi.d.ts +432 -0
- package/dist/types-CsVNVSNY.d.ts +597 -0
- package/package.json +17 -2
|
@@ -0,0 +1,597 @@
|
|
|
1
|
+
import { Editor } from '@tiptap/core';
|
|
2
|
+
import { M as MikeDownAiHost, A as AiSettings, O as AiServedBy, a as AiEngineStatus } from './types-CgEeIUhi.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Toolbar layout model: schema, parse, normalize, migrate and edit helpers.
|
|
6
|
+
*
|
|
7
|
+
* Pure logic, no DOM. A layout is one self-contained, versioned value:
|
|
8
|
+
*
|
|
9
|
+
* { version: 1, items: ['textFormat', ..., '|', ..., '~', ..., 'more'], seen: [...] }
|
|
10
|
+
*
|
|
11
|
+
* `items` holds registry ids plus `'|'` (separator) and `'~'` (flexible
|
|
12
|
+
* spacer). `seen` lists every registry id the layout has been reconciled
|
|
13
|
+
* against, so a button added by a later core is inserted next to its default
|
|
14
|
+
* neighbor while a button the user removed stays removed.
|
|
15
|
+
*
|
|
16
|
+
* Normalization rules (D15), applied by {@link normalizeToolbarLayout}:
|
|
17
|
+
*
|
|
18
|
+
* - Non-string entries are dropped.
|
|
19
|
+
* - Duplicate ids keep the first occurrence.
|
|
20
|
+
* - `textFormat` is moved or inserted first; `more` is moved or appended last;
|
|
21
|
+
* `settings` is appended before `more` if missing.
|
|
22
|
+
* - Runs of the same divider collapse to one (`| |` is one separator, `~ ~` one
|
|
23
|
+
* spacer). A separator next to a spacer is kept: a line followed by flexible
|
|
24
|
+
* space is a deliberate arrangement, and the renderer shows both.
|
|
25
|
+
* - Leading and trailing `'|'`/`'~'` are trimmed (of the list as written; a
|
|
26
|
+
* separator right after `textFormat` or right before `more` is a deliberate
|
|
27
|
+
* placement and is kept).
|
|
28
|
+
* - Unknown ids are kept in place (skipped at render, preserved on save).
|
|
29
|
+
* - A `version` greater than 1 is read the same way.
|
|
30
|
+
* - Non-object or wrong-shape values mean the default layout (nothing is
|
|
31
|
+
* written back until the next save).
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* A toolbar layout. `items` and `seen` are plain strings (not
|
|
36
|
+
* {@link ToolbarLayoutToken}) because a hand-edited or newer-version layout may
|
|
37
|
+
* carry ids this core does not know; they are skipped at render and preserved
|
|
38
|
+
* on save. All helpers return new objects and never mutate their input.
|
|
39
|
+
*/
|
|
40
|
+
interface ToolbarLayout {
|
|
41
|
+
/** Schema version. Higher versions are accepted and preserved. */
|
|
42
|
+
readonly version: number;
|
|
43
|
+
/** Registry ids, `'|'` separators and `'~'` flexible spacers, in toolbar order. */
|
|
44
|
+
readonly items: readonly string[];
|
|
45
|
+
/** Every registry id this layout has been reconciled against. */
|
|
46
|
+
readonly seen: readonly string[];
|
|
47
|
+
}
|
|
48
|
+
/** Ids may be passed as a set or any iterable (e.g. `TOOLBAR_ITEM_IDS`). */
|
|
49
|
+
type ToolbarKnownIds = ReadonlySet<string> | Iterable<string>;
|
|
50
|
+
/** The default layout: today's toolbar, every non-optional known id marked seen. Frozen. */
|
|
51
|
+
declare const DEFAULT_TOOLBAR_LAYOUT: ToolbarLayout;
|
|
52
|
+
/**
|
|
53
|
+
* Apply the D15 rules so the toolbar always renders something sane: drop
|
|
54
|
+
* non-strings, dedupe ids keeping the first, put `textFormat` first and `more`
|
|
55
|
+
* last, append `settings` before `more` if missing, collapse runs of the same
|
|
56
|
+
* divider (`'|'` or `'~'`) to one and trim leading/trailing ones. Unknown ids (not in `knownIds`) stay in
|
|
57
|
+
* place. `version` is preserved (a version above 1 is read the same way). `seen`
|
|
58
|
+
* is reduced to unique strings. Idempotent.
|
|
59
|
+
*
|
|
60
|
+
* `knownIds` is accepted for symmetry with the other entry points; the rules
|
|
61
|
+
* above only need to know which ids are pinned, which the shared table covers.
|
|
62
|
+
*/
|
|
63
|
+
declare function normalizeToolbarLayout(layout: ToolbarLayout, knownIds?: ToolbarKnownIds): ToolbarLayout;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* MikeDown host adapter.
|
|
67
|
+
*
|
|
68
|
+
* The editor core never talks to its environment directly. Everything that
|
|
69
|
+
* needs the outside world (saving, file system, workspace search, opening
|
|
70
|
+
* links, persisting settings) goes through a `MikeDownHost` the embedding
|
|
71
|
+
* application passes to `createMikeDownEditor`.
|
|
72
|
+
*
|
|
73
|
+
* Rules (see core-extraction-decisions.md section 5):
|
|
74
|
+
*
|
|
75
|
+
* - `onChange` is the only required method.
|
|
76
|
+
* - Every other method is optional. An absent method turns its feature off
|
|
77
|
+
* and hides its UI (toolbar button, slash command, sidebar section,
|
|
78
|
+
* settings control).
|
|
79
|
+
* - Request/response pairs are Promise-returning methods. Correlation ids,
|
|
80
|
+
* retries and transport details stay inside the host implementation.
|
|
81
|
+
*/
|
|
82
|
+
|
|
83
|
+
/** How a link should open. Absent means the host's default. */
|
|
84
|
+
type LinkOpenBehavior = 'navigateCurrentTab' | 'openNewTab';
|
|
85
|
+
/** A link target offered by the link dialog autocomplete. */
|
|
86
|
+
interface LinkSuggestion {
|
|
87
|
+
label: string;
|
|
88
|
+
href: string;
|
|
89
|
+
type: 'file' | 'anchor' | 'inDoc' | 'external';
|
|
90
|
+
/** Heading level (1-6) for anchor items, used for hierarchical indentation. */
|
|
91
|
+
level?: number;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Result of resolving one `[[wikilink]]` target. `href` is null when no
|
|
95
|
+
* document matches. `count` is how many documents share the name: 0 means
|
|
96
|
+
* unresolved, 1 unique, more than 1 ambiguous (the host picked the nearest).
|
|
97
|
+
*/
|
|
98
|
+
interface WikilinkResolution {
|
|
99
|
+
target: string;
|
|
100
|
+
href: string | null;
|
|
101
|
+
count?: number;
|
|
102
|
+
}
|
|
103
|
+
/** One workspace tag with the number of documents that carry it. */
|
|
104
|
+
interface TagCount {
|
|
105
|
+
tag: string;
|
|
106
|
+
count: number;
|
|
107
|
+
}
|
|
108
|
+
/** A backlink to the current document, rendered in the sidebar. */
|
|
109
|
+
interface BacklinkItem {
|
|
110
|
+
uri: string;
|
|
111
|
+
displayPath: string;
|
|
112
|
+
line: number;
|
|
113
|
+
lineText?: string;
|
|
114
|
+
/** Href of the link in the source doc, so the opened doc can scroll to it. */
|
|
115
|
+
linkHref?: string;
|
|
116
|
+
/** Which occurrence of linkHref this is (0-based). */
|
|
117
|
+
occurrence?: number;
|
|
118
|
+
}
|
|
119
|
+
/** Image bytes from a paste or drop. */
|
|
120
|
+
interface ImageUploadRequest {
|
|
121
|
+
mime: string;
|
|
122
|
+
bytes: Uint8Array;
|
|
123
|
+
name?: string;
|
|
124
|
+
}
|
|
125
|
+
/** Where an uploaded or picked image lives, as the editor should render it. */
|
|
126
|
+
interface ImageInsertResult {
|
|
127
|
+
src: string;
|
|
128
|
+
alt?: string;
|
|
129
|
+
}
|
|
130
|
+
/** A downscaled copy of an image already in the document. */
|
|
131
|
+
interface ImageResizeRequest {
|
|
132
|
+
/** The image's current `src` attribute. */
|
|
133
|
+
currentSrc: string;
|
|
134
|
+
mime: string;
|
|
135
|
+
bytes: Uint8Array;
|
|
136
|
+
/** Percentage of the natural size (1 to 200). */
|
|
137
|
+
percent: number;
|
|
138
|
+
}
|
|
139
|
+
interface ImageResizeResult {
|
|
140
|
+
/** The `src` to render the resized image from. */
|
|
141
|
+
src: string;
|
|
142
|
+
/** True when the original file was replaced (the editor cache-busts the src). */
|
|
143
|
+
overwritten: boolean;
|
|
144
|
+
}
|
|
145
|
+
/** A link the editor asks the host to validate. */
|
|
146
|
+
interface LinkCheckRequest {
|
|
147
|
+
href: string;
|
|
148
|
+
type: 'anchor' | 'file' | 'fileAnchor';
|
|
149
|
+
}
|
|
150
|
+
/** The committed version of the document, for change highlighting. */
|
|
151
|
+
interface DiffBaseline {
|
|
152
|
+
headContent: string | null;
|
|
153
|
+
hasChanges: boolean;
|
|
154
|
+
}
|
|
155
|
+
/** Status-bar style statistics. Either field may be present. */
|
|
156
|
+
interface MikeDownStats {
|
|
157
|
+
/** Full plain text of the document (for word count and reading time). */
|
|
158
|
+
document?: string;
|
|
159
|
+
/** Selection size, or null when nothing is selected. */
|
|
160
|
+
selection?: {
|
|
161
|
+
words: number;
|
|
162
|
+
chars: number;
|
|
163
|
+
} | null;
|
|
164
|
+
}
|
|
165
|
+
/** Sidebar preference persistence. Absent means in-memory defaults. */
|
|
166
|
+
interface MikeDownSidebarPrefs {
|
|
167
|
+
/** Ask for the persisted sidebar state; the host answers with `handle.setSidebarState`. */
|
|
168
|
+
requestState(): void;
|
|
169
|
+
/** The pin toggle changed the default visibility for new documents. */
|
|
170
|
+
setPref(pref: 'always' | 'never'): void;
|
|
171
|
+
/** "Apply to open documents" in Settings. */
|
|
172
|
+
applyDefaults(): void;
|
|
173
|
+
/** A sidebar section was collapsed or expanded by the user. */
|
|
174
|
+
sectionCollapsed(section: string, collapsed: boolean): void;
|
|
175
|
+
}
|
|
176
|
+
interface MikeDownHost {
|
|
177
|
+
/**
|
|
178
|
+
* The document changed. `pristine` is true when the content matches the
|
|
179
|
+
* last load or save exactly (the user undid every change), in which case
|
|
180
|
+
* `markdown` is the original text byte for byte.
|
|
181
|
+
*/
|
|
182
|
+
onChange(markdown: string, meta: {
|
|
183
|
+
pristine: boolean;
|
|
184
|
+
}): void;
|
|
185
|
+
/** Word count and selection statistics. */
|
|
186
|
+
onStats?(stats: MikeDownStats): void;
|
|
187
|
+
/**
|
|
188
|
+
* Open a link. Absent means external links open in a new browser tab and
|
|
189
|
+
* relative links are ignored. `reveal` asks the target document to scroll
|
|
190
|
+
* to a link back to this one (sidebar backlinks).
|
|
191
|
+
*/
|
|
192
|
+
openLink?(href: string, behavior?: LinkOpenBehavior, reveal?: {
|
|
193
|
+
href?: string;
|
|
194
|
+
occurrence?: number;
|
|
195
|
+
}): void;
|
|
196
|
+
/**
|
|
197
|
+
* Persist settings. Absent means changes made in the Settings modal last
|
|
198
|
+
* for the session only. `source: 'slashMenu'` marks the slash menu's
|
|
199
|
+
* "Turn off slash commands" row; `silent` marks background saves (wheel
|
|
200
|
+
* zoom, Add to Dictionary) that should not show a confirmation.
|
|
201
|
+
*/
|
|
202
|
+
saveSettings?(patch: MikeDownSettingsPatch, opts?: {
|
|
203
|
+
source?: 'slashMenu';
|
|
204
|
+
silent?: boolean;
|
|
205
|
+
}): void;
|
|
206
|
+
/** Flip light and dark. Absent means the editor flips its own theme. */
|
|
207
|
+
toggleTheme?(): void;
|
|
208
|
+
/** "Customize" button on the Hotkeys settings tab. Hidden when absent. */
|
|
209
|
+
openKeybindings?(): void;
|
|
210
|
+
/** Store pasted or dropped image bytes. Absent disables image paste and drop. */
|
|
211
|
+
uploadImage?(file: ImageUploadRequest): Promise<ImageInsertResult>;
|
|
212
|
+
/** Native file picker. Resolves null when cancelled. Absent hides `/image`. */
|
|
213
|
+
pickImage?(): Promise<ImageInsertResult | null>;
|
|
214
|
+
/** Save a resized copy of an image. Absent hides the resize menu items. */
|
|
215
|
+
resizeImage?(req: ImageResizeRequest): Promise<ImageResizeResult>;
|
|
216
|
+
/**
|
|
217
|
+
* Image source policy. The core renders `http:`, `https:`, `data:` and
|
|
218
|
+
* `blob:` sources as they are. For any other source (a relative or
|
|
219
|
+
* absolute path) it calls this and renders the non-null result. Absent, or
|
|
220
|
+
* returning null, the image shows the missing-image placeholder with the raw
|
|
221
|
+
* path. Only the rendered `<img src>` changes; the stored `src`, and so the
|
|
222
|
+
* markdown, is never rewritten.
|
|
223
|
+
*/
|
|
224
|
+
resolveImageSrc?(src: string): string | null;
|
|
225
|
+
/** Files and anchors for link autocomplete and `[[` wikilink autocomplete. */
|
|
226
|
+
getLinkSuggestions?(): Promise<LinkSuggestion[]>;
|
|
227
|
+
/** Heading anchors of another document, for `file.md#` completion. */
|
|
228
|
+
getFileHeadings?(path: string): Promise<LinkSuggestion[]>;
|
|
229
|
+
/** Resolve `[[wikilink]]` targets to hrefs. */
|
|
230
|
+
resolveWikilinks?(targets: string[]): Promise<WikilinkResolution[]>;
|
|
231
|
+
/**
|
|
232
|
+
* Cmd/Ctrl+click on an unresolved wikilink (only when the
|
|
233
|
+
* `wikilinkCreateOnClick` setting is on). May resolve with the new
|
|
234
|
+
* resolution so the link lights up without a reload.
|
|
235
|
+
*/
|
|
236
|
+
createWikilink?(target: string): Promise<WikilinkResolution[] | void> | void;
|
|
237
|
+
/** Validate relative links. Resolves with the hrefs that are broken. */
|
|
238
|
+
checkLinks?(links: LinkCheckRequest[]): Promise<string[]>;
|
|
239
|
+
/** Workspace tag index. Also enables the sidebar Tags section and `#` autocomplete. */
|
|
240
|
+
getTags?(): Promise<TagCount[]>;
|
|
241
|
+
/** Tag click (sidebar or Cmd/Ctrl+click in the document). */
|
|
242
|
+
openTag?(tag: string): void;
|
|
243
|
+
/** Committed version of the document for change highlighting. */
|
|
244
|
+
getDiffBaseline?(): Promise<DiffBaseline>;
|
|
245
|
+
/** A heading's anchor slug changed; in-document links are already fixed. */
|
|
246
|
+
onHeadingRenamed?(oldSlug: string, newSlug: string): void;
|
|
247
|
+
/** A renamed heading's slug is duplicated in the document; nothing was fixed. */
|
|
248
|
+
onHeadingRenameAmbiguous?(baseName: string): void;
|
|
249
|
+
exportHtml?(html: string): void;
|
|
250
|
+
printDocument?(html: string): void;
|
|
251
|
+
viewInBrowser?(html: string): void;
|
|
252
|
+
sidebarPrefs?: MikeDownSidebarPrefs;
|
|
253
|
+
/**
|
|
254
|
+
* Inference through the host. `complete` alone (tier 1) turns the features
|
|
255
|
+
* on; the registry methods (tier 2) turn on the engine UI and core routing.
|
|
256
|
+
* Types and helpers live in `@mikedown/core/ai`.
|
|
257
|
+
*/
|
|
258
|
+
ai?: MikeDownAiHost;
|
|
259
|
+
}
|
|
260
|
+
/** A host with every optional method absent. `onChange` does nothing. */
|
|
261
|
+
declare class NoopHost implements MikeDownHost {
|
|
262
|
+
onChange(_markdown: string, _meta: {
|
|
263
|
+
pristine: boolean;
|
|
264
|
+
}): void;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Public types for the MikeDown editor core: settings, feature flags, the
|
|
269
|
+
* factory options and the editor handle. The host adapter lives in host.ts.
|
|
270
|
+
*/
|
|
271
|
+
|
|
272
|
+
interface NormalizationStyle {
|
|
273
|
+
boldMarker: '**' | '__';
|
|
274
|
+
italicMarker: '*' | '_';
|
|
275
|
+
listMarker: '-' | '*' | '+';
|
|
276
|
+
headingStyle: 'atx' | 'setext';
|
|
277
|
+
}
|
|
278
|
+
/** A webview-resolvable URL prefix and the on-disk folder it maps to. */
|
|
279
|
+
interface ImagePathMapping {
|
|
280
|
+
prefix: string;
|
|
281
|
+
fsPath: string;
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Settings the editor core owns (decisions section 6). Field names match the
|
|
285
|
+
* keys the editor sends to `host.saveSettings`.
|
|
286
|
+
*/
|
|
287
|
+
interface MikeDownSettings {
|
|
288
|
+
fontFamily: string;
|
|
289
|
+
headingFontFamily: string;
|
|
290
|
+
/** Pixels. */
|
|
291
|
+
fontSize: number;
|
|
292
|
+
/** CSS max width of the content column, e.g. "100%" or "780px". */
|
|
293
|
+
contentWidth: string;
|
|
294
|
+
ctrlWheelZoom: boolean;
|
|
295
|
+
editorTheme: 'auto' | 'light' | 'dark';
|
|
296
|
+
headingNumbering: 'off' | 'fromH1' | 'fromH2';
|
|
297
|
+
linkClickBehavior: 'navigateCurrentTab' | 'openNewTab' | 'showContextMenu';
|
|
298
|
+
slashCommandsEnabled: boolean;
|
|
299
|
+
slashCommandsDateFormat: 'iso' | 'long';
|
|
300
|
+
/** "local", "UTC" or an IANA zone. */
|
|
301
|
+
slashCommandsTimeZone: string;
|
|
302
|
+
renderMermaidDiagrams: boolean;
|
|
303
|
+
renderMath: boolean;
|
|
304
|
+
tagsEnabled: boolean;
|
|
305
|
+
/** What Insert > Table of Contents creates (existing TOCs keep their style). */
|
|
306
|
+
tocStyle: 'list' | 'placeholder';
|
|
307
|
+
/** Pad Markdown table cells to a common column width when saving. */
|
|
308
|
+
tablePadColumns: boolean;
|
|
309
|
+
markdownNormalization: 'preserve' | 'normalize';
|
|
310
|
+
normalizationStyle: NormalizationStyle;
|
|
311
|
+
spellCheckEnabled: boolean;
|
|
312
|
+
spellCheckLanguage: 'en' | 'en-GB';
|
|
313
|
+
spellCheckIgnoreCodeBlocks: boolean;
|
|
314
|
+
spellCheckUserWords: string[];
|
|
315
|
+
/**
|
|
316
|
+
* `mikedown.ai.*`, parsed by `parseAiSettings` from `@mikedown/core/ai`.
|
|
317
|
+
* Absent means the defaults (off). Saved as `ai.*` patch keys built by
|
|
318
|
+
* `serializeAiSettings`; API keys are never part of it (`host.ai.setSecret`).
|
|
319
|
+
*/
|
|
320
|
+
ai?: AiSettings;
|
|
321
|
+
/** Words accepted by the spell checker but owned elsewhere (read-only chips). */
|
|
322
|
+
spellCheckExternalWords?: string[];
|
|
323
|
+
/** Cmd/Ctrl+click on an unresolved wikilink calls `host.createWikilink`. */
|
|
324
|
+
wikilinkCreateOnClick?: boolean;
|
|
325
|
+
/** `never` turns off in-document link fixing and `onHeadingRenamed`. */
|
|
326
|
+
headingRenameUpdateLinks?: 'ask' | 'always' | 'never';
|
|
327
|
+
/** Image src rewriting for display in the image popover. */
|
|
328
|
+
imagePathMappings?: ImagePathMapping[];
|
|
329
|
+
/** On-disk folder of the current document (pairs with imagePathMappings). */
|
|
330
|
+
docDir?: string;
|
|
331
|
+
/**
|
|
332
|
+
* The customized toolbar layout: one self-contained, versioned blob
|
|
333
|
+
* (`{ version, items, seen }`, see `ToolbarLayout`). `null`, absent or an
|
|
334
|
+
* invalid value means the default layout. Saved through
|
|
335
|
+
* `host.saveSettings({ toolbarLayout })`; `null` clears a stored layout
|
|
336
|
+
* (Reset to Default). Hand-edited values are normalized on read.
|
|
337
|
+
*/
|
|
338
|
+
toolbarLayout?: ToolbarLayout | null;
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* A settings patch. Core-owned keys are typed; a host's own sections in the
|
|
342
|
+
* Settings modal (see `extraSettingsSections`) add their own keys, which pass
|
|
343
|
+
* through to `host.saveSettings` untouched.
|
|
344
|
+
*/
|
|
345
|
+
type MikeDownSettingsPatch = Partial<MikeDownSettings> & Record<string, unknown>;
|
|
346
|
+
/**
|
|
347
|
+
* Feature switches. A feature that needs a host method (wikilinks, tags,
|
|
348
|
+
* images, export) is also off when that method is absent.
|
|
349
|
+
*/
|
|
350
|
+
interface MikeDownFeatures {
|
|
351
|
+
/** Formatting toolbar. Default on. */
|
|
352
|
+
toolbar: boolean;
|
|
353
|
+
/** Outline / Properties / Backlinks / Tags sidebar. Default off. */
|
|
354
|
+
sidebar: boolean;
|
|
355
|
+
/** CodeMirror source view (Cmd+/). Default on. */
|
|
356
|
+
sourceMode: boolean;
|
|
357
|
+
/** `/` command menu. Default on. */
|
|
358
|
+
slashCommands: boolean;
|
|
359
|
+
/** Spell checking. Default on, but inert unless `spellcheckDictionaryUrl` is set. */
|
|
360
|
+
spellcheck: boolean;
|
|
361
|
+
/** KaTeX math rendering. Default on. */
|
|
362
|
+
math: boolean;
|
|
363
|
+
/** Mermaid diagram rendering. Default on. */
|
|
364
|
+
mermaid: boolean;
|
|
365
|
+
/** Support entry point in the sidebar footer (VS Code only). Default off. */
|
|
366
|
+
supportCard: boolean;
|
|
367
|
+
/** Find and replace bar (Cmd+F / Cmd+H). Default on. */
|
|
368
|
+
findReplace: boolean;
|
|
369
|
+
/** Collapsible frontmatter block above the document. Default on. */
|
|
370
|
+
frontmatter: boolean;
|
|
371
|
+
/** AI features and the AI settings tab. Default on, but inert unless `host.ai` is set. */
|
|
372
|
+
ai: boolean;
|
|
373
|
+
/**
|
|
374
|
+
* "Customize Toolbar" entry points and the Toolbar section in Settings.
|
|
375
|
+
* Default on. Off keeps the toolbar fixed for the user; a `toolbarLayout`
|
|
376
|
+
* setting still applies.
|
|
377
|
+
*/
|
|
378
|
+
customizeToolbar: boolean;
|
|
379
|
+
}
|
|
380
|
+
declare const DEFAULT_FEATURES: MikeDownFeatures;
|
|
381
|
+
/** Row builders the Settings modal hands to host sections, so they match. */
|
|
382
|
+
interface MikeDownSettingsSectionContext {
|
|
383
|
+
makeRow(label: string, description: string, layout?: 'inline' | 'stacked'): HTMLElement;
|
|
384
|
+
makeGroup(...rows: HTMLElement[]): HTMLDivElement;
|
|
385
|
+
makeFieldLabel(text: string, hint: string, layout?: 'inline' | 'stacked'): HTMLLabelElement;
|
|
386
|
+
makeCheckboxRow(label: string, description: string, current: boolean): {
|
|
387
|
+
row: HTMLElement;
|
|
388
|
+
input: HTMLInputElement;
|
|
389
|
+
};
|
|
390
|
+
makeSelectRow<T extends string>(label: string, description: string, current: T, options: Array<{
|
|
391
|
+
value: T;
|
|
392
|
+
label: string;
|
|
393
|
+
}>): {
|
|
394
|
+
row: HTMLElement;
|
|
395
|
+
select: HTMLSelectElement;
|
|
396
|
+
};
|
|
397
|
+
/** Close the modal without saving. */
|
|
398
|
+
close(): void;
|
|
399
|
+
/** Open an external link through the host (`host.openLink`). Absent: links are plain anchors. */
|
|
400
|
+
openLink?: (href: string) => void;
|
|
401
|
+
}
|
|
402
|
+
interface MikeDownSettingsSectionBuild {
|
|
403
|
+
/** Rows appended to the tab, in order. */
|
|
404
|
+
rows: HTMLElement[];
|
|
405
|
+
/** Values merged into the patch sent to `host.saveSettings` on Save. */
|
|
406
|
+
collect?(): Record<string, unknown>;
|
|
407
|
+
/** Runs after Save, once the patch was sent. */
|
|
408
|
+
onSaved?(): void;
|
|
409
|
+
/** Runs when the modal closes without saving (close button, Escape, backdrop, reopen, destroy). */
|
|
410
|
+
onDiscarded?(): void;
|
|
411
|
+
}
|
|
412
|
+
/** A host-owned block of rows in the Settings modal. */
|
|
413
|
+
interface MikeDownSettingsSection {
|
|
414
|
+
/** Core tab id ('appearance', 'behavior', 'markdown', 'spelling', 'hotkeys') or a new tab id. */
|
|
415
|
+
tab: string;
|
|
416
|
+
/** Label for a new tab. Ignored for core tabs. */
|
|
417
|
+
tabLabel?: string;
|
|
418
|
+
/** Insert a new tab after this tab id. Default: after the last tab. */
|
|
419
|
+
afterTab?: string;
|
|
420
|
+
/** Extra class on a new tab's panel (e.g. 'settings-panel--about'). */
|
|
421
|
+
panelClassName?: string;
|
|
422
|
+
/**
|
|
423
|
+
* Where the rows go inside the tab: before the core rows, after them
|
|
424
|
+
* (default), or after the core row with this setting key.
|
|
425
|
+
*/
|
|
426
|
+
placement?: 'start' | 'end' | {
|
|
427
|
+
after: keyof MikeDownSettings;
|
|
428
|
+
};
|
|
429
|
+
build(ctx: MikeDownSettingsSectionContext): MikeDownSettingsSectionBuild;
|
|
430
|
+
}
|
|
431
|
+
interface MikeDownOptions {
|
|
432
|
+
host: MikeDownHost;
|
|
433
|
+
/** Loaded as the pristine baseline. */
|
|
434
|
+
initialMarkdown?: string;
|
|
435
|
+
/** Initial core settings. */
|
|
436
|
+
settings?: Partial<MikeDownSettings>;
|
|
437
|
+
features?: Partial<MikeDownFeatures>;
|
|
438
|
+
/** Overrides `settings.editorTheme`. */
|
|
439
|
+
theme?: 'light' | 'dark' | 'auto';
|
|
440
|
+
readOnly?: boolean;
|
|
441
|
+
/** Base URL of the spell-check dictionaries (contains `en/` and `en-GB/`). */
|
|
442
|
+
spellcheckDictionaryUrl?: string;
|
|
443
|
+
/** Host sections in the Settings modal. */
|
|
444
|
+
extraSettingsSections?: MikeDownSettingsSection[];
|
|
445
|
+
/** Text beside the Settings modal's Save button. */
|
|
446
|
+
settingsFooterNote?: string;
|
|
447
|
+
/**
|
|
448
|
+
* True when the host binds editor shortcuts itself, as the VS Code
|
|
449
|
+
* keybinding does for Cmd/Ctrl+/. The core then leaves `Mod-/` alone so the
|
|
450
|
+
* source toggle never fires twice. Default false: the core binds it, in both
|
|
451
|
+
* the rich editor and source mode.
|
|
452
|
+
*/
|
|
453
|
+
hostOwnsShortcuts?: boolean;
|
|
454
|
+
/** Empty-document placeholder. Default: "Type / for commands…" or "Start writing…". */
|
|
455
|
+
placeholder?: string;
|
|
456
|
+
/** `id` of the editable surface (the contenteditable, and the source view's content). */
|
|
457
|
+
id?: string;
|
|
458
|
+
/** Accessible name of the editable surface. Default "Document text". */
|
|
459
|
+
ariaLabel?: string;
|
|
460
|
+
/** Id of the element that names the editable surface. Wins over `ariaLabel`'s default. */
|
|
461
|
+
ariaLabelledBy?: string;
|
|
462
|
+
/**
|
|
463
|
+
* Put `role="main"` on the editor container. Default true (VS Code, Desktop).
|
|
464
|
+
* Embedded form fields pass false, since a field is not a page landmark.
|
|
465
|
+
*/
|
|
466
|
+
landmark?: boolean;
|
|
467
|
+
}
|
|
468
|
+
type MikeDownCommand = 'toggleBold' | 'toggleItalic' | 'toggleStrike' | 'toggleHighlight' | 'toggleCode' | 'toggleBulletList' | 'toggleOrderedList' | 'toggleTaskList' | 'pasteWithoutFormatting' | 'openEmojiPicker' | 'undo' | 'redo' | 'toggleSource' | 'toggleSidebar' | 'openSettings'
|
|
469
|
+
/**
|
|
470
|
+
* Open the Settings modal on the AI tab (no-op without `host.ai`). With
|
|
471
|
+
* `{ page: true }`, open the full-window AI Engines page instead (engines
|
|
472
|
+
* and routing; hosts with an engine registry only, others get the tab).
|
|
473
|
+
*/
|
|
474
|
+
| 'openAiSettings'
|
|
475
|
+
/** Rewrite the selection with AI: opens the rewrite popover's choices (no-op without `host.ai`). */
|
|
476
|
+
| 'aiRewrite'
|
|
477
|
+
/** Explain the selection with AI: the read-only popover (no-op without `host.ai`). */
|
|
478
|
+
| 'aiExplain'
|
|
479
|
+
/** Translate with AI: the popover's language picker; with nothing selected, the whole document. */
|
|
480
|
+
| 'aiTranslate'
|
|
481
|
+
/** Summarize the document with AI: the popover streams a TL;DR, Insert puts it at the cursor (no-op without `host.ai`). */
|
|
482
|
+
| 'aiSummarize'
|
|
483
|
+
/** Suggest titles with AI: three candidates; a pick sets `title:`, the H1, or a new H1 (no-op without `host.ai`). */
|
|
484
|
+
| 'aiSuggestTitle'
|
|
485
|
+
/** Suggest properties with AI: the sidebar's Suggest (Properties shown and expanded); chips apply a title, description or tag (no-op without `host.ai`). */
|
|
486
|
+
| 'aiSuggestProperties' | 'copyAsRichText' | 'heading1' | 'heading2' | 'heading3' | 'heading4' | 'heading5' | 'heading6' | 'paragraph' | 'openFind' | 'openFindReplace' | 'insertTable' | 'insertLink' | 'insertImage' | 'zoomIn' | 'zoomOut' | 'zoomReset';
|
|
487
|
+
type MikeDownEvent = 'change' | 'focus' | 'blur' | 'ready';
|
|
488
|
+
/**
|
|
489
|
+
* Where the user is in the document: which view is showing, the caret and
|
|
490
|
+
* the scroll offset of that view. A host that keeps several documents in one
|
|
491
|
+
* editor (tabs) saves it when a tab deactivates and restores it when the tab
|
|
492
|
+
* comes back, or across sessions.
|
|
493
|
+
*/
|
|
494
|
+
interface MikeDownViewState {
|
|
495
|
+
sourceMode: boolean;
|
|
496
|
+
/** Caret position in the showing view: a ProseMirror position in rich text, a character offset in source mode. */
|
|
497
|
+
cursor: number;
|
|
498
|
+
/** Scroll offset of the showing view's scroller, in CSS pixels. */
|
|
499
|
+
scrollTop: number;
|
|
500
|
+
}
|
|
501
|
+
/** Sidebar layout and per-document section state pushed by the host. */
|
|
502
|
+
interface SidebarStateUpdate {
|
|
503
|
+
pref?: 'always' | 'never';
|
|
504
|
+
width?: number;
|
|
505
|
+
position?: 'left' | 'right';
|
|
506
|
+
sectionPrefs?: Record<string, boolean>;
|
|
507
|
+
}
|
|
508
|
+
/** Sidebar footer link (the VS Code support appeal uses it). */
|
|
509
|
+
interface SidebarFooterLink {
|
|
510
|
+
label: string;
|
|
511
|
+
dismissLabel: string;
|
|
512
|
+
dismissConfirmation: string;
|
|
513
|
+
onOpen(): void;
|
|
514
|
+
onDismiss(): void;
|
|
515
|
+
}
|
|
516
|
+
interface MikeDownEditorHandle {
|
|
517
|
+
/** Replace the document. `pristine` (default true) makes it the clean baseline. */
|
|
518
|
+
setMarkdown(markdown: string, opts?: {
|
|
519
|
+
pristine?: boolean;
|
|
520
|
+
}): void;
|
|
521
|
+
getMarkdown(): string;
|
|
522
|
+
focus(): void;
|
|
523
|
+
setReadOnly(readOnly: boolean): void;
|
|
524
|
+
setTheme(theme: 'light' | 'dark' | 'auto'): void;
|
|
525
|
+
/** Run a toolbar or keybinding command. `openSettings` takes `{ tab }`, `openAiSettings` takes `{ page }`. */
|
|
526
|
+
command(name: MikeDownCommand, args?: {
|
|
527
|
+
tab?: string;
|
|
528
|
+
page?: boolean;
|
|
529
|
+
}): void;
|
|
530
|
+
/** Apply settings without persisting them. */
|
|
531
|
+
updateSettings(patch: Partial<MikeDownSettings>): void;
|
|
532
|
+
/** The host saved the document; `content` (default: current markdown) is the new baseline. */
|
|
533
|
+
markSaved(content?: string): void;
|
|
534
|
+
/** Rendered HTML of the document (for export and print). */
|
|
535
|
+
getHtml(): string;
|
|
536
|
+
scrollToAnchor(slug: string): void;
|
|
537
|
+
/** Scroll to and flash the Nth link with this href. */
|
|
538
|
+
revealLink(href: string, occurrence?: number): void;
|
|
539
|
+
/**
|
|
540
|
+
* Select and scroll to a match in the markdown source: 1-based `line`,
|
|
541
|
+
* 1-based `column` in UTF-16 units, `length` of the match. Exact in source
|
|
542
|
+
* mode; in rich text the matched string is found again in the rendered text.
|
|
543
|
+
*/
|
|
544
|
+
revealText(line: number, column: number, length?: number): void;
|
|
545
|
+
/** Mark images rendered from `src` as missing or present again. */
|
|
546
|
+
setImageStatus(src: string, status: 'found' | 'missing', detail?: string): void;
|
|
547
|
+
/** Insert a link at the cursor (rich text or source mode). `text` defaults to the href. */
|
|
548
|
+
insertLink(href: string, text?: string): void;
|
|
549
|
+
/** Insert an image at the cursor, e.g. the result of `host.uploadImage` for a dropped file. */
|
|
550
|
+
insertImage(image: ImageInsertResult): void;
|
|
551
|
+
/**
|
|
552
|
+
* Files around the document changed: re-resolve `[[wikilinks]]`, re-check
|
|
553
|
+
* relative links and refresh file suggestions. Also call it after adding
|
|
554
|
+
* the knowledge-base host methods to a host that started without them.
|
|
555
|
+
*/
|
|
556
|
+
refreshLinks(): void;
|
|
557
|
+
setTags(tags: TagCount[]): void;
|
|
558
|
+
/** Push link suggestions without being asked (same data as `host.getLinkSuggestions`). */
|
|
559
|
+
setLinkSuggestions(suggestions: LinkSuggestion[]): void;
|
|
560
|
+
setBacklinks(items: BacklinkItem[]): void;
|
|
561
|
+
setDocMeta(meta: {
|
|
562
|
+
mtimeMs?: number | null;
|
|
563
|
+
}): void;
|
|
564
|
+
setSidebarState(state: SidebarStateUpdate): void;
|
|
565
|
+
/** Show or hide the sidebar footer link (requires `features.supportCard`). */
|
|
566
|
+
setSidebarFooterLink(link: SidebarFooterLink | null): void;
|
|
567
|
+
setDiffAvailable(available: boolean): void;
|
|
568
|
+
/**
|
|
569
|
+
* Show which engine served the last AI request in the sidebar's AI chip
|
|
570
|
+
* (`AI: local · oMLX · Qwen 3.8 Flash Next`). `viaFallback` adds
|
|
571
|
+
* "(fallback)". Null forgets it, so the chip shows the route again.
|
|
572
|
+
*/
|
|
573
|
+
setAiServed(served: AiServedBy | null, opts?: {
|
|
574
|
+
viaFallback?: boolean;
|
|
575
|
+
}): void;
|
|
576
|
+
/** Push engine statuses the host learned on its own (VS Code's `aiEngines` broadcast). */
|
|
577
|
+
setAiEngineStatuses(statuses: AiEngineStatus[]): void;
|
|
578
|
+
/** True while the Settings modal or another core modal is open. */
|
|
579
|
+
isModalOpen(): boolean;
|
|
580
|
+
/** Which view is showing, where the caret is and how far it is scrolled. */
|
|
581
|
+
getViewState(): MikeDownViewState;
|
|
582
|
+
/**
|
|
583
|
+
* Restore a saved view state: switches views when `sourceMode` differs,
|
|
584
|
+
* then places the caret (clamped to the document) and the scroll offset.
|
|
585
|
+
* Call it after `setMarkdown`. Missing fields keep their current value.
|
|
586
|
+
*/
|
|
587
|
+
setViewState(state: Partial<MikeDownViewState>): void;
|
|
588
|
+
/** Subscribe to an event. Returns an unsubscribe function. */
|
|
589
|
+
on(event: MikeDownEvent, fn: (...args: any[]) => void): () => void;
|
|
590
|
+
/** Tear down the editor and every listener it attached to window or document. */
|
|
591
|
+
destroy(): void;
|
|
592
|
+
/** The underlying TipTap editor. Escape hatch for tests and advanced hosts; not a stable API. */
|
|
593
|
+
readonly tiptap: Editor;
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
export { DEFAULT_FEATURES as D, NoopHost as N, DEFAULT_TOOLBAR_LAYOUT as d, normalizeToolbarLayout as y };
|
|
597
|
+
export type { BacklinkItem as B, ImageInsertResult as I, LinkCheckRequest as L, MikeDownSettingsSectionContext as M, SidebarFooterLink as S, TagCount as T, WikilinkResolution as W, MikeDownOptions as a, MikeDownEditorHandle as b, MikeDownHost as c, DiffBaseline as e, ImagePathMapping as f, ImageResizeRequest as g, ImageResizeResult as h, ImageUploadRequest as i, LinkOpenBehavior as j, LinkSuggestion as k, MikeDownCommand as l, MikeDownEvent as m, MikeDownFeatures as n, MikeDownSettings as o, MikeDownSettingsPatch as p, MikeDownSettingsSection as q, MikeDownSettingsSectionBuild as r, MikeDownSidebarPrefs as s, MikeDownStats as t, MikeDownViewState as u, NormalizationStyle as v, SidebarStateUpdate as w, ToolbarLayout as x };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mikedown/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "MikeDown WYSIWYG markdown editor core (TipTap + CodeMirror), framework-agnostic.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -19,6 +19,21 @@
|
|
|
19
19
|
"import": "./dist/index.js",
|
|
20
20
|
"default": "./dist/index.js"
|
|
21
21
|
},
|
|
22
|
+
"./binding": {
|
|
23
|
+
"types": "./dist/index.d.ts",
|
|
24
|
+
"import": "./dist/index.js",
|
|
25
|
+
"default": "./dist/index.js"
|
|
26
|
+
},
|
|
27
|
+
"./ai": {
|
|
28
|
+
"types": "./dist/ai/index.d.ts",
|
|
29
|
+
"import": "./dist/ai/index.js",
|
|
30
|
+
"default": "./dist/ai/index.js"
|
|
31
|
+
},
|
|
32
|
+
"./ai/engines-page": {
|
|
33
|
+
"types": "./dist/ai/engines-page.d.ts",
|
|
34
|
+
"import": "./dist/ai/engines-page.js",
|
|
35
|
+
"default": "./dist/ai/engines-page.js"
|
|
36
|
+
},
|
|
22
37
|
"./styles.css": "./dist/styles.css",
|
|
23
38
|
"./tokens.css": "./dist/tokens.css",
|
|
24
39
|
"./shared/*": {
|
|
@@ -111,7 +126,7 @@
|
|
|
111
126
|
},
|
|
112
127
|
"repository": {
|
|
113
128
|
"type": "git",
|
|
114
|
-
"url": "https://github.com/mikejoseph23/mikedown.git",
|
|
129
|
+
"url": "git+https://github.com/mikejoseph23/mikedown.git",
|
|
115
130
|
"directory": "packages/core"
|
|
116
131
|
}
|
|
117
132
|
}
|