@vectojs/markdown 0.18.2 → 0.19.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/dist/Markdown.d.ts +48 -3
- package/dist/blockAffordances.d.ts +60 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +562 -61
- package/dist/index.mjs +560 -61
- package/dist/markdown-code.d.ts +136 -5
- package/dist/theme.d.ts +21 -0
- package/package.json +2 -2
package/dist/markdown-code.d.ts
CHANGED
|
@@ -2,6 +2,32 @@ import { type ContentProjection, type ContentProjectionHint, GlyphRasterAtlas, t
|
|
|
2
2
|
import { UIComponent } from '@vectojs/ui';
|
|
3
3
|
import { type MarkdownThemePresetName } from './markdown-presets';
|
|
4
4
|
import type { MarkdownTheme } from './theme';
|
|
5
|
+
/**
|
|
6
|
+
* Languages this build can highlight, for an app that wants to check before
|
|
7
|
+
* rendering. A language appears here when it has syntax, keywords, or both.
|
|
8
|
+
*/
|
|
9
|
+
export declare function highlightedLanguages(): string[];
|
|
10
|
+
/** Optional behaviour for {@link CodeBlock}. */
|
|
11
|
+
export interface CodeBlockOptions {
|
|
12
|
+
/**
|
|
13
|
+
* Draw a header band across the top of the block showing the language name.
|
|
14
|
+
*
|
|
15
|
+
* Off by default, and the default is not merely conservative: the band costs
|
|
16
|
+
* vertical space in every block of a document, and a label is worth that only
|
|
17
|
+
* where a document actually mixes languages. A single-language page gets the
|
|
18
|
+
* same word repeated down its length.
|
|
19
|
+
*
|
|
20
|
+
* Turning it on also RESERVES that space, which is what makes the block's
|
|
21
|
+
* own affordance controls stop overlapping the first line of code — measured
|
|
22
|
+
* before this existed: the controls occupied y 8-32 while line one occupied
|
|
23
|
+
* y 18-42, a 14px overlap in the default theme.
|
|
24
|
+
*
|
|
25
|
+
* The reserved height keeps `height` a pure function of line count (the
|
|
26
|
+
* invariant {@link CodeBlock.setWidth} documents); it only changes the
|
|
27
|
+
* constant term.
|
|
28
|
+
*/
|
|
29
|
+
showLanguage?: boolean;
|
|
30
|
+
}
|
|
5
31
|
/**
|
|
6
32
|
* A single self-rendering entity for fenced code blocks.
|
|
7
33
|
*
|
|
@@ -10,6 +36,14 @@ import type { MarkdownTheme } from './theme';
|
|
|
10
36
|
*/
|
|
11
37
|
export declare class CodeBlock extends UIComponent {
|
|
12
38
|
private lines;
|
|
39
|
+
/**
|
|
40
|
+
* Lexical state ENTERING each line, index-aligned with {@link lines}.
|
|
41
|
+
*
|
|
42
|
+
* Entering rather than leaving, so a streamed append can resume tokenizing at
|
|
43
|
+
* the prefix-reuse boundary by reading one entry instead of re-scanning the
|
|
44
|
+
* document for an unclosed block comment.
|
|
45
|
+
*/
|
|
46
|
+
private lineCarry;
|
|
13
47
|
private grid;
|
|
14
48
|
/** Raw (unhighlighted) lines of the last build, for prefix reuse in buildLines. */
|
|
15
49
|
private rawLines;
|
|
@@ -17,6 +51,19 @@ export declare class CodeBlock extends UIComponent {
|
|
|
17
51
|
private source;
|
|
18
52
|
/** Bumped by {@link buildLines} and {@link setSelectable}; read by `Scene`. */
|
|
19
53
|
private contentEpoch;
|
|
54
|
+
/**
|
|
55
|
+
* Horizontal scroll offset in local px, always in `[0, maxScrollX]`.
|
|
56
|
+
*
|
|
57
|
+
* Code does not wrap, so a line wider than the box would otherwise have an
|
|
58
|
+
* unreachable tail. This offset is subtracted from BOTH the painted cell x and
|
|
59
|
+
* the projected line x in the same frame — never one without the other, or the
|
|
60
|
+
* DOM selection carriers detach from the glyphs they are supposed to cover
|
|
61
|
+
* (the defect class `5cf7119` and `ee1de6f` fixed on the vertical axis).
|
|
62
|
+
*/
|
|
63
|
+
private scrollXValue;
|
|
64
|
+
/** Memoized widest prepared line, keyed by the grid identity it came from. */
|
|
65
|
+
private contentWidthGrid;
|
|
66
|
+
private contentWidthValue;
|
|
20
67
|
private lang;
|
|
21
68
|
private theme;
|
|
22
69
|
/**
|
|
@@ -28,6 +75,10 @@ export declare class CodeBlock extends UIComponent {
|
|
|
28
75
|
private pad;
|
|
29
76
|
private codeFont;
|
|
30
77
|
selectable: boolean;
|
|
78
|
+
/** Whether the language header band is drawn. See {@link CodeBlockOptions.showLanguage}. */
|
|
79
|
+
private showLanguage;
|
|
80
|
+
/** Font of the header label, resolved once from the theme. */
|
|
81
|
+
private langFont;
|
|
31
82
|
/**
|
|
32
83
|
* @param theme Any subset of {@link MarkdownTheme}, or the name of a built-in
|
|
33
84
|
* preset (see {@link MarkdownThemePresetName}). Accepting a partial theme
|
|
@@ -39,7 +90,70 @@ export declare class CodeBlock extends UIComponent {
|
|
|
39
90
|
* be constructed directly with a preset name without going through
|
|
40
91
|
* `Markdown`.
|
|
41
92
|
*/
|
|
42
|
-
constructor(code: string, lang: string, maxWidth: number, theme: MarkdownThemePresetName | MarkdownTheme, selectable?: boolean);
|
|
93
|
+
constructor(code: string, lang: string, maxWidth: number, theme: MarkdownThemePresetName | MarkdownTheme, selectable?: boolean, options?: CodeBlockOptions);
|
|
94
|
+
/**
|
|
95
|
+
* The language name shown in the header, or `''` when there is nothing to show.
|
|
96
|
+
*
|
|
97
|
+
* Normalized exactly as the highlighter normalizes its lookup key, so the label
|
|
98
|
+
* and the colouring can never disagree about which language this is: a fence
|
|
99
|
+
* may be written ` ```Bash ` or carry attributes (` ```ts title="a.ts" `), and
|
|
100
|
+
* the label has to be the language, not the raw info string.
|
|
101
|
+
*
|
|
102
|
+
* Lowercased for the same reason `streamdown` lowercases its own
|
|
103
|
+
* (`lib/code-block/header.tsx:15`): the fence's capitalization is incidental,
|
|
104
|
+
* and a document mixing ` ```JS ` with ` ```js ` should not render two
|
|
105
|
+
* different-looking labels for one language.
|
|
106
|
+
*/
|
|
107
|
+
private languageLabel;
|
|
108
|
+
/**
|
|
109
|
+
* Height in px of the header band, or `0` when it is off.
|
|
110
|
+
*
|
|
111
|
+
* The label sits in a band of its own rather than floating over the code,
|
|
112
|
+
* because a translucent overlay above real glyphs is unreadable at small sizes
|
|
113
|
+
* and would fight the horizontal scroll: the code slides under it, so any text
|
|
114
|
+
* drawn on top would collide with a different token every frame.
|
|
115
|
+
*/
|
|
116
|
+
private headerHeight;
|
|
117
|
+
/**
|
|
118
|
+
* Local y of the first line of code.
|
|
119
|
+
*
|
|
120
|
+
* Everything that positions a row — the painter, the projection, the grid's
|
|
121
|
+
* own origin — goes through this, so the header offset cannot be applied to
|
|
122
|
+
* one and forgotten on another. That class of mismatch is exactly what
|
|
123
|
+
* detaches selection carriers from the glyphs they cover.
|
|
124
|
+
*/
|
|
125
|
+
private contentTop;
|
|
126
|
+
/**
|
|
127
|
+
* Current horizontal scroll offset in local px, clamped to what the content
|
|
128
|
+
* currently allows.
|
|
129
|
+
*
|
|
130
|
+
* Clamped on READ, not only on write, because `setWidth()` may shrink the box
|
|
131
|
+
* after a scroll and is contractually forbidden from rebuilding anything. Both
|
|
132
|
+
* the painter and the projection read through here, which is what keeps the
|
|
133
|
+
* glyphs and the selection carriers on the same offset within a frame.
|
|
134
|
+
*/
|
|
135
|
+
get scrollX(): number;
|
|
136
|
+
/**
|
|
137
|
+
* Widest line's overflow past the padded box, i.e. the maximum useful
|
|
138
|
+
* {@link scrollX}. `0` when every line already fits.
|
|
139
|
+
*/
|
|
140
|
+
get maxScrollX(): number;
|
|
141
|
+
/**
|
|
142
|
+
* Widest prepared line, memoized against the grid that produced it.
|
|
143
|
+
*
|
|
144
|
+
* Read by {@link scrollX}, which both `render()` and `getContentProjection()`
|
|
145
|
+
* call every synced frame, so an O(lines) scan here would be an O(document) cost
|
|
146
|
+
* per frame on a long block — the exact shape the per-line projection window
|
|
147
|
+
* exists to avoid. The grid is rebuilt only when the content changes, so the
|
|
148
|
+
* cache key is identity of the grid object.
|
|
149
|
+
*/
|
|
150
|
+
private contentWidth;
|
|
151
|
+
/**
|
|
152
|
+
* Scroll horizontally to `x`, clamped to `[0, maxScrollX]`.
|
|
153
|
+
*
|
|
154
|
+
* @returns `this` for chaining.
|
|
155
|
+
*/
|
|
156
|
+
setScrollX(x: number): this;
|
|
43
157
|
/** Re-parse code content (e.g. for live editing). */
|
|
44
158
|
setCode(code: string, lang?: string): this;
|
|
45
159
|
/** Enable or disable browser-native selection for this code block. */
|
|
@@ -51,9 +165,13 @@ export declare class CodeBlock extends UIComponent {
|
|
|
51
165
|
* Deliberately does **not** rebuild the grid or the highlight, because code does
|
|
52
166
|
* not reflow: lines are placed on a fixed monospace grid at `col × cellWidth` and
|
|
53
167
|
* a long line overflows rather than wrapping, so `height` is a function of line
|
|
54
|
-
* *count* alone. The width
|
|
55
|
-
* change the glyph geometry — the source, the language, the font —
|
|
56
|
-
* {@link setCode} and invalidates the grid there.
|
|
168
|
+
* *count* alone. The width sizes the rounded background and the clip. Anything
|
|
169
|
+
* that would change the glyph geometry — the source, the language, the font —
|
|
170
|
+
* goes through {@link setCode} and invalidates the grid there.
|
|
171
|
+
*
|
|
172
|
+
* A narrower box can leave {@link scrollX} past the new end of travel. That is
|
|
173
|
+
* resolved by clamping on read rather than by adjusting anything here, so this
|
|
174
|
+
* method keeps costing nothing.
|
|
57
175
|
*
|
|
58
176
|
* @returns `this` for chaining.
|
|
59
177
|
*/
|
|
@@ -70,10 +188,23 @@ export declare class CodeBlock extends UIComponent {
|
|
|
70
188
|
*
|
|
71
189
|
* The last previously-seen line is deliberately NOT reused: a chunk usually
|
|
72
190
|
* lands mid-line, so that line's text (and therefore its tokenization) changes.
|
|
191
|
+
*
|
|
192
|
+
* Prefix reuse survives multi-line constructs because {@link lineCarry} records
|
|
193
|
+
* the state ENTERING each line, so resuming at the reuse boundary needs no
|
|
194
|
+
* rescan: a carried state is a pure function of the preceding text, and that
|
|
195
|
+
* text is byte-identical over the reused prefix by construction.
|
|
73
196
|
*/
|
|
74
197
|
private buildLines;
|
|
75
198
|
private ensureGrid;
|
|
76
|
-
/**
|
|
199
|
+
/**
|
|
200
|
+
* Not hit-testable, and deliberately still not `interactive`, even though the
|
|
201
|
+
* block now consumes wheel events to scroll.
|
|
202
|
+
*
|
|
203
|
+
* The wheel arrives from the content-projection div rather than from canvas
|
|
204
|
+
* hit-testing, so no a11y shadow node is needed. Creating one would place a
|
|
205
|
+
* `pointer-events: auto` element above the transparent text mirror and swallow
|
|
206
|
+
* the mousedown that starts a native drag-selection.
|
|
207
|
+
*/
|
|
77
208
|
isPointInside(): boolean;
|
|
78
209
|
render(r: IRenderer): void;
|
|
79
210
|
}
|
package/dist/theme.d.ts
CHANGED
|
@@ -121,6 +121,17 @@ export interface MarkdownTheme {
|
|
|
121
121
|
syntaxCommentColor?: string;
|
|
122
122
|
/** Code-block numeric-literal color. */
|
|
123
123
|
syntaxNumberColor?: string;
|
|
124
|
+
/**
|
|
125
|
+
* Color of the language name in a code block's header band.
|
|
126
|
+
*
|
|
127
|
+
* Derived from {@link syntaxCommentColor} in {@link resolveTheme} when the
|
|
128
|
+
* caller does not set it. A comment is the one token class already defined as
|
|
129
|
+
* "present but subordinate to the code", which is exactly the label's role, so
|
|
130
|
+
* a theme that tuned its comment color for a given background has already
|
|
131
|
+
* answered this question. A literal default would ignore that and read wrong on
|
|
132
|
+
* every light preset.
|
|
133
|
+
*/
|
|
134
|
+
codeLangColor?: string;
|
|
124
135
|
/**
|
|
125
136
|
* Enable `markdown-it`-style typographic substitutions: `--`/`---` to en/em
|
|
126
137
|
* dash, `...` to an ellipsis, `(c)`/`(r)`/`(tm)` to their symbols, `+-` to
|
|
@@ -147,6 +158,16 @@ export interface MarkdownTheme {
|
|
|
147
158
|
headingSizes?: readonly number[];
|
|
148
159
|
/** Code-block font size in px. */
|
|
149
160
|
codeFontSize?: number;
|
|
161
|
+
/**
|
|
162
|
+
* Font size in px of the language name in a code block's header band.
|
|
163
|
+
*
|
|
164
|
+
* Left `undefined` by default and **derived** as `codeFontSize - 3` (clamped
|
|
165
|
+
* to at least 1), following {@link tableFontSize}'s precedent: the label is
|
|
166
|
+
* chrome around the code, so a caller who raises only `codeFontSize` should
|
|
167
|
+
* get a proportionally larger label rather than one that stays put and
|
|
168
|
+
* gradually looks detached from the block it belongs to.
|
|
169
|
+
*/
|
|
170
|
+
codeLangFontSize?: number;
|
|
150
171
|
/**
|
|
151
172
|
* Table cell font size in px.
|
|
152
173
|
*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vectojs/markdown",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.0",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"marked": "^18.0.7"
|
|
49
49
|
},
|
|
50
50
|
"peerDependencies": {
|
|
51
|
-
"@vectojs/core": ">=1.
|
|
51
|
+
"@vectojs/core": ">=1.34.0 <2.0.0",
|
|
52
52
|
"@vectojs/ui": ">=2.6.0 <3.0.0"
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|