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:
@@ -26,8 +26,12 @@ import type { StatSheet } from "../../cli/completions/types";
|
||||
import {
|
||||
FENCED_BLOCK_RE,
|
||||
parseBlockAttrs,
|
||||
parseSparkTableCsv,
|
||||
} from "../../cli/completions/block-scanner";
|
||||
import {
|
||||
scanDirectives,
|
||||
buildSparkTableCompletion,
|
||||
inspectSparkTableCsv,
|
||||
} from "../../cli/completions/directive-scanner";
|
||||
|
||||
export type { StatDef, StatTemplate, StatSheet };
|
||||
|
||||
@@ -105,26 +109,24 @@ async function scanClientSide(): Promise<JournalCompletions> {
|
||||
const sparkTables: SparkTableCompletion[] = [];
|
||||
const stats: StatDef[] = [];
|
||||
const statTemplates: StatTemplate[] = [];
|
||||
const tagRegex = /:md-dice\[([^[]+)\]/gi;
|
||||
|
||||
// Build a temporary index for resolving CSV paths
|
||||
const tempIndex: Record<string, string> = {};
|
||||
|
||||
// First pass: load all .md content into temp index
|
||||
for (const filePath of paths) {
|
||||
const content = await getIndexedData(filePath);
|
||||
if (content) tempIndex[filePath] = content;
|
||||
}
|
||||
|
||||
for (const filePath of paths) {
|
||||
const content = tempIndex[filePath];
|
||||
if (!content) continue;
|
||||
|
||||
// Fresh slugger per file
|
||||
const slugger = new Slugger();
|
||||
|
||||
// ---- Dice directives ----
|
||||
let match: RegExpExecArray | null;
|
||||
tagRegex.lastIndex = 0;
|
||||
while ((match = tagRegex.exec(content)) !== null) {
|
||||
const raw = match[1].trim();
|
||||
if (!raw || raw.length > 80) continue;
|
||||
if (!/^\d*d\d+/i.test(raw) && !/^[+-]/.test(raw)) continue;
|
||||
dice.push({ label: raw, notation: raw, source: filePath });
|
||||
}
|
||||
|
||||
// ---- Links (headings) ----
|
||||
// ---- Links (headings) - from original content ----
|
||||
const basePath = filePath.replace(/\.md$/, "");
|
||||
const fileName = basePath.split("/").filter(Boolean).pop() || basePath;
|
||||
links.push({ path: basePath, label: fileName, section: null });
|
||||
@@ -136,7 +138,7 @@ async function scanClientSide(): Promise<JournalCompletions> {
|
||||
});
|
||||
}
|
||||
|
||||
// ---- Unified block scanning ----
|
||||
// ---- Unified block scanning (stats) ----
|
||||
FENCED_BLOCK_RE.lastIndex = 0;
|
||||
let blockMatch: RegExpExecArray | null;
|
||||
while ((blockMatch = FENCED_BLOCK_RE.exec(content)) !== null) {
|
||||
@@ -164,12 +166,13 @@ async function scanClientSide(): Promise<JournalCompletions> {
|
||||
stats.push(...result.modifierDefs);
|
||||
statTemplates.push(result.template);
|
||||
}
|
||||
|
||||
if (attrs.role === "spark-table") {
|
||||
const parsed = parseSparkTableCsv(body, filePath, slugger);
|
||||
if (parsed) sparkTables.push(parsed);
|
||||
}
|
||||
}
|
||||
|
||||
// ---- Directive scanning (dice + spark tables) ----
|
||||
const fileDir = filePath.split("/").slice(0, -1).join("/") || ".";
|
||||
const directiveResult = scanDirectives(content, filePath, tempIndex, fileDir);
|
||||
dice.push(...directiveResult.dice);
|
||||
sparkTables.push(...directiveResult.sparkTables);
|
||||
}
|
||||
|
||||
return { dice, links, sparkTables, stats, statTemplates, statSheets: [] };
|
||||
|
||||
Reference in New Issue
Block a user