/*! * UI development toolkit for HTML5 (OpenUI5) * (c) Copyright 2009-2018 SAP SE or an SAP affiliate company. * Licensed under the Apache License, Version 2.0 - see LICENSE.txt. */ /* * IMPORTANT: This is a private module, its API must not be used and is subject to change. * Code other than the OpenUI5 libraries must not introduce dependencies to this module. */ /*global UNorm */ sap.ui.define(["sap/ui/thirdparty/unorm", "sap/ui/thirdparty/unormdata"], function() { "use strict"; function apply() { /*eslint-disable no-extend-native */ String.prototype.normalize = function(str) { switch (str) { case 'NFC': return nfcQuickCheck(this) ? this : UNorm.nfc(this); case 'NFD': return UNorm.nfd(this); case 'NFKC': return UNorm.nfkc(this); case 'NFKD': return UNorm.nfkd(this); default: return nfcQuickCheck(this) ? this : UNorm.nfc(this); } }; /*eslint-enable no-extend-native */ } // build a map for quick access var mData = {}; (function() { // derived from http://www.unicode.org/Public/8.0.0/ucd/DerivedNormalizationProps.txt var NFC_QC = [ [0x0340, 0x0341], [0x0343, 0x0344], 0x374, 0x037E, 0x387, [0x0958, 0x095F], [0x09DC, 0x09DD], 0x09DF, 0x0A33, 0x0A36, [0x0A59, 0x0A5B], 0x0A5E, [0x0B5C, 0x0B5D], 0x0F43, 0x0F4D, 0x0F52, 0x0F57, 0x0F5C, 0x0F69,0x0F73, [0x0F75, 0x0F76], 0x0F78, 0x0F81, 0x0F93, 0x0F9D, 0x0FA2, 0x0FA7, 0x0FAC, 0x0FB9, 0x1F71, 0x1F73, 0x1F75, 0x1F77, 0x1F79, 0x1F7B, 0x1F7D, 0x1FBB, 0x1FBE, 0x1FC9, 0x1FCB, 0x1FD3, 0x1FDB, 0x1FE3, 0x1FEB, [0x1FEE, 0x1FEF], 0x1FF9, 0x1FFB, 0x1FFD, [0x2000, 0x2001], 0x2126, [0x212A, 0x212B], 0x2329, 0x232A, 0x2ADC, [0xF900, 0xFA0D], 0xFA10, 0xFA12, [0xFA15, 0xFA1E], 0xFA20, 0xFA22, [0xFA25, 0xFA26], [0xFA2A, 0xFA6D], [0xFA70, 0xFAD9], 0xFB1D, 0xFB1F, [0xFB2A, 0xFB36], [0xFB38, 0xFB3C], 0xFB3E, [0xFB40, 0xFB41], [0xFB43, 0xFB44], [0xFB46, 0xFB4E], [0x1D15E, 0x1D164], [0x1D1BB, 0x1D1C0], [0x2F800, 0x2FA1D], [0x0300, 0x0304], [0x0306, 0x030C], 0x030F, 0x311, [0x0313, 0x0314], 0x031B, [0x0323, 0x0328], [0x032D, 0x032E], [0x0330, 0x0331], 0x338, 0x342, 0x345, [0x0653, 0x0655], 0x093C, 0x09BE, 0x09D7, 0x0B3E, 0x0B56, 0x0B57, 0x0BBE, 0x0BD7, 0x0C56, 0x0CC2, [0x0CD5, 0x0CD6], 0x0D3E, 0x0D57, 0x0DCA, 0x0DCF, 0x0DDF, 0x102E, [0x1161, 0x1175], [0x11A8, 0x11C2], 0x1B35, [0x3099, 0x309A], 0x110BA, 0x11127, 0x1133E, 0x11357, 0x114B0, 0x114BA, 0x114BD, 0x115AF ]; // convert the reference list into a map containing all charcodes or ranges for (var i = 0; i < NFC_QC.length; i++) { if (typeof NFC_QC[i] == "number") { mData[NFC_QC[i]] = true; } else { var a = NFC_QC[i][0]; var b = NFC_QC[i][1]; while (a <= b) { mData[a++] = true; } } } }()); // *** auxiliary functions *** function isHighSurrogate(cp) { // first part of a supplmementary character return cp >= 0xD800 && cp <= 0xDBFF; } function isLowSurrogate(cp) { // second part of a supplmementary character return cp >= 0xDC00 && cp <= 0xDFFF; } function getCanonicalClass(cp) { var dunit, hash; // access the unormdata hash = cp & 0xFF00; dunit = UNorm.UChar.udata[hash]; if (dunit === undefined) { dunit = UNorm.UChar.udata[hash] = {}; } else if (typeof dunit === "string") { // evil eval like unorm.js does it, as JSON.parse does not work for the unormdata /*eslint-disable no-eval */ dunit = UNorm.UChar.udata[hash] = eval("(" + dunit + ")"); /*eslint-enable no-eval */ } // check for existence and validity of canonical class return dunit[cp] && !!dunit[cp][1] ? (dunit[cp][1] & 0xff) : 0; } function isNotAllowed(cp) { // check against the reference data return mData[cp]; } // quickcheck implementations function nfcQuickCheck(s) { // check for only ascii characters first to avoid unnecessary processing if (!/^[\u0001-\u00ff]*$/.test(s)) { var lastCanonicalClass = 0; for (var i = 0; i < s.length; ++i) { var cp = s.charCodeAt(i); // check for supplementary characters, complex, as charCodeAt returns only charcodes smaller than 0xFFFF, // which is the Basic Multilingual Plane (BMP), but for normalizations also characters of the Supplementary // Multilingual Plane (SMP) have to be considered if (isHighSurrogate(cp)) { // check the next character var ncp = s.charCodeAt(i + 1); if (isLowSurrogate(ncp)) { // calculate the according char code in SMP and skip further tests for the next character (ncp) cp = (cp - 0xD800) * 0x400 + (ncp - 0xDC00) + 0x10000; ++i; } } var canonicalClass = getCanonicalClass(cp); // check canonical class or reference list if (lastCanonicalClass > canonicalClass && canonicalClass !== 0 || isNotAllowed(cp)) { return false; } lastCanonicalClass = canonicalClass; } } // nothing has been found return true; } /** * @namespace * @since 1.58 * @alias module:sap/base/strings/NormalizePolyfill * @private */ var NormalizePolyfill = Object.create(null); /** * Applies the polyfill. * @static */ NormalizePolyfill.apply = apply; /** * Checks whether a string should be normalized or not. It evaluates NO and MAYBE entries of the exclusion table * NFC_QC to false. This means it is not a definitive statement, but an indicator for normalization. * * @param s The string to be checked * @returns {boolean} Indicating whether s could be NFC formatted or not */ NormalizePolyfill.isStringNFC = nfcQuickCheck; return NormalizePolyfill; });