refactor(completions): centralize content scanning
Add a browser-safe ContentRegistry owning path and inline content stores, then derive completions from it. Remove the old block-processor, directive-scanner, and link-source modules in favor of scanDoc, deriveCompletions, and injectSparkDirectives, and register an inline resolver for the frontend file index.
This commit is contained in:
@@ -16,49 +16,21 @@
|
||||
*/
|
||||
|
||||
import { parse } from "csv-parse/browser/esm/sync";
|
||||
import { FENCED_BLOCK_RE, parseBlockAttrs } from "./block-scanner.js";
|
||||
|
||||
/**
|
||||
* Scan markdown content for ```csv role=declare blocks and return
|
||||
* parsed declarations and tag modifiers. Shared between CLI and client.
|
||||
*/
|
||||
export function scanDeclareBlocks(content: string, filePath: string): DeclareResult {
|
||||
const variables: VarDeclaration[] = [];
|
||||
const tagModifiers: TagModifier[] = [];
|
||||
|
||||
FENCED_BLOCK_RE.lastIndex = 0;
|
||||
let m: RegExpExecArray | null;
|
||||
while ((m = FENCED_BLOCK_RE.exec(content)) !== null) {
|
||||
const [, , infoString, body] = m;
|
||||
const attrs = parseBlockAttrs(infoString);
|
||||
if (attrs.role !== "declare") continue;
|
||||
|
||||
try {
|
||||
const result = parseDeclareCsv(body, filePath);
|
||||
variables.push(...result.variables);
|
||||
tagModifiers.push(...result.tagModifiers);
|
||||
} catch (e) {
|
||||
console.warn(`[declare-parser] ${filePath}: ${e}`);
|
||||
}
|
||||
}
|
||||
|
||||
return { variables, tagModifiers };
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Types
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export interface VarDeclaration {
|
||||
key: string; // "$hp" (always starts with $)
|
||||
key: string; // "$hp" (always starts with $)
|
||||
expression: string; // "$con*5+$mod_hp"
|
||||
}
|
||||
|
||||
export interface TagModifier {
|
||||
tag: string; // "#warrior"
|
||||
target: string; // "$mod_hp"
|
||||
tag: string; // "#warrior"
|
||||
target: string; // "$mod_hp"
|
||||
expression: string; // "20"
|
||||
threshold: number; // minimum tagmap count to activate (default 1)
|
||||
threshold: number; // minimum tagmap count to activate (default 1)
|
||||
}
|
||||
|
||||
export interface DeclareResult {
|
||||
@@ -104,14 +76,10 @@ export function parseDeclareCsv(csv: string, source: string): DeclareResult {
|
||||
if (tag) {
|
||||
// Tag modifier
|
||||
if (!tag.startsWith("#")) {
|
||||
throw new Error(
|
||||
`${source}: tag must start with #, got "${tag}"`,
|
||||
);
|
||||
throw new Error(`${source}: tag must start with #, got "${tag}"`);
|
||||
}
|
||||
if (!key.startsWith("$")) {
|
||||
throw new Error(
|
||||
`${source}: key must start with $, got "${key}"`,
|
||||
);
|
||||
throw new Error(`${source}: key must start with $, got "${key}"`);
|
||||
}
|
||||
const thresholdRaw = row.threshold?.trim() ?? "";
|
||||
const threshold = thresholdRaw ? parseInt(thresholdRaw, 10) : 1;
|
||||
@@ -124,13 +92,11 @@ export function parseDeclareCsv(csv: string, source: string): DeclareResult {
|
||||
} else {
|
||||
// Variable declaration
|
||||
if (!key.startsWith("$")) {
|
||||
throw new Error(
|
||||
`${source}: key must start with $, got "${key}"`,
|
||||
);
|
||||
throw new Error(`${source}: key must start with $, got "${key}"`);
|
||||
}
|
||||
variables.push({ key, expression: expr });
|
||||
}
|
||||
}
|
||||
|
||||
return { variables, tagModifiers };
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user