Greasy Fork is available in English.

URLToolkit

Lightweight library to build an absolute URL from a base URL and a relative URL, written from the spec (RFC 1808)

Dieses Skript sollte nicht direkt installiert werden. Es handelt sich hier um eine Bibliothek für andere Skripte, welche über folgenden Befehl in den Metadaten eines Skriptes eingebunden wird // @require https://update.greatest.deepsurf.us/scripts/382648/695476/URLToolkit.js

  1. // ==UserScript==
  2. // @name URLToolkit
  3. // @namespace https://greatest.deepsurf.us/users/136230
  4. // @description Lightweight library to build an absolute URL from a base URL and a relative URL, written from the spec (RFC 1808)
  5. // @include *://*
  6. // @version 2.1.6
  7. // @run-at document-start
  8. // @grant none
  9. // ==/UserScript==
  10.  
  11.  
  12. // see https://tools.ietf.org/html/rfc1808
  13.  
  14. /* jshint ignore:start */
  15. (function(root) {
  16. /* jshint ignore:end */
  17.  
  18. var URL_REGEX = /^((?:[a-zA-Z0-9+\-.]+:)?)(\/\/[^\/?#]*)?((?:[^\/\?#]*\/)*.*?)??(;.*?)?(\?.*?)?(#.*?)?$/;
  19. var FIRST_SEGMENT_REGEX = /^([^\/?#]*)(.*)$/;
  20. var SLASH_DOT_REGEX = /(?:\/|^)\.(?=\/)/g;
  21. var SLASH_DOT_DOT_REGEX = /(?:\/|^)\.\.\/(?!\.\.\/).*?(?=\/)/g;
  22.  
  23. var URLToolkit = { // jshint ignore:line
  24. // If opts.alwaysNormalize is true then the path will always be normalized even when it starts with / or //
  25. // E.g
  26. // With opts.alwaysNormalize = false (default, spec compliant)
  27. // http://a.com/b/cd + /e/f/../g => http://a.com/e/f/../g
  28. // With opts.alwaysNormalize = true (not spec compliant)
  29. // http://a.com/b/cd + /e/f/../g => http://a.com/e/g
  30. buildAbsoluteURL: function(baseURL, relativeURL, opts) {
  31. opts = opts || {};
  32. // remove any remaining space and CRLF
  33. baseURL = baseURL.trim();
  34. relativeURL = relativeURL.trim();
  35. if (!relativeURL) {
  36. // 2a) If the embedded URL is entirely empty, it inherits the
  37. // entire base URL (i.e., is set equal to the base URL)
  38. // and we are done.
  39. if (!opts.alwaysNormalize) {
  40. return baseURL;
  41. }
  42. var basePartsForNormalise = URLToolkit.parseURL(baseURL);
  43. if (!basePartsForNormalise) {
  44. throw new Error('Error trying to parse base URL.');
  45. }
  46. basePartsForNormalise.path = URLToolkit.normalizePath(basePartsForNormalise.path);
  47. return URLToolkit.buildURLFromParts(basePartsForNormalise);
  48. }
  49. var relativeParts = URLToolkit.parseURL(relativeURL);
  50. if (!relativeParts) {
  51. throw new Error('Error trying to parse relative URL.');
  52. }
  53. if (relativeParts.scheme) {
  54. // 2b) If the embedded URL starts with a scheme name, it is
  55. // interpreted as an absolute URL and we are done.
  56. if (!opts.alwaysNormalize) {
  57. return relativeURL;
  58. }
  59. relativeParts.path = URLToolkit.normalizePath(relativeParts.path);
  60. return URLToolkit.buildURLFromParts(relativeParts);
  61. }
  62. var baseParts = URLToolkit.parseURL(baseURL);
  63. if (!baseParts) {
  64. throw new Error('Error trying to parse base URL.');
  65. }
  66. if (!baseParts.netLoc && baseParts.path && baseParts.path[0] !== '/') {
  67. // If netLoc missing and path doesn't start with '/', assume everthing before the first '/' is the netLoc
  68. // This causes 'example.com/a' to be handled as '//example.com/a' instead of '/example.com/a'
  69. var pathParts = FIRST_SEGMENT_REGEX.exec(baseParts.path);
  70. baseParts.netLoc = pathParts[1];
  71. baseParts.path = pathParts[2];
  72. }
  73. if (baseParts.netLoc && !baseParts.path) {
  74. baseParts.path = '/';
  75. }
  76. var builtParts = {
  77. // 2c) Otherwise, the embedded URL inherits the scheme of
  78. // the base URL.
  79. scheme: baseParts.scheme,
  80. netLoc: relativeParts.netLoc,
  81. path: null,
  82. params: relativeParts.params,
  83. query: relativeParts.query,
  84. fragment: relativeParts.fragment
  85. };
  86. if (!relativeParts.netLoc) {
  87. // 3) If the embedded URL's <net_loc> is non-empty, we skip to
  88. // Step 7. Otherwise, the embedded URL inherits the <net_loc>
  89. // (if any) of the base URL.
  90. builtParts.netLoc = baseParts.netLoc;
  91. // 4) If the embedded URL path is preceded by a slash "/", the
  92. // path is not relative and we skip to Step 7.
  93. if (relativeParts.path[0] !== '/') {
  94. if (!relativeParts.path) {
  95. // 5) If the embedded URL path is empty (and not preceded by a
  96. // slash), then the embedded URL inherits the base URL path
  97. builtParts.path = baseParts.path;
  98. // 5a) if the embedded URL's <params> is non-empty, we skip to
  99. // step 7; otherwise, it inherits the <params> of the base
  100. // URL (if any) and
  101. if (!relativeParts.params) {
  102. builtParts.params = baseParts.params;
  103. // 5b) if the embedded URL's <query> is non-empty, we skip to
  104. // step 7; otherwise, it inherits the <query> of the base
  105. // URL (if any) and we skip to step 7.
  106. if (!relativeParts.query) {
  107. builtParts.query = baseParts.query;
  108. }
  109. }
  110. } else {
  111. // 6) The last segment of the base URL's path (anything
  112. // following the rightmost slash "/", or the entire path if no
  113. // slash is present) is removed and the embedded URL's path is
  114. // appended in its place.
  115. var baseURLPath = baseParts.path;
  116. var newPath = baseURLPath.substring(0, baseURLPath.lastIndexOf('/') + 1) + relativeParts.path;
  117. builtParts.path = URLToolkit.normalizePath(newPath);
  118. }
  119. }
  120. }
  121. if (builtParts.path === null) {
  122. builtParts.path = opts.alwaysNormalize ? URLToolkit.normalizePath(relativeParts.path) : relativeParts.path;
  123. }
  124. return URLToolkit.buildURLFromParts(builtParts);
  125. },
  126. parseURL: function(url) {
  127. var parts = URL_REGEX.exec(url);
  128. if (!parts) {
  129. return null;
  130. }
  131. return {
  132. scheme: parts[1] || '',
  133. netLoc: parts[2] || '',
  134. path: parts[3] || '',
  135. params: parts[4] || '',
  136. query: parts[5] || '',
  137. fragment: parts[6] || ''
  138. };
  139. },
  140. normalizePath: function(path) {
  141. // The following operations are
  142. // then applied, in order, to the new path:
  143. // 6a) All occurrences of "./", where "." is a complete path
  144. // segment, are removed.
  145. // 6b) If the path ends with "." as a complete path segment,
  146. // that "." is removed.
  147. path = path.split('').reverse().join('').replace(SLASH_DOT_REGEX, '');
  148. // 6c) All occurrences of "<segment>/../", where <segment> is a
  149. // complete path segment not equal to "..", are removed.
  150. // Removal of these path segments is performed iteratively,
  151. // removing the leftmost matching pattern on each iteration,
  152. // until no matching pattern remains.
  153. // 6d) If the path ends with "<segment>/..", where <segment> is a
  154. // complete path segment not equal to "..", that
  155. // "<segment>/.." is removed.
  156. while (path.length !== (path = path.replace(SLASH_DOT_DOT_REGEX, '')).length) {} // jshint ignore:line
  157. return path.split('').reverse().join('');
  158. },
  159. buildURLFromParts: function(parts) {
  160. return parts.scheme + parts.netLoc + parts.path + parts.params + parts.query + parts.fragment;
  161. }
  162. };
  163.  
  164. /* jshint ignore:start */
  165. root["URLToolkit"] = URLToolkit;
  166. })(window);
  167. /* jshint ignore:end */