Skip to content

Commit

Permalink
feat: add getHeadingList() (#413)
Browse files Browse the repository at this point in the history
  • Loading branch information
JeanMeche committed Sep 23, 2023
1 parent 929a8db commit a72b5de
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 10 deletions.
19 changes: 17 additions & 2 deletions lib/index.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -82,22 +82,37 @@ function slug (value, maintainCase) {

let slugger;

let headings = [];

function gfmHeadingId({ prefix = '' } = {}) {
return {
headerIds: false, // prevent deprecation warning; remove this once headerIds option is removed
hooks: {
preprocess(src) {
headings = [];
slugger = new BananaSlug();
return src;
}
},
renderer: {
heading(text, level, raw) {
raw = raw.toLowerCase().trim().replace(/<[!\/a-z].*?>/ig, '');
return `<h${level} id="${prefix}${slugger.slug(raw)}">${text}</h${level}>\n`;
raw = raw
.toLowerCase()
.trim()
.replace(/<[!\/a-z].*?>/gi, '');
const id = `${prefix}${slugger.slug(raw)}`;
const heading = { level, text, id };
headings.push(heading);

return `<h${level} id="${id}">${text}</h${level}>\n`;
}
}
};
}

function getHeadingList() {
return headings;
}

exports.getHeadingList = getHeadingList;
exports.gfmHeadingId = gfmHeadingId;
19 changes: 17 additions & 2 deletions lib/index.umd.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,24 +86,39 @@

let slugger;

let headings = [];

function gfmHeadingId({ prefix = '' } = {}) {
return {
headerIds: false, // prevent deprecation warning; remove this once headerIds option is removed
hooks: {
preprocess(src) {
headings = [];
slugger = new BananaSlug();
return src;
}
},
renderer: {
heading(text, level, raw) {
raw = raw.toLowerCase().trim().replace(/<[!\/a-z].*?>/ig, '');
return `<h${level} id="${prefix}${slugger.slug(raw)}">${text}</h${level}>\n`;
raw = raw
.toLowerCase()
.trim()
.replace(/<[!\/a-z].*?>/gi, '');
const id = `${prefix}${slugger.slug(raw)}`;
const heading = { level, text, id };
headings.push(heading);

return `<h${level} id="${id}">${text}</h${level}>\n`;
}
}
};
}

function getHeadingList() {
return headings;
}

exports.getHeadingList = getHeadingList;
exports.gfmHeadingId = gfmHeadingId;

}));
35 changes: 33 additions & 2 deletions spec/index.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { marked } from 'marked';
import { gfmHeadingId } from '../src/index.js';
import { getHeadingList, gfmHeadingId } from '../src/index.js';

describe('marked-gfm-heading-id', () => {
beforeEach(() => {
Expand Down Expand Up @@ -57,7 +57,16 @@ describe('marked-gfm-heading-id', () => {
});

test('weird headings', () => {
marked.use(gfmHeadingId());
let headings = [];
marked.use(gfmHeadingId(), {
hooks: {
postprocess(html) {
headings = getHeadingList();
return html;
}
}
});

const markdown = `
# foo 1
Expand Down Expand Up @@ -117,5 +126,27 @@ describe('marked-gfm-heading-id', () => {
<h1 id="hello-world-1"><samp>Hello <ins>world!</ins></samp></h1>
"
`);

expect(headings.length).toBe(18);
expect(headings[0].id).toBe('foo-1');
expect(headings[1].id).toBe('foo');
expect(headings[2].id).toBe('foo-2');
expect(headings[3].id).toBe('html-in-header');
expect(headings[4].id).toBe('just-test');
expect(headings[5].id).toBe('just-test-2');

expect(headings[6].id).toBe('just--test-2-spaces-');
expect(headings[7].id).toBe('just-test-3');
expect(headings[8].id).toBe('just-test-4');
expect(headings[9].id).toBe('just-non-tags');
expect(headings[10].id).toBe('just-spaces');

expect(headings[11].id).toBe('just--weird-chars');
expect(headings[12].id).toBe('followed-by-weird-chars');
expect(headings[13].id).toBe('followed--space-then-weird-chars');
expect(headings[14].id).toBe('');
expect(headings[15].id).toBe('comment-');
expect(headings[16].id).toBe('hello-world');
expect(headings[17].id).toBe('hello-world-1');
});
});
23 changes: 21 additions & 2 deletions src/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { MarkedExtension, marked } from "marked"
import type {MarkedExtension, marked} from 'marked';

/** Options for configuring marked-gfm-heading-id extension */
interface GfmHeadingIdOptions {
Expand All @@ -10,6 +10,25 @@ interface GfmHeadingIdOptions {
* Add `id` attribute to headings (h1, h2, h3, etc) like GitHub.
*
* @param options Options for the extension
* @returns A {@link marked.MarkedExtension | MarkedExtension} to be passed to {@link marked.use | `marked.use()`}
* @returns A {@link marked.MarkedExtension | MarkedExtension} to be passed
* to {@link marked.use | `marked.use()`}
*/
export function gfmHeadingId(options?: GfmHeadingIdOptions): MarkedExtension;

/**
* Headings information, can be used to create table of content
*/
export interface HeadingData {
level: number;
text: string;
id: string;
}

/**
* Returns a list of headings with the ids as computed by gfmHeadingId
*
* @param tokens a lexer output
* @param options Options for the extension
* @returns A string formatted the same as what would {@link gfmHeadingId} do.
*/
export function getHeadingList(): HeadingData[];
18 changes: 16 additions & 2 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,34 @@
import GithubSlugger from 'github-slugger';
let slugger;

let headings = [];

export function gfmHeadingId({ prefix = '' } = {}) {
return {
headerIds: false, // prevent deprecation warning; remove this once headerIds option is removed
hooks: {
preprocess(src) {
headings = [];
slugger = new GithubSlugger();
return src;
}
},
renderer: {
heading(text, level, raw) {
raw = raw.toLowerCase().trim().replace(/<[!\/a-z].*?>/ig, '');
return `<h${level} id="${prefix}${slugger.slug(raw)}">${text}</h${level}>\n`;
raw = raw
.toLowerCase()
.trim()
.replace(/<[!\/a-z].*?>/gi, '');
const id = `${prefix}${slugger.slug(raw)}`;
const heading = { level, text, id };
headings.push(heading);

return `<h${level} id="${id}">${text}</h${level}>\n`;
}
}
};
}

export function getHeadingList() {
return headings;
}

0 comments on commit a72b5de

Please sign in to comment.