@latentic/live-markdown 0.1.0 → 0.2.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 CHANGED
@@ -1,5 +1,34 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.2.0] - 2026-08-28
4
+
5
+ ### Added
6
+
7
+ - **A host can theme fenced-code syntax colours.** Each palette entry carries a
8
+ CSS custom property alongside its colour, and the editor paints
9
+ `var(--md-code-…, <One Light value>)`, so a dark theme can restyle code.
10
+ Previously impossible: the editor takes no `extensions` prop and the generated
11
+ highlight classes are content-hashed, leaving no seam at all.
12
+
13
+ The clipboard renderer deliberately keeps literal colours. Pasted HTML arrives
14
+ with no stylesheet, so a `var()` there resolves to nothing and pastes
15
+ colourless code into Google Docs or Word — and the document being pasted into
16
+ is white whatever theme the editor was in.
17
+
18
+ Roles are named individually (`--md-code-keyword`, `--md-code-string`, …) even
19
+ where two share a value, so one can be restyled without the other. A host that
20
+ sets no variables gets a byte-identical palette: the literal is the fallback.
21
+
22
+ ## [0.1.1] - 2026-08-24
23
+
24
+ ### Added
25
+
26
+ - `inlineScanRulesFacet`, `scanInline`, `escapeText`/`escapeAttr` and their
27
+ types are exported. 0.1.0 shipped the seam but left it unreachable: a
28
+ third-party extension could contribute a rule for a construct Lezer parses
29
+ (`nodeRulesFacet`, public since 0.0.1) but not for one it does not, which is
30
+ half a contract.
31
+
3
32
  ## [0.1.0] - 2026-08-24
4
33
 
5
34
  First release from the editor's own repository, and the first with CI on more
package/dist/index.d.ts CHANGED
@@ -160,6 +160,57 @@ declare function structural(why: string): NodeRule;
160
160
  */
161
161
  declare const nodeRulesFacet: Facet<Readonly<Record<string, NodeRule>>, Readonly<Record<string, NodeRule>>>;
162
162
 
