@vectojs/markdown 0.23.3 → 0.25.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/README.md +50 -0
- package/dist/Markdown.d.ts +16 -0
- package/dist/MarkdownWorkerSource.d.ts +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.js +325 -53
- package/dist/index.mjs +321 -53
- package/dist/markdown-image.d.ts +24 -1
- package/dist/markdown-inline.d.ts +10 -2
- package/dist/projection-policy.d.ts +54 -0
- package/package.json +3 -3
package/dist/markdown-image.d.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import type { InlineObjectBox, InlineObjectSurface } from '@vectojs/core';
|
|
2
2
|
import type { Token, Tokens } from 'marked';
|
|
3
|
+
import type { ImageSource } from '@vectojs/ui';
|
|
4
|
+
/** Resolve a markdown image `src` to a generic {@link ImageSource}. */
|
|
5
|
+
export type MarkdownImageResolver = (src: string) => ImageSource | Promise<ImageSource>;
|
|
6
|
+
/** Default resolver — identity mapping to `{kind:'url'}`. */
|
|
7
|
+
export declare const defaultMarkdownImageResolver: MarkdownImageResolver;
|
|
3
8
|
/**
|
|
4
9
|
* Image predicates over a `marked` token tree, plus the raster store for images
|
|
5
10
|
* that render *inline* rather than as their own block.
|
|
@@ -75,16 +80,26 @@ export declare function lastIndexOfImage(tokens: Token[]): number;
|
|
|
75
80
|
* `InlineObject`, and the box it occupies is fixed when the span is collected, so
|
|
76
81
|
* the natural size has to be readable from here before the next layout rather than
|
|
77
82
|
* applied to an entity afterwards.
|
|
83
|
+
*
|
|
84
|
+
* Supports generic {@link ImageSource}: `url` decodes via `HTMLImageElement`,
|
|
85
|
+
* `blob` via `createImageBitmap` (with object-URL fallback), and `bitmap` is used
|
|
86
|
+
* directly. The backing `source` is the `CanvasImageSource` drawn by
|
|
87
|
+
* `paintInlineImage`; `bitmap` is retained as a legacy alias for `url` rasters so
|
|
88
|
+
* existing tests that reach through `raster.bitmap` keep working.
|
|
78
89
|
*/
|
|
79
90
|
export interface InlineImageRaster {
|
|
80
91
|
/** `undefined` when this environment has no `Image` (SSR, plain unit tests). */
|
|
81
92
|
bitmap?: HTMLImageElement;
|
|
93
|
+
/** Generic backing source for `IRenderer.drawImage` / `InlineObjectSurface`. */
|
|
94
|
+
source?: CanvasImageSource;
|
|
82
95
|
decoded: boolean;
|
|
83
96
|
/** Natural size, known only once decoded. */
|
|
84
97
|
naturalWidth?: number;
|
|
85
98
|
naturalHeight?: number;
|
|
86
99
|
/** Set when the decode failed, so a broken URL is not retried every frame. */
|
|
87
100
|
failed?: boolean;
|
|
101
|
+
/** Release `ImageBitmap` / revoke `blob:` URL when evicted or cleared. */
|
|
102
|
+
dispose?: () => void;
|
|
88
103
|
}
|
|
89
104
|
/** Subscribe `notify` to inline-image decodes. Idempotent per closure. */
|
|
90
105
|
export declare function subscribeInlineImageRaster(notify: () => void): void;
|
|
@@ -102,14 +117,22 @@ export declare function unsubscribeInlineImageRaster(notify: () => void): void;
|
|
|
102
117
|
* paint path calls it on every visible frame, and only the first call starts a
|
|
103
118
|
* decode. Exported because the span collector needs the natural size to size its
|
|
104
119
|
* box, which is the whole reason this store reports one.
|
|
120
|
+
*
|
|
121
|
+
* When a resolver is supplied, its result (which may be `blob` or `bitmap`) is
|
|
122
|
+
* decoded instead of the raw `src` URL. Resolver may be async — the raster stays
|
|
123
|
+
* square until the promise settles, then notifies waiters so the owner can
|
|
124
|
+
* re-measure.
|
|
105
125
|
*/
|
|
106
|
-
export declare function ensureInlineImageRaster(src: string): InlineImageRaster;
|
|
126
|
+
export declare function ensureInlineImageRaster(src: string, resolver?: MarkdownImageResolver): InlineImageRaster;
|
|
107
127
|
/**
|
|
108
128
|
* Paint one inline image into the box the layout engine reserved for it.
|
|
109
129
|
*
|
|
110
130
|
* Draws nothing until the raster decodes — one frame of empty box, then a repaint
|
|
111
131
|
* through {@link inlineImageRasterWaiters}. Mirrors `paintInlineMath`; a
|
|
112
132
|
* placeholder slab would flash a grey rectangle mid-sentence on every first paint.
|
|
133
|
+
*
|
|
134
|
+
* Supports generic {@link ImageSource} backing: `source` may be an `ImageBitmap`
|
|
135
|
+
* or an `HTMLImageElement`.
|
|
113
136
|
*/
|
|
114
137
|
export declare function paintInlineImage(src: string, surface: InlineObjectSurface, box: InlineObjectBox): void;
|
|
115
138
|
/** Drop every cached raster. Tests only — a decode is process-wide state. */
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type StyledSpan, type TextStyle } from '@vectojs/core';
|
|
2
2
|
import { RichText } from '@vectojs/ui';
|
|
3
3
|
import type { Token } from 'marked';
|
|
4
|
+
import { type MarkdownImageResolver } from './markdown-image';
|
|
4
5
|
import type { MarkdownTheme } from './theme';
|
|
5
6
|
/**
|
|
6
7
|
* Inline tokens to `RichText` spans: the entity decoder, the span collector and
|
|
@@ -62,7 +63,14 @@ blockFontSize?: number,
|
|
|
62
63
|
* call site that has none to thread — nested recursive calls, and callers
|
|
63
64
|
* predating this feature — costs nothing extra.
|
|
64
65
|
*/
|
|
65
|
-
abbr?: ReadonlyMap<string, string
|
|
66
|
+
abbr?: ReadonlyMap<string, string>,
|
|
67
|
+
/**
|
|
68
|
+
* How a markdown image `src` becomes a generic {@link ImageSource}. When
|
|
69
|
+
* omitted the default identity `{kind:'url'}` mapping is used, so a plain
|
|
70
|
+
* `` keeps its historic path and an app can supply a
|
|
71
|
+
* CapGlyph adapter that returns `{kind:'bitmap'}` for `capglyph:` URLs.
|
|
72
|
+
*/
|
|
73
|
+
imageResolver?: MarkdownImageResolver): void;
|
|
66
74
|
/**
|
|
67
75
|
* One trailing inline construct that has opened but not closed yet.
|
|
68
76
|
*
|
|
@@ -93,4 +101,4 @@ export declare function findUnclosedInline(text: string): UnclosedInline | null;
|
|
|
93
101
|
/** Parse inline markdown tokens and produce a {@link RichText} entity. */
|
|
94
102
|
export declare function renderInlineToRichText(tokens: Token[] | undefined, fallbackText: string, font: string, color: string, maxWidth: number, theme: Required<MarkdownTheme>, selectable: boolean, onLinkClick?: (url: string) => void,
|
|
95
103
|
/** The document's `*[TERM]: definition` dictionary — see {@link emitProse}. */
|
|
96
|
-
abbr?: ReadonlyMap<string, string
|
|
104
|
+
abbr?: ReadonlyMap<string, string>, imageResolver?: MarkdownImageResolver): RichText;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { Entity } from '@vectojs/core';
|
|
2
|
+
import { Stack } from '@vectojs/ui';
|
|
3
|
+
/**
|
|
4
|
+
* Markdown projection-policy switcher (RFC4 §6 dogfood, CTX-0601).
|
|
5
|
+
*
|
|
6
|
+
* Assigns the per-block `domPolicy`/`domKind` the capability negotiation
|
|
7
|
+
* (`Scene.resolveProjectionFor`) consumes. DOM-free plain data only: this
|
|
8
|
+
* module never creates an element — the `'prose'`/`'code'` kind specs that
|
|
9
|
+
* materialize blocks live with the backend (the dogfood page registers them
|
|
10
|
+
* on `DOMProjection`; custom backends register their own).
|
|
11
|
+
*
|
|
12
|
+
* Block → kind mapping (the §4 matrix in Markdown terms):
|
|
13
|
+
*
|
|
14
|
+
* - ui `Text` / `RichText` (headings, paragraphs) → `'prose'`:
|
|
15
|
+
* long/selectable text whose native value (selection, Ctrl+F, translation)
|
|
16
|
+
* outweighs DOM cost, so `'auto'` resolves `dom`.
|
|
17
|
+
* - `CodeBlock` → `'code'`: selectable source text; `'auto'` rests on
|
|
18
|
+
* `canvas` (row default) until measured, explicit `'dom'` materializes it.
|
|
19
|
+
* - `Table` → `''` (unsupported-kind): composite interactive widget, stays
|
|
20
|
+
* canvas with a reported reason.
|
|
21
|
+
* - Grouping wrappers (children present, no specific class) → `'container'`:
|
|
22
|
+
* never materialized itself; children negotiate individually.
|
|
23
|
+
* - Anything else (rules, borders, backgrounds) → `''`: canvas leaves.
|
|
24
|
+
*
|
|
25
|
+
* Kinds are assigned to top-level blocks only; nested content keeps its own
|
|
26
|
+
* `domKind` (default `''` → canvas, reported) until a finer pass tags it.
|
|
27
|
+
*/
|
|
28
|
+
/** Dogfood switcher mode (RFC4 §6): forced canvas, forced dom, or negotiated. */
|
|
29
|
+
export type MarkdownProjectionMode = 'canvas' | 'dom' | 'hybrid';
|
|
30
|
+
/** One top-level document block with its negotiation kind. */
|
|
31
|
+
export interface ClassifiedProjectionBlock {
|
|
32
|
+
node: Entity;
|
|
33
|
+
/** Stable human label for readouts (`index: Class (role)`). */
|
|
34
|
+
label: string;
|
|
35
|
+
/** `domKind` for negotiation; `''` means canvas-only (reported fallback). */
|
|
36
|
+
domKind: string;
|
|
37
|
+
}
|
|
38
|
+
/** Classify one top-level block (see module doc for the mapping). */
|
|
39
|
+
export declare function classifyProjectionBlock(node: Entity, index: number): ClassifiedProjectionBlock;
|
|
40
|
+
/**
|
|
41
|
+
* Top-level blocks of a document's content stack, in order, with kinds
|
|
42
|
+
* assigned onto the blocks (idempotent — re-running keeps prior kinds).
|
|
43
|
+
*/
|
|
44
|
+
export declare function classifyProjectionBlocks(content: Stack): ClassifiedProjectionBlock[];
|
|
45
|
+
/**
|
|
46
|
+
* Apply a switcher mode to a whole Markdown subtree (kinds must already be
|
|
47
|
+
* assigned via {@link classifyProjectionBlocks} or by hand):
|
|
48
|
+
*
|
|
49
|
+
* - `'canvas'` — every node `'canvas'`: byte-identical to today.
|
|
50
|
+
* - `'dom'` — `'dom'` where the node has a materializable kind
|
|
51
|
+
* (`'prose'`/`'code'`), `'canvas'` elsewhere (tables, figures, chrome).
|
|
52
|
+
* - `'hybrid'` — every node `'auto'`: the engine negotiates per block.
|
|
53
|
+
*/
|
|
54
|
+
export declare function applyProjectionMode(root: Entity, mode: MarkdownProjectionMode): void;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vectojs/markdown",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.25.0",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"@vectojs/tex": "^0.1.3",
|
|
48
|
-
"marked": "^18.0.
|
|
48
|
+
"marked": "^18.0.11"
|
|
49
49
|
},
|
|
50
50
|
"peerDependencies": {
|
|
51
51
|
"@vectojs/core": ">=1.34.0 <2.0.0",
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"@vectojs/ui": "workspace:*",
|
|
57
57
|
"esbuild": "^0.28.1",
|
|
58
58
|
"prettier": "^3.9.6",
|
|
59
|
-
"puppeteer-core": "^25.
|
|
59
|
+
"puppeteer-core": "^25.9.0",
|
|
60
60
|
"tsup": "^8.3.5",
|
|
61
61
|
"vitest": "^4.1.11"
|
|
62
62
|
}
|