56 lines
1.3 KiB
JavaScript
56 lines
1.3 KiB
JavaScript
/**
|
|
* Slugger generates header id
|
|
*/
|
|
export class Slugger {
|
|
constructor() {
|
|
this.seen = {};
|
|
}
|
|
|
|
/**
|
|
* @param {string} value
|
|
*/
|
|
serialize(value) {
|
|
return value
|
|
.toLowerCase()
|
|
.trim()
|
|
// remove html tags
|
|
.replace(/<[!\/a-z].*?>/ig, '')
|
|
// remove unwanted chars
|
|
.replace(/[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,./:;<=>?@[\]^`{|}~]/g, '')
|
|
.replace(/\s/g, '-');
|
|
}
|
|
|
|
/**
|
|
* Finds the next safe (unique) slug to use
|
|
* @param {string} originalSlug
|
|
* @param {boolean} isDryRun
|
|
*/
|
|
getNextSafeSlug(originalSlug, isDryRun) {
|
|
let slug = originalSlug;
|
|
let occurenceAccumulator = 0;
|
|
if (this.seen.hasOwnProperty(slug)) {
|
|
occurenceAccumulator = this.seen[originalSlug];
|
|
do {
|
|
occurenceAccumulator++;
|
|
slug = originalSlug + '-' + occurenceAccumulator;
|
|
} while (this.seen.hasOwnProperty(slug));
|
|
}
|
|
if (!isDryRun) {
|
|
this.seen[originalSlug] = occurenceAccumulator;
|
|
this.seen[slug] = 0;
|
|
}
|
|
return slug;
|
|
}
|
|
|
|
/**
|
|
* Convert string to unique id
|
|
* @param {object} [options]
|
|
* @param {boolean} [options.dryrun] Generates the next unique slug without
|
|
* updating the internal accumulator.
|
|
*/
|
|
slug(value, options = {}) {
|
|
const slug = this.serialize(value);
|
|
return this.getNextSafeSlug(slug, options.dryrun);
|
|
}
|
|
}
|