163
+ /**
164
+ * Constructs Lezer never parses.
165
+ *
166
+ * Wikilinks, `==highlight==`, footnote references and `$math$` are not
167
+ * CommonMark, so no node exists for any of them and the editor finds each by
168
+ * scanning text (`codeContext.ts` documents the shared code guard). A renderer
169
+ * that walks the tree is therefore blind to all four — which is how a table cell
170
+ * came to show `$440 = 2 \times \frac{22}{7} \times r$` as literal source while
171
+ * the same expression rendered as mathematics in the paragraph above it.
172
+ *
173
+ * A feature contributes its pattern and its markup through this facet; the
174
+ * string renderers consult the facet and stay ignorant of what the constructs
175
+ * are. The decoration plugins keep their own viewport-scanning path — the two
176
+ * paths share the pattern, not the machinery, because one produces decorations
177
+ * over a live document and the other an HTML string.
178
+ */
179
+
180
+ interface InlineScanRule {
181
+ readonly name: string;
182
+ /** Global-flagged; the scanner drives `exec` and resets `lastIndex`. */
183
+ readonly pattern: RegExp;
184
+ /** Markup for one match. Escaping document text is the rule's job. */
185
+ render(match: RegExpExecArray): string;
186
+ /**
187
+ * Upgrade rendered markup to real DOM, after sanitisation. Only for a
188
+ * construct whose rendering is DOM rather than markup (KaTeX): the generated
189
+ * nodes bypass the sanitiser, so a hydrate reads inert text from the element
190
+ * it replaces and never trusts the document.
191
+ */
192
+ hydrate?(root: HTMLElement): void;
193
+ }
194
+ declare const inlineScanRulesFacet: Facet<InlineScanRule, readonly InlineScanRule[]>;
195
+ interface InlineScanMatch {
196
+ readonly from: number;
197
+ readonly to: number;
198
+ readonly html: string;
199
+ }
200
+ /**
201
+ * Every rule's matches in `text`, in document order, offset by `at`.
202
+ *
203
+ * Earliest wins, then longest — two constructs cannot both own one span, and
204
+ * the alternative (rule declaration order) would make the result depend on
205
+ * extension load order.
206
+ */
207
+ declare function scanInline(rules: readonly InlineScanRule[], text: string, at?: number): InlineScanMatch[];
208
+
209
+ /** Entity-escaping for the string renderers (table cells), which build HTML
210
+ * text rather than DOM and so must neutralise markup in document content. */
211
+ declare function escapeText(value: string): string;
212
+ declare function escapeAttr(value: string): string;
213
+
163
214
  /**
164
215
  * A syntax tree that reaches `pos`.
165
216
  *
@@ -801,4 +852,4 @@ interface ResolveWorkspaceLinkOptions {
801
852
  }
802
853
  declare function resolveWorkspaceLink(href: string, options: ResolveWorkspaceLinkOptions): ResolvedWorkspaceLink | null;
803
854
 
804
- 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 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, extractImageBlobs, extractImageFiles, footnoteExtension, formatCommands, getCachedMermaidPng, hasUriScheme, headingLine, hideAlways, highlightExtension, highlightFenceSpans, imageInsertHandlers, insertImageBlob, isAbsolutePath, isMermaidFenceInfo, joinPath, line, mark, markdownDecorationsPlugin, mathExtension, mermaidExtension, nodeRulesFacet, onEditorUpdate, parseFrontmatter, parseWikilinkBody, pickImageFileForCaret, raw, renderMermaidToSvg, resolveWikilinkTarget, resolveWorkspaceLink, serializeMarkdown, setFrontmatterField, showImageActionMenu, structural, tableExtension, treeAt, warmMermaidPng, wikilinkExtension };
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 };
package/dist/index.js CHANGED
@@ -443,23 +443,59 @@ function onEditorUpdate(view, fn) {
443
443
  };
444
444
  }
445
445
  var CODE_PALETTE = [
446
- { tag: [tags.keyword, tags.modifier, tags.operatorKeyword], color: "#a626a4" },
447
- { tag: [tags.string, tags.special(tags.string)], color: "#50a14f" },
448
- { tag: tags.comment, color: "#a0a1a7", fontStyle: "italic" },
449
- { tag: [tags.number, tags.bool, tags.null, tags.atom], color: "#986801" },
450
- { tag: [tags.function(tags.variableName), tags.function(tags.propertyName)], color: "#4078f2" },
451
- { tag: [tags.typeName, tags.className, tags.namespace], color: "#c18401" },
452
- { tag: tags.definition(tags.variableName), color: "#e45649" },
453
- { tag: tags.propertyName, color: "#4078f2" },
454
- { tag: [tags.tagName, tags.self], color: "#e45649" },
455
- { tag: tags.attributeName, color: "#986801" },
456
- { tag: [tags.regexp, tags.escape], color: "#0184bc" },
457
- { tag: tags.invalid, color: "#ca1243" }
446
+ {
447
+ tag: [tags.keyword, tags.modifier, tags.operatorKeyword],
448
+ color: "#a626a4",
449
+ cssVar: "--md-code-keyword"
450
+ },
451
+ {
452
+ tag: [tags.string, tags.special(tags.string)],
453
+ color: "#50a14f",
454
+ cssVar: "--md-code-string"
455
+ },
456
+ {
457
+ tag: tags.comment,
458
+ color: "#a0a1a7",
459
+ cssVar: "--md-code-comment",
460
+ fontStyle: "italic"
461
+ },
462
+ {
463
+ tag: [tags.number, tags.bool, tags.null, tags.atom],
464
+ color: "#986801",
465
+ cssVar: "--md-code-literal"
466
+ },
467
+ {
468
+ tag: [tags.function(tags.variableName), tags.function(tags.propertyName)],
469
+ color: "#4078f2",
470
+ cssVar: "--md-code-function"
471
+ },
472
+ {
473
+ tag: [tags.typeName, tags.className, tags.namespace],
474
+ color: "#c18401",
475
+ cssVar: "--md-code-type"
476
+ },
477
+ {
478
+ tag: tags.definition(tags.variableName),
479
+ color: "#e45649",
480
+ cssVar: "--md-code-variable"
481
+ },
482
+ { tag: tags.propertyName, color: "#4078f2", cssVar: "--md-code-property" },
483
+ { tag: [tags.tagName, tags.self], color: "#e45649", cssVar: "--md-code-tag" },
484
+ { tag: tags.attributeName, color: "#986801", cssVar: "--md-code-attribute" },
485
+ { tag: [tags.regexp, tags.escape], color: "#0184bc", cssVar: "--md-code-regexp" },
486
+ { tag: tags.invalid, color: "#ca1243", cssVar: "--md-code-invalid" }
458
487
  ];
488
+ function themedColor(spec) {
489
+ return `var(${spec.cssVar}, ${spec.color})`;
490
+ }
459
491
 
460
492
  // src/codemirror/code/codeHighlight.ts
461
493
  var style = HighlightStyle.define(
462
- CODE_PALETTE.map((spec) => ({ tag: spec.tag, color: spec.color, fontStyle: spec.fontStyle }))
494
+ CODE_PALETTE.map((spec) => ({
495
+ tag: spec.tag,
496
+ color: themedColor(spec),
497
+ fontStyle: spec.fontStyle
498
+ }))
463
499
  );
464
500
  var codeHighlight = syntaxHighlighting(style);
465
501
 
@@ -5929,6 +5965,6 @@ function CodeMirrorMarkdownEditorInner({
5929
5965
  }
5930
5966
  var CodeMirrorMarkdownEditor = memo(CodeMirrorMarkdownEditorInner);
5931
5967
 
5932
- export { CodeMirrorMarkdownEditor, IMAGE_EDIT_ALT_EVENT, blockCommands, buildImageMarkdown, composeExtensions, computeFileDir, defaultResolveImageSrc, dirnamePath, editorBaseTheme, extractImageBlobs, extractImageFiles, footnoteExtension, formatCommands, getCachedMermaidPng, hasUriScheme, headingLine, hideAlways, highlightExtension, highlightFenceSpans, imageInsertHandlers, insertImageBlob, isAbsolutePath, isMermaidFenceInfo, joinPath, line, mark, markdownDecorationsPlugin, mathExtension, mermaidExtension, nodeRulesFacet, onEditorUpdate, parseFrontmatter, parseWikilinkBody, pickImageFileForCaret, raw, renderMermaidToSvg, resolveWikilinkTarget, resolveWorkspaceLink, serializeMarkdown, setFrontmatterField, showImageActionMenu, structural, tableExtension, treeAt, warmMermaidPng, wikilinkExtension };
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 };
5933
5969
  //# sourceMappingURL=index.js.map
5934
5970
  //# sourceMappingURL=index.js.map