Slugger.js 1.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849
  1. /**
  2. * Slugger generates header id
  3. */
  4. export class Slugger {
  5. constructor() {
  6. this.seen = {};
  7. }
  8. serialize(value) {
  9. return value
  10. .toLowerCase()
  11. .trim()
  12. // remove html tags
  13. .replace(/<[!\/a-z].*?>/ig, '')
  14. // remove unwanted chars
  15. .replace(/[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,./:;<=>?@[\]^`{|}~]/g, '')
  16. .replace(/\s/g, '-');
  17. }
  18. /**
  19. * Finds the next safe (unique) slug to use
  20. */
  21. getNextSafeSlug(originalSlug, isDryRun) {
  22. let slug = originalSlug;
  23. let occurenceAccumulator = 0;
  24. if (this.seen.hasOwnProperty(slug)) {
  25. occurenceAccumulator = this.seen[originalSlug];
  26. do {
  27. occurenceAccumulator++;
  28. slug = originalSlug + '-' + occurenceAccumulator;
  29. } while (this.seen.hasOwnProperty(slug));
  30. }
  31. if (!isDryRun) {
  32. this.seen[originalSlug] = occurenceAccumulator;
  33. this.seen[slug] = 0;
  34. }
  35. return slug;
  36. }
  37. /**
  38. * Convert string to unique id
  39. * @param {object} options
  40. * @param {boolean} options.dryrun Generates the next unique slug without updating the internal accumulator.
  41. */
  42. slug(value, options = {}) {
  43. const slug = this.serialize(value);
  44. return this.getNextSafeSlug(slug, options.dryrun);
  45. }
  46. }