| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394 | 
							- 'use strict';
 
- var token = '%[a-f0-9]{2}';
 
- var singleMatcher = new RegExp('(' + token + ')|([^%]+?)', 'gi');
 
- var multiMatcher = new RegExp('(' + token + ')+', 'gi');
 
- function decodeComponents(components, split) {
 
- 	try {
 
- 		// Try to decode the entire string first
 
- 		return [decodeURIComponent(components.join(''))];
 
- 	} catch (err) {
 
- 		// Do nothing
 
- 	}
 
- 	if (components.length === 1) {
 
- 		return components;
 
- 	}
 
- 	split = split || 1;
 
- 	// Split the array in 2 parts
 
- 	var left = components.slice(0, split);
 
- 	var right = components.slice(split);
 
- 	return Array.prototype.concat.call([], decodeComponents(left), decodeComponents(right));
 
- }
 
- function decode(input) {
 
- 	try {
 
- 		return decodeURIComponent(input);
 
- 	} catch (err) {
 
- 		var tokens = input.match(singleMatcher) || [];
 
- 		for (var i = 1; i < tokens.length; i++) {
 
- 			input = decodeComponents(tokens, i).join('');
 
- 			tokens = input.match(singleMatcher) || [];
 
- 		}
 
- 		return input;
 
- 	}
 
- }
 
- function customDecodeURIComponent(input) {
 
- 	// Keep track of all the replacements and prefill the map with the `BOM`
 
- 	var replaceMap = {
 
- 		'%FE%FF': '\uFFFD\uFFFD',
 
- 		'%FF%FE': '\uFFFD\uFFFD'
 
- 	};
 
- 	var match = multiMatcher.exec(input);
 
- 	while (match) {
 
- 		try {
 
- 			// Decode as big chunks as possible
 
- 			replaceMap[match[0]] = decodeURIComponent(match[0]);
 
- 		} catch (err) {
 
- 			var result = decode(match[0]);
 
- 			if (result !== match[0]) {
 
- 				replaceMap[match[0]] = result;
 
- 			}
 
- 		}
 
- 		match = multiMatcher.exec(input);
 
- 	}
 
- 	// Add `%C2` at the end of the map to make sure it does not replace the combinator before everything else
 
- 	replaceMap['%C2'] = '\uFFFD';
 
- 	var entries = Object.keys(replaceMap);
 
- 	for (var i = 0; i < entries.length; i++) {
 
- 		// Replace all decoded components
 
- 		var key = entries[i];
 
- 		input = input.replace(new RegExp(key, 'g'), replaceMap[key]);
 
- 	}
 
- 	return input;
 
- }
 
- module.exports = function (encodedURI) {
 
- 	if (typeof encodedURI !== 'string') {
 
- 		throw new TypeError('Expected `encodedURI` to be of type `string`, got `' + typeof encodedURI + '`');
 
- 	}
 
- 	try {
 
- 		encodedURI = encodedURI.replace(/\+/g, ' ');
 
- 		// Try the built in decoder first
 
- 		return decodeURIComponent(encodedURI);
 
- 	} catch (err) {
 
- 		// Fallback to a more advanced decoder
 
- 		return customDecodeURIComponent(encodedURI);
 
- 	}
 
- };
 
 
  |