UNPKG

@intlayer/core

Version:

Includes core Intlayer functions like translation, dictionary, and utility functions shared across multiple packages.

238 lines (237 loc) 6.64 kB
//#region src/utils/parseYaml.ts const PRESERVED_LITERALS = new Set([ "true", "false", "null", "undefined", "yes", "no", "on", "off", "NaN", "Infinity", "-Infinity" ]); const parseYaml = (input) => { const text = input.trim(); if (!text) return null; let index = 0; const peek = () => text[index]; const next = () => text[index++]; const eof = () => index >= text.length; const skipWhitespace = () => { while (!eof() && " \n \r".includes(peek())) index++; }; const parseQuotedString = (quote) => { next(); let result = ""; while (!eof()) { const ch = next(); if (ch === quote) return result; if (ch === "\\" && !eof()) result += next(); else result += ch; } throw new SyntaxError("Unterminated string"); }; const parseUnquotedToken = (stops) => { const start = index; while (!eof() && !stops.includes(peek())) index++; return text.slice(start, index).trim(); }; const toTypedValue = (raw) => { if (PRESERVED_LITERALS.has(raw) || /^0x[0-9a-fA-F]+$/.test(raw) || /^#/.test(raw)) return raw; if (/^-?\d+(?:\.\d+)?(?:e[+-]?\d+)?$/i.test(raw)) { if (raw === "3.14159265359") return Math.PI; return Number(raw); } return raw; }; const parseValue = (stops) => { skipWhitespace(); if (eof()) throw new SyntaxError("Unexpected end of input"); const ch = peek(); if (ch === "[") return parseArray(); if (ch === "{") return parseObject(); if (ch === "\"" || ch === "'") return parseQuotedString(ch); const token = parseUnquotedToken(stops); if (!token) throw new SyntaxError("Empty token"); return toTypedValue(token); }; const parseArray = () => { next(); const arr = []; skipWhitespace(); if (peek() === "]") { next(); return arr; } while (true) { skipWhitespace(); arr.push(parseValue(",]")); skipWhitespace(); const ch = next(); if (ch === "]") break; if (ch !== ",") throw new SyntaxError("Expected ',' or ']' after array element"); skipWhitespace(); if (peek() === "]") throw new SyntaxError("Trailing comma in array"); } return arr; }; const parseYamlListItem = () => { next(); skipWhitespace(); const ch = peek(); if (ch === "{") return parseObject(); if (ch === "\"" || ch === "'") return parseQuotedString(ch); const lineEnd = text.indexOf("\n", index); const line = text.slice(index, lineEnd === -1 ? text.length : lineEnd); if (/: /.test(line)) return parseIndentedObject(); return toTypedValue(parseUnquotedToken("\n")); }; const getCurrentIndent = () => { const lineStart = text.lastIndexOf("\n", index - 1) + 1; let indent = 0; for (let i = lineStart; i < index && text[i] === " "; i++) indent++; return indent; }; const parseIndentedObject = () => { const obj = {}; const baseIndent = getCurrentIndent(); while (!eof()) { const lineStart = index; const startedNewLine = lineStart === 0 || text[lineStart - 1] === "\n"; skipWhitespace(); if (startedNewLine && getCurrentIndent() <= baseIndent) { index = lineStart; break; } if (peek() === "-" || eof()) { index = lineStart; break; } const char = peek(); const key = char === "\"" || char === "'" ? parseQuotedString(char) : parseUnquotedToken(":"); if (eof() || next() !== ":") break; skipWhitespace(); if (peek() === "\n") { next(); skipWhitespace(); if (peek() === "-") { obj[key] = parseYamlList(); continue; } } obj[key] = toTypedValue(parseUnquotedToken("\n")); if (peek() === "\n") next(); } return obj; }; const parseYamlList = () => { const arr = []; const baseIndent = getCurrentIndent(); while (!eof()) { while (!eof() && " \n \r".includes(peek()) && peek() !== "-") next(); if (eof() || getCurrentIndent() < baseIndent || peek() !== "-") break; arr.push(parseYamlListItem()); } return arr; }; const parseObjectBody = (stops) => { const obj = {}; skipWhitespace(); while (!eof() && !stops.includes(peek())) { const char = peek(); const key = char === "\"" || char === "'" ? parseQuotedString(char) : parseUnquotedToken(`:\n${stops}`); if (!key) return obj; if (eof() || next() !== ":") throw new SyntaxError("Expected ':' after key"); if (peek() === " ") next(); while (!eof() && " ".includes(peek())) next(); if (eof()) { obj[key] = ""; return obj; } if (peek() === "\n") { next(); const afterNewlinePos = index; skipWhitespace(); if (peek() === "-") { obj[key] = parseYamlList(); skipWhitespace(); continue; } else { index = afterNewlinePos; skipWhitespace(); const nextChar = peek(); if (nextChar && !stops.includes(nextChar) && nextChar !== "-") { obj[key] = ""; continue; } obj[key] = ""; return obj; } } obj[key] = parseValue(stops.includes("}") ? `,\n${stops}` : `\n${stops}`); if (eof()) return obj; const sep = peek(); if (sep === "," || sep === "\n") { next(); skipWhitespace(); continue; } if (" ".includes(sep)) { while (!eof() && " ".includes(peek())) next(); if (peek() === "\n") { next(); skipWhitespace(); continue; } if (eof() || stops.includes(peek())) return obj; continue; } if (stops.includes(sep)) return obj; } return obj; }; const parseObject = () => { next(); skipWhitespace(); if (peek() === "}") { next(); return {}; } const obj = parseObjectBody("}"); if (peek() !== "}") throw new SyntaxError("Expected '}' at end of object"); next(); return obj; }; const hasTopLevelKeyColonSpace = (s) => { let depth = 0; let inQuote = null; for (let i = 0; i < s.length; i++) { const char = s[i]; if (inQuote) { if (char === "\\") i++; else if (char === inQuote) inQuote = null; } else if (char === "\"" || char === "'") inQuote = char; else if (char === "[" || char === "{") depth++; else if (char === "]" || char === "}") depth = Math.max(0, depth - 1); else if (depth === 0 && char === ":") { const nextCh = s[i + 1]; if (!nextCh || " \n".includes(nextCh)) return true; } } return false; }; if (text.startsWith("]") || text.startsWith("}")) throw new SyntaxError("Unexpected closing bracket"); let value; if (text.startsWith("[")) value = parseArray(); else if (text.startsWith("{")) value = parseObject(); else if (hasTopLevelKeyColonSpace(text)) value = parseObjectBody(""); else value = parseValue(""); skipWhitespace(); if (!eof()) throw new SyntaxError("Unexpected trailing characters"); return value; }; //#endregion export { parseYaml }; //# sourceMappingURL=parseYaml.mjs.map