UNPKG

yarn-spinner-runner-ts

Version:

TypeScript parser, compiler, and runtime for Yarn Spinner 3.x with React adapter [NPM package](https://www.npmjs.com/package/yarn-spinner-runner-ts)

78 lines 2.97 kB
// Minimal indentation-sensitive lexer to support options and their bodies. export function lex(input) { const lines = input.replace(/\r\n?/g, "\n").split("\n"); const tokens = []; const indentStack = [0]; let inHeaders = true; function push(type, text, line, column) { tokens.push({ type, text, line, column }); } for (let i = 0; i < lines.length; i++) { const raw = lines[i]; const lineNum = i + 1; const indent = raw.match(/^[ \t]*/)?.[0] ?? ""; const content = raw.slice(indent.length); if (content.trim() === "") { push("EMPTY", "", lineNum, 1); continue; } // Manage indentation tokens only within node bodies and on non-empty lines if (!inHeaders) { const prev = indentStack[indentStack.length - 1]; if (indent.length > prev) { indentStack.push(indent.length); push("INDENT", "", lineNum, 1); } else if (indent.length < prev) { while (indentStack.length && indent.length < indentStack[indentStack.length - 1]) { indentStack.pop(); push("DEDENT", "", lineNum, 1); } } } if (content === "---") { inHeaders = false; push("NODE_START", content, lineNum, indent.length + 1); continue; } if (content === "===") { inHeaders = true; // flush indentation to root while (indentStack.length > 1) { indentStack.pop(); push("DEDENT", "", lineNum, 1); } push("NODE_END", content, lineNum, indent.length + 1); continue; } // Header: key: value (only valid while inHeaders) if (inHeaders) { const m = content.match(/^([A-Za-z_][A-Za-z0-9_]*)\s*:\s*(.*)$/); if (m) { push("HEADER_KEY", m[1], lineNum, indent.length + 1); push("HEADER_VALUE", m[2], lineNum, indent.length + 1 + m[0].indexOf(m[2])); continue; } } if (content.startsWith("->")) { push("OPTION", content.slice(2).trim(), lineNum, indent.length + 1); continue; } // Commands like <<...>> (single line) const cmd = content.match(/^<<(.+?)>>\s*$/); if (cmd) { push("COMMAND", cmd[1].trim(), lineNum, indent.length + 1); continue; } // Plain text line push("TEXT", content, lineNum, indent.length + 1); } // close remaining indentation at EOF while (indentStack.length > 1) { indentStack.pop(); tokens.push({ type: "DEDENT", text: "", line: lines.length, column: 1 }); } tokens.push({ type: "EOF", text: "", line: lines.length + 1, column: 1 }); return tokens; } //# sourceMappingURL=lexer.js.map