UNPKG

uritemplate

Version:

An UriTemplate implementation of rfc 6570

121 lines (114 loc) 4.03 kB
/*jshint unused:false */ /*global charHelper, unescape*/ var pctEncoder = (function () { "use strict"; var utf8 = { encode: function (chr) { // see http://ecmanaut.blogspot.de/2006/07/encoding-decoding-utf8-in-javascript.html return unescape(encodeURIComponent(chr)); }, numBytes: function (firstCharCode) { if (firstCharCode <= 0x7F) { return 1; } else if (0xC2 <= firstCharCode && firstCharCode <= 0xDF) { return 2; } else if (0xE0 <= firstCharCode && firstCharCode <= 0xEF) { return 3; } else if (0xF0 <= firstCharCode && firstCharCode <= 0xF4) { return 4; } // no valid first octet return 0; }, isValidFollowingCharCode: function (charCode) { return 0x80 <= charCode && charCode <= 0xBF; } }; /** * encodes a character, if needed or not. * @param chr * @return pct-encoded character */ function encodeCharacter (chr) { var result = '', octets = utf8.encode(chr), octet, index; for (index = 0; index < octets.length; index += 1) { octet = octets.charCodeAt(index); result += '%' + (octet < 0x10 ? '0' : '') + octet.toString(16).toUpperCase(); } return result; } /** * Returns, whether the given text at start is in the form 'percent hex-digit hex-digit', like '%3F' * @param text * @param start * @return {boolean|*|*} */ function isPercentDigitDigit (text, start) { return text.charAt(start) === '%' && charHelper.isHexDigit(text.charAt(start + 1)) && charHelper.isHexDigit(text.charAt(start + 2)); } /** * Parses a hex number from start with length 2. * @param text a string * @param start the start index of the 2-digit hex number * @return {Number} */ function parseHex2 (text, start) { return parseInt(text.substr(start, 2), 16); } /** * Returns whether or not the given char sequence is a correctly pct-encoded sequence. * @param chr * @return {boolean} */ function isPctEncoded (chr) { if (!isPercentDigitDigit(chr, 0)) { return false; } var firstCharCode = parseHex2(chr, 1); var numBytes = utf8.numBytes(firstCharCode); if (numBytes === 0) { return false; } for (var byteNumber = 1; byteNumber < numBytes; byteNumber += 1) { if (!isPercentDigitDigit(chr, 3*byteNumber) || !utf8.isValidFollowingCharCode(parseHex2(chr, 3*byteNumber + 1))) { return false; } } return true; } /** * Reads as much as needed from the text, e.g. '%20' or '%C3%B6'. It does not decode! * @param text * @param startIndex * @return the character or pct-string of the text at startIndex */ function pctCharAt(text, startIndex) { var chr = text.charAt(startIndex); if (!isPercentDigitDigit(text, startIndex)) { return chr; } var utf8CharCode = parseHex2(text, startIndex + 1); var numBytes = utf8.numBytes(utf8CharCode); if (numBytes === 0) { return chr; } for (var byteNumber = 1; byteNumber < numBytes; byteNumber += 1) { if (!isPercentDigitDigit(text, startIndex + 3 * byteNumber) || !utf8.isValidFollowingCharCode(parseHex2(text, startIndex + 3 * byteNumber + 1))) { return chr; } } return text.substr(startIndex, 3 * numBytes); } return { encodeCharacter: encodeCharacter, isPctEncoded: isPctEncoded, pctCharAt: pctCharAt }; }());