UNPKG

valve-key-values

Version:

A simple parser of the KeyValues format from Valve

154 lines 5.22 kB
var VKV; (function (VKV) { let TokenType; (function (TokenType) { TokenType["ObjectOpen"] = "object_open"; TokenType["ObjectClose"] = "object_close"; TokenType["String"] = "string"; TokenType["Word"] = "word"; })(TokenType || (TokenType = {})); function tokenizer(input) { let current = 0; const tokens = []; const length = input.length; while (current < length) { let char = input[current]; if (char === "{") { tokens.push({ type: TokenType.ObjectOpen, value: char }); current++; continue; } if (char === "}") { tokens.push({ type: TokenType.ObjectClose, value: char }); current++; continue; } if (char === '"') { let value = ""; let escape = false; char = input[++current]; while (char !== '"' || escape) { if (char == "\\" && !escape) { escape = true; char = input[++current]; continue; } value += char; char = input[++current]; escape = false; } current++; tokens.push({ type: TokenType.String, value }); continue; } if (/[\d\w]/.test(char)) { // if it's a number or a word character let value = ""; while (/[\d\w]/.test(char)) { value += char; char = input[++current]; } tokens.push({ type: TokenType.Word, value }); continue; } if (/\s/.test(char)) { current++; continue; } throw new Error("Unexpected character: " + char); } return tokens; } function parser(tokens) { if (!tokens.length) { throw new Error("Nothing to parse. Exiting!"); } let current = 0; function advance() { return tokens[current++]; } const root = {}; function parseKey() { const token = advance(); switch (token.type) { case TokenType.String: case TokenType.Word: return token.value.toLowerCase(); default: throw new Error(`Unexpected token type: ${token.type}`); } } function parseValue() { const token = advance(); switch (token.type) { case TokenType.String: case TokenType.Word: return token.value; case TokenType.ObjectOpen: const obj = {}; while (tokens[current].type != TokenType.ObjectClose) { const [key, value] = parsePair(); obj[key] = value; } current++; return obj; default: throw new Error(`Unexpected token type: ${token.type}`); } } function parsePair() { let key = parseKey(); let value = parseValue(); return [key, value]; } while (tokens[current]) { const [key, value] = parsePair(); root[key] = value; } return root; } function parse(input) { const tokens = tokenizer(input); return parser(tokens); } VKV.parse = parse; const escape_chars = ["\"", "{", "}", "\\"]; function strigify(root) { let output = ""; function stringifyString(value) { let result = '"'; for (const char of value) { if (escape_chars.indexOf(char) != -1) result += "\\"; result += char; } result += '"'; return result; } function strigifyObject(root, nested = 1) { let output = "".padStart(nested - 1, "\t") + "{\n"; for (const key in root) { output += "".padStart(nested, "\t") + `${stringifyString(key)}`; const value = root[key]; if (typeof value == "string") output += `\t${stringifyString(value)}\n`; else output += `\n${strigifyObject(value, nested + 1)}\n`; } output += "".padStart(nested - 1, "\t") + "}"; return output; } for (const key in root) { output += `${stringifyString(key)}`; const value = root[key]; if (typeof value == "string") output += `\t${stringifyString(value)}\n`; else output += `\n${strigifyObject(value)}\n`; } return output; } VKV.strigify = strigify; })(VKV || (VKV = {})); export default VKV; //# sourceMappingURL=index.js.map