rfc3986.js 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. 'use strict';
  2. // Load modules
  3. // Delcare internals
  4. const internals = {
  5. rfc3986: {}
  6. };
  7. internals.generate = function () {
  8. /**
  9. * elements separated by forward slash ("/") are alternatives.
  10. */
  11. const or = '|';
  12. /**
  13. * DIGIT = %x30-39 ; 0-9
  14. */
  15. const digit = '0-9';
  16. const digitOnly = '[' + digit + ']';
  17. /**
  18. * ALPHA = %x41-5A / %x61-7A ; A-Z / a-z
  19. */
  20. const alpha = 'a-zA-Z';
  21. const alphaOnly = '[' + alpha + ']';
  22. /**
  23. * cidr = DIGIT ; 0-9
  24. * / %x31-32 DIGIT ; 10-29
  25. * / "3" %x30-32 ; 30-32
  26. */
  27. internals.rfc3986.cidr = digitOnly + or + '[1-2]' + digitOnly + or + '3' + '[0-2]';
  28. /**
  29. * HEXDIG = DIGIT / "A" / "B" / "C" / "D" / "E" / "F"
  30. */
  31. const hexDigit = digit + 'A-Fa-f';
  32. const hexDigitOnly = '[' + hexDigit + ']';
  33. /**
  34. * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
  35. */
  36. const unreserved = alpha + digit + '-\\._~';
  37. /**
  38. * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="
  39. */
  40. const subDelims = '!\\$&\'\\(\\)\\*\\+,;=';
  41. /**
  42. * pct-encoded = "%" HEXDIG HEXDIG
  43. */
  44. const pctEncoded = '%' + hexDigit;
  45. /**
  46. * pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
  47. */
  48. const pchar = unreserved + pctEncoded + subDelims + ':@';
  49. const pcharOnly = '[' + pchar + ']';
  50. /**
  51. * Rule to support zero-padded addresses.
  52. */
  53. const zeroPad = '0?';
  54. /**
  55. * dec-octet = DIGIT ; 0-9
  56. * / %x31-39 DIGIT ; 10-99
  57. * / "1" 2DIGIT ; 100-199
  58. * / "2" %x30-34 DIGIT ; 200-249
  59. * / "25" %x30-35 ; 250-255
  60. */
  61. const decOctect = '(?:' + zeroPad + zeroPad + digitOnly + or + zeroPad + '[1-9]' + digitOnly + or + '1' + digitOnly + digitOnly + or + '2' + '[0-4]' + digitOnly + or + '25' + '[0-5])';
  62. /**
  63. * IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet
  64. */
  65. internals.rfc3986.IPv4address = '(?:' + decOctect + '\\.){3}' + decOctect;
  66. /**
  67. * h16 = 1*4HEXDIG ; 16 bits of address represented in hexadecimal
  68. * ls32 = ( h16 ":" h16 ) / IPv4address ; least-significant 32 bits of address
  69. * IPv6address = 6( h16 ":" ) ls32
  70. * / "::" 5( h16 ":" ) ls32
  71. * / [ h16 ] "::" 4( h16 ":" ) ls32
  72. * / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
  73. * / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
  74. * / [ *3( h16 ":" ) h16 ] "::" h16 ":" ls32
  75. * / [ *4( h16 ":" ) h16 ] "::" ls32
  76. * / [ *5( h16 ":" ) h16 ] "::" h16
  77. * / [ *6( h16 ":" ) h16 ] "::"
  78. */
  79. const h16 = hexDigitOnly + '{1,4}';
  80. const ls32 = '(?:' + h16 + ':' + h16 + '|' + internals.rfc3986.IPv4address + ')';
  81. const IPv6SixHex = '(?:' + h16 + ':){6}' + ls32;
  82. const IPv6FiveHex = '::(?:' + h16 + ':){5}' + ls32;
  83. const IPv6FourHex = '(?:' + h16 + ')?::(?:' + h16 + ':){4}' + ls32;
  84. const IPv6ThreeHex = '(?:(?:' + h16 + ':){0,1}' + h16 + ')?::(?:' + h16 + ':){3}' + ls32;
  85. const IPv6TwoHex = '(?:(?:' + h16 + ':){0,2}' + h16 + ')?::(?:' + h16 + ':){2}' + ls32;
  86. const IPv6OneHex = '(?:(?:' + h16 + ':){0,3}' + h16 + ')?::' + h16 + ':' + ls32;
  87. const IPv6NoneHex = '(?:(?:' + h16 + ':){0,4}' + h16 + ')?::' + ls32;
  88. const IPv6NoneHex2 = '(?:(?:' + h16 + ':){0,5}' + h16 + ')?::' + h16;
  89. const IPv6NoneHex3 = '(?:(?:' + h16 + ':){0,6}' + h16 + ')?::';
  90. internals.rfc3986.IPv6address = '(?:' + IPv6SixHex + or + IPv6FiveHex + or + IPv6FourHex + or + IPv6ThreeHex + or + IPv6TwoHex + or + IPv6OneHex + or + IPv6NoneHex + or + IPv6NoneHex2 + or + IPv6NoneHex3 + ')';
  91. /**
  92. * IPvFuture = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
  93. */
  94. internals.rfc3986.IPvFuture = 'v' + hexDigitOnly + '+\\.[' + unreserved + subDelims + ':]+';
  95. /**
  96. * scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
  97. */
  98. internals.rfc3986.scheme = alphaOnly + '[' + alpha + digit + '+-\\.]*';
  99. /**
  100. * userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
  101. */
  102. const userinfo = '[' + unreserved + pctEncoded + subDelims + ':]*';
  103. /**
  104. * IP-literal = "[" ( IPv6address / IPvFuture ) "]"
  105. */
  106. const IPLiteral = '\\[(?:' + internals.rfc3986.IPv6address + or + internals.rfc3986.IPvFuture + ')\\]';
  107. /**
  108. * reg-name = *( unreserved / pct-encoded / sub-delims )
  109. */
  110. const regName = '[' + unreserved + pctEncoded + subDelims + ']{0,255}';
  111. /**
  112. * host = IP-literal / IPv4address / reg-name
  113. */
  114. const host = '(?:' + IPLiteral + or + internals.rfc3986.IPv4address + or + regName + ')';
  115. /**
  116. * port = *DIGIT
  117. */
  118. const port = digitOnly + '*';
  119. /**
  120. * authority = [ userinfo "@" ] host [ ":" port ]
  121. */
  122. const authority = '(?:' + userinfo + '@)?' + host + '(?::' + port + ')?';
  123. /**
  124. * segment = *pchar
  125. * segment-nz = 1*pchar
  126. * path = path-abempty ; begins with "/" or is empty
  127. * / path-absolute ; begins with "/" but not "//"
  128. * / path-noscheme ; begins with a non-colon segment
  129. * / path-rootless ; begins with a segment
  130. * / path-empty ; zero characters
  131. * path-abempty = *( "/" segment )
  132. * path-absolute = "/" [ segment-nz *( "/" segment ) ]
  133. * path-rootless = segment-nz *( "/" segment )
  134. */
  135. const segment = pcharOnly + '*';
  136. const segmentNz = pcharOnly + '+';
  137. const segmentNzNc = '[' + unreserved + pctEncoded + subDelims + '@' + ']+';
  138. const pathEmpty = '';
  139. const pathAbEmpty = '(?:\\/' + segment + ')*';
  140. const pathAbsolute = '\\/(?:' + segmentNz + pathAbEmpty + ')?';
  141. const pathRootless = segmentNz + pathAbEmpty;
  142. const pathNoScheme = segmentNzNc + pathAbEmpty;
  143. /**
  144. * hier-part = "//" authority path
  145. */
  146. internals.rfc3986.hierPart = '(?:' + '(?:\\/\\/' + authority + pathAbEmpty + ')' + or + pathAbsolute + or + pathRootless + ')';
  147. /**
  148. * relative-part = "//" authority path-abempty
  149. * / path-absolute
  150. * / path-noscheme
  151. * / path-empty
  152. */
  153. internals.rfc3986.relativeRef = '(?:' + '(?:\\/\\/' + authority + pathAbEmpty + ')' + or + pathAbsolute + or + pathNoScheme + or + pathEmpty + ')';
  154. /**
  155. * query = *( pchar / "/" / "?" )
  156. */
  157. internals.rfc3986.query = '[' + pchar + '\\/\\?]*(?=#|$)'; //Finish matching either at the fragment part or end of the line.
  158. /**
  159. * fragment = *( pchar / "/" / "?" )
  160. */
  161. internals.rfc3986.fragment = '[' + pchar + '\\/\\?]*';
  162. };
  163. internals.generate();
  164. module.exports = internals.rfc3986;