...
This commit is contained in:
103
static/js/macro-parser.js
Normal file
103
static/js/macro-parser.js
Normal file
@@ -0,0 +1,103 @@
|
||||
/**
|
||||
* Macro Parser and Processor
|
||||
* Parses HeroScript-style macros from markdown content
|
||||
*/
|
||||
|
||||
class MacroParser {
|
||||
/**
|
||||
* Parse and extract all macros from content
|
||||
* Returns array of { fullMatch, actor, method, params }
|
||||
*/
|
||||
static extractMacros(content) {
|
||||
const macroRegex = /!!([\w.]+)\s*([\s\S]*?)(?=\n!!|\n#|$)/g;
|
||||
const macros = [];
|
||||
let match;
|
||||
|
||||
while ((match = macroRegex.exec(content)) !== null) {
|
||||
const fullMatch = match[0];
|
||||
const actionPart = match[1]; // e.g., "include" or "core.include"
|
||||
const paramsPart = match[2];
|
||||
|
||||
// Parse action: "method" or "actor.method"
|
||||
const [actor, method] = actionPart.includes('.')
|
||||
? actionPart.split('.')
|
||||
: ['core', actionPart];
|
||||
|
||||
// Parse parameters from HeroScript-like syntax
|
||||
const params = this.parseParams(paramsPart);
|
||||
|
||||
macros.push({
|
||||
fullMatch: fullMatch.trim(),
|
||||
actor,
|
||||
method,
|
||||
params,
|
||||
start: match.index,
|
||||
end: match.index + fullMatch.length
|
||||
});
|
||||
}
|
||||
|
||||
return macros;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse HeroScript-style parameters
|
||||
* key: value
|
||||
* key: 'value with spaces'
|
||||
* key: |
|
||||
* multiline
|
||||
* value
|
||||
*/
|
||||
static parseParams(paramsPart) {
|
||||
const params = {};
|
||||
|
||||
if (!paramsPart || !paramsPart.trim()) {
|
||||
return params;
|
||||
}
|
||||
|
||||
// Split by newlines but preserve multiline values
|
||||
const lines = paramsPart.split('\n');
|
||||
let currentKey = null;
|
||||
let currentValue = [];
|
||||
|
||||
for (const line of lines) {
|
||||
const trimmed = line.trim();
|
||||
|
||||
if (!trimmed) continue;
|
||||
|
||||
// Check if this is a key: value line
|
||||
if (trimmed.includes(':')) {
|
||||
// Save previous key-value
|
||||
if (currentKey) {
|
||||
params[currentKey] = currentValue.join('\n').trim();
|
||||
}
|
||||
|
||||
const [key, ...valueParts] = trimmed.split(':');
|
||||
currentKey = key.trim();
|
||||
currentValue = [valueParts.join(':').trim()];
|
||||
} else if (currentKey) {
|
||||
// Continuation of multiline value
|
||||
currentValue.push(trimmed);
|
||||
}
|
||||
}
|
||||
|
||||
// Save last key-value
|
||||
if (currentKey) {
|
||||
params[currentKey] = currentValue.join('\n').trim();
|
||||
}
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if macro is valid
|
||||
*/
|
||||
static validateMacro(macro) {
|
||||
if (!macro.actor || !macro.method) {
|
||||
return { valid: false, error: 'Invalid macro format' };
|
||||
}
|
||||
|
||||
return { valid: true };
|
||||
}
|
||||
}
|
||||
|
||||
window.MacroParser = MacroParser;
|
||||
Reference in New Issue
Block a user