diff --git a/librz/cons/html.c b/librz/cons/html.c
index 0511ced8d8f..b65ce3dae1c 100644
--- a/librz/cons/html.c
+++ b/librz/cons/html.c
@@ -30,6 +30,20 @@ static const char *gethtmlcolor(const char ptrch) {
return "";
}
+static const char *gethtmlbrightcolor(const char ptrch) {
+ switch (ptrch) {
+ case '0': return "#777"; // Bright Black (Gray)
+ case '1': return "#ff5555"; // Bright Red
+ case '2': return "#55ff55"; // Bright Green
+ case '3': return "#ffff55"; // Bright Yellow
+ case '4': return "#5555ff"; // Bright Blue
+ case '5': return "#ff55ff"; // Bright Magenta
+ case '6': return "#55ffff"; // Bright Cyan
+ case '7': return "#ffffff"; // Bright White
+ }
+ return "";
+}
+
// TODO: move into rz_util/str
RZ_API char *rz_cons_html_filter(const char *ptr, int *newlen) {
const char *str = ptr;
@@ -183,6 +197,14 @@ RZ_API char *rz_cons_html_filter(const char *ptr, int *newlen) {
esc = 0;
continue;
// invert color
+ } else if (!strncmp(ptr, "39m", 3)) {
+ // Reset foreground to default
+ text_color[0] = '\0';
+ need_to_set = true;
+ ptr += 2;
+ str = ptr + 1;
+ esc = 0;
+ continue;
} else if (ptr[0] == '3' && ptr[2] == 'm') {
const char *htmlColor = gethtmlcolor(ptr[1]);
if (htmlColor) {
@@ -193,6 +215,14 @@ RZ_API char *rz_cons_html_filter(const char *ptr, int *newlen) {
str = ptr + 1;
esc = 0;
continue;
+ } else if (!strncmp(ptr, "49m", 3)) {
+ // Reset background to default
+ background_color[0] = '\0';
+ need_to_set = true;
+ ptr += 2;
+ str = ptr + 1;
+ esc = 0;
+ continue;
} else if (ptr[0] == '4' && ptr[2] == 'm') {
const char *htmlColor = gethtmlcolor(ptr[1]);
if (htmlColor) {
@@ -203,6 +233,31 @@ RZ_API char *rz_cons_html_filter(const char *ptr, int *newlen) {
str = ptr + 1;
esc = 0;
continue;
+ } else if (ptr[0] == '9' && ptr[2] == 'm') {
+ const char *htmlColor = gethtmlbrightcolor(ptr[1]);
+ if (htmlColor) {
+ rz_str_ncpy(text_color, htmlColor, sizeof(text_color));
+ }
+ need_to_set = true;
+ ptr = ptr + 2;
+ str = ptr + 1;
+ esc = 0;
+ continue;
+ } else if (ptr[0] == '1' &&
+ ptr[1] == '0' &&
+ ptr[3] == 'm' &&
+ ptr[2] >= '0' &&
+ ptr[2] <= '7') {
+ const char *htmlColor = gethtmlbrightcolor(ptr[2]);
+ if (htmlColor) {
+ rz_str_ncpy(background_color, htmlColor,
+ sizeof(background_color));
+ }
+ need_to_set = true;
+ ptr = ptr + 3;
+ str = ptr + 1;
+ esc = 0;
+ continue;
}
}
}
diff --git a/test/unit/test_cons_html.c b/test/unit/test_cons_html.c
index 7e27cb8c3ac..930bf7574d6 100644
--- a/test/unit/test_cons_html.c
+++ b/test/unit/test_cons_html.c
@@ -76,6 +76,82 @@ bool test_cons_to_html() {
html = rz_cons_html_filter(Color_RED Color_BGGREEN "aaa" Color_RESET_BG Color_RESET "bbb", NULL);
mu_assert_streq_free(html, "aaabbb", "Two different resets opposite order");
+ /* Bright foreground colors (90-97) */
+
+ html = rz_cons_html_filter("\x1b[90mBright foreground\x1b[0m", NULL);
+ mu_assert_streq_free(html, "Bright foreground", "Bright black");
+
+ html = rz_cons_html_filter("\x1b[91mBright foreground\x1b[0m", NULL);
+ mu_assert_streq_free(html, "Bright foreground", "Bright red");
+
+ html = rz_cons_html_filter("\x1b[92mBright foreground\x1b[0m", NULL);
+ mu_assert_streq_free(html, "Bright foreground", "Bright green");
+
+ html = rz_cons_html_filter("\x1b[93mBright foreground\x1b[0m", NULL);
+ mu_assert_streq_free(html, "Bright foreground", "Bright yellow");
+
+ html = rz_cons_html_filter("\x1b[94mBright foreground\x1b[0m", NULL);
+ mu_assert_streq_free(html, "Bright foreground", "Bright blue");
+
+ html = rz_cons_html_filter("\x1b[95mBright foreground\x1b[0m", NULL);
+ mu_assert_streq_free(html, "Bright foreground", "Bright magenta");
+
+ html = rz_cons_html_filter("\x1b[96mBright foreground\x1b[0m", NULL);
+ mu_assert_streq_free(html, "Bright foreground", "Bright cyan");
+
+ html = rz_cons_html_filter("\x1b[97mBright foreground\x1b[0m", NULL);
+ mu_assert_streq_free(html, "Bright foreground", "Bright white");
+
+ /* Bright background colors (100-107) */
+
+ html = rz_cons_html_filter("\x1b[100mBright background\x1b[0m", NULL);
+ mu_assert_streq_free(html, "Bright background", "Bright background black");
+
+ html = rz_cons_html_filter("\x1b[101mBright background\x1b[0m", NULL);
+ mu_assert_streq_free(html, "Bright background", "Bright background red");
+
+ html = rz_cons_html_filter("\x1b[102mBright background\x1b[0m", NULL);
+ mu_assert_streq_free(html, "Bright background", "Bright background green");
+
+ html = rz_cons_html_filter("\x1b[103mBright background\x1b[0m", NULL);
+ mu_assert_streq_free(html, "Bright background", "Bright background yellow");
+
+ html = rz_cons_html_filter("\x1b[104mBright background\x1b[0m", NULL);
+ mu_assert_streq_free(html, "Bright background", "Bright background blue");
+
+ html = rz_cons_html_filter("\x1b[105mBright background\x1b[0m", NULL);
+ mu_assert_streq_free(html, "Bright background", "Bright background magenta");
+
+ html = rz_cons_html_filter("\x1b[106mBright background\x1b[0m", NULL);
+ mu_assert_streq_free(html, "Bright background", "Bright background cyan");
+
+ html = rz_cons_html_filter("\x1b[107mBright background\x1b[0m", NULL);
+ mu_assert_streq_free(html, "Bright background", "Bright background white");
+
+ /* Explicit foreground reset (39m) */
+
+ html = rz_cons_html_filter("\x1b[91mAA\x1b[39mBB", NULL);
+ mu_assert_streq_free(html,
+ "AABB",
+ "Reset bright foreground");
+
+ html = rz_cons_html_filter("\x1b[91m\x1b[42mAA\x1b[39mBB", NULL);
+ mu_assert_streq_free(html,
+ "AA"
+ "BB",
+ "Reset foreground preserve background");
+
+ html = rz_cons_html_filter("\x1b[101mAA\x1b[49mBB", NULL);
+ mu_assert_streq_free(html,
+ "AABB",
+ "Reset bright background");
+
+ html = rz_cons_html_filter("\x1b[91m\x1b[101mAA\x1b[49mBB", NULL);
+ mu_assert_streq_free(html,
+ "AA"
+ "BB",
+ "Reset background preserve foreground");
+
mu_end;
}