md2x 0.1.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 +43 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.mjs +128069 -0
- package/dist/md2x.mjs +128296 -0
- package/dist/renderer/puppeteer-render-worker.js +815 -0
- package/dist/renderer/puppeteer-render.html +2829 -0
- package/dist/themes/code-themes/business-contrast.json +31 -0
- package/dist/themes/code-themes/colorful.json +32 -0
- package/dist/themes/code-themes/cool-modern.json +31 -0
- package/dist/themes/code-themes/high-contrast.json +31 -0
- package/dist/themes/code-themes/light-clean.json +31 -0
- package/dist/themes/code-themes/warm-book.json +31 -0
- package/dist/themes/color-schemes/candy.json +34 -0
- package/dist/themes/color-schemes/cool.json +34 -0
- package/dist/themes/color-schemes/coral.json +34 -0
- package/dist/themes/color-schemes/dino.json +34 -0
- package/dist/themes/color-schemes/forest.json +34 -0
- package/dist/themes/color-schemes/garden.json +34 -0
- package/dist/themes/color-schemes/neutral.json +34 -0
- package/dist/themes/color-schemes/ocean.json +34 -0
- package/dist/themes/color-schemes/rainbow.json +43 -0
- package/dist/themes/color-schemes/sakura.json +34 -0
- package/dist/themes/color-schemes/sepia.json +34 -0
- package/dist/themes/color-schemes/space.json +34 -0
- package/dist/themes/color-schemes/starry.json +34 -0
- package/dist/themes/color-schemes/sunset.json +34 -0
- package/dist/themes/color-schemes/warm.json +34 -0
- package/dist/themes/font-config.json +184 -0
- package/dist/themes/layout-schemes/academic.json +40 -0
- package/dist/themes/layout-schemes/book.json +40 -0
- package/dist/themes/layout-schemes/document.json +40 -0
- package/dist/themes/layout-schemes/magazine.json +40 -0
- package/dist/themes/layout-schemes/student.json +40 -0
- package/dist/themes/layout-schemes/technical.json +40 -0
- package/dist/themes/presets/academic.json +24 -0
- package/dist/themes/presets/business.json +22 -0
- package/dist/themes/presets/candy.json +23 -0
- package/dist/themes/presets/century.json +22 -0
- package/dist/themes/presets/coral.json +22 -0
- package/dist/themes/presets/default.json +22 -0
- package/dist/themes/presets/dinosaur.json +23 -0
- package/dist/themes/presets/elegant.json +22 -0
- package/dist/themes/presets/forest.json +22 -0
- package/dist/themes/presets/garamond.json +22 -0
- package/dist/themes/presets/garden.json +23 -0
- package/dist/themes/presets/handwritten.json +23 -0
- package/dist/themes/presets/heiti.json +22 -0
- package/dist/themes/presets/magazine.json +24 -0
- package/dist/themes/presets/manuscript.json +22 -0
- package/dist/themes/presets/minimal.json +22 -0
- package/dist/themes/presets/mixed.json +24 -0
- package/dist/themes/presets/newspaper.json +24 -0
- package/dist/themes/presets/ocean.json +22 -0
- package/dist/themes/presets/palatino.json +22 -0
- package/dist/themes/presets/rainbow.json +23 -0
- package/dist/themes/presets/space.json +23 -0
- package/dist/themes/presets/starry.json +23 -0
- package/dist/themes/presets/sunset.json +22 -0
- package/dist/themes/presets/swiss.json +22 -0
- package/dist/themes/presets/technical.json +22 -0
- package/dist/themes/presets/typewriter.json +23 -0
- package/dist/themes/presets/verdana.json +22 -0
- package/dist/themes/presets/water.json +22 -0
- package/dist/themes/registry.json +270 -0
- package/dist/themes/table-styles/academic.json +30 -0
- package/dist/themes/table-styles/borderless.json +26 -0
- package/dist/themes/table-styles/compact.json +24 -0
- package/dist/themes/table-styles/grid.json +22 -0
- package/dist/themes/table-styles/high-contrast.json +22 -0
- package/dist/themes/table-styles/minimal-gray.json +26 -0
- package/dist/themes/table-styles/modern-tech.json +34 -0
- package/dist/themes/table-styles/professional.json +34 -0
- package/dist/themes/table-styles/zebra.json +22 -0
- package/dist/types/node/src/host/browser-renderer.d.ts +40 -0
- package/dist/types/node/src/host/node-exporter.d.ts +63 -0
- package/dist/types/node/src/host/node-platform.d.ts +30 -0
- package/dist/types/node/src/index.d.ts +8 -0
- package/dist/types/src/core/markdown-block-splitter.d.ts +16 -0
- package/dist/types/src/core/markdown-document.d.ts +286 -0
- package/dist/types/src/core/markdown-processor.d.ts +228 -0
- package/dist/types/src/core/viewer/viewer-controller.d.ts +85 -0
- package/dist/types/src/exporters/docx-blockquote-converter.d.ts +24 -0
- package/dist/types/src/exporters/docx-code-highlighter.d.ts +14 -0
- package/dist/types/src/exporters/docx-download.d.ts +27 -0
- package/dist/types/src/exporters/docx-exporter.d.ts +77 -0
- package/dist/types/src/exporters/docx-image-utils.d.ts +71 -0
- package/dist/types/src/exporters/docx-inline-converter.d.ts +124 -0
- package/dist/types/src/exporters/docx-list-converter.d.ts +50 -0
- package/dist/types/src/exporters/docx-math-converter.d.ts +11 -0
- package/dist/types/src/exporters/docx-table-converter.d.ts +22 -0
- package/dist/types/src/exporters/mml2omml.d.ts +2 -0
- package/dist/types/src/exporters/theme-to-docx.d.ts +144 -0
- package/dist/types/src/plugins/base-plugin.d.ts +67 -0
- package/dist/types/src/plugins/canvas-plugin.d.ts +9 -0
- package/dist/types/src/plugins/dot-plugin.d.ts +9 -0
- package/dist/types/src/plugins/html-plugin.d.ts +28 -0
- package/dist/types/src/plugins/index.d.ts +56 -0
- package/dist/types/src/plugins/infographic-plugin.d.ts +9 -0
- package/dist/types/src/plugins/mermaid-plugin.d.ts +9 -0
- package/dist/types/src/plugins/plugin-content-utils.d.ts +40 -0
- package/dist/types/src/plugins/plugin-html-utils.d.ts +23 -0
- package/dist/types/src/plugins/rehype-image-uri.d.ts +13 -0
- package/dist/types/src/plugins/remark-super-sub.d.ts +17 -0
- package/dist/types/src/plugins/remark-toc-filter.d.ts +10 -0
- package/dist/types/src/plugins/svg-plugin.d.ts +51 -0
- package/dist/types/src/plugins/vega-plugin.d.ts +10 -0
- package/dist/types/src/plugins/vegalite-plugin.d.ts +23 -0
- package/dist/types/src/types/cache.d.ts +85 -0
- package/dist/types/src/types/core.d.ts +99 -0
- package/dist/types/src/types/docx.d.ts +240 -0
- package/dist/types/src/types/index.d.ts +18 -0
- package/dist/types/src/types/messaging.d.ts +142 -0
- package/dist/types/src/types/platform.d.ts +203 -0
- package/dist/types/src/types/plugin.d.ts +101 -0
- package/dist/types/src/types/render.d.ts +57 -0
- package/dist/types/src/types/theme.d.ts +234 -0
- package/dist/types/src/types/toolbar.d.ts +53 -0
- package/dist/types/src/ui/popup/i18n-helpers.d.ts +21 -0
- package/dist/types/src/ui/popup/settings-tab.d.ts +56 -0
- package/dist/types/src/ui/popup/storage-helper.d.ts +12 -0
- package/dist/types/src/utils/fetch-utils.d.ts +12 -0
- package/dist/types/src/utils/hash.d.ts +17 -0
- package/dist/types/src/utils/html-sanitizer.d.ts +26 -0
- package/dist/types/src/utils/localization.d.ts +49 -0
- package/dist/types/src/utils/theme-manager.d.ts +152 -0
- package/dist/types/src/utils/theme-to-css.d.ts +171 -0
- package/package.json +47 -0
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Markdown Document - In-memory document structure for incremental updates
|
|
3
|
+
*
|
|
4
|
+
* This module provides a pure data structure for managing markdown documents
|
|
5
|
+
* without any DOM dependencies. It handles:
|
|
6
|
+
* - Block-level parsing and tracking with stable IDs
|
|
7
|
+
* - Content hashing for change detection
|
|
8
|
+
* - Incremental diff computation
|
|
9
|
+
* - Virtual DOM with precise DOM operation commands
|
|
10
|
+
* - Line number mapping for scroll sync
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Block metadata stored in memory
|
|
14
|
+
*/
|
|
15
|
+
export interface BlockMeta {
|
|
16
|
+
/** Unique block ID (stable across updates for same content position) */
|
|
17
|
+
id: string;
|
|
18
|
+
/** Block hash (content-based) */
|
|
19
|
+
hash: string;
|
|
20
|
+
/** Source line number (0-based) */
|
|
21
|
+
startLine: number;
|
|
22
|
+
/** Number of source lines */
|
|
23
|
+
lineCount: number;
|
|
24
|
+
/** Raw markdown content */
|
|
25
|
+
content: string;
|
|
26
|
+
/** Rendered HTML (if available) */
|
|
27
|
+
html?: string;
|
|
28
|
+
/** Whether this block contains async placeholder */
|
|
29
|
+
hasPlaceholder?: boolean;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Block attributes for DOM elements
|
|
33
|
+
*/
|
|
34
|
+
export interface BlockAttrs {
|
|
35
|
+
'data-block-id': string;
|
|
36
|
+
'data-block-hash': string;
|
|
37
|
+
'data-line': number;
|
|
38
|
+
'data-line-count': number;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* DOM operation command - platform-agnostic instructions for updating the DOM
|
|
42
|
+
*/
|
|
43
|
+
export type DOMCommand = {
|
|
44
|
+
type: 'clear';
|
|
45
|
+
} | {
|
|
46
|
+
type: 'append';
|
|
47
|
+
blockId: string;
|
|
48
|
+
html: string;
|
|
49
|
+
attrs: BlockAttrs;
|
|
50
|
+
} | {
|
|
51
|
+
type: 'insertBefore';
|
|
52
|
+
blockId: string;
|
|
53
|
+
html: string;
|
|
54
|
+
refId: string;
|
|
55
|
+
attrs: BlockAttrs;
|
|
56
|
+
} | {
|
|
57
|
+
type: 'remove';
|
|
58
|
+
blockId: string;
|
|
59
|
+
} | {
|
|
60
|
+
type: 'replace';
|
|
61
|
+
blockId: string;
|
|
62
|
+
html: string;
|
|
63
|
+
attrs: BlockAttrs;
|
|
64
|
+
} | {
|
|
65
|
+
type: 'updateAttrs';
|
|
66
|
+
blockId: string;
|
|
67
|
+
attrs: Partial<BlockAttrs>;
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* Result of computing DOM commands
|
|
71
|
+
*/
|
|
72
|
+
export interface DOMCommandResult {
|
|
73
|
+
commands: DOMCommand[];
|
|
74
|
+
stats: {
|
|
75
|
+
kept: number;
|
|
76
|
+
inserted: number;
|
|
77
|
+
removed: number;
|
|
78
|
+
replaced: number;
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Normalize math blocks in markdown text
|
|
83
|
+
* Converts single-line $$...$$ to multi-line format for proper display math rendering
|
|
84
|
+
*/
|
|
85
|
+
export declare function normalizeMathBlocks(markdown: string): string;
|
|
86
|
+
/**
|
|
87
|
+
* In-memory markdown document with virtual DOM support
|
|
88
|
+
*/
|
|
89
|
+
export declare class MarkdownDocument {
|
|
90
|
+
private blocks;
|
|
91
|
+
private blockIdMap;
|
|
92
|
+
private rawContent;
|
|
93
|
+
private normalizedContent;
|
|
94
|
+
private idCounter;
|
|
95
|
+
/**
|
|
96
|
+
* Create a new document (optionally with initial content)
|
|
97
|
+
*/
|
|
98
|
+
constructor(markdown?: string);
|
|
99
|
+
/**
|
|
100
|
+
* Rebuild the blockId -> index map
|
|
101
|
+
*/
|
|
102
|
+
private rebuildBlockIdMap;
|
|
103
|
+
/**
|
|
104
|
+
* Get all blocks
|
|
105
|
+
*/
|
|
106
|
+
getBlocks(): readonly BlockMeta[];
|
|
107
|
+
/**
|
|
108
|
+
* Get block by index
|
|
109
|
+
*/
|
|
110
|
+
getBlock(index: number): BlockMeta | undefined;
|
|
111
|
+
/**
|
|
112
|
+
* Get block by ID (O(1) lookup)
|
|
113
|
+
*/
|
|
114
|
+
getBlockById(id: string): BlockMeta | undefined;
|
|
115
|
+
/**
|
|
116
|
+
* Get block index by ID (O(1) lookup)
|
|
117
|
+
*/
|
|
118
|
+
getBlockIndexById(id: string): number;
|
|
119
|
+
/**
|
|
120
|
+
* Get block count
|
|
121
|
+
*/
|
|
122
|
+
get blockCount(): number;
|
|
123
|
+
/**
|
|
124
|
+
* Get raw markdown content
|
|
125
|
+
*/
|
|
126
|
+
getRawContent(): string;
|
|
127
|
+
/**
|
|
128
|
+
* Get normalized content (math blocks expanded)
|
|
129
|
+
*/
|
|
130
|
+
getNormalizedContent(): string;
|
|
131
|
+
/**
|
|
132
|
+
* Find block by line number
|
|
133
|
+
*/
|
|
134
|
+
findBlockByLine(line: number): {
|
|
135
|
+
block: BlockMeta;
|
|
136
|
+
index: number;
|
|
137
|
+
} | null;
|
|
138
|
+
/**
|
|
139
|
+
* Get total line count of the document
|
|
140
|
+
*/
|
|
141
|
+
getTotalLineCount(): number;
|
|
142
|
+
/**
|
|
143
|
+
* Get line position info for scroll sync.
|
|
144
|
+
* Returns the block containing the line and progress within that block.
|
|
145
|
+
*
|
|
146
|
+
* @param line - Source line number (can be fractional for sub-line precision)
|
|
147
|
+
* @returns Object with block info and progress (0-1) within block, or null if out of range
|
|
148
|
+
*/
|
|
149
|
+
getLinePosition(line: number): {
|
|
150
|
+
block: BlockMeta;
|
|
151
|
+
index: number;
|
|
152
|
+
progress: number;
|
|
153
|
+
} | null;
|
|
154
|
+
/**
|
|
155
|
+
* Calculate line number from block index and progress within block.
|
|
156
|
+
* Inverse of getLinePosition.
|
|
157
|
+
*
|
|
158
|
+
* @param index - Block index
|
|
159
|
+
* @param progress - Progress within block (0-1)
|
|
160
|
+
* @returns Line number (with fractional part)
|
|
161
|
+
*/
|
|
162
|
+
getLineFromPosition(index: number, progress: number): number;
|
|
163
|
+
/**
|
|
164
|
+
* Find surrounding blocks for a given line (for interpolation).
|
|
165
|
+
* Returns previous and next blocks relative to the line.
|
|
166
|
+
*/
|
|
167
|
+
getSurroundingBlocks(line: number): {
|
|
168
|
+
previous?: {
|
|
169
|
+
block: BlockMeta;
|
|
170
|
+
index: number;
|
|
171
|
+
};
|
|
172
|
+
next?: {
|
|
173
|
+
block: BlockMeta;
|
|
174
|
+
index: number;
|
|
175
|
+
};
|
|
176
|
+
};
|
|
177
|
+
/**
|
|
178
|
+
* Calculate source line number from block ID and progress within block.
|
|
179
|
+
* Used by scroll sync: DOM provides blockId + pixel progress, we compute line.
|
|
180
|
+
*
|
|
181
|
+
* @param blockId - Block ID from DOM element's data-block-id
|
|
182
|
+
* @param progress - Progress within block (0-1) based on pixel position
|
|
183
|
+
* @returns Line number (with fractional part), or null if block not found
|
|
184
|
+
*/
|
|
185
|
+
getLineFromBlockId(blockId: string, progress?: number): number | null;
|
|
186
|
+
/**
|
|
187
|
+
* Get block position for a source line number.
|
|
188
|
+
* Used by scroll sync: editor provides line, we compute blockId + progress for DOM scroll.
|
|
189
|
+
*
|
|
190
|
+
* @param line - Source line number (can be fractional)
|
|
191
|
+
* @returns Object with blockId and progress (0-1) within block, or null if out of range
|
|
192
|
+
*/
|
|
193
|
+
getBlockPositionFromLine(line: number): {
|
|
194
|
+
blockId: string;
|
|
195
|
+
progress: number;
|
|
196
|
+
} | null;
|
|
197
|
+
/**
|
|
198
|
+
* Update document content and return DOM commands for incremental update
|
|
199
|
+
*/
|
|
200
|
+
update(markdown: string): DOMCommandResult;
|
|
201
|
+
/**
|
|
202
|
+
* Generate a new unique block ID
|
|
203
|
+
*/
|
|
204
|
+
private generateNewId;
|
|
205
|
+
/**
|
|
206
|
+
* Compute diff between old and new block arrays using LCS-based algorithm
|
|
207
|
+
*/
|
|
208
|
+
private computeDiff;
|
|
209
|
+
/**
|
|
210
|
+
* Generate DOM commands from diff operations
|
|
211
|
+
*/
|
|
212
|
+
private generateDOMCommands;
|
|
213
|
+
/**
|
|
214
|
+
* Get block attributes for DOM element
|
|
215
|
+
*/
|
|
216
|
+
private getBlockAttrs;
|
|
217
|
+
/**
|
|
218
|
+
* Set rendered HTML for a block by index
|
|
219
|
+
*/
|
|
220
|
+
setBlockHtml(index: number, html: string): void;
|
|
221
|
+
/**
|
|
222
|
+
* Set rendered HTML for a block by ID
|
|
223
|
+
*/
|
|
224
|
+
setBlockHtmlById(id: string, html: string): void;
|
|
225
|
+
/**
|
|
226
|
+
* Get blocks that need rendering (no cached HTML or has placeholder)
|
|
227
|
+
*/
|
|
228
|
+
getBlocksNeedingRender(): {
|
|
229
|
+
block: BlockMeta;
|
|
230
|
+
index: number;
|
|
231
|
+
}[];
|
|
232
|
+
/**
|
|
233
|
+
* Get all block IDs in order
|
|
234
|
+
*/
|
|
235
|
+
getBlockIds(): string[];
|
|
236
|
+
/**
|
|
237
|
+
* Clear all cached HTML
|
|
238
|
+
*/
|
|
239
|
+
clearHtmlCache(): void;
|
|
240
|
+
/**
|
|
241
|
+
* Get full HTML content (all blocks concatenated)
|
|
242
|
+
*/
|
|
243
|
+
getFullHtml(): string;
|
|
244
|
+
/**
|
|
245
|
+
* Wrap block HTML with container div and attributes
|
|
246
|
+
*/
|
|
247
|
+
wrapBlockHtml(block: BlockMeta): string;
|
|
248
|
+
/**
|
|
249
|
+
* Export document state for serialization
|
|
250
|
+
*/
|
|
251
|
+
toJSON(): {
|
|
252
|
+
blocks: Omit<BlockMeta, 'html' | 'hasPlaceholder'>[];
|
|
253
|
+
rawContent: string;
|
|
254
|
+
idCounter: number;
|
|
255
|
+
};
|
|
256
|
+
/**
|
|
257
|
+
* Create document from serialized state
|
|
258
|
+
*/
|
|
259
|
+
static fromJSON(data: {
|
|
260
|
+
blocks: Omit<BlockMeta, 'html' | 'hasPlaceholder'>[];
|
|
261
|
+
rawContent: string;
|
|
262
|
+
idCounter: number;
|
|
263
|
+
}): MarkdownDocument;
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Extract title from markdown content
|
|
267
|
+
*/
|
|
268
|
+
export declare function extractTitle(markdown: string): string | null;
|
|
269
|
+
/**
|
|
270
|
+
* Heading info for TOC
|
|
271
|
+
*/
|
|
272
|
+
export interface HeadingInfo {
|
|
273
|
+
level: number;
|
|
274
|
+
text: string;
|
|
275
|
+
id: string;
|
|
276
|
+
line: number;
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Extract headings from parsed blocks (without DOM)
|
|
280
|
+
*/
|
|
281
|
+
export declare function extractHeadingsFromBlocks(blocks: readonly BlockMeta[]): HeadingInfo[];
|
|
282
|
+
/**
|
|
283
|
+
* Execute DOM commands on a container element
|
|
284
|
+
* This is the only function that touches the real DOM
|
|
285
|
+
*/
|
|
286
|
+
export declare function executeDOMCommands(container: HTMLElement, commands: DOMCommand[], document: Document): void;
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import { type Processor } from 'unified';
|
|
2
|
+
import { type BlockWithLine } from './markdown-block-splitter';
|
|
3
|
+
import type { TranslateFunction, TaskStatus, TaskData, PluginRenderer, AsyncTaskPlugin } from '../types/index';
|
|
4
|
+
export type { TranslateFunction };
|
|
5
|
+
/**
|
|
6
|
+
* Task context for cancellation
|
|
7
|
+
*/
|
|
8
|
+
interface TaskContext {
|
|
9
|
+
cancelled: boolean;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Plugin interface for async tasks
|
|
13
|
+
*/
|
|
14
|
+
type Plugin = AsyncTaskPlugin;
|
|
15
|
+
/**
|
|
16
|
+
* Async task interface
|
|
17
|
+
*/
|
|
18
|
+
interface AsyncTask {
|
|
19
|
+
id: string;
|
|
20
|
+
callback: (data: TaskData) => Promise<void>;
|
|
21
|
+
data: TaskData;
|
|
22
|
+
type: string;
|
|
23
|
+
status: TaskStatus;
|
|
24
|
+
error: Error | null;
|
|
25
|
+
context: TaskContext;
|
|
26
|
+
setReady: () => void;
|
|
27
|
+
setError: (error: Error) => void;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Normalize math blocks in markdown text
|
|
31
|
+
* Converts single-line $$...$$ to multi-line format for proper display math rendering
|
|
32
|
+
* @param markdown - Raw markdown content
|
|
33
|
+
* @returns Normalized markdown
|
|
34
|
+
*/
|
|
35
|
+
export declare function normalizeMathBlocks(markdown: string): string;
|
|
36
|
+
export type { BlockWithLine };
|
|
37
|
+
/**
|
|
38
|
+
* Split markdown into semantic blocks (paragraphs, code blocks, tables, etc.)
|
|
39
|
+
* Each block is a complete markdown element that can be processed independently.
|
|
40
|
+
* @param markdown - Raw markdown content
|
|
41
|
+
* @returns Array of markdown blocks
|
|
42
|
+
*/
|
|
43
|
+
export declare function splitMarkdownIntoBlocks(markdown: string): string[];
|
|
44
|
+
/**
|
|
45
|
+
* Split markdown into semantic blocks with source line numbers.
|
|
46
|
+
* Each block includes its starting line number for scroll sync.
|
|
47
|
+
* @param markdown - Raw markdown content
|
|
48
|
+
* @returns Array of blocks with line info
|
|
49
|
+
*/
|
|
50
|
+
export declare function splitMarkdownIntoBlocksWithLines(markdown: string): BlockWithLine[];
|
|
51
|
+
/**
|
|
52
|
+
* Escape HTML special characters
|
|
53
|
+
* @param text - Text to escape
|
|
54
|
+
* @returns Escaped text
|
|
55
|
+
*/
|
|
56
|
+
export declare function escapeHtml(text: string): string;
|
|
57
|
+
/**
|
|
58
|
+
* Check if a block is a frontmatter block
|
|
59
|
+
* Frontmatter must start and end with ---, and typically appears at line 0
|
|
60
|
+
*/
|
|
61
|
+
export declare function isFrontmatterBlock(block: string, startLine: number): boolean;
|
|
62
|
+
/**
|
|
63
|
+
* Parse frontmatter YAML content (simple key: value parsing)
|
|
64
|
+
*/
|
|
65
|
+
export declare function parseFrontmatter(block: string): Record<string, string>;
|
|
66
|
+
/**
|
|
67
|
+
* Render frontmatter as HTML table
|
|
68
|
+
*/
|
|
69
|
+
export declare function renderFrontmatterAsTable(data: Record<string, string>): string;
|
|
70
|
+
/**
|
|
71
|
+
* Render frontmatter as pre block (raw format)
|
|
72
|
+
*/
|
|
73
|
+
export declare function renderFrontmatterAsRaw(block: string): string;
|
|
74
|
+
/**
|
|
75
|
+
* Validate URL values and block javascript-style protocols
|
|
76
|
+
* @param url - URL to validate
|
|
77
|
+
* @returns True when URL is considered safe
|
|
78
|
+
*/
|
|
79
|
+
export declare function isSafeUrl(url: string | null | undefined): boolean;
|
|
80
|
+
/**
|
|
81
|
+
* Validate that every URL candidate in a srcset attribute is safe
|
|
82
|
+
* @param value - Raw srcset value
|
|
83
|
+
* @returns True when every entry is safe
|
|
84
|
+
*/
|
|
85
|
+
export declare function isSafeSrcset(value: string | null | undefined): boolean;
|
|
86
|
+
/**
|
|
87
|
+
* Sanitize rendered HTML to remove active content like scripts before injection
|
|
88
|
+
* @param html - Raw HTML string produced by the markdown pipeline
|
|
89
|
+
* @returns Sanitized HTML safe for innerHTML assignment
|
|
90
|
+
*/
|
|
91
|
+
export declare function sanitizeRenderedHtml(html: string): string;
|
|
92
|
+
/**
|
|
93
|
+
* Process tables to add centering attributes for Word compatibility
|
|
94
|
+
* @param html - HTML content
|
|
95
|
+
* @returns HTML with centered tables
|
|
96
|
+
*/
|
|
97
|
+
export declare function processTablesForWordCompatibility(html: string): string;
|
|
98
|
+
/**
|
|
99
|
+
* Async task manager for plugin rendering
|
|
100
|
+
*/
|
|
101
|
+
export interface AsyncTaskManagerOptions {
|
|
102
|
+
/** Callback triggered when abort() is called, for cleanup of downstream resources */
|
|
103
|
+
onAbort?: () => void;
|
|
104
|
+
}
|
|
105
|
+
export declare class AsyncTaskManager {
|
|
106
|
+
private queue;
|
|
107
|
+
private idCounter;
|
|
108
|
+
private translate;
|
|
109
|
+
private aborted;
|
|
110
|
+
private context;
|
|
111
|
+
private onAbort?;
|
|
112
|
+
constructor(translate?: TranslateFunction, options?: AsyncTaskManagerOptions);
|
|
113
|
+
/**
|
|
114
|
+
* Abort all pending tasks
|
|
115
|
+
* Called when starting a new render to cancel previous tasks
|
|
116
|
+
*/
|
|
117
|
+
abort(): void;
|
|
118
|
+
/**
|
|
119
|
+
* Reset abort flag (call before starting new task collection)
|
|
120
|
+
*/
|
|
121
|
+
reset(): void;
|
|
122
|
+
/**
|
|
123
|
+
* Check if manager has been aborted
|
|
124
|
+
*/
|
|
125
|
+
isAborted(): boolean;
|
|
126
|
+
/**
|
|
127
|
+
* Get current context for callbacks to reference
|
|
128
|
+
*/
|
|
129
|
+
getContext(): TaskContext;
|
|
130
|
+
/**
|
|
131
|
+
* Generate unique ID for async tasks
|
|
132
|
+
*/
|
|
133
|
+
generateId(): string;
|
|
134
|
+
/**
|
|
135
|
+
* Register async task for later execution
|
|
136
|
+
* @param callback - The async callback function
|
|
137
|
+
* @param data - Data to pass to callback
|
|
138
|
+
* @param plugin - Plugin instance
|
|
139
|
+
* @param initialStatus - Initial task status
|
|
140
|
+
* @returns Task control and placeholder content
|
|
141
|
+
*/
|
|
142
|
+
createTask(callback: (data: TaskData, context: TaskContext) => Promise<void>, data?: Record<string, unknown>, plugin?: Plugin | null, initialStatus?: TaskStatus): {
|
|
143
|
+
task: AsyncTask;
|
|
144
|
+
placeholder: {
|
|
145
|
+
type: 'html';
|
|
146
|
+
value: string;
|
|
147
|
+
};
|
|
148
|
+
};
|
|
149
|
+
/**
|
|
150
|
+
* Process all async tasks in parallel
|
|
151
|
+
* @param onProgress - Progress callback (completed, total)
|
|
152
|
+
* @param onError - Error handler for individual task
|
|
153
|
+
* @returns Returns true if completed, false if aborted
|
|
154
|
+
*/
|
|
155
|
+
processAll(onProgress?: ((completed: number, total: number) => void) | null, onError?: ((error: Error, task: AsyncTask) => void) | null): Promise<boolean>;
|
|
156
|
+
/**
|
|
157
|
+
* Get pending task count
|
|
158
|
+
*/
|
|
159
|
+
get pendingCount(): number;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Create the unified markdown processor pipeline
|
|
163
|
+
* @param renderer - Renderer instance for diagrams
|
|
164
|
+
* @param taskManager - Async task manager
|
|
165
|
+
* @param translate - Translation function
|
|
166
|
+
* @returns Configured unified processor
|
|
167
|
+
*/
|
|
168
|
+
export declare function createMarkdownProcessor(renderer: PluginRenderer, taskManager: AsyncTaskManager, translate?: TranslateFunction): Processor;
|
|
169
|
+
/**
|
|
170
|
+
* Frontmatter display mode
|
|
171
|
+
*/
|
|
172
|
+
export type FrontmatterDisplay = 'hide' | 'table' | 'raw';
|
|
173
|
+
/**
|
|
174
|
+
* Options for processing markdown to HTML
|
|
175
|
+
*/
|
|
176
|
+
interface ProcessMarkdownOptions {
|
|
177
|
+
renderer: PluginRenderer;
|
|
178
|
+
taskManager: AsyncTaskManager;
|
|
179
|
+
translate?: TranslateFunction;
|
|
180
|
+
frontmatterDisplay?: FrontmatterDisplay;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Clear the HTML result cache (call when settings change)
|
|
184
|
+
*/
|
|
185
|
+
export declare function clearHtmlResultCache(): void;
|
|
186
|
+
/**
|
|
187
|
+
* Process markdown to HTML with block-level caching
|
|
188
|
+
* Each block's top-level elements are tagged with hash for efficient DOM diffing.
|
|
189
|
+
* @param markdown - Raw markdown content
|
|
190
|
+
* @param options - Processing options
|
|
191
|
+
* @returns Processed HTML
|
|
192
|
+
*/
|
|
193
|
+
export declare function processMarkdownToHtml(markdown: string, options: ProcessMarkdownOptions): Promise<string>;
|
|
194
|
+
/**
|
|
195
|
+
* Extract title from markdown content
|
|
196
|
+
* @param markdown - Markdown content
|
|
197
|
+
* @returns Extracted title or null
|
|
198
|
+
*/
|
|
199
|
+
export declare function extractTitle(markdown: string): string | null;
|
|
200
|
+
/**
|
|
201
|
+
* Heading information for TOC
|
|
202
|
+
*/
|
|
203
|
+
export interface HeadingInfo {
|
|
204
|
+
level: number;
|
|
205
|
+
text: string;
|
|
206
|
+
id: string;
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Extract headings for TOC generation (from DOM)
|
|
210
|
+
* @param container - DOM container with rendered content
|
|
211
|
+
* @returns Array of heading objects
|
|
212
|
+
*/
|
|
213
|
+
export declare function extractHeadings(container: Element): HeadingInfo[];
|
|
214
|
+
/**
|
|
215
|
+
* Options for incremental HTML rendering
|
|
216
|
+
*/
|
|
217
|
+
interface RenderHtmlOptions {
|
|
218
|
+
batchSize?: number;
|
|
219
|
+
yieldDelay?: number;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Render HTML content incrementally to avoid blocking the main thread.
|
|
223
|
+
* Parses HTML, then appends top-level nodes in batches with yields between them.
|
|
224
|
+
* @param container - Target container element
|
|
225
|
+
* @param html - Full HTML content to render
|
|
226
|
+
* @param options - Rendering options
|
|
227
|
+
*/
|
|
228
|
+
export declare function renderHtmlIncrementally(container: HTMLElement, html: string, options?: RenderHtmlOptions): Promise<void>;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ViewerController - Shared, platform-agnostic markdown rendering orchestration.
|
|
3
|
+
*
|
|
4
|
+
* This version uses MarkdownDocument for block-ID based virtual DOM,
|
|
5
|
+
* providing precise incremental updates without morphdom.
|
|
6
|
+
*/
|
|
7
|
+
import { AsyncTaskManager, type HeadingInfo } from '../markdown-processor';
|
|
8
|
+
import { MarkdownDocument } from '../markdown-document';
|
|
9
|
+
import type { PluginRenderer, TranslateFunction } from '../../types/index';
|
|
10
|
+
export type { HeadingInfo };
|
|
11
|
+
export type ViewerRenderResult = {
|
|
12
|
+
title: string | null;
|
|
13
|
+
headings: HeadingInfo[];
|
|
14
|
+
taskManager: AsyncTaskManager;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Frontmatter display mode
|
|
18
|
+
*/
|
|
19
|
+
export type FrontmatterDisplay = 'hide' | 'table' | 'raw';
|
|
20
|
+
export type RenderMarkdownOptions = {
|
|
21
|
+
markdown: string;
|
|
22
|
+
container: HTMLElement;
|
|
23
|
+
renderer: PluginRenderer;
|
|
24
|
+
translate: TranslateFunction;
|
|
25
|
+
/**
|
|
26
|
+
* Optional external task manager, useful for cancellation.
|
|
27
|
+
* If not provided, a new AsyncTaskManager will be created.
|
|
28
|
+
*/
|
|
29
|
+
taskManager?: AsyncTaskManager;
|
|
30
|
+
/**
|
|
31
|
+
* When true, container.innerHTML will be cleared before rendering.
|
|
32
|
+
* Keep false if the caller wants to clear before applying theme to avoid flicker.
|
|
33
|
+
*/
|
|
34
|
+
clearContainer?: boolean;
|
|
35
|
+
/**
|
|
36
|
+
* When true, use incremental DOM diffing instead of full re-render.
|
|
37
|
+
* This preserves already-rendered plugin content when possible.
|
|
38
|
+
* @deprecated Now always uses block-ID based incremental update
|
|
39
|
+
*/
|
|
40
|
+
incrementalUpdate?: boolean;
|
|
41
|
+
/** Called when headings are extracted (may be called multiple times during streaming) */
|
|
42
|
+
onHeadings?: (headings: HeadingInfo[]) => void;
|
|
43
|
+
/** Called when initial DOM streaming is complete (before async tasks) */
|
|
44
|
+
onStreamingComplete?: () => void;
|
|
45
|
+
/** Frontmatter display mode: 'hide', 'table', or 'raw' */
|
|
46
|
+
frontmatterDisplay?: FrontmatterDisplay;
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Get or create the markdown document instance
|
|
50
|
+
*/
|
|
51
|
+
export declare function getDocument(): MarkdownDocument;
|
|
52
|
+
/**
|
|
53
|
+
* Reset the document instance (call when switching files)
|
|
54
|
+
*/
|
|
55
|
+
export declare function resetDocument(): void;
|
|
56
|
+
/**
|
|
57
|
+
* Clear HTML cache (for backward compatibility)
|
|
58
|
+
* @deprecated Use resetDocument() instead
|
|
59
|
+
*/
|
|
60
|
+
export declare function clearHtmlCache(): void;
|
|
61
|
+
/**
|
|
62
|
+
* Sync block HTML from DOM after async rendering completes.
|
|
63
|
+
* Called when a placeholder is replaced with rendered content.
|
|
64
|
+
* This ensures the in-memory cache matches the actual DOM state.
|
|
65
|
+
*
|
|
66
|
+
* @param placeholderId - The ID of the placeholder element that was replaced
|
|
67
|
+
*/
|
|
68
|
+
export declare function syncBlockHtmlFromDOM(placeholderId: string): void;
|
|
69
|
+
/**
|
|
70
|
+
* Main render function using MarkdownDocument architecture
|
|
71
|
+
*/
|
|
72
|
+
export declare function renderMarkdownDocument(options: RenderMarkdownOptions): Promise<ViewerRenderResult>;
|
|
73
|
+
/**
|
|
74
|
+
* Find block element by ID
|
|
75
|
+
*/
|
|
76
|
+
export declare function findBlockElement(container: HTMLElement, blockId: string): HTMLElement | null;
|
|
77
|
+
/**
|
|
78
|
+
* Get all block elements in order
|
|
79
|
+
*/
|
|
80
|
+
export declare function getBlockElements(container: HTMLElement): HTMLElement[];
|
|
81
|
+
/**
|
|
82
|
+
* Check if incremental update is possible (for backward compatibility)
|
|
83
|
+
* @deprecated Always returns true now since we use block-ID based updates
|
|
84
|
+
*/
|
|
85
|
+
export declare function canIncrementalUpdate(container: HTMLElement): boolean;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Table, type FileChild } from 'docx';
|
|
2
|
+
import type { DOCXThemeStyles, DOCXBlockquoteNode, DOCXASTNode } from '../types/docx';
|
|
3
|
+
import type { InlineResult, InlineNode } from './docx-inline-converter';
|
|
4
|
+
type ConvertInlineNodesFunction = (children: InlineNode[], options?: {
|
|
5
|
+
color?: string;
|
|
6
|
+
}) => Promise<InlineResult[]>;
|
|
7
|
+
type ConvertChildNodeFunction = (node: DOCXASTNode, blockquoteNestLevel?: number) => Promise<FileChild | FileChild[] | null>;
|
|
8
|
+
interface BlockquoteConverterOptions {
|
|
9
|
+
themeStyles: DOCXThemeStyles;
|
|
10
|
+
convertInlineNodes: ConvertInlineNodesFunction;
|
|
11
|
+
convertChildNode?: ConvertChildNodeFunction;
|
|
12
|
+
}
|
|
13
|
+
export interface BlockquoteConverter {
|
|
14
|
+
convertBlockquote(node: DOCXBlockquoteNode, listLevel?: number): Promise<Table>;
|
|
15
|
+
setConvertChildNode(fn: ConvertChildNodeFunction): void;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Create a blockquote converter using table-based approach
|
|
19
|
+
* This allows true nesting and supports any content type inside blockquotes
|
|
20
|
+
* @param options - Configuration options
|
|
21
|
+
* @returns Blockquote converter
|
|
22
|
+
*/
|
|
23
|
+
export declare function createBlockquoteConverter({ themeStyles, convertInlineNodes, convertChildNode: initialConvertChildNode }: BlockquoteConverterOptions): BlockquoteConverter;
|
|
24
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { TextRun } from 'docx';
|
|
2
|
+
import type { DOCXThemeStyles } from '../types/docx';
|
|
3
|
+
export interface CodeHighlighter {
|
|
4
|
+
getHighlightColor(classList: string | string[] | DOMTokenList | null): string | null;
|
|
5
|
+
appendCodeTextRuns(text: string, runs: TextRun[], color: string | null): void;
|
|
6
|
+
collectHighlightedRuns(node: Node, runs: TextRun[], inheritedColor?: string | null): void;
|
|
7
|
+
getHighlightedRunsForCode(code: string, language: string | null | undefined): TextRun[];
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Create a code highlighter for DOCX export
|
|
11
|
+
* @param themeStyles - Theme configuration with code colors
|
|
12
|
+
* @returns Highlighter instance with methods
|
|
13
|
+
*/
|
|
14
|
+
export declare function createCodeHighlighter(themeStyles: DOCXThemeStyles | null): CodeHighlighter;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DOCX Download Utilities
|
|
3
|
+
* Functions for downloading DOCX files
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Convert byte array chunk to base64 without exceeding call stack limits
|
|
7
|
+
* @param bytes - Binary chunk
|
|
8
|
+
* @returns Base64 encoded chunk
|
|
9
|
+
*/
|
|
10
|
+
export declare function encodeBytesToBase64(bytes: Uint8Array): string;
|
|
11
|
+
/**
|
|
12
|
+
* Fallback download method using <a> element
|
|
13
|
+
* @param blob - File blob
|
|
14
|
+
* @param filename - Output filename
|
|
15
|
+
*/
|
|
16
|
+
export declare function fallbackDownload(blob: Blob, filename: string): void;
|
|
17
|
+
/**
|
|
18
|
+
* Progress callback for upload phase
|
|
19
|
+
*/
|
|
20
|
+
export type UploadProgressCallback = (uploaded: number, total: number) => void;
|
|
21
|
+
/**
|
|
22
|
+
* Download blob as file using platform file service
|
|
23
|
+
* @param blob - File blob
|
|
24
|
+
* @param filename - Output filename
|
|
25
|
+
* @param onProgress - Optional progress callback for upload phase
|
|
26
|
+
*/
|
|
27
|
+
export declare function downloadBlob(blob: Blob, filename: string, onProgress?: UploadProgressCallback): Promise<void>;
|