{"id":15414154,"url":"https://github.com/jrson83/rehype-slug-anchor-sectionize","last_synced_at":"2025-10-16T22:30:38.399Z","repository":{"id":196851543,"uuid":"697402740","full_name":"jrson83/rehype-slug-anchor-sectionize","owner":"jrson83","description":"rehype plugin which wraps headings and their descendants in nested \u003csection\u003e elements and applies slugged anchor links to them","archived":false,"fork":false,"pushed_at":"2025-01-20T08:23:35.000Z","size":200,"stargazers_count":1,"open_issues_count":3,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-01-29T02:52:16.660Z","etag":null,"topics":["anchor","anchorize","ast","hast","heading","markdown","plugin","rehype","rehype-plugin","section","sectionize","slug","slugify","unified"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/rehype-slug-anchor-sectionize","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jrson83.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-09-27T16:52:02.000Z","updated_at":"2025-01-20T04:46:47.000Z","dependencies_parsed_at":"2024-02-05T05:28:31.942Z","dependency_job_id":"b50991c1-d00b-4ddd-9d96-cbe3ab912b07","html_url":"https://github.com/jrson83/rehype-slug-anchor-sectionize","commit_stats":{"total_commits":128,"total_committers":3,"mean_commits":"42.666666666666664","dds":0.078125,"last_synced_commit":"cbe3fb6ae064c8329aa8a90a537e407e6f168b1e"},"previous_names":["jrson83/rehype-slug-anchor-sectionize"],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jrson83%2Frehype-slug-anchor-sectionize","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jrson83%2Frehype-slug-anchor-sectionize/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jrson83%2Frehype-slug-anchor-sectionize/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jrson83%2Frehype-slug-anchor-sectionize/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jrson83","download_url":"https://codeload.github.com/jrson83/rehype-slug-anchor-sectionize/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":236752361,"owners_count":19199229,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["anchor","anchorize","ast","hast","heading","markdown","plugin","rehype","rehype-plugin","section","sectionize","slug","slugify","unified"],"created_at":"2024-10-01T17:00:14.367Z","updated_at":"2025-10-16T22:30:38.393Z","avatar_url":"https://github.com/jrson83.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# rehype-slug-anchor-sectionize\n\n**[rehype](https://github.com/rehypejs/rehype)** plugin which wraps headings and their descendants in nested `\u003csection\u003e` elements and applies `slugged anchor links` to them.\n\n## Contents\n\n- [What is this?](#what-is-this)\n- [When should I use this?](#when-should-i-use-this)\n- [Demo](#demo)\n- [Install](#install)\n- [Use](#use)\n- [API](#api)\n- [`unified().use(rehypeSlugAnchorSectionize, options?)`](#unifieduserehypesluganchorsectionize-options)\n- [Types](#types)\n- [Security](#security)\n- [License](#license)\n\n## What is this?\n\nThis package is a [unified](https://github.com/unifiedjs/unified) ([rehype](https://github.com/rehypejs/rehype)) plugin to wrap headings and their descendants in nested `\u003csection\u003e` elements and apply `slugged anchor links` to them.\n\n**unified** is a project that transforms content with abstract syntax trees\n(ASTs).\n**rehype** adds support for HTML to unified.\n**vfile** is the virtual file interface used in unified.\n**hast** is the HTML AST that rehype uses.\n\nThis is a rehype plugin that inspects and transforms hast.\n\n## When should I use this?\n\nThe plugin tries to minimize the configuration effort and complexity by combining the following already existing similar plugin approaches:\n\n- `sectionize` or `section`\n- `section-headings`\n- `heading-anchor`\n- `autolink-headings`\n- `slug`\n\nIt is useful if you want to use `IntersectionObserver` or similar to observe changes in the intersection of a target element with an ancestor.\n\n## Demo\n\nInspect the DOM tree and heading elements on any of my [Blog posts](https://jrson.me/blog/).\n\n## Install\n\nThis package is [ESM only](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c).\nIn Node.js (version 16.0+, or 18.0+), install with [npm](https://docs.npmjs.com/cli/install):\n\n```shell\nnpm install rehype-slug-anchor-sectionize\n```\n\nIn Deno, with [esm.sh](https://esm.sh/):\n\n```ts\nimport rehypeSlugAnchorSectionize from 'https://esm.sh/rehype-slug-anchor-sectionize'\n```\n\nIn browsers, with [esm.sh](https://esm.sh/):\n\n```html\n\u003cscript type=\"module\"\u003e\n  import rehypeSlugAnchorSectionize from 'https://esm.sh/rehype-slug-anchor-sectionize?bundle'\n\u003c/script\u003e\n```\n\n## Use\n\nSay our module `example.js` looks as follows:\n\n```ts\nimport { unified } from 'unified'\nimport remarkParse from 'remark-parse'\nimport remarkRehype from 'remark-rehype'\nimport rehypeSlugAnchorSectionize from 'rehype-slug-anchor-sectionize'\nimport rehypeStringify from 'rehype-stringify'\n\nconst file = await unified()\n  .use(remarkParse)\n  .use(remarkRehype)\n  .use(rehypeSlugAnchorSectionize)\n  .use(rehypeStringify).process(`## Heading 2.1\n\nParagraph 1\n\n## Heading 2.2\n\n### Heading 3.1\n\nParagraph 3\n\n## Heading 2.3\n\nParagraph 4`)\n\nconsole.log(value)\n```\n\n…now running `node example.js` yields HTML Output::\n\n```html\n\u003csection id=\"heading-21-section\"\u003e\n  \u003ch2 id=\"heading-21\" role=\"presentation\"\u003e\n    \u003ca href=\"#heading-21\" class=\"heading-anchor\"\u003e\n      \u003cbutton type=\"button\" class=\"heading-anchor__btn\"\u003e#\u003c/button\u003e\n    \u003c/a\u003e\n    \u003cspan role=\"heading\" aria-level=\"2\"\u003eHeading 2.1\u003c/span\u003e\n  \u003c/h2\u003e\n  \u003cp\u003eParagraph 1\u003c/p\u003e\n\u003c/section\u003e\n\n\u003csection id=\"heading-22-section\"\u003e\n  \u003ch2 id=\"heading-22\" role=\"presentation\"\u003e\n    \u003ca href=\"#heading-22\" class=\"heading-anchor\"\u003e\n      \u003cbutton type=\"button\" class=\"heading-anchor__btn\"\u003e#\u003c/button\u003e\n    \u003c/a\u003e\n    \u003cspan role=\"heading\" aria-level=\"2\"\u003eHeading 2.2\u003c/span\u003e\n  \u003c/h2\u003e\n  \u003cp\u003eParagraph 2\u003c/p\u003e\n  \u003csection id=\"heading-31-section\"\u003e\n    \u003ch3 id=\"heading-31\" role=\"presentation\"\u003e\n      \u003ca href=\"#heading-31\" class=\"heading-anchor\"\u003e\n        \u003cbutton type=\"button\" class=\"heading-anchor__btn\"\u003e#\u003c/button\u003e\n      \u003c/a\u003e\n      \u003cspan role=\"heading\" aria-level=\"3\"\u003eHeading 3.1\u003c/span\u003e\n    \u003c/h3\u003e\n    \u003cp\u003eParagraph 3\u003c/p\u003e\n  \u003c/section\u003e\n\u003c/section\u003e\n\n\u003csection id=\"heading-23-section\"\u003e\n  \u003ch2 id=\"heading-23\" role=\"presentation\"\u003e\n    \u003ca href=\"#heading-23\" class=\"heading-anchor\"\u003e\n      \u003cbutton type=\"button\" class=\"heading-anchor__btn\"\u003e#\u003c/button\u003e\n    \u003c/a\u003e\n    \u003cspan role=\"heading\" aria-level=\"2\"\u003eHeading 2.3\u003c/span\u003e\n  \u003c/h2\u003e\n  \u003cp\u003eParagraph 4\u003c/p\u003e\n\u003c/section\u003e\n```\n\n## Styling\n\nThe following styles should be added as minimal setup.\n\n```css\nh2 a[class=\"heading-anchor\"],\nh3 a[class=\"heading-anchor\"] {\n  margin-left: -2rem;\n}\n\n.heading-anchor__btn {\n  all: unset; /** replace with button reset */\n  width: 2rem;\n  opacity: 0;\n  color: #eee;\n}\n\nh2:hover a[class=\"heading-anchor\"] .heading-anchor__btn,\nh3:hover a[class=\"heading-anchor\"] .heading-anchor__btn {\n  opacity: 1;\n  cursor: pointer;\n}\n```\n\nYou can change the class names by providing a custom `property` for the element class attributes.\n\n## API\n\nThis package exports no identifiers.\nThe default export is `rehypeSlugAnchorSectionize`.\n\n### `unified().use(rehypeSlugAnchorSectionize, options?)`\n\n- Wraps headings and their descendants in `\u003csection\u003e` elements.\n- In addition it applies slugged anchor-id's to the `\u003csection\u003e` and heading elements.\n\n##### `options`\n\nConfiguration (optional).\n\n##### `options.depth`\n\nThe heading level depth to sectionize. (`number`, default: `3`).\n\n##### `options.wrapperTagName`\n\nThe wrapper Element `tagName`. (`string`, default: `section`).\n\n##### `options.wrapperProperties`\n\nThe wrapper Element `properties`. (`Element['properties']`, default: `undefined`).\n\n##### `options.wrapperSlugAdditive`\n\nAdds an additive at end of the wrappers id. (`string`, default: `-section`).\n\n##### `options.linkProperties`\n\nThe link Element `properties`. (`Element['properties']`, default: `{ className: 'heading-anchor' }`).\n\n##### `options.buttonProperties`\n\nThe button Element `properties`. (`Element['properties']`, default: `{ className: 'heading-anchor__btn' }`).\n\n## Types\n\nThis package is fully typed with [TypeScript](https://www.typescriptlang.org/).\nThe additional type `RehypeSlugAnchorSectionizeOptions` is exported.\n\n## Security\n\nAs improper use of HTML can open you up to a [cross-site scripting (XSS)][xss]\nattacks, use of rehype can also be unsafe.\nUse [`rehype-sanitize`][rehype-sanitize] to make the tree safe.\n\nUse of rehype plugins could also open you up to other attacks.\nCarefully assess each plugin and the risks involved in using them.\n\n## License\n\n[MIT](./LICENSE.md)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjrson83%2Frehype-slug-anchor-sectionize","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjrson83%2Frehype-slug-anchor-sectionize","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjrson83%2Frehype-slug-anchor-sectionize/lists"}