Files

44 lines
1.8 KiB
JavaScript

"use strict";
// Edit one INI value without rewriting comments, unrelated keys, or line endings.
const HeroIni = (() => {
const split = (raw) => raw.split(/\r\n|\n|\r/);
const ending = (raw) => raw.includes("\r\n") ? "\r\n" : raw.includes("\r") ? "\r" : "\n";
function parse(raw) {
const lines = split(raw), sections = [];
let current = null;
for (let i = 0; i < lines.length; i++) {
const header = /^\s*\[([^\]]+)\]\s*(?:;.*)?$/.exec(lines[i]);
if (header) {
if (current) current.end = i;
current = { name: header[1].trim(), start: i, end: lines.length, fields: [] };
sections.push(current);
continue;
}
const m = /^\s*([^\s=;#]+)\s*=\s*(.*)$/.exec(lines[i]);
if (m && current) current.fields.push({ key: m[1], value: m[2].trim(), line: i });
}
return { raw, lines, sections };
}
function section(doc, name) { return doc.sections.find((s) => s.name.toLowerCase() === name.toLowerCase()); }
function get(doc, name, key) {
const s = section(doc, name);
return s?.fields.findLast((f) => f.key.toLowerCase() === key.toLowerCase())?.value ?? "";
}
function set(raw, name, key, value) {
const doc = parse(raw), s = section(doc, name);
if (!s) throw new Error(`Section [${name}] is missing`);
const field = s.fields.findLast((f) => f.key.toLowerCase() === key.toLowerCase());
const lines = doc.lines;
if (field) {
const old = lines[field.line], prefix = /^\s*[^\s=;#]+\s*=\s*/.exec(old)?.[0] || `${key} = `;
lines[field.line] = prefix + value;
} else {
lines.splice(s.end, 0, `${key} = ${value}`);
}
return lines.join(ending(raw));
}
return { parse, section, get, set };
})();
if (typeof module !== "undefined") module.exports = HeroIni;