From 95fe1c43ebfbfb627c5f86d764da4d9d1210677e Mon Sep 17 00:00:00 2001 From: Ardis Lu Date: Fri, 6 Jan 2023 00:48:20 -0800 Subject: [PATCH] Split raw UTF-8 bytes into significant parts --- script.js | 33 +++++++++++++++++++++++++++++++-- style.css | 10 ++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/script.js b/script.js index 1fe7499..49e05a3 100644 --- a/script.js +++ b/script.js @@ -31,13 +31,42 @@ function calculateOutput(input) { char: invisibleCharacters.includes(point) ? '◌' : char, // Visual representation of the code point, replacing whitespace with ◌ point: `U+${pointHex.toUpperCase()}`, // Unicode code point, in hex pointBinary: pointBinary.padStart(8 * Math.ceil(pointBinary.length / 8), '0'), // Unicode code point, in binary - bytes: [...encoder.encode(char)].map(c => c.toString(2).padStart(8, '0')).join(' ') // UTF-8 encoding of the code point, in binary + bytes: [...encoder.encode(char)].map(c => c.toString(2).padStart(8, '0')) // UTF-8 encoding of the code point, in binary }); } return output; } +function parseBytes(bytes) { + switch (bytes.length) { + // UTF-8 byte length of 1 is always encoded with this pattern: 0xxxxxxx + case 1: + return `0${bytes[0].substring(2)}`; + + // All other lengths follow the same pattern + // Examples: + // - For 3 bytes: 1110xxxx 10xxxxxx 10xxxxxx + // - For 4 bytes: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + default: + let template = ''; + + // The number of insignificant bits in the first byte are always the length of the array plus one 0 + const initialLength = bytes.length; + const firstByte = bytes.shift(); + template += `${firstByte.substring(0, initialLength + 1)}`; + template += `${firstByte.substring(initialLength + 1)}`; + + // Remaining bytes always have 2 insignificant bits + for (const byte of bytes) { + template += `10`; + template += `${byte.substring(2)}`; + } + + return template; + } +} + function render(output) { const vizContainer = document.getElementById('visualizations'); vizContainer.innerHTML = ''; @@ -47,7 +76,7 @@ function render(output) { viz.insertAdjacentHTML('beforeend', `${item.char}`); viz.insertAdjacentHTML('beforeend', `${item.point}`); viz.insertAdjacentHTML('beforeend', `${item.pointBinary}`); - viz.insertAdjacentHTML('beforeend', `${item.bytes}`); + viz.insertAdjacentHTML('beforeend', `${parseBytes(item.bytes)}`); vizContainer.insertAdjacentElement('beforeend', viz); } diff --git a/style.css b/style.css index 344f4b1..c26abd6 100644 --- a/style.css +++ b/style.css @@ -77,6 +77,16 @@ a>svg { transition: transform 200ms; } +/* For the raw UTF-8 bytes */ +.insignificant { + transition: opacity 600ms; +} + +:is(al-point-visualization:hover, al-point-visualization:focus-within) .insignificant { + opacity: 20%; + transition: opacity 200ms; +} + @keyframes slideIn { from { transform: translateY(-100%); -- 2.47.3