@meldscience/meld
Version:
pipeable one-shot prompt scripting toolkit
161 lines • 6.94 kB
JavaScript
"use strict";
/**
* extractPlaceholders.ts
*
* Extracts placeholders from a markdown file.
* Placeholders can be:
* - @cmd[command] - Execute a command
* - @import[file.md#heading] - Import a section from a markdown file
* - @import[file.ts:symbol] - Import a symbol from a code file
* - @import[file.ts:symbol1,symbol2] - Import multiple symbols from a code file
* - @import[file.md#heading as h2] - Import with heading level override
* - @import[file.md#heading as h2 "New Title"] - Import with heading level and text override
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.extractPlaceholders = extractPlaceholders;
const CMD_REGEX = /@cmd\[(.*?)\]/g;
const IMPORT_REGEX = /@import\[(?<importSpec>[^\]]*)\](?:\s+as\s+(?<asSpec>[^@\n]+))?/g;
const AS_SPEC_REGEX = /^(?<level>#{1,6}|h[1-6])(?:\s+(?<text>[^"\n]+))?$/;
function extractPlaceholders(content) {
const placeholders = [];
const lines = content.split('\n');
lines.forEach((line, index) => {
const lineNumber = index + 1;
let lastIndex = 0;
// Handle all placeholders in order
const allMatches = [];
// Find all cmd matches
CMD_REGEX.lastIndex = 0;
let cmdMatch;
while ((cmdMatch = CMD_REGEX.exec(line)) !== null) {
allMatches.push({ type: 'cmd', match: cmdMatch });
}
// Find all import matches
IMPORT_REGEX.lastIndex = 0;
let importMatch;
while ((importMatch = IMPORT_REGEX.exec(line)) !== null) {
allMatches.push({ type: 'import', match: importMatch });
}
// Sort matches by index
allMatches.sort((a, b) => a.match.index - b.match.index);
// Process matches in order
for (const { type, match } of allMatches) {
if (type === 'cmd') {
placeholders.push({
type: 'cmd',
raw: match[0],
command: match[1],
lineNumber
});
}
else {
const rawDirective = match[0];
const importSpec = match.groups?.importSpec.trim() ?? '';
const asSpec = match.groups?.asSpec?.trim() ?? '';
// Parse the as spec to get heading level and text
let headingLevelOverride;
let headingTextOverride;
if (asSpec) {
console.log('asSpec:', asSpec);
const asMatch = AS_SPEC_REGEX.exec(asSpec);
console.log('asMatch:', asMatch);
if (asMatch?.groups) {
console.log('asMatch.groups:', asMatch.groups);
headingLevelOverride = asMatch.groups.level;
headingTextOverride = asMatch.groups.text;
}
}
// Handle empty import placeholders
if (!importSpec.trim()) {
placeholders.push({
type: 'import',
raw: rawDirective,
lineNumber
});
continue;
}
// Parse the import spec
let filePath;
let specifier;
if (importSpec.includes('#')) {
// Split on the first # only
const firstHash = importSpec.indexOf('#');
filePath = importSpec.slice(0, firstHash).trim();
specifier = importSpec.slice(firstHash + 1).trim();
console.log('importSpec:', importSpec);
console.log('filePath:', filePath);
console.log('specifier:', specifier);
}
else if (importSpec.includes('::')) {
// Split on the first :: only
const firstColon = importSpec.indexOf('::');
filePath = importSpec.slice(0, firstColon).trim();
specifier = importSpec.slice(firstColon + 2).trim();
console.log('importSpec:', importSpec);
console.log('filePath:', filePath);
console.log('specifier:', specifier);
}
else {
filePath = importSpec;
}
if (!specifier) {
placeholders.push({
type: 'import',
raw: rawDirective,
lineNumber,
importPath: filePath
});
continue;
}
// Check if it's a markdown file or code file
const isMarkdown = filePath.endsWith('.md');
if (isMarkdown) {
// Markdown heading import
placeholders.push({
type: 'import',
raw: rawDirective,
lineNumber,
importPath: filePath,
heading: specifier,
headingLevelOverride: headingLevelOverride,
headingTextOverride: headingTextOverride
});
}
else {
// Code symbol import
// Check if it's a list of symbols in brackets
console.log('specifier:', specifier);
// Remove the closing bracket if it exists
if (specifier.endsWith(']')) {
specifier = specifier.slice(0, -1).trim();
}
const symbolMatch = specifier.match(/^\s*\[([^\]]+)\]?\s*$/);
console.log('symbolMatch:', symbolMatch);
if (symbolMatch) {
const symbols = symbolMatch[1].split(',').map(s => s.trim());
console.log('symbols:', symbols);
placeholders.push({
type: 'import',
raw: rawDirective,
lineNumber,
importPath: filePath,
importSymbolList: symbols
});
}
else {
// Single symbol (either myFunction or {interface})
placeholders.push({
type: 'import',
raw: rawDirective,
lineNumber,
importPath: filePath,
importSymbol: specifier.trim()
});
}
}
}
}
});
return placeholders;
}
//# sourceMappingURL=extractPlaceholders.js.map