(function () { Normalization.COMPOSABLE_CHARS = {} for (var composition in Normalization.DECOMPOSABLE_CHARS) { var decomposition = Normalization.DECOMPOSABLE_CHARS[composition]; Normalization.COMPOSABLE_CHARS[decomposition] = composition; } Normalization.isCombining = function (character) { return (character in this.COMBINING_CHARS); } Normalization.isStarter = function (character) { return !this.isCombining(character); } Normalization.decomposeChar = function (character) { if (character in this.DECOMPOSABLE_CHARS) { return this.DECOMPOSABLE_CHARS[character]; } else { return character; } } Normalization.composeSubstring = function (str) { if (str in this.COMPOSABLE_CHARS) { return this.COMPOSABLE_CHARS[str]; } else { return str; } } Normalization.decomposeString = function (str) { var buffer = ""; var length = str.length; for (var count = 0; count < length; count++) { buffer += this.decomposeChar(str[count]); } return buffer; } Normalization.isBlocked = function (str, character) { var length = str.length; if (length < 2) { return false; } for (var count = 1; count < length; count++) { var current = str[count]; if (this.is_starter(current)) { return true; } else if (this.COMBINING_CHARS[current] >= this.COMBINING_CHARS[character]) { return true; } } return false; } Normalization.composeString = function (str) { var buffer = ""; var length = str.length; var possibility = str[0]; for (var count = 1; count < length; count++) { var current = str[count]; if (this.isStarter(current)) { buffer += possibility; possibility = current; continue; } else if (this.isBlocked(possibility, current)) { buffer += possibility; if (this.isCombining(current)) { buffer += current; possibility = ""; } else { possibility = current; } continue; } else { buffer += this.composeSubstring(possibility + current); possibility = ""; } } buffer += possibility; return buffer; } String.prototype.toNFD = function () { return Normalization.decomposeString(this); } String.prototype.toNFC = function () { return Normalization.composeString(this.toNFD()); } })();