44 lines
1.8 KiB
JavaScript
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;
|