Advertisement
Guest User

Untitled

a guest
Feb 9th, 2016
54
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.98 KB | None | 0 0
  1. // Regular segments do not begin with / : or *
  2. // But they can start with ?:, which is when they are optional
  3. var regular = '([^/:\*](?:\\?:)?\\w+)';
  4.  
  5. // Dynamic segments match letters and hyphens
  6. var dynamicSegment = ':(\\w+)';
  7.  
  8. // Specify a custom regex for the dynamic segment by
  9. // wrapping it in {} after the name of the segment
  10. var dynamicRegex = '(?:=([^\\/]+))?';
  11.  
  12. // Combine the two dynamic pieces together
  13. var dynamic = dynamicSegment + dynamicRegex;
  14.  
  15. // Like dynamic segments, letters and hyphens are allowed
  16. var splat = '\\*(\\w+)';
  17.  
  18. // Create our RegExp from our base strings
  19. var regexStr = [regular, dynamic, splat].join('|');
  20. var regex = new RegExp(regexStr, 'g');
  21.  
  22. // These are the built-in expressions that folks can use
  23. // for the most commonly-used data types. For instance,
  24. // you could write `/:id=int` to specify an integer.
  25. var builtInRegExp = {
  26. int: '\\d+',
  27. string: '[a-zA-Z]+',
  28. alphanum: '[\\da-zA-Z]+',
  29. bool: '0|1'
  30. };
  31.  
  32. // Optional parameters are anything wrapped in parentheses
  33. var optionalParam = /\((.*?)\)/g;
  34.  
  35. // Takes in a routePath, and returns an array of named segments and a RegExp to match against
  36. function compile(path, namedRegex = {}) {
  37.  
  38. // The individual segments of the route's url
  39. var parts = [];
  40.  
  41. // We build our specificity as a string. Comparing magnitude of numbers written in positional
  42. // notation is a similar algorithm to comparing routes. The string "721", when converted to a
  43. // number, is larger then any number where the leading value is less than "7". In other words,
  44. // numbers to the left are a magnitude greater than numbers to the right. So it goes with routes:
  45. // the specificity of segments to the left are a magnitude greater than segments to the right.
  46. var specificity = '';
  47.  
  48. // Begin by replacing the optional pieces
  49. path = path.replace(optionalParam, '(?:$1)?');
  50. var str = '^' + path.replace(regex, (matched, regular, dynamic, customRegex, splat, location) => {
  51. var part = {};
  52.  
  53. // Regular
  54. if (regular) {
  55. part = {
  56. type: 'regular',
  57. value: regular
  58. };
  59. parts.push(part);
  60. specificity += '4';
  61. return regular;
  62. }
  63.  
  64. // Dynamic
  65. else if (dynamic) {
  66. part = {
  67. type: 'dynamic',
  68. value: dynamic
  69. };
  70. parts.push(part);
  71. var regex = customRegex || '[^/]+';
  72. var builtIn = namedRegex[regex] || builtInRegExp[regex];
  73. regex = builtIn ? builtIn : regex;
  74. // Custom RegExp are more specific than the default
  75. specificity += customRegex ? '3' : '2';
  76. return `(${regex})`;
  77. }
  78.  
  79. // Splats
  80. else if (splat) {
  81. part = {
  82. type: 'splat',
  83. value: splat
  84. };
  85. parts.push(part);
  86. specificity += '1';
  87. return '([^?]*?)';
  88. }
  89. }) + '$';
  90. return {
  91. parts,
  92. specificity: +specificity,
  93. regex: new RegExp(str)
  94. };
  95. }
  96.  
  97. // Takes a routeRegex generated by `compile` and a URL,
  98. // and returns an array of matched values
  99. function match(routeRegex, url) {
  100. url = decodeURI(url);
  101. var matches = routeRegex.regex.exec(url);
  102.  
  103. // Bail if there are no matches
  104. if (!matches) { return; }
  105.  
  106. // Otherwise, we match up our named params through a loop
  107. matches.shift();
  108.  
  109. // Filter out our non-static parts of the route
  110. var nonStaticParts = routeRegex.parts.filter(part => part.type !== 'regular');
  111.  
  112. var values = {}, item;
  113. for (var i = 0; i < matches.length; i++) {
  114. item = matches[i];
  115. values[nonStaticParts[i].value] = item ? item : undefined;
  116. }
  117.  
  118. return values;
  119. }
  120.  
  121. function generate(routeRegex, parts = {}) {
  122. return routeRegex.parts.reduce((memo, part) => {
  123. var dynamicValue;
  124. if (part.type === 'regular') {
  125. return memo + part.value + '/';
  126. } else {
  127. dynamicValue = parts[part.value] || '';
  128. if (dynamicValue) {
  129. dynamicValue += '/';
  130. }
  131. return memo + dynamicValue;
  132. }
  133.  
  134. // We start with a `/`, then remove a trailing `/`. Immediately after we
  135. // ensure that the route is at least a `/`.
  136. }, '/').slice(0, -1) || '/';
  137. }
  138.  
  139. export default {compile, match, generate};
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement