Add support for 0x04 hex colors
Ref: https://modern.ircdocs.horse/formatting.html#hex-color
This commit is contained in:
parent
0773bf1ecb
commit
0b645d54c6
@ -3,6 +3,7 @@
|
|||||||
// Styling control codes
|
// Styling control codes
|
||||||
const BOLD = "\x02";
|
const BOLD = "\x02";
|
||||||
const COLOR = "\x03";
|
const COLOR = "\x03";
|
||||||
|
const HEX_COLOR = "\x04";
|
||||||
const RESET = "\x0f";
|
const RESET = "\x0f";
|
||||||
const REVERSE = "\x16";
|
const REVERSE = "\x16";
|
||||||
const ITALIC = "\x1d";
|
const ITALIC = "\x1d";
|
||||||
@ -12,6 +13,9 @@ const UNDERLINE = "\x1f";
|
|||||||
// integers, `XX` is the text color and `YY` is an optional background color.
|
// integers, `XX` is the text color and `YY` is an optional background color.
|
||||||
const colorRx = /^(\d{1,2})(?:,(\d{1,2}))?/;
|
const colorRx = /^(\d{1,2})(?:,(\d{1,2}))?/;
|
||||||
|
|
||||||
|
// 6-char Hex color code matcher
|
||||||
|
const hexColorRx = /^([0-9a-f]{6})(?:,([0-9a-f]{6}))?/i;
|
||||||
|
|
||||||
// Represents all other control codes that to be ignored/filtered from the text
|
// Represents all other control codes that to be ignored/filtered from the text
|
||||||
const controlCodesRx = /[\u0000-\u001F]/g;
|
const controlCodesRx = /[\u0000-\u001F]/g;
|
||||||
|
|
||||||
@ -26,12 +30,14 @@ function parseStyle(text) {
|
|||||||
|
|
||||||
// At any given time, these carry style information since last time a styling
|
// At any given time, these carry style information since last time a styling
|
||||||
// control code was met.
|
// control code was met.
|
||||||
let colorCodes, bold, textColor, bgColor, reverse, italic, underline;
|
let colorCodes, bold, textColor, bgColor, hexColor, hexBgColor, reverse, italic, underline;
|
||||||
|
|
||||||
const resetStyle = () => {
|
const resetStyle = () => {
|
||||||
bold = false;
|
bold = false;
|
||||||
textColor = undefined;
|
textColor = undefined;
|
||||||
bgColor = undefined;
|
bgColor = undefined;
|
||||||
|
hexColor = undefined;
|
||||||
|
hexBgColor = undefined;
|
||||||
reverse = false;
|
reverse = false;
|
||||||
italic = false;
|
italic = false;
|
||||||
underline = false;
|
underline = false;
|
||||||
@ -57,6 +63,8 @@ function parseStyle(text) {
|
|||||||
bold,
|
bold,
|
||||||
textColor,
|
textColor,
|
||||||
bgColor,
|
bgColor,
|
||||||
|
hexColor,
|
||||||
|
hexBgColor,
|
||||||
reverse,
|
reverse,
|
||||||
italic,
|
italic,
|
||||||
underline,
|
underline,
|
||||||
@ -113,6 +121,28 @@ function parseStyle(text) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case HEX_COLOR:
|
||||||
|
emitFragment();
|
||||||
|
|
||||||
|
colorCodes = text.slice(position + 1).match(hexColorRx);
|
||||||
|
|
||||||
|
if (colorCodes) {
|
||||||
|
hexColor = colorCodes[1].toUpperCase();
|
||||||
|
if (colorCodes[2]) {
|
||||||
|
hexBgColor = colorCodes[2].toUpperCase();
|
||||||
|
}
|
||||||
|
// Color code length is > 1, so bump the current position cursor by as
|
||||||
|
// much (and reset the start cursor for the current text block as well)
|
||||||
|
position += colorCodes[0].length;
|
||||||
|
start = position + 1;
|
||||||
|
} else {
|
||||||
|
// If no color codes were found, toggles back to no colors (like BOLD).
|
||||||
|
hexColor = undefined;
|
||||||
|
hexBgColor = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
case REVERSE:
|
case REVERSE:
|
||||||
emitFragment();
|
emitFragment();
|
||||||
reverse = !reverse;
|
reverse = !reverse;
|
||||||
@ -139,7 +169,7 @@ function parseStyle(text) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
const properties = ["bold", "textColor", "bgColor", "italic", "underline", "reverse"];
|
const properties = ["bold", "textColor", "bgColor", "hexColor", "hexBgColor", "italic", "underline", "reverse"];
|
||||||
|
|
||||||
function prepare(text) {
|
function prepare(text) {
|
||||||
return parseStyle(text)
|
return parseStyle(text)
|
||||||
|
@ -24,10 +24,24 @@ function createFragment(fragment) {
|
|||||||
if (fragment.underline) {
|
if (fragment.underline) {
|
||||||
classes.push("irc-underline");
|
classes.push("irc-underline");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let attributes = classes.length ? ` class="${classes.join(" ")}"` : "";
|
||||||
const escapedText = Handlebars.Utils.escapeExpression(fragment.text);
|
const escapedText = Handlebars.Utils.escapeExpression(fragment.text);
|
||||||
if (classes.length) {
|
|
||||||
return `<span class="${classes.join(" ")}">${escapedText}</span>`;
|
if (fragment.hexColor) {
|
||||||
|
attributes += ` style="color:#${fragment.hexColor}`;
|
||||||
|
|
||||||
|
if (fragment.hexBgColor) {
|
||||||
|
attributes += `;background-color:#${fragment.hexBgColor}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
attributes += "\"";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.length) {
|
||||||
|
return `<span${attributes}>${escapedText}</span>`;
|
||||||
|
}
|
||||||
|
|
||||||
return escapedText;
|
return escapedText;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,6 +10,8 @@ describe("parseStyle", () => {
|
|||||||
bold: false,
|
bold: false,
|
||||||
textColor: undefined,
|
textColor: undefined,
|
||||||
bgColor: undefined,
|
bgColor: undefined,
|
||||||
|
hexColor: undefined,
|
||||||
|
hexBgColor: undefined,
|
||||||
reverse: false,
|
reverse: false,
|
||||||
italic: false,
|
italic: false,
|
||||||
underline: false,
|
underline: false,
|
||||||
@ -30,6 +32,8 @@ describe("parseStyle", () => {
|
|||||||
bold: true,
|
bold: true,
|
||||||
textColor: undefined,
|
textColor: undefined,
|
||||||
bgColor: undefined,
|
bgColor: undefined,
|
||||||
|
hexColor: undefined,
|
||||||
|
hexBgColor: undefined,
|
||||||
reverse: false,
|
reverse: false,
|
||||||
italic: false,
|
italic: false,
|
||||||
underline: false,
|
underline: false,
|
||||||
@ -50,6 +54,8 @@ describe("parseStyle", () => {
|
|||||||
bold: false,
|
bold: false,
|
||||||
textColor: 8,
|
textColor: 8,
|
||||||
bgColor: undefined,
|
bgColor: undefined,
|
||||||
|
hexColor: undefined,
|
||||||
|
hexBgColor: undefined,
|
||||||
reverse: false,
|
reverse: false,
|
||||||
italic: false,
|
italic: false,
|
||||||
underline: false,
|
underline: false,
|
||||||
@ -69,6 +75,8 @@ describe("parseStyle", () => {
|
|||||||
const expected = [{
|
const expected = [{
|
||||||
textColor: 4,
|
textColor: 4,
|
||||||
bgColor: 8,
|
bgColor: 8,
|
||||||
|
hexColor: undefined,
|
||||||
|
hexBgColor: undefined,
|
||||||
bold: false,
|
bold: false,
|
||||||
reverse: false,
|
reverse: false,
|
||||||
italic: false,
|
italic: false,
|
||||||
@ -90,6 +98,8 @@ describe("parseStyle", () => {
|
|||||||
bold: false,
|
bold: false,
|
||||||
textColor: undefined,
|
textColor: undefined,
|
||||||
bgColor: undefined,
|
bgColor: undefined,
|
||||||
|
hexColor: undefined,
|
||||||
|
hexBgColor: undefined,
|
||||||
reverse: false,
|
reverse: false,
|
||||||
italic: true,
|
italic: true,
|
||||||
underline: false,
|
underline: false,
|
||||||
@ -104,12 +114,101 @@ describe("parseStyle", () => {
|
|||||||
expect(actual).to.deep.equal(expected);
|
expect(actual).to.deep.equal(expected);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should parse hex colors", () => {
|
||||||
|
const input = "test \x04FFFFFFnice \x02\x04RES006 \x0303,04\x04ff00FFcolored\x04eeeaFF,001122 background\x04\x03\x02?";
|
||||||
|
const expected = [{
|
||||||
|
bold: false,
|
||||||
|
textColor: undefined,
|
||||||
|
bgColor: undefined,
|
||||||
|
hexColor: undefined,
|
||||||
|
hexBgColor: undefined,
|
||||||
|
reverse: false,
|
||||||
|
italic: false,
|
||||||
|
underline: false,
|
||||||
|
text: "test ",
|
||||||
|
|
||||||
|
start: 0,
|
||||||
|
end: 5
|
||||||
|
}, {
|
||||||
|
bold: false,
|
||||||
|
textColor: undefined,
|
||||||
|
bgColor: undefined,
|
||||||
|
hexColor: "FFFFFF",
|
||||||
|
hexBgColor: undefined,
|
||||||
|
reverse: false,
|
||||||
|
italic: false,
|
||||||
|
underline: false,
|
||||||
|
text: "nice ",
|
||||||
|
|
||||||
|
start: 5,
|
||||||
|
end: 10
|
||||||
|
}, {
|
||||||
|
bold: true,
|
||||||
|
textColor: undefined,
|
||||||
|
bgColor: undefined,
|
||||||
|
hexColor: undefined,
|
||||||
|
hexBgColor: undefined,
|
||||||
|
reverse: false,
|
||||||
|
italic: false,
|
||||||
|
underline: false,
|
||||||
|
text: "RES006 ",
|
||||||
|
|
||||||
|
start: 10,
|
||||||
|
end: 17
|
||||||
|
}, {
|
||||||
|
bold: true,
|
||||||
|
textColor: 3,
|
||||||
|
bgColor: 4,
|
||||||
|
hexColor: "FF00FF",
|
||||||
|
hexBgColor: undefined,
|
||||||
|
reverse: false,
|
||||||
|
italic: false,
|
||||||
|
underline: false,
|
||||||
|
text: "colored",
|
||||||
|
|
||||||
|
start: 17,
|
||||||
|
end: 24
|
||||||
|
}, {
|
||||||
|
bold: true,
|
||||||
|
textColor: 3,
|
||||||
|
bgColor: 4,
|
||||||
|
hexColor: "EEEAFF",
|
||||||
|
hexBgColor: "001122",
|
||||||
|
reverse: false,
|
||||||
|
italic: false,
|
||||||
|
underline: false,
|
||||||
|
text: " background",
|
||||||
|
|
||||||
|
start: 24,
|
||||||
|
end: 35
|
||||||
|
}, {
|
||||||
|
bold: false,
|
||||||
|
textColor: undefined,
|
||||||
|
bgColor: undefined,
|
||||||
|
hexColor: undefined,
|
||||||
|
hexBgColor: undefined,
|
||||||
|
reverse: false,
|
||||||
|
italic: false,
|
||||||
|
underline: false,
|
||||||
|
text: "?",
|
||||||
|
|
||||||
|
start: 35,
|
||||||
|
end: 36
|
||||||
|
}];
|
||||||
|
|
||||||
|
const actual = parseStyle(input);
|
||||||
|
|
||||||
|
expect(actual).to.deep.equal(expected);
|
||||||
|
});
|
||||||
|
|
||||||
it("should carry state corretly forward", () => {
|
it("should carry state corretly forward", () => {
|
||||||
const input = "\x02bold\x038yellow\x02nonBold\x03default";
|
const input = "\x02bold\x038yellow\x02nonBold\x03default";
|
||||||
const expected = [{
|
const expected = [{
|
||||||
bold: true,
|
bold: true,
|
||||||
textColor: undefined,
|
textColor: undefined,
|
||||||
bgColor: undefined,
|
bgColor: undefined,
|
||||||
|
hexColor: undefined,
|
||||||
|
hexBgColor: undefined,
|
||||||
reverse: false,
|
reverse: false,
|
||||||
italic: false,
|
italic: false,
|
||||||
underline: false,
|
underline: false,
|
||||||
@ -121,6 +220,8 @@ describe("parseStyle", () => {
|
|||||||
bold: true,
|
bold: true,
|
||||||
textColor: 8,
|
textColor: 8,
|
||||||
bgColor: undefined,
|
bgColor: undefined,
|
||||||
|
hexColor: undefined,
|
||||||
|
hexBgColor: undefined,
|
||||||
reverse: false,
|
reverse: false,
|
||||||
italic: false,
|
italic: false,
|
||||||
underline: false,
|
underline: false,
|
||||||
@ -132,6 +233,8 @@ describe("parseStyle", () => {
|
|||||||
bold: false,
|
bold: false,
|
||||||
textColor: 8,
|
textColor: 8,
|
||||||
bgColor: undefined,
|
bgColor: undefined,
|
||||||
|
hexColor: undefined,
|
||||||
|
hexBgColor: undefined,
|
||||||
reverse: false,
|
reverse: false,
|
||||||
italic: false,
|
italic: false,
|
||||||
underline: false,
|
underline: false,
|
||||||
@ -143,6 +246,8 @@ describe("parseStyle", () => {
|
|||||||
bold: false,
|
bold: false,
|
||||||
textColor: undefined,
|
textColor: undefined,
|
||||||
bgColor: undefined,
|
bgColor: undefined,
|
||||||
|
hexColor: undefined,
|
||||||
|
hexBgColor: undefined,
|
||||||
reverse: false,
|
reverse: false,
|
||||||
italic: false,
|
italic: false,
|
||||||
underline: false,
|
underline: false,
|
||||||
@ -163,6 +268,8 @@ describe("parseStyle", () => {
|
|||||||
bold: true,
|
bold: true,
|
||||||
textColor: undefined,
|
textColor: undefined,
|
||||||
bgColor: undefined,
|
bgColor: undefined,
|
||||||
|
hexColor: undefined,
|
||||||
|
hexBgColor: undefined,
|
||||||
reverse: false,
|
reverse: false,
|
||||||
italic: false,
|
italic: false,
|
||||||
underline: false,
|
underline: false,
|
||||||
@ -174,6 +281,8 @@ describe("parseStyle", () => {
|
|||||||
bold: false,
|
bold: false,
|
||||||
textColor: undefined,
|
textColor: undefined,
|
||||||
bgColor: undefined,
|
bgColor: undefined,
|
||||||
|
hexColor: undefined,
|
||||||
|
hexBgColor: undefined,
|
||||||
reverse: false,
|
reverse: false,
|
||||||
italic: false,
|
italic: false,
|
||||||
underline: false,
|
underline: false,
|
||||||
@ -185,6 +294,8 @@ describe("parseStyle", () => {
|
|||||||
bold: true,
|
bold: true,
|
||||||
textColor: undefined,
|
textColor: undefined,
|
||||||
bgColor: undefined,
|
bgColor: undefined,
|
||||||
|
hexColor: undefined,
|
||||||
|
hexBgColor: undefined,
|
||||||
reverse: false,
|
reverse: false,
|
||||||
italic: false,
|
italic: false,
|
||||||
underline: false,
|
underline: false,
|
||||||
@ -205,6 +316,8 @@ describe("parseStyle", () => {
|
|||||||
bold: true,
|
bold: true,
|
||||||
textColor: 4,
|
textColor: 4,
|
||||||
bgColor: undefined,
|
bgColor: undefined,
|
||||||
|
hexColor: undefined,
|
||||||
|
hexBgColor: undefined,
|
||||||
reverse: true,
|
reverse: true,
|
||||||
italic: true,
|
italic: true,
|
||||||
underline: true,
|
underline: true,
|
||||||
@ -216,6 +329,8 @@ describe("parseStyle", () => {
|
|||||||
bold: false,
|
bold: false,
|
||||||
textColor: undefined,
|
textColor: undefined,
|
||||||
bgColor: undefined,
|
bgColor: undefined,
|
||||||
|
hexColor: undefined,
|
||||||
|
hexBgColor: undefined,
|
||||||
reverse: false,
|
reverse: false,
|
||||||
italic: false,
|
italic: false,
|
||||||
underline: false,
|
underline: false,
|
||||||
@ -236,6 +351,8 @@ describe("parseStyle", () => {
|
|||||||
bold: false,
|
bold: false,
|
||||||
textColor: undefined,
|
textColor: undefined,
|
||||||
bgColor: undefined,
|
bgColor: undefined,
|
||||||
|
hexColor: undefined,
|
||||||
|
hexBgColor: undefined,
|
||||||
reverse: false,
|
reverse: false,
|
||||||
italic: false,
|
italic: false,
|
||||||
underline: false,
|
underline: false,
|
||||||
@ -258,6 +375,8 @@ describe("parseStyle", () => {
|
|||||||
bold: false,
|
bold: false,
|
||||||
textColor: 12,
|
textColor: 12,
|
||||||
bgColor: undefined,
|
bgColor: undefined,
|
||||||
|
hexColor: undefined,
|
||||||
|
hexBgColor: undefined,
|
||||||
reverse: false,
|
reverse: false,
|
||||||
italic: false,
|
italic: false,
|
||||||
underline: false,
|
underline: false,
|
||||||
|
Loading…
Reference in New Issue
Block a user