UNPKG

@nitrogenbuilder/client-core

Version:

Nitrogen Builder Core Client

108 lines (93 loc) 2.69 kB
import type { ParsedFilter } from './templateFilters.js'; export interface ParsedSegmentPart { type: 'path' | 'literal'; value: string; filters: ParsedFilter[]; } export interface ParsedSegment { parts: ParsedSegmentPart[]; } export function parseSegment(raw: string): ParsedSegment { const trimmed = raw.trim(); const parts: ParsedSegmentPart[] = []; const tokens = splitOnPlus(trimmed); for (const token of tokens) { const t = token.trim(); if ( (t.startsWith("'") && t.endsWith("'")) || (t.startsWith('"') && t.endsWith('"')) ) { parts.push({ type: 'literal', value: t.slice(1, -1), filters: [] }); } else { const colonParts = splitOnColons(t); const path = colonParts[0]; const filters = colonParts.slice(1).map(parseFilterToken); parts.push({ type: 'path', value: path, filters }); } } return { parts }; } function parseFilterToken(token: string): ParsedFilter { const parenIndex = token.indexOf('('); if (parenIndex === -1) { return { name: token, args: [] }; } const name = token.slice(0, parenIndex); const argsStr = token.slice(parenIndex + 1, -1); // strip parens const args = splitArgs(argsStr).map(parseArg); return { name, args }; } function parseArg(raw: string): string | number { const trimmed = raw.trim(); if ( (trimmed.startsWith("'") && trimmed.endsWith("'")) || (trimmed.startsWith('"') && trimmed.endsWith('"')) ) { return trimmed.slice(1, -1); } const num = Number(trimmed); return isNaN(num) ? trimmed : num; } /** Split on `+` outside of quotes and parentheses */ function splitOnPlus(str: string): string[] { return splitOutside(str, '+'); } /** Split on `:` outside of quotes and parentheses */ function splitOnColons(str: string): string[] { return splitOutside(str, ':'); } /** Split on `,` outside of quotes and parentheses */ function splitArgs(str: string): string[] { return splitOutside(str, ','); } function splitOutside(str: string, delimiter: string): string[] { const results: string[] = []; let current = ''; let inQuote: string | false = false; let parenDepth = 0; for (let i = 0; i < str.length; i++) { const ch = str[i]; if ((ch === "'" || ch === '"') && parenDepth === 0 && !inQuote) { inQuote = ch; current += ch; } else if (inQuote && ch === inQuote) { inQuote = false; current += ch; } else if (inQuote) { current += ch; } else if (ch === '(') { parenDepth++; current += ch; } else if (ch === ')') { parenDepth--; current += ch; } else if (ch === delimiter && parenDepth === 0) { results.push(current); current = ''; } else { current += ch; } } if (current) results.push(current); return results; }