@latentic/live-markdown 0.2.0 → 0.3.1
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 +42 -0
- package/README.md +28 -8
- package/dist/index.d.ts +86 -61
- package/dist/index.js +52 -24
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,47 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.3.1] - 2026-08-29
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- **The task tick is centred in its box, and its stroke is lighter.** The tick
|
|
8
|
+
is an `L` rotated 45°, and the L's ink sits below and right of its own rect
|
|
9
|
+
centre — the rotation turns that diagonal offset into a purely downward one of
|
|
10
|
+
0.065em. The rect therefore has to ride that much above the box centre to look
|
|
11
|
+
centred: `top: 0.125em`, not the geometric `0.1875em`, which renders visibly
|
|
12
|
+
low. Stroke 0.125em → 0.1em, from 14.3% of the box to 11.4%.
|
|
13
|
+
|
|
14
|
+
## [0.3.0] - 2026-08-29
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
|
|
18
|
+
- **A host can contribute extension modules.** `extensions?: readonly
|
|
19
|
+
MarkdownExtension[]` on the editor, merged in one pass with the built-ins and
|
|
20
|
+
host-last, so a module can deliberately override a construct and the merger
|
|
21
|
+
still warns when a node rule is redefined. Applies in source mode as well as
|
|
22
|
+
wysiwyg — a keymap is not a rendering concern. Read when an editor state is
|
|
23
|
+
built, so building the array inline cannot remount the editor.
|
|
24
|
+
|
|
25
|
+
Toolbar contributions now reach the host through the `toolbar` slot's
|
|
26
|
+
context; the merger always collected them and the component dropped them.
|
|
27
|
+
|
|
28
|
+
- `composeExtensions` is renamed **`mergeExtensions`**, with the old name kept
|
|
29
|
+
as a deprecated alias. "compose" read as the name of an app rather than as the
|
|
30
|
+
verb, which is the wrong signal for a package meant for many hosts.
|
|
31
|
+
|
|
32
|
+
### Fixed
|
|
33
|
+
|
|
34
|
+
- **A checked task box reads as checked in dark.** The tick used
|
|
35
|
+
`--cds-icon-on-color` — white in every theme — against a fill of
|
|
36
|
+
`--cds-icon-primary`, which inverts. In dark that was #ffffff on #f4f4f4, a
|
|
37
|
+
contrast ratio of 1.10. It now uses `--cds-background`, the inverse of the
|
|
38
|
+
fill by construction.
|
|
39
|
+
|
|
40
|
+
- **The task box is sized to the text.** 1rem beside 1rem text is as tall as the
|
|
41
|
+
whole em box; it now derives from its own `font-size: 0.875em`, with box, tick
|
|
42
|
+
and baseline offset all in `em` of that, and sits on the x-height instead of
|
|
43
|
+
hanging off the baseline.
|
|
44
|
+
|
|
3
45
|
## [0.2.0] - 2026-08-28
|
|
4
46
|
|
|
5
47
|
### 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,27 @@ 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.
|
|
2654
|
+
//
|
|
2655
|
+
// `top` is the OPTICAL centre, not the geometric one. The L's ink sits below
|
|
2656
|
+
// and right of its own rect centre, and `rotate(45deg)` turns that diagonal
|
|
2657
|
+
// offset into a purely downward one — 0.065em of it — so the rect has to ride
|
|
2658
|
+
// that much higher for the tick to look centred. Geometric centring (0.1875em)
|
|
2659
|
+
// renders visibly low; the old 0.0625em was visibly high.
|
|
2642
2660
|
".cm-task-checkbox:checked::after": {
|
|
2643
2661
|
content: "''",
|
|
2644
2662
|
position: "absolute",
|
|
2645
|
-
left: "0.
|
|
2646
|
-
top: "0.
|
|
2647
|
-
width: "0.
|
|
2648
|
-
height: "0.
|
|
2649
|
-
border: "solid var(--cds-
|
|
2650
|
-
|
|
2663
|
+
left: "0.3125em",
|
|
2664
|
+
top: "0.125em",
|
|
2665
|
+
width: "0.25em",
|
|
2666
|
+
height: "0.5em",
|
|
2667
|
+
border: "solid var(--cds-background, #ffffff)",
|
|
2668
|
+
// 0.125em read as a heavy slab once the box shrank to 0.875em.
|
|
2669
|
+
borderWidth: "0 0.1em 0.1em 0",
|
|
2651
2670
|
transform: "rotate(45deg)"
|
|
2652
2671
|
},
|
|
2653
2672
|
".cm-task-checkbox:focus-visible": {
|
|
@@ -4350,7 +4369,7 @@ function pickImageFileForCaret(view) {
|
|
|
4350
4369
|
};
|
|
4351
4370
|
input.click();
|
|
4352
4371
|
}
|
|
4353
|
-
function
|
|
4372
|
+
function mergeExtensions(modules) {
|
|
4354
4373
|
const extensions = [];
|
|
4355
4374
|
const toolbar = [];
|
|
4356
4375
|
const allKeyBindings = [];
|
|
@@ -4374,6 +4393,7 @@ function composeExtensions(modules) {
|
|
|
4374
4393
|
if (allKeyBindings.length) extensions.push(keymap.of(allKeyBindings));
|
|
4375
4394
|
return { extensions, toolbar };
|
|
4376
4395
|
}
|
|
4396
|
+
var composeExtensions = mergeExtensions;
|
|
4377
4397
|
var HIGHLIGHT_RE = /==([^=\n]+?)==/g;
|
|
4378
4398
|
var HIDE2 = Decoration.replace({});
|
|
4379
4399
|
var highlightMark = Decoration.mark({ class: "cm-highlight" });
|
|
@@ -5576,6 +5596,7 @@ function CodeMirrorMarkdownEditorInner({
|
|
|
5576
5596
|
filePath,
|
|
5577
5597
|
linkTargets,
|
|
5578
5598
|
onNavigateToLink,
|
|
5599
|
+
extensions: hostExtensions,
|
|
5579
5600
|
toolbar,
|
|
5580
5601
|
selectionActions,
|
|
5581
5602
|
resolveImageSrc,
|
|
@@ -5624,6 +5645,9 @@ function CodeMirrorMarkdownEditorInner({
|
|
|
5624
5645
|
const syncedHashRef = useRef(/* @__PURE__ */ new Map());
|
|
5625
5646
|
const currentFileRef = useRef(filePath);
|
|
5626
5647
|
const modeInitializedRef = useRef(decorationsEnabled);
|
|
5648
|
+
const hostExtensionsRef = useRef(hostExtensions);
|
|
5649
|
+
hostExtensionsRef.current = hostExtensions;
|
|
5650
|
+
const toolbarContributionsRef = useRef([]);
|
|
5627
5651
|
function buildExtensions() {
|
|
5628
5652
|
const base = [
|
|
5629
5653
|
history(),
|
|
@@ -5783,16 +5807,20 @@ function CodeMirrorMarkdownEditorInner({
|
|
|
5783
5807
|
];
|
|
5784
5808
|
if (decorationsEnabled) {
|
|
5785
5809
|
base.push(markdownDecorationsPlugin);
|
|
5786
|
-
|
|
5810
|
+
}
|
|
5811
|
+
const merged = mergeExtensions([
|
|
5812
|
+
...decorationsEnabled ? [
|
|
5787
5813
|
wikilinkExtension,
|
|
5788
5814
|
highlightExtension,
|
|
5789
5815
|
footnoteExtension,
|
|
5790
5816
|
mathExtension,
|
|
5791
5817
|
mermaidExtension,
|
|
5792
5818
|
tableExtension()
|
|
5793
|
-
]
|
|
5794
|
-
|
|
5795
|
-
|
|
5819
|
+
] : [],
|
|
5820
|
+
...hostExtensionsRef.current ?? []
|
|
5821
|
+
]);
|
|
5822
|
+
base.push(...merged.extensions);
|
|
5823
|
+
toolbarContributionsRef.current = merged.toolbar;
|
|
5796
5824
|
return base;
|
|
5797
5825
|
}
|
|
5798
5826
|
const buildExtensionsRef = useRef(buildExtensions);
|
|
@@ -5950,7 +5978,7 @@ function CodeMirrorMarkdownEditorInner({
|
|
|
5950
5978
|
view.dispatch({ selection: EditorSelection.cursor(head) });
|
|
5951
5979
|
}, []);
|
|
5952
5980
|
const toolbarNode = useMemo(
|
|
5953
|
-
() => viewForToolbar && toolbar ? toolbar({ view: viewForToolbar }) : null,
|
|
5981
|
+
() => viewForToolbar && toolbar ? toolbar({ view: viewForToolbar, contributions: toolbarContributionsRef.current }) : null,
|
|
5954
5982
|
[viewForToolbar, toolbar]
|
|
5955
5983
|
);
|
|
5956
5984
|
const selectionNode = useMemo(
|
|
@@ -5965,6 +5993,6 @@ function CodeMirrorMarkdownEditorInner({
|
|
|
5965
5993
|
}
|
|
5966
5994
|
var CodeMirrorMarkdownEditor = memo(CodeMirrorMarkdownEditorInner);
|
|
5967
5995
|
|
|
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 };
|
|
5996
|
+
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
5997
|
//# sourceMappingURL=index.js.map
|
|
5970
5998
|
//# sourceMappingURL=index.js.map
|