@meldscience/meld
Version:
pipeable one-shot prompt scripting toolkit
97 lines (85 loc) • 2.93 kB
text/typescript
import { Node } from 'unist';
import { buildMeldDirectiveNode } from './parseMeldDirective';
import { Handle } from 'mdast-util-to-markdown';
import { Text, Parent, RootContent, RootContentMap } from 'mdast';
import { visit } from 'unist-util-visit';
import { Plugin } from 'unified';
declare module 'mdast' {
interface RootContentMap {
meldDirective: MeldDirectiveNode;
}
}
export interface MeldDirectiveNode extends Node {
type: 'meldDirective';
meldType: 'cmd' | 'import';
raw: string;
lineNumber?: number;
data?: {
command?: string;
importPath?: string;
heading?: string;
importSymbol?: string;
importSymbolList?: string[];
headingLevelOverride?: string;
headingTextOverride?: string;
importWholeFile?: boolean;
};
}
export const remarkMeldDirectives: Plugin = function remarkMeldDirectives() {
return (tree: Node, file: any) => {
// Store the AST in file.data for testing
file.data.ast = tree;
visit(tree, 'text', (node: Text, index: number | null, parent: Parent) => {
if (!node.value || !parent || index === null) return;
const newNodes: RootContent[] = [];
let lastIndex = 0;
const regex = /@(cmd|import)(?:\[([^\[\]]*(?:\[[^\[\]]*\][^\[\]]*)*)\])?(?:\s+as\s+#{1,6}(?:\s+"[^"]*")?)?/g;
let match: RegExpExecArray | null;
console.log('Node value:', node.value);
while ((match = regex.exec(node.value)) !== null) {
const [fullMatch, type, content] = match;
const start = match.index;
console.log('Full match:', fullMatch);
console.log('Type:', type);
console.log('Content:', content);
// Add text before the match
if (start > lastIndex) {
newNodes.push({
type: 'text',
value: node.value.slice(lastIndex, start)
} as Text);
}
try {
if (!content || !fullMatch.includes('[') || !fullMatch.includes(']')) {
throw new Error(type === 'cmd' ? 'Invalid command format' : 'Invalid import format');
}
const meldNode = buildMeldDirectiveNode(fullMatch);
newNodes.push(meldNode);
} catch (err: any) {
// If parsing fails, keep the original text
newNodes.push({
type: 'text',
value: fullMatch
} as Text);
newNodes.push({
type: 'text',
value: ` Error: ${err.message}`
} as Text);
}
lastIndex = start + fullMatch.length;
}
// Add remaining text
if (lastIndex < node.value.length) {
newNodes.push({
type: 'text',
value: node.value.slice(lastIndex)
} as Text);
}
if (newNodes.length > 0) {
// Replace the current node with our new nodes
parent.children.splice(index, 1, ...newNodes);
return index + newNodes.length;
}
});
};
}