@jacobbubu/md-to-lark 1.4.11 → 1.5.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/README.md +2 -0
- package/dist/commands/publish-md/args.js +8 -1
- package/dist/commands/publish-md/command.js +1 -3
- package/dist/commands/publish-md/pipeline-transform.js +1 -1
- package/dist/interop/btt-to-last.js +1 -1
- package/dist/lark/docx/render-btt.js +2 -2
- package/dist/lark/docx/render-payload.js +8 -2
- package/dist/lark/docx/render-post-process.js +3 -1
- package/dist/pipeline/hast-to-last.js +74 -20
- package/dist/pipeline/markdown/md-to-hast.js +2 -2
- package/dist/preview/markdown-terminal.js +2 -1
- package/dist/publish/btt-patch.js +3 -1
- package/dist/publish/index.js +2 -2
- package/dist/publish/process-file.js +2 -2
- package/dist/publish/runtime.js +7 -0
- package/dist/shared/image-metadata.js +2 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -112,6 +112,7 @@ Presets, Mermaid, and stage artifacts:
|
|
|
112
112
|
npm run publish:md -- --input ./test-md/comp/comp.md --preset medium --dry-run
|
|
113
113
|
npm run publish:md -- --input ./test-md/comp/comp.md --preset zh-format --dry-run
|
|
114
114
|
npm run publish:md -- --input ./test-md/comp/comp.md --preset zh-format --preset ./my-preset.mjs --dry-run
|
|
115
|
+
npm run publish:md -- --input ./paper.md --single-dollar-text-math --dry-run
|
|
115
116
|
npm run publish:md -- --input ./tmp/generated/article.md --resource-base-dir ./source-assets --dry-run
|
|
116
117
|
npm run publish:md -- --input ./test-md/mermaid.md --mermaid-target board --dry-run
|
|
117
118
|
npm run publish:md -- --input ./test-md/comp/comp.md --pipeline-cache-dir ./out/debug-cache --dry-run
|
|
@@ -175,6 +176,7 @@ Guardrails:
|
|
|
175
176
|
- Local attachment and image detection with real upload
|
|
176
177
|
- Remote image download and standalone URL preparation
|
|
177
178
|
- Mermaid `text-drawing` and `board` output paths
|
|
179
|
+
- Opt-in single-dollar inline math parsing for LaTeX-heavy papers
|
|
178
180
|
- Table width heuristics and numeric-column right alignment
|
|
179
181
|
- Chinese Markdown formatting preset (`zh-format`)
|
|
180
182
|
- Ordered preset composition from CLI and programmatic usage
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
function usage() {
|
|
2
2
|
return [
|
|
3
|
-
'Usage: npm run publish:md -- --input <file.md|dir> [--title <doc_title_or_prefix>] [--date-prefix|--no-date-prefix] [--preset <preset_name_or_module_path>]... [--document-base-url <base_url>] [--resource-base-dir <dir>] [--folder <folder_token>] [--doc <document_id>] [--download-remote-images|--no-download-remote-images] [--yt-dlp-path <path>] [--yt-dlp-cookies-path <path>] [--pipeline-cache-dir <dir>] [--mermaid-target <text-drawing|board>] [--mermaid-board-syntax-type <int>] [--mermaid-board-style-type <int>] [--mermaid-board-diagram-type <int>] [--dry-run] [--help|-h]',
|
|
3
|
+
'Usage: npm run publish:md -- --input <file.md|dir> [--title <doc_title_or_prefix>] [--date-prefix|--no-date-prefix] [--preset <preset_name_or_module_path>]... [--document-base-url <base_url>] [--resource-base-dir <dir>] [--folder <folder_token>] [--doc <document_id>] [--download-remote-images|--no-download-remote-images] [--yt-dlp-path <path>] [--yt-dlp-cookies-path <path>] [--pipeline-cache-dir <dir>] [--single-dollar-text-math] [--mermaid-target <text-drawing|board>] [--mermaid-board-syntax-type <int>] [--mermaid-board-style-type <int>] [--mermaid-board-diagram-type <int>] [--dry-run] [--help|-h]',
|
|
4
4
|
'',
|
|
5
5
|
'Options:',
|
|
6
6
|
' --input Markdown file path, or directory path (publish all *.md recursively).',
|
|
@@ -17,6 +17,7 @@ function usage() {
|
|
|
17
17
|
' --yt-dlp-path Optional yt-dlp executable path for standalone URL extraction.',
|
|
18
18
|
' --yt-dlp-cookies-path Optional cookie file path passed to yt-dlp --cookies.',
|
|
19
19
|
' --pipeline-cache-dir Pipeline cache root directory. Default: ./out/pipeline-cache',
|
|
20
|
+
' --single-dollar-text-math Opt in to parsing $...$ as inline math. Default: disabled to avoid currency false positives.',
|
|
20
21
|
' --mermaid-target Mermaid render target: text-drawing (default) or board.',
|
|
21
22
|
' --mermaid-board-syntax-type Optional integer syntax_type for board createPlantuml (default: 2).',
|
|
22
23
|
' --mermaid-board-style-type Optional integer style_type for board createPlantuml.',
|
|
@@ -63,6 +64,7 @@ export function parsePublishMdArgs(argv, env = process.env) {
|
|
|
63
64
|
let ytDlpPath = '';
|
|
64
65
|
let ytDlpCookiesPath = '';
|
|
65
66
|
let pipelineCacheDir = '';
|
|
67
|
+
let singleDollarTextMath;
|
|
66
68
|
let mermaidTarget;
|
|
67
69
|
let mermaidBoardSyntaxType;
|
|
68
70
|
let mermaidBoardStyleType;
|
|
@@ -175,6 +177,10 @@ export function parsePublishMdArgs(argv, env = process.env) {
|
|
|
175
177
|
i += 1;
|
|
176
178
|
continue;
|
|
177
179
|
}
|
|
180
|
+
if (arg === '--single-dollar-text-math' || arg === '--single-dollar-math') {
|
|
181
|
+
singleDollarTextMath = true;
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
178
184
|
if (arg === '--mermaid-target') {
|
|
179
185
|
const value = argv[i + 1];
|
|
180
186
|
if (!value)
|
|
@@ -245,6 +251,7 @@ export function parsePublishMdArgs(argv, env = process.env) {
|
|
|
245
251
|
...(ytDlpPath.trim() ? { ytDlpPath: ytDlpPath.trim() } : {}),
|
|
246
252
|
...(ytDlpCookiesPath.trim() ? { ytDlpCookiesPath: ytDlpCookiesPath.trim() } : {}),
|
|
247
253
|
...(pipelineCacheDir.trim() ? { pipelineCacheDir: pipelineCacheDir.trim() } : {}),
|
|
254
|
+
...(singleDollarTextMath === undefined ? {} : { singleDollarTextMath }),
|
|
248
255
|
...(mermaidTarget ? { mermaidTarget } : {}),
|
|
249
256
|
...(mermaidBoardSyntaxType === undefined ? {} : { mermaidBoardSyntaxType }),
|
|
250
257
|
...(mermaidBoardStyleType === undefined ? {} : { mermaidBoardStyleType }),
|
|
@@ -73,9 +73,7 @@ export async function publishMdToLark(options, env = process.env) {
|
|
|
73
73
|
const runtime = buildPublishRuntime(options, env, markdownPresets);
|
|
74
74
|
logPublishRuntimeSummary(runtime, inputSet.markdownFiles.length, inputSet.mode);
|
|
75
75
|
const normalizedDocumentId = options.documentId ? normalizeDocumentId(options.documentId) : undefined;
|
|
76
|
-
const resolveTargetDocumentId = options.dryRun || normalizedDocumentId
|
|
77
|
-
? undefined
|
|
78
|
-
: createFolderDocumentResolver(runtime, options);
|
|
76
|
+
const resolveTargetDocumentId = options.dryRun || normalizedDocumentId ? undefined : createFolderDocumentResolver(runtime, options);
|
|
79
77
|
const results = [];
|
|
80
78
|
for (let index = 0; index < inputSet.markdownFiles.length; index += 1) {
|
|
81
79
|
const markdownPath = inputSet.markdownFiles[index];
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { applyStandaloneAttachmentTransforms } from '../../publish/asset-adapter.js';
|
|
2
2
|
export { patchBTTForMermaidAndAssets } from '../../publish/btt-patch.js';
|
|
3
3
|
export { buildPipelineDocumentId } from '../../publish/ids.js';
|
|
4
|
-
export { applyTableColumnWidthHeuristics, collectMermaidPatches, ensureLastBlockBttIds } from '../../publish/last-normalize.js';
|
|
4
|
+
export { applyTableColumnWidthHeuristics, collectMermaidPatches, ensureLastBlockBttIds, } from '../../publish/last-normalize.js';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { buildLASTIndexes, flattenTreeBlocks, fromRawBlockToLAST
|
|
1
|
+
import { buildLASTIndexes, flattenTreeBlocks, fromRawBlockToLAST } from './codec-btt-to-last.js';
|
|
2
2
|
import { normalizeDocumentIdToLAST } from './codec-last-to-btt.js';
|
|
3
3
|
export function convertBTTToLAST(bttDoc) {
|
|
4
4
|
const rawBlocks = Object.keys(bttDoc.flatBlocks ?? {}).length
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { createDocumentChildren
|
|
2
|
-
import { DEFAULT_MERMAID_RENDER_CONFIG
|
|
1
|
+
import { createDocumentChildren } from './ops.js';
|
|
2
|
+
import { DEFAULT_MERMAID_RENDER_CONFIG } from './render-types.js';
|
|
3
3
|
import { applyCreatedBoardMermaid, applyCreatedFileBlock, applyCreatedImageBlock } from './render-post-process.js';
|
|
4
4
|
import { renderCreatedTableNode } from './render-table.js';
|
|
5
5
|
import { buildCreatePayloadFromRawBlock, createRenderBatchEntry, getSourceBlockId, toObjectRecord, } from './render-payload.js';
|
|
@@ -124,7 +124,8 @@ export function canUseElementsOnlyPatch(rawBlock) {
|
|
|
124
124
|
if (effectiveEntries.length === 0)
|
|
125
125
|
return true;
|
|
126
126
|
for (const [key, value] of effectiveEntries) {
|
|
127
|
-
if (key === 'align' &&
|
|
127
|
+
if (key === 'align' &&
|
|
128
|
+
(value === 1 || value === 2 || value === 3 || value === 'left' || value === 'center' || value === 'right')) {
|
|
128
129
|
continue;
|
|
129
130
|
}
|
|
130
131
|
return false;
|
|
@@ -310,7 +311,12 @@ export function getSourceBlockId(node, rawBlockRecord) {
|
|
|
310
311
|
: node.blockId;
|
|
311
312
|
}
|
|
312
313
|
function isBatchSafeBlockType(blockType) {
|
|
313
|
-
if (blockType === 1 ||
|
|
314
|
+
if (blockType === 1 ||
|
|
315
|
+
blockType === 23 ||
|
|
316
|
+
blockType === 27 ||
|
|
317
|
+
blockType === 31 ||
|
|
318
|
+
blockType === 32 ||
|
|
319
|
+
blockType === 43) {
|
|
314
320
|
return false;
|
|
315
321
|
}
|
|
316
322
|
return true;
|
|
@@ -33,7 +33,9 @@ export async function applyCreatedImageBlock(client, documentId, createdBlockId,
|
|
|
33
33
|
...(typeof width === 'number' ? { width } : {}),
|
|
34
34
|
...(typeof proportionalHeight === 'number' ? { height: proportionalHeight } : {}),
|
|
35
35
|
...(image && typeof image.align === 'number' ? { align: image.align } : {}),
|
|
36
|
-
...(image && toObjectRecord(image.caption)
|
|
36
|
+
...(image && toObjectRecord(image.caption)
|
|
37
|
+
? { caption: toObjectRecord(image.caption) }
|
|
38
|
+
: {}),
|
|
37
39
|
...(image && typeof image.scale === 'number' ? { scale: image.scale } : {}),
|
|
38
40
|
};
|
|
39
41
|
let imageToken = await uploadBinaryToNode(client, 'docx_image', createdBlockId, localPath, authOptions, mediaLimiter);
|
|
@@ -145,7 +145,7 @@ function createDividerBlock(ctx, parentId) {
|
|
|
145
145
|
});
|
|
146
146
|
return blockId;
|
|
147
147
|
}
|
|
148
|
-
function createImageBlock(ctx, parentId, sourceUrl) {
|
|
148
|
+
function createImageBlock(ctx, parentId, sourceUrl, alt = null) {
|
|
149
149
|
const blockId = nextBlockId(ctx);
|
|
150
150
|
const parentBlock = ctx.blocks[parentId];
|
|
151
151
|
const blockBase = {
|
|
@@ -155,8 +155,15 @@ function createImageBlock(ctx, parentId, sourceUrl) {
|
|
|
155
155
|
children: [],
|
|
156
156
|
payload: createDefaultImagePayload(parentBlock?.type),
|
|
157
157
|
};
|
|
158
|
+
const selectorAttrs = {};
|
|
158
159
|
if (sourceUrl) {
|
|
159
|
-
|
|
160
|
+
selectorAttrs.sourceUrl = sourceUrl;
|
|
161
|
+
}
|
|
162
|
+
if (alt) {
|
|
163
|
+
selectorAttrs.alt = alt;
|
|
164
|
+
}
|
|
165
|
+
if (Object.keys(selectorAttrs).length > 0) {
|
|
166
|
+
blockBase.selector = { attrs: selectorAttrs };
|
|
160
167
|
}
|
|
161
168
|
addBlock(ctx, blockBase);
|
|
162
169
|
return blockId;
|
|
@@ -358,14 +365,31 @@ function isWhitespaceTextNode(node) {
|
|
|
358
365
|
function getMeaningfulChildren(nodes) {
|
|
359
366
|
return nodes.filter((child) => !isWhitespaceTextNode(child));
|
|
360
367
|
}
|
|
361
|
-
function
|
|
368
|
+
function extractImageSourceFromElement(element) {
|
|
369
|
+
if (element.tagName === 'img') {
|
|
370
|
+
return {
|
|
371
|
+
sourceUrl: getStringProp(element, 'src'),
|
|
372
|
+
alt: getStringProp(element, 'alt'),
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
if (element.tagName !== 'a')
|
|
376
|
+
return null;
|
|
377
|
+
const meaningfulChildren = getMeaningfulChildren(getChildren(element));
|
|
378
|
+
if (meaningfulChildren.length !== 1)
|
|
379
|
+
return null;
|
|
380
|
+
const only = meaningfulChildren[0];
|
|
381
|
+
if (!only || !isElement(only))
|
|
382
|
+
return null;
|
|
383
|
+
return extractImageSourceFromElement(only);
|
|
384
|
+
}
|
|
385
|
+
function findStandaloneImageInParagraph(paragraph) {
|
|
362
386
|
const meaningfulChildren = getMeaningfulChildren(getChildren(paragraph));
|
|
363
387
|
if (meaningfulChildren.length !== 1)
|
|
364
388
|
return null;
|
|
365
389
|
const only = meaningfulChildren[0];
|
|
366
|
-
if (!only || !isElement(only)
|
|
390
|
+
if (!only || !isElement(only))
|
|
367
391
|
return null;
|
|
368
|
-
return
|
|
392
|
+
return extractImageSourceFromElement(only);
|
|
369
393
|
}
|
|
370
394
|
function parseHttpUrl(url) {
|
|
371
395
|
try {
|
|
@@ -472,10 +496,11 @@ function findStandaloneRichItemInTableCell(cell) {
|
|
|
472
496
|
}
|
|
473
497
|
if (!only || !isElement(only))
|
|
474
498
|
return null;
|
|
475
|
-
|
|
499
|
+
const imageSource = extractImageSourceFromElement(only);
|
|
500
|
+
if (imageSource) {
|
|
476
501
|
return {
|
|
477
502
|
kind: 'image',
|
|
478
|
-
|
|
503
|
+
...imageSource,
|
|
479
504
|
};
|
|
480
505
|
}
|
|
481
506
|
if (only.tagName !== 'a')
|
|
@@ -667,7 +692,7 @@ function convertTable(ctx, table, parentId) {
|
|
|
667
692
|
const cellBlock = ctx.blocks[cellId];
|
|
668
693
|
const richItem = cell ? findStandaloneRichItemInTableCell(cell) : null;
|
|
669
694
|
if (cellBlock?.type === 'table_cell' && richItem?.kind === 'image') {
|
|
670
|
-
const imageId = createImageBlock(ctx, cellId, richItem.sourceUrl);
|
|
695
|
+
const imageId = createImageBlock(ctx, cellId, richItem.sourceUrl, richItem.alt);
|
|
671
696
|
cellBlock.children = [imageId];
|
|
672
697
|
cells.push(cellId);
|
|
673
698
|
continue;
|
|
@@ -733,6 +758,44 @@ function convertUnknownElement(ctx, element, parentId) {
|
|
|
733
758
|
]),
|
|
734
759
|
];
|
|
735
760
|
}
|
|
761
|
+
function hasNonWhitespaceInline(inlines) {
|
|
762
|
+
return inlines.some((inline) => toSearchText(inline).text.trim().length > 0);
|
|
763
|
+
}
|
|
764
|
+
function convertParagraph(ctx, paragraph, parentId) {
|
|
765
|
+
const standaloneImage = findStandaloneImageInParagraph(paragraph);
|
|
766
|
+
if (standaloneImage?.sourceUrl) {
|
|
767
|
+
return [createImageBlock(ctx, parentId, standaloneImage.sourceUrl, standaloneImage.alt)];
|
|
768
|
+
}
|
|
769
|
+
const standaloneIframe = findStandaloneIframePayloadInParagraph(paragraph);
|
|
770
|
+
if (standaloneIframe) {
|
|
771
|
+
return [createIframeBlock(ctx, parentId, standaloneIframe.url, standaloneIframe.iframeType)];
|
|
772
|
+
}
|
|
773
|
+
const ids = [];
|
|
774
|
+
let pendingInlineNodes = [];
|
|
775
|
+
const flushText = () => {
|
|
776
|
+
if (pendingInlineNodes.length === 0)
|
|
777
|
+
return;
|
|
778
|
+
const inlines = parseInlineNodes(ctx, pendingInlineNodes);
|
|
779
|
+
pendingInlineNodes = [];
|
|
780
|
+
if (!hasNonWhitespaceInline(inlines))
|
|
781
|
+
return;
|
|
782
|
+
ids.push(createTextualBlock(ctx, 'text', parentId, inlines));
|
|
783
|
+
};
|
|
784
|
+
for (const child of getChildren(paragraph)) {
|
|
785
|
+
const image = isElement(child) ? extractImageSourceFromElement(child) : null;
|
|
786
|
+
if (image?.sourceUrl) {
|
|
787
|
+
flushText();
|
|
788
|
+
ids.push(createImageBlock(ctx, parentId, image.sourceUrl, image.alt));
|
|
789
|
+
continue;
|
|
790
|
+
}
|
|
791
|
+
pendingInlineNodes.push(child);
|
|
792
|
+
}
|
|
793
|
+
flushText();
|
|
794
|
+
if (ids.length > 0) {
|
|
795
|
+
return ids;
|
|
796
|
+
}
|
|
797
|
+
return [createTextualBlock(ctx, 'text', parentId, parseInlineNodes(ctx, getChildren(paragraph)))];
|
|
798
|
+
}
|
|
736
799
|
function convertBlock(ctx, node, parentId) {
|
|
737
800
|
if (isWhitespaceTextNode(node)) {
|
|
738
801
|
return [];
|
|
@@ -753,17 +816,8 @@ function convertBlock(ctx, node, parentId) {
|
|
|
753
816
|
return [];
|
|
754
817
|
}
|
|
755
818
|
switch (node.tagName) {
|
|
756
|
-
case 'p':
|
|
757
|
-
|
|
758
|
-
if (standaloneImageSrc) {
|
|
759
|
-
return [createImageBlock(ctx, parentId, standaloneImageSrc)];
|
|
760
|
-
}
|
|
761
|
-
const standaloneIframe = findStandaloneIframePayloadInParagraph(node);
|
|
762
|
-
if (standaloneIframe) {
|
|
763
|
-
return [createIframeBlock(ctx, parentId, standaloneIframe.url, standaloneIframe.iframeType)];
|
|
764
|
-
}
|
|
765
|
-
return [createTextualBlock(ctx, 'text', parentId, parseInlineNodes(ctx, getChildren(node)))];
|
|
766
|
-
}
|
|
819
|
+
case 'p':
|
|
820
|
+
return convertParagraph(ctx, node, parentId);
|
|
767
821
|
case 'h1':
|
|
768
822
|
case 'h2':
|
|
769
823
|
case 'h3':
|
|
@@ -789,7 +843,7 @@ function convertBlock(ctx, node, parentId) {
|
|
|
789
843
|
case 'table':
|
|
790
844
|
return convertTable(ctx, node, parentId);
|
|
791
845
|
case 'img':
|
|
792
|
-
return [createImageBlock(ctx, parentId, getStringProp(node, 'src'))];
|
|
846
|
+
return [createImageBlock(ctx, parentId, getStringProp(node, 'src'), getStringProp(node, 'alt'))];
|
|
793
847
|
case 'br':
|
|
794
848
|
return [
|
|
795
849
|
createTextualBlock(ctx, 'text', parentId, [
|
|
@@ -4,12 +4,12 @@ import remarkGfm from 'remark-gfm';
|
|
|
4
4
|
import remarkMath from 'remark-math';
|
|
5
5
|
import remarkRehype from 'remark-rehype';
|
|
6
6
|
import { normalizeMarkdownBeforeParse } from './normalize-markdown.js';
|
|
7
|
-
export async function markdownToHast(markdown) {
|
|
7
|
+
export async function markdownToHast(markdown, options = {}) {
|
|
8
8
|
const content = normalizeMarkdownBeforeParse(markdown);
|
|
9
9
|
const processor = unified()
|
|
10
10
|
.use(remarkParse)
|
|
11
11
|
.use(remarkGfm)
|
|
12
|
-
.use(remarkMath, { singleDollarTextMath: false })
|
|
12
|
+
.use(remarkMath, { singleDollarTextMath: options.singleDollarTextMath ?? false })
|
|
13
13
|
.use(remarkRehype, { allowDangerousHtml: false });
|
|
14
14
|
const mdast = processor.parse(content);
|
|
15
15
|
const hast = await processor.run(mdast);
|
|
@@ -345,6 +345,7 @@ export function renderHASTToTerminal(root, options = {}) {
|
|
|
345
345
|
return `${ctx.lines.join('\n')}\n`;
|
|
346
346
|
}
|
|
347
347
|
export async function renderMarkdownToTerminal(markdown, options = {}) {
|
|
348
|
-
const
|
|
348
|
+
const parseOptions = options.singleDollarTextMath === undefined ? {} : { singleDollarTextMath: options.singleDollarTextMath };
|
|
349
|
+
const hast = await markdownToHast(markdown, parseOptions);
|
|
349
350
|
return renderHASTToTerminal(hast, options);
|
|
350
351
|
}
|
|
@@ -44,7 +44,9 @@ function applyRawBlockPatch(rawBlock, blockId, mermaidByBlockId, assetByBlockId,
|
|
|
44
44
|
file.media_kind = asset.mediaKind;
|
|
45
45
|
}
|
|
46
46
|
if (typeof file.view_type !== 'number') {
|
|
47
|
-
file.view_type = shouldUsePreviewView(path.extname(asset.fileName).toLowerCase(), asset.mediaKind ?? 'file')
|
|
47
|
+
file.view_type = shouldUsePreviewView(path.extname(asset.fileName).toLowerCase(), asset.mediaKind ?? 'file')
|
|
48
|
+
? 2
|
|
49
|
+
: 1;
|
|
48
50
|
}
|
|
49
51
|
rawBlock.file = file;
|
|
50
52
|
}
|
package/dist/publish/index.js
CHANGED
|
@@ -2,6 +2,6 @@ export { applyStandaloneAttachmentTransforms } from './asset-adapter.js';
|
|
|
2
2
|
export { patchBTTForMermaidAndAssets } from './btt-patch.js';
|
|
3
3
|
export { buildPipelineDocumentId } from './ids.js';
|
|
4
4
|
export { applyTableColumnWidthHeuristics, collectMermaidPatches, ensureLastBlockBttIds } from './last-normalize.js';
|
|
5
|
-
export { processSingleMarkdownFile } from './process-file.js';
|
|
6
|
-
export { buildPublishRuntime, logPublishRuntimeSummary } from './runtime.js';
|
|
5
|
+
export { processSingleMarkdownFile, } from './process-file.js';
|
|
6
|
+
export { buildPublishRuntime, logPublishRuntimeSummary, } from './runtime.js';
|
|
7
7
|
export { buildPipelineStagePaths, ensureDir, writeJson, writeSourceStage, writePrepareStage, writePrepareLogFile, writeHastStage, writeLastStage, writeBttStage, writePublishStageArtifact, } from './stage-cache.js';
|
|
@@ -2,7 +2,7 @@ import { readFile } from 'node:fs/promises';
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { convertLASTToBTT } from '../interop/index.js';
|
|
4
4
|
import { clearDocumentContent, normalizeDocumentId } from '../lark/docx/ops.js';
|
|
5
|
-
import { renderBTTToDocument
|
|
5
|
+
import { renderBTTToDocument } from '../lark/docx/render-btt.js';
|
|
6
6
|
import { hastToLAST, markdownToHast, prepareMarkdownBeforePublish } from '../pipeline/index.js';
|
|
7
7
|
import { applySingleH1TitleRule, buildTitleForMarkdown } from '../commands/publish-md/title-policy.js';
|
|
8
8
|
import { applyStandaloneAttachmentTransforms } from './asset-adapter.js';
|
|
@@ -95,7 +95,7 @@ export async function processSingleMarkdownFile(params) {
|
|
|
95
95
|
markdown = prepareResult.preparedContent;
|
|
96
96
|
await writePrepareStage(stagePaths, markdown, prepareResult);
|
|
97
97
|
console.error(`[prepare ${index + 1}/${inputSet.markdownFiles.length}] rewritten=${prepareResult.rewrittenCount} downloaded=${prepareResult.downloadedCount} failed=${prepareResult.failedCount} log=${prepareResult.logFilePath}`);
|
|
98
|
-
const hast = await markdownToHast(markdown);
|
|
98
|
+
const hast = await markdownToHast(markdown, runtime.markdownParseConfig);
|
|
99
99
|
await writeHastStage(stagePaths, hast);
|
|
100
100
|
const h1RuleResult = options.title ? {} : applySingleH1TitleRule(hast);
|
|
101
101
|
const title = buildTitleForMarkdown(markdownPath, inputSet, options.title, h1RuleResult.derivedTitle, {
|
package/dist/publish/runtime.js
CHANGED
|
@@ -99,6 +99,9 @@ export function buildPublishRuntime(options, env, markdownPresets) {
|
|
|
99
99
|
...(mermaidBoardDiagramType === undefined ? {} : { diagramType: mermaidBoardDiagramType }),
|
|
100
100
|
},
|
|
101
101
|
};
|
|
102
|
+
const markdownParseConfig = {
|
|
103
|
+
singleDollarTextMath: options.singleDollarTextMath ?? false,
|
|
104
|
+
};
|
|
102
105
|
return {
|
|
103
106
|
env,
|
|
104
107
|
markdownPresets,
|
|
@@ -118,6 +121,7 @@ export function buildPublishRuntime(options, env, markdownPresets) {
|
|
|
118
121
|
downloadRemoteImages,
|
|
119
122
|
...(ytDlpPath ? { ytDlpPath } : {}),
|
|
120
123
|
mermaidRenderConfig,
|
|
124
|
+
markdownParseConfig,
|
|
121
125
|
prepareConfig: {
|
|
122
126
|
enabled: downloadRemoteImages,
|
|
123
127
|
timeoutMs: prepareTimeoutMs,
|
|
@@ -138,6 +142,9 @@ export function logPublishRuntimeSummary(runtime, inputCount, inputMode) {
|
|
|
138
142
|
console.error(runtime.mermaidRenderConfig.target === 'board'
|
|
139
143
|
? `Mermaid: target=board syntax_type=${String(runtime.mermaidRenderConfig.board.syntaxType)} style_type=${String(runtime.mermaidRenderConfig.board.styleType ?? '(default)')} diagram_type=${String(runtime.mermaidRenderConfig.board.diagramType ?? '(default)')}`
|
|
140
144
|
: 'Mermaid: target=text-drawing');
|
|
145
|
+
if (runtime.markdownParseConfig.singleDollarTextMath) {
|
|
146
|
+
console.error('Markdown parse: single_dollar_text_math=true');
|
|
147
|
+
}
|
|
141
148
|
console.error(`Document URL base: ${runtime.documentBaseUrl}`);
|
|
142
149
|
if (runtime.resourceBaseDir) {
|
|
143
150
|
console.error(`Local asset base override: ${runtime.resourceBaseDir}`);
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { readFileSync } from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
const PNG_SIGNATURE = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]);
|
|
4
|
-
const JPEG_SOF_MARKERS = new Set([
|
|
5
|
-
0xc0, 0xc1, 0xc2, 0xc3, 0xc5, 0xc6, 0xc7, 0xc9, 0xca, 0xcb, 0xcd, 0xce, 0xcf,
|
|
6
|
-
]);
|
|
4
|
+
const JPEG_SOF_MARKERS = new Set([0xc0, 0xc1, 0xc2, 0xc3, 0xc5, 0xc6, 0xc7, 0xc9, 0xca, 0xcb, 0xcd, 0xce, 0xcf]);
|
|
7
5
|
function isPositiveInteger(value) {
|
|
8
6
|
return Number.isInteger(value) && value > 0;
|
|
9
7
|
}
|
|
@@ -68,9 +66,7 @@ function readJpegDimensions(buffer) {
|
|
|
68
66
|
return null;
|
|
69
67
|
}
|
|
70
68
|
function readWebpDimensions(buffer) {
|
|
71
|
-
if (buffer.length < 30 ||
|
|
72
|
-
buffer.toString('ascii', 0, 4) !== 'RIFF' ||
|
|
73
|
-
buffer.toString('ascii', 8, 12) !== 'WEBP') {
|
|
69
|
+
if (buffer.length < 30 || buffer.toString('ascii', 0, 4) !== 'RIFF' || buffer.toString('ascii', 8, 12) !== 'WEBP') {
|
|
74
70
|
return null;
|
|
75
71
|
}
|
|
76
72
|
const chunkType = buffer.toString('ascii', 12, 16);
|