Skip to content

Commit

Permalink
Merge pull request #1728 from flouc001/nfe/dry-run-slug
Browse files Browse the repository at this point in the history
NFE: add dry run capabilities to default slugger
  • Loading branch information
styfle authored Jul 15, 2020
2 parents 1ad8e69 + 75b2646 commit ba13064
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 10 deletions.
12 changes: 12 additions & 0 deletions docs/USING_PRO.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,18 @@ slugger.slug('foo-1') // foo-1-2
...
```

`slugger.slug` can also be called with the `dryrun` option for stateless operation:
```js
slugger.slug('foo') // foo
slugger.slug('foo') // foo-1
slugger.slug('foo') // foo-2
slugger.slug('foo', { dryrun: true }) // foo-3
slugger.slug('foo', { dryrun: true }) // foo-3
slugger.slug('foo') // foo-3
slugger.slug('foo') // foo-4
...
```

`flags` has the following properties:

```js
Expand Down
36 changes: 26 additions & 10 deletions src/Slugger.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,44 @@ module.exports = class Slugger {
this.seen = {};
}

/**
* Convert string to unique id
*/
slug(value) {
let slug = 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
*/
getNextSafeSlug(originalSlug, isDryRun) {
let slug = originalSlug;
let occurenceAccumulator = 0;
if (this.seen.hasOwnProperty(slug)) {
const originalSlug = slug;
occurenceAccumulator = this.seen[originalSlug];
do {
this.seen[originalSlug]++;
slug = originalSlug + '-' + this.seen[originalSlug];
occurenceAccumulator++;
slug = originalSlug + '-' + occurenceAccumulator;
} while (this.seen.hasOwnProperty(slug));
}
this.seen[slug] = 0;

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);
}
};
23 changes: 23 additions & 0 deletions test/unit/marked-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,29 @@ describe('Test slugger functionality', () => {
const slugger = new marked.Slugger();
expect(slugger.slug('<em>html</em>')).toBe('html');
});

it('should not increment seen when using dryrun option', () => {
const slugger = new marked.Slugger();
expect(slugger.slug('<h1>This Section</h1>', { dryrun: true })).toBe('this-section');
expect(slugger.slug('<h1>This Section</h1>')).toBe('this-section');
});

it('should still return the next unique id when using dryrun', () => {
const slugger = new marked.Slugger();
expect(slugger.slug('<h1>This Section</h1>')).toBe('this-section');
expect(slugger.slug('<h1>This Section</h1>', { dryrun: true })).toBe('this-section-1');
});

it('should be repeatable in a sequence', () => {
const slugger = new marked.Slugger();
expect(slugger.slug('foo')).toBe('foo');
expect(slugger.slug('foo')).toBe('foo-1');
expect(slugger.slug('foo')).toBe('foo-2');
expect(slugger.slug('foo', { dryrun: true })).toBe('foo-3');
expect(slugger.slug('foo', { dryrun: true })).toBe('foo-3');
expect(slugger.slug('foo')).toBe('foo-3');
expect(slugger.slug('foo')).toBe('foo-4');
});
});

describe('Test paragraph token type', () => {
Expand Down

1 comment on commit ba13064

@vercel
Copy link

@vercel vercel bot commented on ba13064 Jul 15, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.