Blame view

node_modules/decode-uri-component/index.js 2.17 KB
aaac7fed   liuqimichale   add
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
  '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);
  	}
  };