Created
August 7, 2025 11:56
-
-
Save FlameWolf/dc2661ee6a7e77910235e7f9c8ae070f to your computer and use it in GitHub Desktop.
Reverse a Unicode text while preserving grapheme clusters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const segmenter = new Intl.Segmenter(); | |
const zeroWidthSpace = "\u200B"; | |
/** | |
* Checks if the combination of segments is a single grapheme unit. | |
* @param {Intl.SegmentData} combination | |
* @returns {Boolean} | |
*/ | |
const isGraphemeUnit = combination => Array.from(segmenter.segment(combination)).length === 1; | |
/** | |
* Removes unwanted zero-width spaces based on their context in the text. | |
* @param {Intl.SegmentData} current | |
* @param {Number} index | |
* @param {Array<SegmentData>} source | |
* @returns | |
*/ | |
const removeUnwantedZws = (current, index, { [index - 1]: previous, [index + 1]: next }) => { | |
const currentSegment = current.segment; | |
if (currentSegment === zeroWidthSpace) { | |
if (previous) { | |
return isGraphemeUnit(`${previous.segment}${currentSegment}`); | |
} else if (next) { | |
return isGraphemeUnit(`${currentSegment}${next.segment}`); | |
} | |
} | |
return true; | |
}; | |
/** | |
* Adds a zero-width space to current grapheme segment to prevent it from combining with | |
* the previous segment if they could become a single grapheme unit when placed together. | |
* @param {Intl.SegmentData} current | |
* @param {Number} index | |
* @param {Array<SegmentData>} source | |
* @returns | |
*/ | |
const mapGrapheme = (current, index, { [index - 1]: previous }) => { | |
const currentSegment = current.segment; | |
if (previous && isGraphemeUnit(`${currentSegment}${previous.segment}`)) { | |
return `${currentSegment}${zeroWidthSpace}`; | |
} | |
return currentSegment; | |
}; | |
/** | |
* Reverses the Unicode text while preserving grapheme clusters and handling zero-width spaces. | |
* @param {String} text | |
* @returns | |
*/ | |
const reverseUnicodeText = text => Array.from(segmenter.segment(text)).filter(removeUnwantedZws).map(mapGrapheme).reverse().join(""); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment