{"id":34035502,"url":"https://github.com/foliant-docs/foliantcontrib.utils.header_anchors","last_synced_at":"2026-04-02T00:38:10.560Z","repository":{"id":57431759,"uuid":"229269250","full_name":"foliant-docs/foliantcontrib.utils.header_anchors","owner":"foliant-docs","description":"[DEPRECATED] Utils for converting headers to anchors for different backends","archived":false,"fork":false,"pushed_at":"2021-07-20T13:34:23.000Z","size":14,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-12-15T11:50:37.634Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Python","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/foliant-docs.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}},"created_at":"2019-12-20T13:23:57.000Z","updated_at":"2021-07-20T13:34:34.000Z","dependencies_parsed_at":"2022-09-02T12:40:20.471Z","dependency_job_id":null,"html_url":"https://github.com/foliant-docs/foliantcontrib.utils.header_anchors","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/foliant-docs/foliantcontrib.utils.header_anchors","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/foliant-docs%2Ffoliantcontrib.utils.header_anchors","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/foliant-docs%2Ffoliantcontrib.utils.header_anchors/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/foliant-docs%2Ffoliantcontrib.utils.header_anchors/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/foliant-docs%2Ffoliantcontrib.utils.header_anchors/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/foliant-docs","download_url":"https://codeload.github.com/foliant-docs/foliantcontrib.utils.header_anchors/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/foliant-docs%2Ffoliantcontrib.utils.header_anchors/sbom","scorecard":{"id":406114,"data":{"date":"2025-08-11","repo":{"name":"github.com/foliant-docs/foliantcontrib.utils.header_anchors","commit":"f5048a227fe9bc9293542f550c12d1ce3f139228"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Code-Review","score":0,"reason":"Found 0/7 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}}]},"last_synced_at":"2025-08-18T21:18:03.889Z","repository_id":57431759,"created_at":"2025-08-18T21:18:03.889Z","updated_at":"2025-08-18T21:18:03.889Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31044974,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-27T09:35:52.079Z","status":"ssl_error","status_checked_at":"2026-03-27T09:35:20.916Z","response_time":164,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":[],"created_at":"2025-12-13T20:02:22.671Z","updated_at":"2026-04-02T00:38:10.548Z","avatar_url":"https://github.com/foliant-docs.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![](https://img.shields.io/pypi/v/foliantcontrib.utils.header_anchors.svg)](https://pypi.org/project/foliantcontrib.utils.header_anchors/)  [![](https://img.shields.io/github/v/tag/foliant-docs/foliantcontrib.utils.header_anchors.svg?label=GitHub)](https://github.com/foliant-docs/foliantcontrib.utils.header_anchors)\n\n**This package is deprecated and will be removed in future. HeaderAnchors moved to the [main utils package](https://github.com/foliant-docs/foliantcontrib.utils).**\n\n# HeaderAnchors\n\nHeaderAnchors is a module which converts heading titles into IDs just like it is done by specific backends.\n\nModule exports three main functions:\n- **to_id** which converts a title into an ID by the rules of specific backend,\n- **make_unique** which adds a digit to make duplicate heading ID unique, according to the rules of specific backend.\n- **is_flat** which determines whether backend uses flatten preprocessor or not.\n\n# Introduction\n\nAll Foliant backends add anchors to each heading to make it possible to reference headings in URLs. The problem is that each backend has its own way to do that. For example, the heading **My wife's birthday-party** will get an ID `my-wifes-birthday-party` in Pandoc, `header-my-wife’s-birthday-party` in aglio and `my-wife-39-s-birthday-party` in slate.\n\nMoreover, different backends have different ways to deal with duplicate IDs. Utils in this module help you cope with these problems.\n\n# Usage\n\nTo use functions from this module, first install it with command\n\n```bash\npip3 install foliantcontrib.utils.header_anchors\n```\n\nThen import the main functions:\n\n```python\n\u003e\u003e\u003e from foliant.preprocessors.utils.header_anchors import to_id, make_unique, is_flat\n\n```\n\n## to_id\n\nFeed a header title to the `to_id` function to get the proper id for each backend:\n\n```python\n\u003e\u003e\u003e title = \"My wife's birthday-party\"\n\u003e\u003e\u003e to_id(title, 'pandoc')\n'my-wifes-birthday-party'\n\u003e\u003e\u003e to_id(title, 'aglio')\n'header-my-wife’s-birthday-party'\n\u003e\u003e\u003e to_id(title, 'slate')\n'my-wife-39-s-birthday-party'\n\n```\n\n**available backends**:\n\nparam | backend\n----- | -------\n`'pandoc'` | [Pandoc](https://foliant-docs.github.io/docs/backends/pandoc/)\n`'mdtopdf'` | [MdToPdf](https://foliant-docs.github.io/docs/backends/mdtopdf/)\n`'aglio'` | [Aglio](https://foliant-docs.github.io/docs/backends/aglio/)\n`'mkdocs'` | [MkDocs](https://foliant-docs.github.io/docs/backends/mkdocs/)\n`'slate'` | [Slate](https://foliant-docs.github.io/docs/backends/slate/)\n`'confluence'` | [Confluence](https://foliant-docs.github.io/docs/backends/confluence/)\n`'no_transform'` | no transformations, return string as is\n\nIf the name of the backend is not recognized, pandoc will be used as a fallback backend:\n\n```python\n\u003e\u003e\u003e to_id(title, 'nonexistent backend')\n'my-wifes-birthday-party'\n\n```\n\n## make_unique\n\nIf some headers in the document have the same title or their IDs match, each backend transforms the ID for it to remain unique. Pandoc adds subsequent numbers with a hyphen, MkDocs — numbers with an unerscore.\n\n`make_unique` function handles the proper transformations for you. Feed it an id, backend name and number of occurrences of this title in the document to get the proper unique id:\n\n```python\n\u003e\u003e\u003e make_unique('my-title', 3, 'pandoc')\n'my-title-2'\n\u003e\u003e\u003e make_unique('my-title', 3, 'mkdocs')\n'my-title_2'\n\u003e\u003e\u003e make_unique('my-title', 3, 'slate')\n'my-title-3'\n\n```\n\nIf the name of the backend is not recognized, pandoc will be used as a fallback backend:\n\n```python\n\u003e\u003e\u003e make_unique('my-title', 3, 'nonexistent backend')\n'my-title-2'\n\n```\n\n## is_flat\n\nis_flat function takes the backend name as parameter and returns True if backend uses flatten preprocessor to make a single file out of all chapters.\n\n```python\n\u003e\u003e\u003e is_flat('pandoc')\nTrue\n\u003e\u003e\u003e is_flat('mkdocs')\nFalse\n\n```\n\n## IDGenerator class\n\nIDGenerator is a class which helps generate unique anchors in seemless way. It records every call to generate an anchor from a title, and if the anchor repeats, it calls make_unique to make it unique.\n\nHere's an example usage:\n\n```python\n\u003e\u003e\u003e from foliant.preprocessors.utils.header_anchors import IDGenerator\n\u003e\u003e\u003e idgen = IDGenerator('pandoc')\n\u003e\u003e\u003e idgen.generate('My title')\n'my-title'\n\u003e\u003e\u003e idgen.generate('Another title!')\n'another-title'\n\u003e\u003e\u003e idgen.generate('My title')\n'my-title-1'\n\n```\n\nAfter generating id for **My title** for a second time generator had added a `-1` to it. To reset the id count call the `reset` method:\n\n```python\n\u003e\u003e\u003e idgen.reset()\n\u003e\u003e\u003e idgen.generate('My title')\n'my-title'\n\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffoliant-docs%2Ffoliantcontrib.utils.header_anchors","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffoliant-docs%2Ffoliantcontrib.utils.header_anchors","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffoliant-docs%2Ffoliantcontrib.utils.header_anchors/lists"}