{"id":16788732,"url":"https://github.com/markmead/alpinejs-table-of-content","last_synced_at":"2025-07-23T17:35:18.484Z","repository":{"id":243374214,"uuid":"812249256","full_name":"markmead/alpinejs-table-of-content","owner":"markmead","description":"Generate a table of content from headings within an element 📖","archived":false,"fork":false,"pushed_at":"2025-03-07T08:13:36.000Z","size":18,"stargazers_count":6,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-07-14T20:09:56.082Z","etag":null,"topics":["alpinejs","alpinejs-directive","alpinejs-plugin","table-of-contents","toc","toc-generator"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","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/markmead.png","metadata":{"files":{"readme":"README.md","changelog":null,"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,"zenodo":null}},"created_at":"2024-06-08T11:05:13.000Z","updated_at":"2025-03-07T08:13:39.000Z","dependencies_parsed_at":"2025-07-14T17:42:14.389Z","dependency_job_id":null,"html_url":"https://github.com/markmead/alpinejs-table-of-content","commit_stats":null,"previous_names":["markmead/alpinejs-table-of-contents","markmead/alpinejs-table-of-content"],"tags_count":0,"template":false,"template_full_name":"markmead/alpinejs-plugin-template","purl":"pkg:github/markmead/alpinejs-table-of-content","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/markmead%2Falpinejs-table-of-content","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/markmead%2Falpinejs-table-of-content/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/markmead%2Falpinejs-table-of-content/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/markmead%2Falpinejs-table-of-content/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/markmead","download_url":"https://codeload.github.com/markmead/alpinejs-table-of-content/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/markmead%2Falpinejs-table-of-content/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266720543,"owners_count":23973994,"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","status":"online","status_checked_at":"2025-07-23T02:00:09.312Z","response_time":66,"last_error":null,"robots_txt_status":null,"robots_txt_updated_at":null,"robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["alpinejs","alpinejs-directive","alpinejs-plugin","table-of-contents","toc","toc-generator"],"created_at":"2024-10-13T08:24:32.788Z","updated_at":"2025-07-23T17:35:18.439Z","avatar_url":"https://github.com/markmead.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Alpine JS Table of Content\n\nGenerate a table of content from headings within an element 📖\n\n## Install\n\n### With a CDN\n\n```html\n\u003cscript\n  defer\n  src=\"https://unpkg.com/alpinejs-table-of-content@latest/dist/toc.min.js\"\n\u003e\u003c/script\u003e\n\n\u003cscript defer src=\"https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js\"\u003e\u003c/script\u003e\n```\n\n### With a Package Manager\n\n```shell\nyarn add -D alpinejs-table-of-content\n\nnpm install -D alpinejs-table-of-content\n```\n\n```js\nimport Alpine from 'alpinejs'\nimport toc from 'alpinejs-table-of-content'\n\nAlpine.plugin(toc)\n\nAlpine.start()\n```\n\n## Example\n\n```html\n\u003carticle\n  class=\"prose mx-auto\"\n  x-data=\"{ tableOfContent: [] }\"\n  x-table-of-content\n\u003e\n  \u003ch1 id=\"heading-1\"\u003eHeading 1\u003c/h1\u003e\n\n  \u003ctemplate x-if=\"tableOfContent.length\"\u003e\n    \u003cul class=\"not-prose list-disc\"\u003e\n      \u003ctemplate\n        x-for=\"{ headingId, headingChildren, textContent } in tableOfContent\"\n      \u003e\n        \u003cli\u003e\n          \u003ca :href=\"`#${headingId}`\" x-text=\"textContent\"\u003e \u003c/a\u003e\n\n          \u003ctemplate x-if=\"headingChildren.length\"\u003e\n            \u003cul class=\"list-disc ml-4\"\u003e\n              \u003ctemplate\n                x-for=\"{ headingId, headingChildren, textContent } in headingChildren\"\n              \u003e\n                \u003cli\u003e\n                  \u003ca :href=\"`#${headingId}`\" x-text=\"textContent\"\u003e \u003c/a\u003e\n\n                  \u003ctemplate x-if=\"headingChildren.length\"\u003e\n                    \u003cul class=\"list-disc ml-4\"\u003e\n                      \u003ctemplate\n                        x-for=\"{ headingId, headingChildren, textContent } in headingChildren\"\n                      \u003e\n                        \u003cli\u003e\n                          \u003ca :href=\"`#${headingId}`\" x-text=\"textContent\"\u003e \u003c/a\u003e\n                        \u003c/li\u003e\n                      \u003c/template\u003e\n                    \u003c/ul\u003e\n                  \u003c/template\u003e\n                \u003c/li\u003e\n              \u003c/template\u003e\n            \u003c/ul\u003e\n          \u003c/template\u003e\n        \u003c/li\u003e\n      \u003c/template\u003e\n    \u003c/ul\u003e\n  \u003c/template\u003e\n\n  \u003cp\u003e\n    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Sit, commodi.\n  \u003c/p\u003e\n\n  \u003ch2 id=\"heading-2\"\u003eHeading 2\u003c/h2\u003e\n\n  \u003cp\u003eLorem ipsum dolor sit amet consectetur adipisicing elit.\u003c/p\u003e\n\n  \u003ch3 id=\"heading-3\"\u003eHeading 3\u003c/h3\u003e\n\n  \u003cp\u003eLorem, ipsum dolor.\u003c/p\u003e\n\n  \u003ch4 id=\"heading-4\"\u003eHeading 4\u003c/h4\u003e\n\n  \u003cp\u003e\n    Lorem ipsum dolor sit amet consectetur adipisicing elit. Quo sunt alias,\n    possimus mollitia nisi pariatur vero numquam at iure labore! Labore est\n    laudantium nam voluptates laborum, inventore delectus dolore placeat impedit\n    quae?\n  \u003c/p\u003e\n\n  \u003ch3 id=\"heading-3.1\"\u003eHeading 3.1\u003c/h3\u003e\n\n  \u003cp\u003e\n    Lorem ipsum dolor sit amet consectetur adipisicing elit. Accusantium velit\n    unde, pariatur dolore, eveniet consectetur eligendi tempora dolor nesciunt\n    cumque quis repellendus, voluptate perspiciatis eaque quibusdam?\n  \u003c/p\u003e\n\n  \u003ch2 id=\"heading-2.1\"\u003eHeading 2.1\u003c/h2\u003e\n\n  \u003cp\u003e\n    Lorem ipsum dolor sit amet consectetur adipisicing elit. A, eaque ratione.\n    Mollitia placeat vitae voluptas!\n  \u003c/p\u003e\n\n  \u003ch2 id=\"heading-2.2\"\u003eHeading 2.2\u003c/h2\u003e\n\n  \u003cp\u003e\n    Lorem ipsum dolor sit amet consectetur adipisicing elit. Similique minima\n    harum ipsam!\n  \u003c/p\u003e\n\n  \u003ch3 id=\"heading-3.2\"\u003eHeading 3.2\u003c/h3\u003e\n\n  \u003cp\u003e\n    Lorem ipsum dolor sit amet consectetur adipisicing elit. Magni a est porro\n    facilis nam commodi ullam fugiat? Quisquam reprehenderit incidunt sint ad\n    facilis ducimus est rerum? Non commodi tempore provident.\n  \u003c/p\u003e\n\u003c/article\u003e\n```\n\nAll you need is the `x-table-of-content` directive and a `tableOfContent: []`\nwithin the `x-data` of the same element. Exactly as shown in the example.\n\nFrom there, Alpine JS will read the content within the element with the\n`x-table-of-content` directive and locate all the H2, H3 and H4 elements.\nGenerating a nested array of objects which parent and child relationships.\nWithin these objects you'll have:\n\n- `headingId` (Comes from the `id` attribute on the heading - Useful for jump\n  links)\n- `headingChildren` (If the heading has child headings, these will appear here)\n- `textContent` (The text content of the heading)\n\nIn the example above there is this piece of HTML:\n\n```html\n\u003ctemplate x-if=\"tableOfContent.length\"\u003e\n  \u003cul class=\"not-prose list-disc\"\u003e\n    \u003ctemplate\n      x-for=\"{ headingId, headingChildren, textContent } in tableOfContent\"\n    \u003e\n      \u003cli\u003e\n        \u003ca :href=\"`#${headingId}`\" x-text=\"textContent\"\u003e \u003c/a\u003e\n\n        \u003ctemplate x-if=\"headingChildren.length\"\u003e\n          \u003cul class=\"list-disc ml-4\"\u003e\n            \u003ctemplate\n              x-for=\"{ headingId, headingChildren, textContent } in headingChildren\"\n            \u003e\n              \u003cli\u003e\n                \u003ca :href=\"`#${headingId}`\" x-text=\"textContent\"\u003e \u003c/a\u003e\n\n                \u003ctemplate x-if=\"headingChildren.length\"\u003e\n                  \u003cul class=\"list-disc ml-4\"\u003e\n                    \u003ctemplate\n                      x-for=\"{ headingId, headingChildren, textContent } in headingChildren\"\n                    \u003e\n                      \u003cli\u003e\n                        \u003ca :href=\"`#${headingId}`\" x-text=\"textContent\"\u003e \u003c/a\u003e\n                      \u003c/li\u003e\n                    \u003c/template\u003e\n                  \u003c/ul\u003e\n                \u003c/template\u003e\n              \u003c/li\u003e\n            \u003c/template\u003e\n          \u003c/ul\u003e\n        \u003c/template\u003e\n      \u003c/li\u003e\n    \u003c/template\u003e\n  \u003c/ul\u003e\n\u003c/template\u003e\n```\n\nThis is looping through the `tableOfContent` and generating the nested list for\nthe user to use to jump to, or just view the headings within the content.\n\n_This example uses Tailwind CSS, this is not required._\n\n## Stats\n\n![](https://img.shields.io/bundlephobia/min/alpinejs-table-of-content)\n![](https://img.shields.io/npm/v/alpinejs-table-of-content)\n![](https://img.shields.io/npm/dt/alpinejs-table-of-content)\n![](https://img.shields.io/github/license/markmead/alpinejs-table-of-content)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarkmead%2Falpinejs-table-of-content","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmarkmead%2Falpinejs-table-of-content","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarkmead%2Falpinejs-table-of-content/lists"}