@latentic/live-markdown 0.2.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 +31 -0
- package/README.md +28 -8
- package/dist/index.d.ts +86 -61
- package/dist/index.js +45 -24
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,36 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.3.0] - 2026-08-29
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- **A host can contribute extension modules.** `extensions?: readonly
|
|
8
|
+
MarkdownExtension[]` on the editor, merged in one pass with the built-ins and
|
|
9
|
+
host-last, so a module can deliberately override a construct and the merger
|
|
10
|
+
still warns when a node rule is redefined. Applies in source mode as well as
|
|
11
|
+
wysiwyg — a keymap is not a rendering concern. Read when an editor state is
|
|
12
|
+
built, so building the array inline cannot remount the editor.
|
|
13
|
+
|
|
14
|
+
Toolbar contributions now reach the host through the `toolbar` slot's
|
|
15
|
+
context; the merger always collected them and the component dropped them.
|
|
16
|
+
|
|
17
|
+
- `composeExtensions` is renamed **`mergeExtensions`**, with the old name kept
|
|
18
|
+
as a deprecated alias. "compose" read as the name of an app rather than as the
|
|
19
|
+
verb, which is the wrong signal for a package meant for many hosts.
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
|
|
23
|
+
- **A checked task box reads as checked in dark.** The tick used
|
|
24
|
+
`--cds-icon-on-color` — white in every theme — against a fill of
|
|
25
|
+
`--cds-icon-primary`, which inverts. In dark that was #ffffff on #f4f4f4, a
|
|
26
|
+
contrast ratio of 1.10. It now uses `--cds-background`, the inverse of the
|
|
27
|
+
fill by construction.
|
|
28
|
+
|
|
29
|
+
- **The task box is sized to the text.** 1rem beside 1rem text is as tall as the
|
|
30
|
+
whole em box; it now derives from its own `font-size: 0.875em`, with box, tick
|
|
31
|
+
and baseline offset all in `em` of that, and sits on the x-height instead of
|
|
32
|
+
hanging off the baseline.
|
|
33
|
+
|
|
3
34
|
## [0.2.0] - 2026-08-28
|
|
4
35
|
|
|
5
36
|
### Added
|
package/README.md
CHANGED
|
@@ -186,7 +186,8 @@ The `toolbar` render prop receives the live `EditorView`, so host buttons can dr
|
|
|
186
186
|
| `value` | `string` | — | The markdown content (controlled) |
|
|
187
187
|
| `onChange` | `(value: string, changes: DocumentTextChange[]) => void` | — | Called after edits, debounced |
|
|
188
188
|
| `mode` | `"wysiwyg" \| "source"` | `"wysiwyg"` | Rich rendering or raw markdown |
|
|
189
|
-
| `
|
|
189
|
+
| `extensions` | `readonly MarkdownExtension[]` | — | Host-contributed extension modules, merged after the built-ins |
|
|
190
|
+
| `toolbar` | `(ctx: { view, contributions }) => ReactNode` | — | Host-rendered toolbar, given the live editor view and any toolbar items the extensions contributed |
|
|
190
191
|
| `selectionActions` | `(ctx: { selection, dismiss }) => ReactNode` | — | Host-rendered actions for the current selection (e.g. a comment bubble) |
|
|
191
192
|
| `linkTargets` | `ReadonlySet<string>` | — | Known file paths for wikilink resolution |
|
|
192
193
|
| `onNavigateToLink` | `(path: string) => void` | — | Called on Cmd/Ctrl-click of an internal link |
|
|
@@ -209,13 +210,32 @@ Built-in extensions:
|
|
|
209
210
|
- `tableExtension` — GFM tables with cell navigation
|
|
210
211
|
- `wikilinkExtension` — `[[wikilink]]` rendering and navigation
|
|
211
212
|
|
|
213
|
+
The built-ins load themselves. To add your own, hand the editor your modules:
|
|
214
|
+
|
|
215
|
+
```tsx
|
|
216
|
+
<CodeMirrorMarkdownEditor value={md} onChange={setMd} extensions={[myExtension]} />
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
They are merged **after** the built-ins, so a module can deliberately override a
|
|
220
|
+
construct — the merger warns when a node rule is redefined, so an accidental
|
|
221
|
+
shadow is not silent. Modules apply in source mode as well as wysiwyg: a keymap
|
|
222
|
+
or a plain CM6 extension is not a markdown-rendering concern, and node rules
|
|
223
|
+
simply go unread while the painter is off.
|
|
224
|
+
|
|
225
|
+
The prop is read when an editor state is built, not on every render, so building
|
|
226
|
+
the array inline costs nothing and cannot remount the editor. Changing it
|
|
227
|
+
mid-session takes effect at the next rebuild.
|
|
228
|
+
|
|
229
|
+
To merge modules yourself — composing a preset, or feeding a CodeMirror view you
|
|
230
|
+
own — `mergeExtensions` is the same function the editor uses:
|
|
231
|
+
|
|
212
232
|
```tsx
|
|
213
|
-
import {
|
|
233
|
+
import { mergeExtensions, mathExtension, tableExtension } from "@latentic/live-markdown";
|
|
214
234
|
|
|
215
|
-
const
|
|
216
|
-
//
|
|
217
|
-
//
|
|
218
|
-
//
|
|
235
|
+
const merged = mergeExtensions([mathExtension, tableExtension]);
|
|
236
|
+
// merged.extensions — CM6 Extension[] (each module's node rules ride along via
|
|
237
|
+
// a facet, so this is all a view needs)
|
|
238
|
+
// merged.toolbar — merged ToolbarContribution[]
|
|
219
239
|
```
|
|
220
240
|
|
|
221
241
|
### A custom extension
|
|
@@ -223,7 +243,7 @@ const composed = composeExtensions([mathExtension, tableExtension]);
|
|
|
223
243
|
A rule is one function per Lezer node name, returning how that node paints. The `mark` combinator covers the common "style this span" case. Rules merge last-wins, so an extension can introduce a construct from its own grammar or deliberately restyle a built-in one:
|
|
224
244
|
|
|
225
245
|
```tsx
|
|
226
|
-
import {
|
|
246
|
+
import { mark, type MarkdownExtension } from "@latentic/live-markdown";
|
|
227
247
|
|
|
228
248
|
const fancyEmphasis: MarkdownExtension = {
|
|
229
249
|
name: "fancy-emphasis",
|
|
@@ -234,7 +254,7 @@ const fancyEmphasis: MarkdownExtension = {
|
|
|
234
254
|
},
|
|
235
255
|
};
|
|
236
256
|
|
|
237
|
-
|
|
257
|
+
<CodeMirrorMarkdownEditor value={md} onChange={setMd} extensions={[fancyEmphasis]} />
|
|
238
258
|
```
|
|
239
259
|
|
|
240
260
|
`Paint` is a closed set — line class, span mark, hide, widget, or nothing — while node names grow, so styling a construct is always one rule in one place.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
3
|
import * as _codemirror_view from '@codemirror/view';
|
|
4
|
-
import { Decoration, ViewPlugin, DecorationSet, ViewUpdate, EditorView, Command
|
|
4
|
+
import { Decoration, ViewPlugin, DecorationSet, ViewUpdate, KeyBinding, EditorView, Command } from '@codemirror/view';
|
|
5
5
|
import * as _codemirror_state from '@codemirror/state';
|
|
6
6
|
import { EditorState, Facet, Extension } from '@codemirror/state';
|
|
7
7
|
import { syntaxTree } from '@codemirror/language';
|
|
@@ -384,6 +384,71 @@ type CommentOnExcerpt = (excerpt: {
|
|
|
384
384
|
range: SourceRange;
|
|
385
385
|
}, anchor: CommentAnchor) => void;
|
|
386
386
|
|
|
387
|
+
interface ToolbarContribution {
|
|
388
|
+
readonly id: string;
|
|
389
|
+
readonly group: "heading" | "format" | "block" | "insert" | string;
|
|
390
|
+
readonly label: string;
|
|
391
|
+
readonly icon: ReactNode;
|
|
392
|
+
readonly shortcut?: string;
|
|
393
|
+
readonly isActive?: (caretContext: CaretContextSnapshot) => boolean;
|
|
394
|
+
readonly run: (view: _codemirror_view.EditorView) => void;
|
|
395
|
+
}
|
|
396
|
+
interface CaretContextSnapshot {
|
|
397
|
+
readonly bold: boolean;
|
|
398
|
+
readonly italic: boolean;
|
|
399
|
+
readonly code: boolean;
|
|
400
|
+
readonly link: boolean;
|
|
401
|
+
readonly heading: 1 | 2 | 3 | 4 | 5 | 6 | 0;
|
|
402
|
+
readonly bulletList: boolean;
|
|
403
|
+
readonly orderedList: boolean;
|
|
404
|
+
readonly blockquote: boolean;
|
|
405
|
+
}
|
|
406
|
+
interface MarkdownExtension {
|
|
407
|
+
readonly name: string;
|
|
408
|
+
readonly version: string;
|
|
409
|
+
readonly description?: string;
|
|
410
|
+
/** Node rules for constructs this extension's grammar introduces (or
|
|
411
|
+
* deliberately overrides) — merged into the decoration painter via
|
|
412
|
+
* `nodeRulesFacet`, so an extension never edits the base table. */
|
|
413
|
+
readonly rules?: NodeRules;
|
|
414
|
+
readonly extensions?: Extension[];
|
|
415
|
+
readonly keymap?: KeyBinding[];
|
|
416
|
+
readonly toolbar?: ToolbarContribution[];
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
interface ComposedExtension {
|
|
420
|
+
extensions: Extension[];
|
|
421
|
+
toolbar: ToolbarContribution[];
|
|
422
|
+
}
|
|
423
|
+
/**
|
|
424
|
+
* Merge extension modules into one set of CodeMirror extensions plus the
|
|
425
|
+
* toolbar items they contribute. Later modules win: a host's rules are applied
|
|
426
|
+
* after the built-ins, so it can deliberately override a construct.
|
|
427
|
+
*/
|
|
428
|
+
declare function mergeExtensions(modules: readonly MarkdownExtension[]): ComposedExtension;
|
|
429
|
+
/**
|
|
430
|
+
* @deprecated Renamed to {@link mergeExtensions}. "compose" reads as the app
|
|
431
|
+
* this package was extracted from rather than as the verb; the editor is meant
|
|
432
|
+
* for more hosts than that one. Kept as an alias so the rename is not breaking.
|
|
433
|
+
*/
|
|
434
|
+
declare const composeExtensions: typeof mergeExtensions;
|
|
435
|
+
|
|
436
|
+
declare const highlightExtension: MarkdownExtension;
|
|
437
|
+
|
|
438
|
+
declare const footnoteExtension: MarkdownExtension;
|
|
439
|
+
|
|
440
|
+
declare const mathExtension: MarkdownExtension;
|
|
441
|
+
|
|
442
|
+
declare const mermaidExtension: MarkdownExtension;
|
|
443
|
+
|
|
444
|
+
/**
|
|
445
|
+
* A FACTORY, not a const: each composition gets its own editing surface (the
|
|
446
|
+
* one-active-edit state), so two mounted editors can never share a cell edit.
|
|
447
|
+
*/
|
|
448
|
+
declare function tableExtension(): MarkdownExtension;
|
|
449
|
+
|
|
450
|
+
declare const wikilinkExtension: MarkdownExtension;
|
|
451
|
+
|
|
387
452
|
type CodeMirrorEditorMode = "wysiwyg" | "source";
|
|
388
453
|
/** A non-empty editor selection, in document byte offsets. */
|
|
389
454
|
interface EditorSelectionSnapshot {
|
|
@@ -399,13 +464,27 @@ interface CodeMirrorMarkdownEditorProps {
|
|
|
399
464
|
linkTargets?: ReadonlySet<string>;
|
|
400
465
|
onNavigateToLink?: (path: string) => void;
|
|
401
466
|
/**
|
|
402
|
-
*
|
|
403
|
-
*
|
|
404
|
-
*
|
|
405
|
-
*
|
|
467
|
+
* Extension modules contributed by the host, merged AFTER the built-ins so a
|
|
468
|
+
* host can deliberately override a construct (the merger warns when a node
|
|
469
|
+
* rule is redefined).
|
|
470
|
+
*
|
|
471
|
+
* Read when an editor state is built — on mount, and on the swaps that
|
|
472
|
+
* rebuild one — not on every render, so passing a fresh array each time costs
|
|
473
|
+
* nothing and cannot remount the editor. Changing it mid-session therefore
|
|
474
|
+
* takes effect at the next rebuild.
|
|
475
|
+
*
|
|
476
|
+
* Applies in BOTH modes: a module's node rules simply go unread while the
|
|
477
|
+
* decoration painter is off, but its keymaps and plain CodeMirror extensions
|
|
478
|
+
* are not markdown-rendering concerns and should not be silently dropped in
|
|
479
|
+
* source mode.
|
|
406
480
|
*/
|
|
481
|
+
extensions?: readonly MarkdownExtension[];
|
|
482
|
+
/** Host-rendered toolbar. `contributions` carries the toolbar items the
|
|
483
|
+
* extension modules asked for; the host decides whether and how to render
|
|
484
|
+
* them alongside its own. */
|
|
407
485
|
toolbar?: (ctx: {
|
|
408
486
|
view: EditorView;
|
|
487
|
+
contributions: readonly ToolbarContribution[];
|
|
409
488
|
}) => ReactNode;
|
|
410
489
|
/**
|
|
411
490
|
* Host-rendered actions for the current text selection (e.g. a comment / ask
|
|
@@ -456,7 +535,7 @@ interface CodeMirrorMarkdownEditorProps {
|
|
|
456
535
|
*/
|
|
457
536
|
onFlushReady?: (flush: (() => void) | null) => void;
|
|
458
537
|
}
|
|
459
|
-
declare function CodeMirrorMarkdownEditorInner({ mode, onChange, value, workspaceRoot, filePath, linkTargets, onNavigateToLink, toolbar, selectionActions, resolveImageSrc, saveImageBytes, onOpenExternalUrl, onCommentOnExcerpt, renderClipboardHtml, onAfterContentSwap, onFlushReady, }: CodeMirrorMarkdownEditorProps): react.JSX.Element;
|
|
538
|
+
declare function CodeMirrorMarkdownEditorInner({ mode, onChange, value, workspaceRoot, filePath, linkTargets, onNavigateToLink, extensions: hostExtensions, toolbar, selectionActions, resolveImageSrc, saveImageBytes, onOpenExternalUrl, onCommentOnExcerpt, renderClipboardHtml, onAfterContentSwap, onFlushReady, }: CodeMirrorMarkdownEditorProps): react.JSX.Element;
|
|
460
539
|
/**
|
|
461
540
|
* Memoised export — same reason as the Tiptap editor. AppShell
|
|
462
541
|
* re-renders on every chat-thread token; without memoisation each
|
|
@@ -504,60 +583,6 @@ declare const blockCommands: {
|
|
|
504
583
|
*/
|
|
505
584
|
declare function onEditorUpdate(view: EditorView, fn: (update: ViewUpdate) => void): () => void;
|
|
506
585
|
|
|
507
|
-
interface ToolbarContribution {
|
|
508
|
-
readonly id: string;
|
|
509
|
-
readonly group: "heading" | "format" | "block" | "insert" | string;
|
|
510
|
-
readonly label: string;
|
|
511
|
-
readonly icon: ReactNode;
|
|
512
|
-
readonly shortcut?: string;
|
|
513
|
-
readonly isActive?: (caretContext: CaretContextSnapshot) => boolean;
|
|
514
|
-
readonly run: (view: _codemirror_view.EditorView) => void;
|
|
515
|
-
}
|
|
516
|
-
interface CaretContextSnapshot {
|
|
517
|
-
readonly bold: boolean;
|
|
518
|
-
readonly italic: boolean;
|
|
519
|
-
readonly code: boolean;
|
|
520
|
-
readonly link: boolean;
|
|
521
|
-
readonly heading: 1 | 2 | 3 | 4 | 5 | 6 | 0;
|
|
522
|
-
readonly bulletList: boolean;
|
|
523
|
-
readonly orderedList: boolean;
|
|
524
|
-
readonly blockquote: boolean;
|
|
525
|
-
}
|
|
526
|
-
interface MarkdownExtension {
|
|
527
|
-
readonly name: string;
|
|
528
|
-
readonly version: string;
|
|
529
|
-
readonly description?: string;
|
|
530
|
-
/** Node rules for constructs this extension's grammar introduces (or
|
|
531
|
-
* deliberately overrides) — merged into the decoration painter via
|
|
532
|
-
* `nodeRulesFacet`, so an extension never edits the base table. */
|
|
533
|
-
readonly rules?: NodeRules;
|
|
534
|
-
readonly extensions?: Extension[];
|
|
535
|
-
readonly keymap?: KeyBinding[];
|
|
536
|
-
readonly toolbar?: ToolbarContribution[];
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
interface ComposedExtension {
|
|
540
|
-
extensions: Extension[];
|
|
541
|
-
toolbar: ToolbarContribution[];
|
|
542
|
-
}
|
|
543
|
-
declare function composeExtensions(modules: readonly MarkdownExtension[]): ComposedExtension;
|
|
544
|
-
|
|
545
|
-
declare const highlightExtension: MarkdownExtension;
|
|
546
|
-
|
|
547
|
-
declare const footnoteExtension: MarkdownExtension;
|
|
548
|
-
|
|
549
|
-
declare const mathExtension: MarkdownExtension;
|
|
550
|
-
|
|
551
|
-
declare const mermaidExtension: MarkdownExtension;
|
|
552
|
-
|
|
553
|
-
/**
|
|
554
|
-
* A FACTORY, not a const: each composition gets its own editing surface (the
|
|
555
|
-
* one-active-edit state), so two mounted editors can never share a cell edit.
|
|
556
|
-
*/
|
|
557
|
-
declare function tableExtension(): MarkdownExtension;
|
|
558
|
-
|
|
559
|
-
declare const wikilinkExtension: MarkdownExtension;
|
|
560
|
-
|
|
561
586
|
/**
|
|
562
587
|
* Mermaid rendering, decoupled from CodeMirror — shared by the editor widget,
|
|
563
588
|
* the document export (which ships the SVG to the backend), and the clipboard
|
|
@@ -852,4 +877,4 @@ interface ResolveWorkspaceLinkOptions {
|
|
|
852
877
|
}
|
|
853
878
|
declare function resolveWorkspaceLink(href: string, options: ResolveWorkspaceLinkOptions): ResolvedWorkspaceLink | null;
|
|
854
879
|
|
|
855
|
-
export { type CaretContextSnapshot, type CodeMirrorEditorMode, CodeMirrorMarkdownEditor, type CodeMirrorMarkdownEditorProps, type ComposedExtension, type DocumentTextChange, type EditorSelectionSnapshot, type Frontmatter, type FrontmatterValue, type HighlightedSpan, IMAGE_EDIT_ALT_EVENT, type ImageEditAltEventDetail, type ImageInsertOptions, type ImageInsertResult, type ImageResolveContext, type InlineScanMatch, type InlineScanRule, type MarkdownDocument, type MarkdownExtension, type MermaidRenderResult, type NodeContext, type NodeRule, type NodeRules, type OpenExternalUrl, type Paint, type ResolveImageSrc, type ResolveWorkspaceLinkOptions, type ResolvedWorkspaceLink, type SaveImageBytes, type SourceRange, type ToolbarContribution, blockCommands, buildImageMarkdown, composeExtensions, computeFileDir, defaultResolveImageSrc, dirnamePath, editorBaseTheme, escapeAttr, escapeText, extractImageBlobs, extractImageFiles, footnoteExtension, formatCommands, getCachedMermaidPng, hasUriScheme, headingLine, hideAlways, highlightExtension, highlightFenceSpans, imageInsertHandlers, inlineScanRulesFacet, insertImageBlob, isAbsolutePath, isMermaidFenceInfo, joinPath, line, mark, markdownDecorationsPlugin, mathExtension, mermaidExtension, nodeRulesFacet, onEditorUpdate, parseFrontmatter, parseWikilinkBody, pickImageFileForCaret, raw, renderMermaidToSvg, resolveWikilinkTarget, resolveWorkspaceLink, scanInline, serializeMarkdown, setFrontmatterField, showImageActionMenu, structural, tableExtension, treeAt, warmMermaidPng, wikilinkExtension };
|
|
880
|
+
export { type CaretContextSnapshot, type CodeMirrorEditorMode, CodeMirrorMarkdownEditor, type CodeMirrorMarkdownEditorProps, type ComposedExtension, type DocumentTextChange, type EditorSelectionSnapshot, type Frontmatter, type FrontmatterValue, type HighlightedSpan, IMAGE_EDIT_ALT_EVENT, type ImageEditAltEventDetail, type ImageInsertOptions, type ImageInsertResult, type ImageResolveContext, type InlineScanMatch, type InlineScanRule, type MarkdownDocument, type MarkdownExtension, type MermaidRenderResult, type NodeContext, type NodeRule, type NodeRules, type OpenExternalUrl, type Paint, type ResolveImageSrc, type ResolveWorkspaceLinkOptions, type ResolvedWorkspaceLink, type SaveImageBytes, type SourceRange, type ToolbarContribution, blockCommands, buildImageMarkdown, composeExtensions, computeFileDir, defaultResolveImageSrc, dirnamePath, editorBaseTheme, escapeAttr, escapeText, extractImageBlobs, extractImageFiles, footnoteExtension, formatCommands, getCachedMermaidPng, hasUriScheme, headingLine, hideAlways, highlightExtension, highlightFenceSpans, imageInsertHandlers, inlineScanRulesFacet, insertImageBlob, isAbsolutePath, isMermaidFenceInfo, joinPath, line, mark, markdownDecorationsPlugin, mathExtension, mergeExtensions, mermaidExtension, nodeRulesFacet, onEditorUpdate, parseFrontmatter, parseWikilinkBody, pickImageFileForCaret, raw, renderMermaidToSvg, resolveWikilinkTarget, resolveWorkspaceLink, scanInline, serializeMarkdown, setFrontmatterField, showImageActionMenu, structural, tableExtension, treeAt, warmMermaidPng, wikilinkExtension };
|
package/dist/index.js
CHANGED
|
@@ -2615,23 +2615,30 @@ var editorBaseTheme = EditorView.theme({
|
|
|
2615
2615
|
marginRight: "0.3em",
|
|
2616
2616
|
fontWeight: "normal"
|
|
2617
2617
|
},
|
|
2618
|
-
// Task list checkbox — drawn as a Carbon checkbox, not the native control
|
|
2619
|
-
//
|
|
2620
|
-
//
|
|
2621
|
-
//
|
|
2622
|
-
//
|
|
2618
|
+
// Task list checkbox — drawn as a Carbon checkbox, not the native control.
|
|
2619
|
+
// `appearance: none` is what replaces WebKit's small rounded default; the box
|
|
2620
|
+
// then matches the design system rather than approximating it with an accent
|
|
2621
|
+
// colour over the native shape.
|
|
2622
|
+
//
|
|
2623
|
+
// Sized in `em`, not `rem`: a 1rem box beside 1rem text is as tall as the
|
|
2624
|
+
// whole em box, so it towered over lowercase letters, whose cap height is
|
|
2625
|
+
// nearer 0.7em. One knob — the checkbox's own `font-size` — drives the box,
|
|
2626
|
+
// the tick and the baseline offset, so the parts cannot drift apart, and the
|
|
2627
|
+
// control tracks the text if a list ever renders at another size.
|
|
2623
2628
|
".cm-task-checkbox": {
|
|
2624
2629
|
appearance: "none",
|
|
2625
2630
|
WebkitAppearance: "none",
|
|
2626
2631
|
boxSizing: "border-box",
|
|
2627
2632
|
position: "relative",
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2633
|
+
fontSize: "0.875em",
|
|
2634
|
+
width: "1em",
|
|
2635
|
+
height: "1em",
|
|
2636
|
+
margin: "0 0.45em 0 0",
|
|
2631
2637
|
cursor: "pointer",
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2638
|
+
// Centres the box on the x-height rather than hanging it off the baseline.
|
|
2639
|
+
verticalAlign: "-0.2em",
|
|
2640
|
+
border: "0.0625em solid var(--cds-icon-primary, #161616)",
|
|
2641
|
+
borderRadius: "0.0625em",
|
|
2635
2642
|
background: "transparent"
|
|
2636
2643
|
},
|
|
2637
2644
|
".cm-task-checkbox:checked": {
|
|
@@ -2639,15 +2646,20 @@ var editorBaseTheme = EditorView.theme({
|
|
|
2639
2646
|
borderColor: "var(--cds-icon-primary, #161616)"
|
|
2640
2647
|
},
|
|
2641
2648
|
// The tick: an L (right + bottom border) rotated 45° into a check.
|
|
2649
|
+
//
|
|
2650
|
+
// Drawn in `--cds-background`, NOT `--cds-icon-on-color`. "On color" means an
|
|
2651
|
+
// icon on a branded fill and is white in every theme, while the box here is
|
|
2652
|
+
// filled with `--cds-icon-primary` — which inverts. In dark that was a white
|
|
2653
|
+
// tick on a near-white box: a checked item read as unchecked.
|
|
2642
2654
|
".cm-task-checkbox:checked::after": {
|
|
2643
2655
|
content: "''",
|
|
2644
2656
|
position: "absolute",
|
|
2645
|
-
left: "0.
|
|
2646
|
-
top: "0.
|
|
2647
|
-
width: "0.
|
|
2648
|
-
height: "0.
|
|
2649
|
-
border: "solid var(--cds-
|
|
2650
|
-
borderWidth: "0 0.
|
|
2657
|
+
left: "0.3125em",
|
|
2658
|
+
top: "0.0625em",
|
|
2659
|
+
width: "0.25em",
|
|
2660
|
+
height: "0.5em",
|
|
2661
|
+
border: "solid var(--cds-background, #ffffff)",
|
|
2662
|
+
borderWidth: "0 0.125em 0.125em 0",
|
|
2651
2663
|
transform: "rotate(45deg)"
|
|
2652
2664
|
},
|
|
2653
2665
|
".cm-task-checkbox:focus-visible": {
|
|
@@ -4350,7 +4362,7 @@ function pickImageFileForCaret(view) {
|
|
|
4350
4362
|
};
|
|
4351
4363
|
input.click();
|
|
4352
4364
|
}
|
|
4353
|
-
function
|
|
4365
|
+
function mergeExtensions(modules) {
|
|
4354
4366
|
const extensions = [];
|
|
4355
4367
|
const toolbar = [];
|
|
4356
4368
|
const allKeyBindings = [];
|
|
@@ -4374,6 +4386,7 @@ function composeExtensions(modules) {
|
|
|
4374
4386
|
if (allKeyBindings.length) extensions.push(keymap.of(allKeyBindings));
|
|
4375
4387
|
return { extensions, toolbar };
|
|
4376
4388
|
}
|
|
4389
|
+
var composeExtensions = mergeExtensions;
|
|
4377
4390
|
var HIGHLIGHT_RE = /==([^=\n]+?)==/g;
|
|
4378
4391
|
var HIDE2 = Decoration.replace({});
|
|
4379
4392
|
var highlightMark = Decoration.mark({ class: "cm-highlight" });
|
|
@@ -5576,6 +5589,7 @@ function CodeMirrorMarkdownEditorInner({
|
|
|
5576
5589
|
filePath,
|
|
5577
5590
|
linkTargets,
|
|
5578
5591
|
onNavigateToLink,
|
|
5592
|
+
extensions: hostExtensions,
|
|
5579
5593
|
toolbar,
|
|
5580
5594
|
selectionActions,
|
|
5581
5595
|
resolveImageSrc,
|
|
@@ -5624,6 +5638,9 @@ function CodeMirrorMarkdownEditorInner({
|
|
|
5624
5638
|
const syncedHashRef = useRef(/* @__PURE__ */ new Map());
|
|
5625
5639
|
const currentFileRef = useRef(filePath);
|
|
5626
5640
|
const modeInitializedRef = useRef(decorationsEnabled);
|
|
5641
|
+
const hostExtensionsRef = useRef(hostExtensions);
|
|
5642
|
+
hostExtensionsRef.current = hostExtensions;
|
|
5643
|
+
const toolbarContributionsRef = useRef([]);
|
|
5627
5644
|
function buildExtensions() {
|
|
5628
5645
|
const base = [
|
|
5629
5646
|
history(),
|
|
@@ -5783,16 +5800,20 @@ function CodeMirrorMarkdownEditorInner({
|
|
|
5783
5800
|
];
|
|
5784
5801
|
if (decorationsEnabled) {
|
|
5785
5802
|
base.push(markdownDecorationsPlugin);
|
|
5786
|
-
|
|
5803
|
+
}
|
|
5804
|
+
const merged = mergeExtensions([
|
|
5805
|
+
...decorationsEnabled ? [
|
|
5787
5806
|
wikilinkExtension,
|
|
5788
5807
|
highlightExtension,
|
|
5789
5808
|
footnoteExtension,
|
|
5790
5809
|
mathExtension,
|
|
5791
5810
|
mermaidExtension,
|
|
5792
5811
|
tableExtension()
|
|
5793
|
-
]
|
|
5794
|
-
|
|
5795
|
-
|
|
5812
|
+
] : [],
|
|
5813
|
+
...hostExtensionsRef.current ?? []
|
|
5814
|
+
]);
|
|
5815
|
+
base.push(...merged.extensions);
|
|
5816
|
+
toolbarContributionsRef.current = merged.toolbar;
|
|
5796
5817
|
return base;
|
|
5797
5818
|
}
|
|
5798
5819
|
const buildExtensionsRef = useRef(buildExtensions);
|
|
@@ -5950,7 +5971,7 @@ function CodeMirrorMarkdownEditorInner({
|
|
|
5950
5971
|
view.dispatch({ selection: EditorSelection.cursor(head) });
|
|
5951
5972
|
}, []);
|
|
5952
5973
|
const toolbarNode = useMemo(
|
|
5953
|
-
() => viewForToolbar && toolbar ? toolbar({ view: viewForToolbar }) : null,
|
|
5974
|
+
() => viewForToolbar && toolbar ? toolbar({ view: viewForToolbar, contributions: toolbarContributionsRef.current }) : null,
|
|
5954
5975
|
[viewForToolbar, toolbar]
|
|
5955
5976
|
);
|
|
5956
5977
|
const selectionNode = useMemo(
|
|
@@ -5965,6 +5986,6 @@ function CodeMirrorMarkdownEditorInner({
|
|
|
5965
5986
|
}
|
|
5966
5987
|
var CodeMirrorMarkdownEditor = memo(CodeMirrorMarkdownEditorInner);
|
|
5967
5988
|
|
|
5968
|
-
export { CodeMirrorMarkdownEditor, IMAGE_EDIT_ALT_EVENT, blockCommands, buildImageMarkdown, composeExtensions, computeFileDir, defaultResolveImageSrc, dirnamePath, editorBaseTheme, escapeAttr, escapeText, extractImageBlobs, extractImageFiles, footnoteExtension, formatCommands, getCachedMermaidPng, hasUriScheme, headingLine, hideAlways, highlightExtension, highlightFenceSpans, imageInsertHandlers, inlineScanRulesFacet, insertImageBlob, isAbsolutePath, isMermaidFenceInfo, joinPath, line, mark, markdownDecorationsPlugin, mathExtension, mermaidExtension, nodeRulesFacet, onEditorUpdate, parseFrontmatter, parseWikilinkBody, pickImageFileForCaret, raw, renderMermaidToSvg, resolveWikilinkTarget, resolveWorkspaceLink, scanInline, serializeMarkdown, setFrontmatterField, showImageActionMenu, structural, tableExtension, treeAt, warmMermaidPng, wikilinkExtension };
|
|
5989
|
+
export { CodeMirrorMarkdownEditor, IMAGE_EDIT_ALT_EVENT, blockCommands, buildImageMarkdown, composeExtensions, computeFileDir, defaultResolveImageSrc, dirnamePath, editorBaseTheme, escapeAttr, escapeText, extractImageBlobs, extractImageFiles, footnoteExtension, formatCommands, getCachedMermaidPng, hasUriScheme, headingLine, hideAlways, highlightExtension, highlightFenceSpans, imageInsertHandlers, inlineScanRulesFacet, insertImageBlob, isAbsolutePath, isMermaidFenceInfo, joinPath, line, mark, markdownDecorationsPlugin, mathExtension, mergeExtensions, mermaidExtension, nodeRulesFacet, onEditorUpdate, parseFrontmatter, parseWikilinkBody, pickImageFileForCaret, raw, renderMermaidToSvg, resolveWikilinkTarget, resolveWorkspaceLink, scanInline, serializeMarkdown, setFrontmatterField, showImageActionMenu, structural, tableExtension, treeAt, warmMermaidPng, wikilinkExtension };
|
|
5969
5990
|
//# sourceMappingURL=index.js.map
|
|
5970
5991
|
//# sourceMappingURL=index.js.map
|