暫無描述

punycode.js 6.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. //Javascript Punycode converter derived from example in RFC3492.
  2. //This implementation is created by some@domain.name and released into public domain
  3. 'use strict';
  4. var punycode = new function Punycode() { // eslint-disable-line
  5. // This object converts to and from puny-code used in IDN
  6. //
  7. // punycode.ToASCII ( domain )
  8. //
  9. // Returns a puny coded representation of "domain".
  10. // It only converts the part of the domain name that
  11. // has non ASCII characters. I.e. it dosent matter if
  12. // you call it with a domain that already is in ASCII.
  13. //
  14. // punycode.ToUnicode (domain)
  15. //
  16. // Converts a puny-coded domain name to unicode.
  17. // It only converts the puny-coded parts of the domain name.
  18. // I.e. it dosent matter if you call it on a string
  19. // that already has been converted to unicode.
  20. //
  21. //
  22. this.utf16 = {
  23. // The utf16-class is necessary to convert from javascripts internal character representation to unicode and back.
  24. decode:function( input ) {
  25. var output = [],
  26. i = 0,
  27. len = input.length,
  28. value, extra;
  29. while ( i < len ) {
  30. value = input.charCodeAt( i++ );
  31. if ( ( value & 0xF800 ) === 0xD800 ) {
  32. extra = input.charCodeAt( i++ );
  33. if ( ( ( value & 0xFC00 ) !== 0xD800 ) || ( ( extra & 0xFC00 ) !== 0xDC00 ) ) {
  34. throw new RangeError( 'UTF-16(decode): Illegal UTF-16 sequence' );
  35. }
  36. value = ( ( value & 0x3FF ) << 10 ) + ( extra & 0x3FF ) + 0x10000;
  37. }
  38. output.push( value );
  39. }
  40. return output;
  41. },
  42. encode:function( input ) {
  43. var output = [],
  44. i = 0,
  45. len = input.length,
  46. value;
  47. while ( i < len ) {
  48. value = input[i++];
  49. if ( ( value & 0xF800 ) === 0xD800 ) {
  50. throw new RangeError( 'UTF-16(encode): Illegal UTF-16 value' );
  51. }
  52. if ( value > 0xFFFF ) {
  53. value -= 0x10000;
  54. output.push( String.fromCharCode( ( ( value >>> 10 ) & 0x3FF ) | 0xD800 ) );
  55. value = 0xDC00 | ( value & 0x3FF );
  56. }
  57. output.push( String.fromCharCode( value ) );
  58. }
  59. return output.join( '' );
  60. },
  61. };
  62. //Default parameters
  63. var initialN = 0x80;
  64. var initialBias = 72;
  65. var delimiter = '\x2D';
  66. var base = 36;
  67. var damp = 700;
  68. var tmin = 1;
  69. var tmax = 26;
  70. var skew = 38;
  71. var maxint = 0x7FFFFFFF;
  72. /**
  73. * Dode_digit(cp) returns the numeric value of a basic code
  74. * point (for use in representing integers) in the range 0 to
  75. * base-1, or base if cp is does not represent a value.
  76. *
  77. * @param {string} cp String to decode.
  78. *
  79. * @returns {numeric} Decoded digit.
  80. */
  81. function decodeDigit( cp ) {
  82. return cp - 48 < 10 ? cp - 22 : cp - 65 < 26 ? cp - 65 : cp - 97 < 26 ? cp - 97 : base;
  83. }
  84. /**
  85. * Bias adaptation function.
  86. *
  87. * @param {string} delta Delta.
  88. * @param {string} numpoints Numpoints.
  89. * @param {string} firsttime Firsttime.
  90. *
  91. * @returns {string} Adapted string.
  92. */
  93. function adapt( delta, numpoints, firsttime ) {
  94. var k;
  95. delta = firsttime ? Math.floor( delta / damp ) : ( delta >> 1 );
  96. delta += Math.floor( delta / numpoints );
  97. for ( k = 0; delta > ( ( ( base - tmin ) * tmax ) >> 1 ); k += base ) {
  98. delta = Math.floor( delta / ( base - tmin ) );
  99. }
  100. return Math.floor( k + ( base - tmin + 1 ) * delta / ( delta + skew ) );
  101. }
  102. // Main decode
  103. this.decode = function( input, preserveCase ) { // eslint-disable-line
  104. // Dont use utf16
  105. var output = [];
  106. var caseFlags = [];
  107. var inputLength = input.length;
  108. var n, out, i, bias, basic, j, ic, oldi, w, k, digit, t, len;
  109. // Initialize the state:
  110. n = initialN;
  111. i = 0;
  112. bias = initialBias;
  113. // Handle the basic code points: Let basic be the number of input code
  114. // points before the last delimiter, or 0 if there is none, then
  115. // copy the first basic code points to the output.
  116. basic = input.lastIndexOf( delimiter );
  117. if ( basic < 0 ) {
  118. basic = 0;
  119. }
  120. for ( j = 0; j < basic; ++j ) {
  121. if ( preserveCase ) {
  122. caseFlags[output.length] = ( input.charCodeAt( j ) - 65 < 26 );
  123. }
  124. if ( input.charCodeAt( j ) >= 0x80 ) {
  125. throw new RangeError( 'Illegal input >= 0x80' );
  126. }
  127. output.push( input.charCodeAt( j ) );
  128. }
  129. // Main decoding loop: Start just after the last delimiter if any
  130. // basic code points were copied; start at the beginning otherwise.
  131. for ( ic = basic > 0 ? basic + 1 : 0; ic < inputLength; ) {
  132. // ic is the index of the next character to be consumed,
  133. // Decode a generalized variable-length integer into delta,
  134. // which gets added to i. The overflow checking is easier
  135. // if we increase i as we go, then subtract off its starting
  136. // value at the end to obtain delta.
  137. for ( oldi = i, w = 1, k = base; ; k += base ) {
  138. if ( ic >= inputLength ) {
  139. return;
  140. }
  141. digit = decodeDigit( input.charCodeAt( ic++ ) );
  142. if ( digit >= base ) {
  143. return;
  144. }
  145. if ( digit > Math.floor( ( maxint - i ) / w ) ) {
  146. return;
  147. }
  148. i += digit * w;
  149. t = k <= bias ? tmin : k >= bias + tmax ? tmax : k - bias;
  150. if ( digit < t ) {
  151. break;
  152. }
  153. if ( w > Math.floor( maxint / ( base - t ) ) ) {
  154. return;
  155. }
  156. w *= ( base - t );
  157. }
  158. out = output.length + 1;
  159. bias = adapt( i - oldi, out, oldi === 0 );
  160. // i was supposed to wrap around from out to 0,
  161. // incrementing n each time, so we'll fix that now:
  162. if ( Math.floor( i / out ) > maxint - n ) {
  163. return;
  164. }
  165. n += Math.floor( i / out ) ;
  166. i %= out;
  167. // Insert n at position i of the output:
  168. // Case of last character determines uppercase flag:
  169. if ( preserveCase ) {
  170. caseFlags.splice( i, 0, input.charCodeAt( ic - 1 ) - 65 < 26 );
  171. }
  172. output.splice( i, 0, n );
  173. i++;
  174. }
  175. if ( preserveCase ) {
  176. for ( i = 0, len = output.length; i < len; i++ ) {
  177. if ( caseFlags[i] ) {
  178. output[i] = ( String.fromCharCode( output[i] ).toUpperCase() ).charCodeAt( 0 );
  179. }
  180. }
  181. }
  182. return this.utf16.encode( output );
  183. };
  184. this.toUnicode = function( domain ) {
  185. var domainArray = domain.split( '.' );
  186. var out = [];
  187. for ( var i = 0; i < domainArray.length; ++i ) {
  188. var s = domainArray[i];
  189. out.push(
  190. s.match( /^xn--/ ) ?
  191. punycode.decode( s.slice( 4 ) ) :
  192. s
  193. );
  194. }
  195. return out.join( '.' );
  196. };
  197. }();