UNPKG

@meldscience/meld

Version:

pipeable one-shot prompt scripting toolkit

105 lines (93 loc) 3.09 kB
import { readFileSync } from 'fs'; import { dirname } from 'path'; import { unified } from 'unified'; import remarkParse from 'remark-parse'; import remarkStringify, { Options } from 'remark-stringify'; import { remarkMeldDirectives } from './plugins/remarkMeldDirectives'; import { remarkProcessMeldNodes } from './plugins/remarkProcessMeldNodes'; import { remarkMeldDirectiveHandler } from './plugins/remarkMeldDirectiveHandler'; export interface MeldOptions { inputPath: string; workspacePath: string; outputFile?: string; dryRun?: boolean; debug?: boolean; } export interface MeldResult { content: string; errors: string[]; } export async function processMeldFile(options: MeldOptions): Promise<MeldResult> { const { inputPath, workspacePath, debug } = options; try { const content = readFileSync(inputPath, 'utf-8'); // Process the file through our remark pipeline const file = await unified() .use(remarkParse) .use(() => (tree) => { if (debug) console.log('After parse:', JSON.stringify(tree, null, 2)); return tree; }) .use(remarkMeldDirectives) .use(() => (tree) => { if (debug) console.log('After meldDirectives:', JSON.stringify(tree, null, 2)); return tree; }) .use(remarkProcessMeldNodes, { currentFileDir: dirname(inputPath), debug }) .use(() => (tree) => { if (debug) console.log('After processMeldNodes:', JSON.stringify(tree, null, 2)); return tree; }) .use(remarkMeldDirectiveHandler) .use(() => (tree) => { if (debug) console.log('After meldDirectiveHandler:', JSON.stringify(tree, null, 2)); return tree; }) .use(remarkStringify, { // Disable escaping and other markdown processing entities: false, bullet: '-', fence: '`', fences: true, incrementListMarker: true, rule: '-', ruleRepetition: 3, ruleSpaces: false, setext: false, quote: '"', strong: '*', emphasis: '_' } as Options) .process(content); const meldErrors = (file.data as any).meldErrors || []; // Clean up any double newlines and trailing whitespace let processedContent = String(file); processedContent = processedContent.split('\n').map(line => line.trimRight()).join('\n'); processedContent = processedContent.replace(/\n{3,}/g, '\n\n'); processedContent = processedContent.replace(/\n+$/, '\n'); return { content: processedContent, errors: meldErrors }; } catch (error) { if ((error as NodeJS.ErrnoException).code === 'ENOENT') { return { content: '', errors: ['Input file not found'] }; } return { content: '', errors: [`Error processing file: ${(error as Error).message}`] }; } } export class Meld { private options: MeldOptions; constructor(options: MeldOptions) { this.options = options; } async process(): Promise<MeldResult> { return processMeldFile(this.options); } }