summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cli/rt/02_console.js130
-rw-r--r--cli/tests/unit/console_test.ts40
2 files changed, 104 insertions, 66 deletions
diff --git a/cli/rt/02_console.js b/cli/rt/02_console.js
index 913ea44f2..8c853deb9 100644
--- a/cli/rt/02_console.js
+++ b/cli/rt/02_console.js
@@ -1097,8 +1097,8 @@
return null;
}
- function parseCss(cssString) {
- const css = {
+ function getDefaultCss() {
+ return {
backgroundColor: null,
color: null,
fontWeight: null,
@@ -1106,6 +1106,10 @@
textDecorationColor: null,
textDecorationLine: [],
};
+ }
+
+ function parseCss(cssString) {
+ const css = getDefaultCss();
const rawEntries = [];
let inValue = false;
@@ -1160,12 +1164,12 @@
css.color = color;
}
} else if (key == "font-weight") {
- if (["normal", "bold"].includes(value)) {
+ if (value == "bold") {
css.fontWeight = value;
}
} else if (key == "font-style") {
- if (["normal", "italic", "oblique", "oblique 14deg"].includes(value)) {
- css.fontStyle = value;
+ if (["italic", "oblique", "oblique 14deg"].includes(value)) {
+ css.fontStyle = "italic";
}
} else if (key == "text-decoration-line") {
css.textDecorationLine = [];
@@ -1196,50 +1200,81 @@
return css;
}
- function cssToAnsi(css) {
+ function colorEquals(color1, color2) {
+ return color1?.[0] == color2?.[0] && color1?.[1] == color2?.[1] &&
+ color1?.[2] == color2?.[2];
+ }
+
+ function cssToAnsi(css, prevCss = null) {
+ prevCss = prevCss ?? getDefaultCss();
let ansi = "";
- if (css.backgroundColor != null) {
- const [r, g, b] = css.backgroundColor;
- ansi += `\x1b[48;2;${r};${g};${b}m`;
- } else {
- ansi += "\x1b[49m";
+ if (!colorEquals(css.backgroundColor, prevCss.backgroundColor)) {
+ if (css.backgroundColor != null) {
+ const [r, g, b] = css.backgroundColor;
+ ansi += `\x1b[48;2;${r};${g};${b}m`;
+ } else {
+ ansi += "\x1b[49m";
+ }
}
- if (css.color != null) {
- const [r, g, b] = css.color;
- ansi += `\x1b[38;2;${r};${g};${b}m`;
- } else {
- ansi += "\x1b[39m";
+ if (!colorEquals(css.color, prevCss.color)) {
+ if (css.color != null) {
+ const [r, g, b] = css.color;
+ ansi += `\x1b[38;2;${r};${g};${b}m`;
+ } else {
+ ansi += "\x1b[39m";
+ }
}
- if (css.fontWeight == "bold") {
- ansi += `\x1b[1m`;
- } else {
- ansi += "\x1b[22m";
+ if (css.fontWeight != prevCss.fontWeight) {
+ if (css.fontWeight == "bold") {
+ ansi += `\x1b[1m`;
+ } else {
+ ansi += "\x1b[22m";
+ }
}
- if (["italic", "oblique"].includes(css.fontStyle)) {
- ansi += `\x1b[3m`;
- } else {
- ansi += "\x1b[23m";
+ if (css.fontStyle != prevCss.fontStyle) {
+ if (css.fontStyle == "italic") {
+ ansi += `\x1b[3m`;
+ } else {
+ ansi += "\x1b[23m";
+ }
}
- if (css.textDecorationColor != null) {
- const [r, g, b] = css.textDecorationColor;
- ansi += `\x1b[58;2;${r};${g};${b}m`;
- } else {
- ansi += "\x1b[59m";
+ if (!colorEquals(css.textDecorationColor, prevCss.textDecorationColor)) {
+ if (css.textDecorationColor != null) {
+ const [r, g, b] = css.textDecorationColor;
+ ansi += `\x1b[58;2;${r};${g};${b}m`;
+ } else {
+ ansi += "\x1b[59m";
+ }
}
- if (css.textDecorationLine.includes("line-through")) {
- ansi += "\x1b[9m";
- } else {
- ansi += "\x1b[29m";
+ if (
+ css.textDecorationLine.includes("line-through") !=
+ prevCss.textDecorationLine.includes("line-through")
+ ) {
+ if (css.textDecorationLine.includes("line-through")) {
+ ansi += "\x1b[9m";
+ } else {
+ ansi += "\x1b[29m";
+ }
}
- if (css.textDecorationLine.includes("overline")) {
- ansi += "\x1b[53m";
- } else {
- ansi += "\x1b[55m";
+ if (
+ css.textDecorationLine.includes("overline") !=
+ prevCss.textDecorationLine.includes("overline")
+ ) {
+ if (css.textDecorationLine.includes("overline")) {
+ ansi += "\x1b[53m";
+ } else {
+ ansi += "\x1b[55m";
+ }
}
- if (css.textDecorationLine.includes("underline")) {
- ansi += "\x1b[4m";
- } else {
- ansi += "\x1b[24m";
+ if (
+ css.textDecorationLine.includes("underline") !=
+ prevCss.textDecorationLine.includes("underline")
+ ) {
+ if (css.textDecorationLine.includes("underline")) {
+ ansi += "\x1b[4m";
+ } else {
+ ansi += "\x1b[24m";
+ }
}
return ansi;
}
@@ -1257,6 +1292,7 @@
// have to append to `string` when a substitution occurs / at the end.
let appendedChars = 0;
let usedStyle = false;
+ let prevCss = null;
for (let i = 0; i < first.length - 1; i++) {
if (first[i] == "%") {
const char = first[++i];
@@ -1293,9 +1329,15 @@
);
} else if (char == "c") {
const value = args[a++];
- formattedArg = noColor ? "" : cssToAnsi(parseCss(value));
- if (formattedArg != "") {
- usedStyle = true;
+ if (!noColor) {
+ const css = parseCss(value);
+ formattedArg = cssToAnsi(css, prevCss);
+ if (formattedArg != "") {
+ usedStyle = true;
+ prevCss = css;
+ }
+ } else {
+ formattedArg = "";
}
}
diff --git a/cli/tests/unit/console_test.ts b/cli/tests/unit/console_test.ts
index caee51a31..2270f9724 100644
--- a/cli/tests/unit/console_test.ts
+++ b/cli/tests/unit/console_test.ts
@@ -57,8 +57,8 @@ function parseCssColor(colorString: string): Css {
}
/** ANSI-fy the CSS, replace "\x1b" with "_". */
-function cssToAnsiEsc(css: Css): string {
- return cssToAnsi_(css).replaceAll("\x1b", "_");
+function cssToAnsiEsc(css: Css, prevCss: Css | null = null): string {
+ return cssToAnsi_(css, prevCss).replaceAll("\x1b", "_");
}
// test cases from web-platform-tests
@@ -944,7 +944,7 @@ unitTest(function consoleParseCss(): void {
);
assertEquals(
parseCss("font-style: oblique"),
- { ...DEFAULT_CSS, fontStyle: "oblique" },
+ { ...DEFAULT_CSS, fontStyle: "italic" },
);
assertEquals(
parseCss("text-decoration-color: green"),
@@ -983,46 +983,42 @@ unitTest(function consoleParseCss(): void {
});
unitTest(function consoleCssToAnsi(): void {
- // TODO(nayeemrmn): Optimize these by accounting for the previous CSS.
assertEquals(
cssToAnsiEsc({ ...DEFAULT_CSS, backgroundColor: [200, 201, 202] }),
- "_[48;2;200;201;202m_[39m_[22m_[23m_[59m_[29m_[55m_[24m",
+ "_[48;2;200;201;202m",
);
assertEquals(
cssToAnsiEsc({ ...DEFAULT_CSS, color: [203, 204, 205] }),
- "_[49m_[38;2;203;204;205m_[22m_[23m_[59m_[29m_[55m_[24m",
- );
- assertEquals(
- cssToAnsiEsc({ ...DEFAULT_CSS, fontWeight: "bold" }),
- "_[49m_[39m_[1m_[23m_[59m_[29m_[55m_[24m",
- );
- assertEquals(
- cssToAnsiEsc({ ...DEFAULT_CSS, fontStyle: "italic" }),
- "_[49m_[39m_[22m_[3m_[59m_[29m_[55m_[24m",
- );
- assertEquals(
- cssToAnsiEsc({ ...DEFAULT_CSS, fontStyle: "oblique" }),
- "_[49m_[39m_[22m_[3m_[59m_[29m_[55m_[24m",
+ "_[38;2;203;204;205m",
);
+ assertEquals(cssToAnsiEsc({ ...DEFAULT_CSS, fontWeight: "bold" }), "_[1m");
+ assertEquals(cssToAnsiEsc({ ...DEFAULT_CSS, fontStyle: "italic" }), "_[3m");
assertEquals(
cssToAnsiEsc({ ...DEFAULT_CSS, textDecorationColor: [206, 207, 208] }),
- "_[49m_[39m_[22m_[23m_[58;2;206;207;208m_[29m_[55m_[24m",
+ "_[58;2;206;207;208m",
);
assertEquals(
cssToAnsiEsc({ ...DEFAULT_CSS, textDecorationLine: ["underline"] }),
- "_[49m_[39m_[22m_[23m_[59m_[29m_[55m_[4m",
+ "_[4m",
);
assertEquals(
cssToAnsiEsc(
{ ...DEFAULT_CSS, textDecorationLine: ["overline", "line-through"] },
),
- "_[49m_[39m_[22m_[23m_[59m_[9m_[53m_[24m",
+ "_[9m_[53m",
);
assertEquals(
cssToAnsiEsc(
{ ...DEFAULT_CSS, color: [203, 204, 205], fontWeight: "bold" },
),
- "_[49m_[38;2;203;204;205m_[1m_[23m_[59m_[29m_[55m_[24m",
+ "_[38;2;203;204;205m_[1m",
+ );
+ assertEquals(
+ cssToAnsiEsc(
+ { ...DEFAULT_CSS, color: [0, 0, 0], fontWeight: "bold" },
+ { ...DEFAULT_CSS, color: [203, 204, 205], fontStyle: "italic" },
+ ),
+ "_[38;2;0;0;0m_[1m_[23m",
);
});