From 3935e75bf5568192e6501ad78c82cdaeb4ac10fb Mon Sep 17 00:00:00 2001 From: RickyDeath79 Date: Sun, 2 Aug 2026 12:31:55 -0400 Subject: [PATCH 1/2] feat(rgb): enhance decodeLegacy with HTML tags, raw hex & format modifier support --- src/util/rgb/Decode.ts | 77 ++++++++++++++++++++++++------------------ 1 file changed, 45 insertions(+), 32 deletions(-) diff --git a/src/util/rgb/Decode.ts b/src/util/rgb/Decode.ts index e809cf33..4e88dc83 100644 --- a/src/util/rgb/Decode.ts +++ b/src/util/rgb/Decode.ts @@ -70,9 +70,13 @@ export function getSignificantPoints(gradient: string[], threshold: number) { } export function decodeLegacy(rgbtext: string) { - const legacyCodeRegex = - /(?:(?:[&§]|\\u00a7)x(?:(?:[&§]|\\u00a7)[0-9A-Fa-f]){6}|&#[0-9A-Fa-f]{6}|(?:[&§]|\\u00a7)[l-orL-ORkK])/g; - const matches = [...rgbtext.matchAll(legacyCodeRegex)]; + if (!rgbtext || !rgbtext.trim()) return null; + + // Universal pattern for Legacy Hex (&x&1&2...), Modern Hex (𞉀), Raw Hex (#123456), HTML spans, and Formatting (&l, &o, etc.) + const codeRegex = + /(?:(?:[&§]|\\u00a7)x(?:(?:[&§]|\\u00a7)[0-9A-Fa-f]){6}|[&#§]\b[0-9A-Fa-f]{6}\b|&#[0-9A-Fa-f]{6}|]*style=["']([^"']*)["'][^>]*>|<\/span>|(?:[&§]|\\u00a7)[l-orL-ORkK])/gi; + + const matches = [...rgbtext.matchAll(codeRegex)]; if (matches.length === 0) return null; const colors: Array<{ hex: string; pos: number }> = []; @@ -98,38 +102,47 @@ export function decodeLegacy(rgbtext: string) { const match = matches[i]; const codeStr = match[0]; - const lastChar = codeStr.charAt(codeStr.length - 1).toLowerCase(); - if (codeStr.length === 2 || codeStr.startsWith('\\u00a7')) { - if (lastChar === 'r') { - currentColor = '#ffffff'; - currentFmts.bold = false; - currentFmts.italic = false; - currentFmts.underline = false; - currentFmts.strikethrough = false; - currentFmts.obfuscate = false; - } else if (lastChar === 'l') { - currentFmts.bold = true; - } else if (lastChar === 'o') { - currentFmts.italic = true; - } else if (lastChar === 'n') { - currentFmts.underline = true; - } else if (lastChar === 'm') { - currentFmts.strikethrough = true; - } else if (lastChar === 'k') { - currentFmts.obfuscate = true; - } + if (codeStr.toLowerCase().startsWith('') { + // closing tag } else { - if (codeStr.startsWith('&#')) { - currentColor = '#' + codeStr.slice(2); + const lastChar = codeStr.charAt(codeStr.length - 1).toLowerCase(); + if (codeStr.length === 2 || codeStr.startsWith('\\u00a7')) { + if (lastChar === 'r') { + currentColor = '#ffffff'; + currentFmts.bold = false; + currentFmts.italic = false; + currentFmts.underline = false; + currentFmts.strikethrough = false; + currentFmts.obfuscate = false; + } else if (lastChar === 'l') { + currentFmts.bold = true; + } else if (lastChar === 'o') { + currentFmts.italic = true; + } else if (lastChar === 'n') { + currentFmts.underline = true; + } else if (lastChar === 'm') { + currentFmts.strikethrough = true; + } else if (lastChar === 'k') { + currentFmts.obfuscate = true; + } } else { - const hexDigits = codeStr.replace(/(?:[&§]|\\u00a7|x)/g, ''); - currentColor = '#' + hexDigits; + if (codeStr.startsWith('&#') || codeStr.startsWith('§#')) { + currentColor = '#' + codeStr.slice(2); + } else if (codeStr.startsWith('#')) { + currentColor = codeStr; + } else { + const hexDigits = codeStr.replace(/(?:[&§]|\\u00a7|x)/gi, ''); + currentColor = '#' + hexDigits; + } } - currentFmts.bold = false; - currentFmts.italic = false; - currentFmts.underline = false; - currentFmts.strikethrough = false; - currentFmts.obfuscate = false; } const startIdx = match.index + codeStr.length; From 150dbd86d2e2352547bd60352407c895a288765a Mon Sep 17 00:00:00 2001 From: RickyDeath79 Date: Mon, 3 Aug 2026 12:44:41 -0400 Subject: [PATCH 2/2] style: fix formatting in Decode.ts --- src/util/rgb/Decode.ts | 47 ++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/src/util/rgb/Decode.ts b/src/util/rgb/Decode.ts index 4e88dc83..3ec2b628 100644 --- a/src/util/rgb/Decode.ts +++ b/src/util/rgb/Decode.ts @@ -1,16 +1,19 @@ function hexToHSL(hex: string) { const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); if (!result) return { h: 100, s: 100, l: 100 }; + const r = parseInt(result[1], 16) / 255; const g = parseInt(result[2], 16) / 255; const b = parseInt(result[3], 16) / 255; - const max = Math.max(r, g, b), - min = Math.min(r, g, b); + const max = Math.max(r, g, b); + const min = Math.min(r, g, b); + let h = 0; - let s, - l = (max + min) / 2; + let s = 0; + let l = (max + min) / 2; + if (max === min) { - h = s = 0; // achromatic + h = s = 0; } else { const d = max - min; s = l > 0.5 ? d / (2 - max - min) : d / (max + min); @@ -36,43 +39,35 @@ function hexToHSL(hex: string) { } export function getSignificantPoints(gradient: string[], threshold: number) { - // Convert all colors to HSL const hslColors = gradient.map(hexToHSL); - // Calculate differences between consecutive colors const differences = []; for (let i = 1; i < hslColors.length; i++) { const hDiff = Math.abs(hslColors[i].h - hslColors[i - 1].h); const sDiff = Math.abs(hslColors[i].s - hslColors[i - 1].s); const lDiff = Math.abs(hslColors[i].l - hslColors[i - 1].l); - // Weight hue, saturation, and lightness changes differences.push({ index: i, - change: hDiff * 2 + sDiff + lDiff, // Hue changes weighted more heavily + change: hDiff * 2 + sDiff + lDiff, }); } - // Identify significant points based on notable changes const significantPoints = [gradient[0]]; // Always include the first color - // Iterate over differences to capture significant transitions for (let i = 1; i < differences.length; i++) { if (differences[i - 1].change > threshold) { - // Dynamic threshold based on gradient characteristics significantPoints.push(gradient[differences[i - 1].index]); } } - significantPoints.push(gradient[gradient.length - 1]); // Always include the last color + significantPoints.push(gradient[gradient.length - 1]); return significantPoints; } export function decodeLegacy(rgbtext: string) { if (!rgbtext || !rgbtext.trim()) return null; - - // Universal pattern for Legacy Hex (&x&1&2...), Modern Hex (𞉀), Raw Hex (#123456), HTML spans, and Formatting (&l, &o, etc.) const codeRegex = /(?:(?:[&§]|\\u00a7)x(?:(?:[&§]|\\u00a7)[0-9A-Fa-f]){6}|[&#§]\b[0-9A-Fa-f]{6}\b|&#[0-9A-Fa-f]{6}|]*style=["']([^"']*)["'][^>]*>|<\/span>|(?:[&§]|\\u00a7)[l-orL-ORkK])/gi; @@ -108,8 +103,12 @@ export function decodeLegacy(rgbtext: string) { if (colorMatch) currentColor = colorMatch[1]; if (/font-weight:\s*bold/i.test(styleAttr)) currentFmts.bold = true; if (/font-style:\s*italic/i.test(styleAttr)) currentFmts.italic = true; - if (/text-decoration:[^;]*underline/i.test(styleAttr)) currentFmts.underline = true; - if (/text-decoration:[^;]*line-through/i.test(styleAttr)) currentFmts.strikethrough = true; + if (/text-decoration:[^;]*underline/i.test(styleAttr)) { + currentFmts.underline = true; + } + if (/text-decoration:[^;]*line-through/i.test(styleAttr)) { + currentFmts.strikethrough = true; + } } else if (codeStr.toLowerCase() === '') { // closing tag } else { @@ -133,15 +132,13 @@ export function decodeLegacy(rgbtext: string) { } else if (lastChar === 'k') { currentFmts.obfuscate = true; } + } else if (codeStr.startsWith('&#') || codeStr.startsWith('§#')) { + currentColor = '#' + codeStr.slice(2); + } else if (codeStr.startsWith('#')) { + currentColor = codeStr; } else { - if (codeStr.startsWith('&#') || codeStr.startsWith('§#')) { - currentColor = '#' + codeStr.slice(2); - } else if (codeStr.startsWith('#')) { - currentColor = codeStr; - } else { - const hexDigits = codeStr.replace(/(?:[&§]|\\u00a7|x)/gi, ''); - currentColor = '#' + hexDigits; - } + const hexDigits = codeStr.replace(/(?:[&§]|\\u00a7|x)/gi, ''); + currentColor = '#' + hexDigits; } }