.pragma library
// Line shapes shared by dnf, pacman, apt, zypper, xbps and flatpak upgrade output.
var COUNTER_RE = /^(\s*[\[(]\s*\d+\/\d+\s*[\])])(.*)$/;
var STATS_RE = /\s+\d+%\s*\|.*$/;
var SUMMARY_RE = /^(\s*[A-Z][A-Za-z ]*:)(\s+\d.*)$/;
var SECTION_RE = /^(\s*[A-Z][A-Za-z ,]*:?|::\s.*)$/;
var TABLE_ROW_RE = /^(\s+)(\S+)(\s{2,}\S.*)$/;
function segments(line) {
const text = String(line ?? "");
if (/^== .+ ==$/.test(text))
return [{ text, kind: "header" }];
if (/^\s*(error|e|fatal|problem)\s*:/i.test(text))
return [{ text, kind: "error" }];
if (/^\s*(warning|w)\s*:/i.test(text) || text === "Upgrade stopped.")
return [{ text, kind: "warning" }];
if (/^\s*(complete!|upgrade complete\.|nothing to do\.?)\s*$/i.test(text))
return [{ text, kind: "success" }];
const counter = COUNTER_RE.exec(text);
if (counter) {
const rest = counter[2];
const stats = STATS_RE.exec(rest);
const out = [{ text: counter[1], kind: "counter" }];
if (!stats)
return out.concat([{ text: rest, kind: "plain" }]);
return out.concat([{ text: rest.slice(0, stats.index), kind: "plain" }, { text: stats[0], kind: "dim" }]);
}
const summary = SUMMARY_RE.exec(text);
if (summary)
return [{ text: summary[1], kind: "section" }, { text: summary[2], kind: "plain" }];
if (SECTION_RE.test(text))
return [{ text, kind: "section" }];
const row = TABLE_ROW_RE.exec(text);
if (row)
return [{ text: row[1], kind: "plain" }, { text: row[2], kind: "name" }, { text: row[3], kind: "dim" }];
return [{ text, kind: "plain" }];
}
// StyledText collapses runs of spaces, which breaks the column alignment package managers print.
function escape(text) {
return text.replace(/&/g, "&").replace(//g, ">").replace(/^ +| {2,}/g, (run, offset) => offset === 0 ? " ".repeat(run.length) : " " + " ".repeat(run.length - 1));
}
// palette maps a segment kind to a color string; kinds without one inherit the Text color.
function markup(lines, palette) {
return (lines || []).map(line => segments(line).map(seg => {
const body = escape(seg.text);
const color = palette[seg.kind];
if (!color)
return body;
const bold = seg.kind === "header" || seg.kind === "section";
const span = "" + body + "";
return bold ? "" + span + "" : span;
}).join("")).join("
");
}