permalink.js 1.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. 'use strict';
  2. const escapeRegExp = require('./escape_regexp');
  3. const rParam = /:(\w*[^_\W])/g;
  4. class Permalink {
  5. constructor(rule, options) {
  6. if (!rule) { throw new TypeError('rule is required!'); }
  7. options = options || {};
  8. const segments = options.segments || {};
  9. const params = [];
  10. const regex = escapeRegExp(rule)
  11. .replace(rParam, (match, name) => {
  12. params.push(name);
  13. if (Object.prototype.hasOwnProperty.call(segments, name)) {
  14. const segment = segments[name];
  15. if (segment instanceof RegExp) {
  16. return segment.source;
  17. }
  18. return segment;
  19. }
  20. return '(.+?)';
  21. });
  22. this.rule = rule;
  23. this.regex = new RegExp(`^${regex}$`);
  24. this.params = params;
  25. }
  26. test(str) {
  27. return this.regex.test(str);
  28. }
  29. parse(str) {
  30. const match = str.match(this.regex);
  31. const { params } = this;
  32. const result = {};
  33. if (!match) { return; }
  34. for (let i = 1, len = match.length; i < len; i++) {
  35. result[params[i - 1]] = match[i];
  36. }
  37. return result;
  38. }
  39. stringify(data) {
  40. return this.rule.replace(rParam, (match, name) => data[name]);
  41. }
  42. }
  43. module.exports = Permalink;