refactor: move spark table parsing to directive scanner
Relocate spark table logic from the block processor to a dedicated directive scanner. This allows spark tables to be treated as `:md-table` directives and ensures they are processed in a second pass after the content index is fully populated.
This commit is contained in:
@@ -15,6 +15,10 @@ import {
|
||||
processBlocks,
|
||||
type ProcessedBlocks,
|
||||
} from "../completions/block-processor.js";
|
||||
import {
|
||||
scanDirectives,
|
||||
type DirectiveScanResult,
|
||||
} from "../completions/directive-scanner.js";
|
||||
import type { StatSheet } from "../completions/types.js";
|
||||
|
||||
interface ContentIndex {
|
||||
@@ -106,14 +110,16 @@ function labelFromId(id: string): string {
|
||||
export function scanDirectory(dir: string): {
|
||||
index: ContentIndex;
|
||||
blocks: ProcessedBlocks;
|
||||
directiveResults: DirectiveScanResult[];
|
||||
} {
|
||||
const index: ContentIndex = {};
|
||||
const blocks: ProcessedBlocks = {
|
||||
stats: [],
|
||||
statTemplates: [],
|
||||
sparkTables: [],
|
||||
statSheets: [],
|
||||
};
|
||||
const directiveResults: DirectiveScanResult[] = [];
|
||||
const mdFiles: { content: string; relPath: string }[] = [];
|
||||
|
||||
function scan(currentPath: string, relativePath: string) {
|
||||
const entries = readdirSync(currentPath);
|
||||
@@ -141,7 +147,7 @@ export function scanDirectory(dir: string): {
|
||||
index[normalizedRelPath] = result.stripped;
|
||||
blocks.stats.push(...result.blocks.stats);
|
||||
blocks.statTemplates.push(...result.blocks.statTemplates);
|
||||
blocks.sparkTables.push(...result.blocks.sparkTables);
|
||||
mdFiles.push({ content: result.stripped, relPath: normalizedRelPath });
|
||||
} else if (entry.endsWith(".sheet.svg")) {
|
||||
index[normalizedRelPath] = content;
|
||||
const id = entry.replace(/\.sheet\.svg$/i, "");
|
||||
@@ -164,7 +170,32 @@ export function scanDirectory(dir: string): {
|
||||
}
|
||||
|
||||
scan(dir, "");
|
||||
return { index, blocks };
|
||||
|
||||
// ---- Directive scanning pass (after all blocks processed) ----
|
||||
const posixDir = dir.split(sep).join("/");
|
||||
for (const { content, relPath } of mdFiles) {
|
||||
const fileDir = posixRelDir(relPath);
|
||||
const result = scanDirectives(content, relPath, index, fileDir);
|
||||
|
||||
// Apply rewritten content back to index
|
||||
index[relPath] = result.rewritten;
|
||||
|
||||
// Inject new index entries (inline CSV bodies)
|
||||
for (const [key, value] of Object.entries(result.newIndexEntries)) {
|
||||
index[key] = value;
|
||||
}
|
||||
|
||||
directiveResults.push(result);
|
||||
}
|
||||
|
||||
return { index, blocks, directiveResults };
|
||||
}
|
||||
|
||||
/** Get the POSIX directory of a file path */
|
||||
function posixRelDir(filePath: string): string {
|
||||
const parts = filePath.split("/");
|
||||
parts.pop();
|
||||
return parts.join("/") || ".";
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -310,9 +341,9 @@ export function createContentServer(
|
||||
let collectedBlocks: ProcessedBlocks = {
|
||||
stats: [],
|
||||
statTemplates: [],
|
||||
sparkTables: [],
|
||||
statSheets: [],
|
||||
};
|
||||
let directiveResults: DirectiveScanResult[] = [];
|
||||
let completionsIndex: CompletionsPayload = {
|
||||
dice: [],
|
||||
links: [],
|
||||
@@ -324,7 +355,7 @@ export function createContentServer(
|
||||
|
||||
/** 从当前内容索引和已收集的块重新扫描补全数据 */
|
||||
function recomputeCompletions(): void {
|
||||
completionsIndex = scanCompletions(contentIndex, collectedBlocks);
|
||||
completionsIndex = scanCompletions(contentIndex, collectedBlocks, directiveResults);
|
||||
console.log(
|
||||
`[completions] dice=${completionsIndex.dice.length} links=${completionsIndex.links.length} sparkTables=${completionsIndex.sparkTables.length} stats=${completionsIndex.stats.length} templates=${completionsIndex.statTemplates.length} sheets=${completionsIndex.statSheets.length}`,
|
||||
);
|
||||
@@ -335,6 +366,7 @@ export function createContentServer(
|
||||
const scanResult = scanDirectory(contentDir);
|
||||
contentIndex = scanResult.index;
|
||||
collectedBlocks = scanResult.blocks;
|
||||
directiveResults = scanResult.directiveResults;
|
||||
console.log(`已索引 ${Object.keys(contentIndex).length} 个文件`);
|
||||
recomputeCompletions();
|
||||
|
||||
@@ -363,12 +395,14 @@ export function createContentServer(
|
||||
// Re-scan to get fresh blocks (simpler than per-file merge)
|
||||
const rescan = scanDirectory(contentDir);
|
||||
collectedBlocks = rescan.blocks;
|
||||
directiveResults = rescan.directiveResults;
|
||||
recomputeCompletions();
|
||||
} else {
|
||||
contentIndex[relPath] = content;
|
||||
if (relPath.endsWith(".sheet.svg")) {
|
||||
const rescan = scanDirectory(contentDir);
|
||||
collectedBlocks = rescan.blocks;
|
||||
directiveResults = rescan.directiveResults;
|
||||
recomputeCompletions();
|
||||
}
|
||||
}
|
||||
@@ -393,12 +427,14 @@ export function createContentServer(
|
||||
contentIndex[relPath] = result.stripped;
|
||||
const rescan = scanDirectory(contentDir);
|
||||
collectedBlocks = rescan.blocks;
|
||||
directiveResults = rescan.directiveResults;
|
||||
recomputeCompletions();
|
||||
} else {
|
||||
contentIndex[relPath] = content;
|
||||
if (relPath.endsWith(".sheet.svg")) {
|
||||
const rescan = scanDirectory(contentDir);
|
||||
collectedBlocks = rescan.blocks;
|
||||
directiveResults = rescan.directiveResults;
|
||||
recomputeCompletions();
|
||||
}
|
||||
}
|
||||
@@ -421,6 +457,7 @@ export function createContentServer(
|
||||
if (relPath.endsWith(".md") || relPath.endsWith(".sheet.svg")) {
|
||||
const rescan = scanDirectory(contentDir);
|
||||
collectedBlocks = rescan.blocks;
|
||||
directiveResults = rescan.directiveResults;
|
||||
recomputeCompletions();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user