From 1f8e18c83e1c72292edfbbd83f8dd9b8fde339f8 Mon Sep 17 00:00:00 2001 From: lid0a <70815650+lid0a@users.noreply.github.com> Date: Wed, 17 Apr 2024 16:21:17 +0500 Subject: [PATCH] docs: add heading anchors (#814) * docs: add heading anchors * refactor: remove hastscript from docs deps --------- Co-authored-by: Odil Abdulloyev --- docs/.astro/types.d.ts | 2 +- docs/astro.config.mjs | 19 +++++++ docs/package-lock.json | 101 ++++++++++++++++++++++++++++++------- docs/package.json | 8 +-- docs/src/styles/custom.css | 43 +++++++++++++++- 5 files changed, 151 insertions(+), 22 deletions(-) diff --git a/docs/.astro/types.d.ts b/docs/.astro/types.d.ts index 461c97ad7..61f54eea0 100644 --- a/docs/.astro/types.d.ts +++ b/docs/.astro/types.d.ts @@ -440,5 +440,5 @@ declare module 'astro:content' { type AnyEntryMap = ContentEntryMap & DataEntryMap; - export type ContentConfig = typeof import("../src/content/config.js"); + export type ContentConfig = typeof import("./../src/content/config.js"); } diff --git a/docs/astro.config.mjs b/docs/astro.config.mjs index 47becc9c1..3d8764d3b 100644 --- a/docs/astro.config.mjs +++ b/docs/astro.config.mjs @@ -2,6 +2,9 @@ import { $ } from 'zx' import { defineConfig } from 'astro/config' import starlight from '@astrojs/starlight' import rehypeExternalLinks from 'rehype-external-links' +import rehypeAutolinkHeadings from 'rehype-autolink-headings' +import rehypeSlug from 'rehype-slug' + if (!process.env.VERCEL) await $`tsx sync-readme-to-pages.ts` // https://astro.build/config @@ -100,6 +103,22 @@ export default defineConfig({ target: '_blank', }, ], + rehypeSlug, + [ + rehypeAutolinkHeadings, + { + properties: { class: 'anchor-link' }, + behavior: 'after', + content: () => [{ type: 'text', value: '#' }], + group: ({ tagName }) => ({ + type: 'element', + tagName: 'div', + properties: { + class: `heading-wrapper level-${tagName}`, + }, + }), + }, + ], ], }, }) diff --git a/docs/package-lock.json b/docs/package-lock.json index 675ef4948..1cffc4df7 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -18,7 +18,9 @@ }, "devDependencies": { "@astrojs/starlight": "^0.21.2", + "rehype-autolink-headings": "^7.1.0", "rehype-external-links": "^3.0.0", + "rehype-slug": "^6.0.0", "sharp": "^0.33.3", "tsx": "^4.7.1", "typescript": "^5.4.3", @@ -161,6 +163,23 @@ "astro": "^4.2.7" } }, + "node_modules/@astrojs/starlight/node_modules/hastscript": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-8.0.0.tgz", + "integrity": "sha512-dMOtzCEd3ABUeSIISmrETiKuyydk1w0pa+gE/uormcTpSYuaNJPbX1NU3JLyscSLjwAQM8bWMhhIlnCqnRvDTw==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-parse-selector": "^4.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/@astrojs/telemetry": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/@astrojs/telemetry/-/telemetry-3.0.4.tgz", @@ -5199,6 +5218,23 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/hast-util-from-parse5/node_modules/hastscript": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-8.0.0.tgz", + "integrity": "sha512-dMOtzCEd3ABUeSIISmrETiKuyydk1w0pa+gE/uormcTpSYuaNJPbX1NU3JLyscSLjwAQM8bWMhhIlnCqnRvDTw==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-parse-selector": "^4.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-has-property": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/hast-util-has-property/-/hast-util-has-property-3.0.0.tgz", @@ -5212,6 +5248,19 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/hast-util-heading-rank": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-heading-rank/-/hast-util-heading-rank-3.0.0.tgz", + "integrity": "sha512-EJKb8oMUXVHcWZTDepnr+WNbfnXKFNf9duMesmr4S8SXTJBJ9M4Yok08pu9vxdJwdlGRhVumk9mEhkEvKGifwA==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-is-element": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-3.0.0.tgz", @@ -5446,23 +5495,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/hastscript": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-8.0.0.tgz", - "integrity": "sha512-dMOtzCEd3ABUeSIISmrETiKuyydk1w0pa+gE/uormcTpSYuaNJPbX1NU3JLyscSLjwAQM8bWMhhIlnCqnRvDTw==", - "dev": true, - "dependencies": { - "@types/hast": "^3.0.0", - "comma-separated-tokens": "^2.0.0", - "hast-util-parse-selector": "^4.0.0", - "property-information": "^6.0.0", - "space-separated-tokens": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/heap": { "version": "0.2.7", "resolved": "https://registry.npmjs.org/heap/-/heap-0.2.7.tgz", @@ -8854,6 +8886,24 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/rehype-autolink-headings": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/rehype-autolink-headings/-/rehype-autolink-headings-7.1.0.tgz", + "integrity": "sha512-rItO/pSdvnvsP4QRB1pmPiNHUskikqtPojZKJPPPAVx9Hj8i8TwMBhofrrAYRhYOOBZH9tgmG5lPqDLuIWPWmw==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0", + "@ungap/structured-clone": "^1.0.0", + "hast-util-heading-rank": "^3.0.0", + "hast-util-is-element": "^3.0.0", + "unified": "^11.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/rehype-external-links": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/rehype-external-links/-/rehype-external-links-3.0.0.tgz", @@ -8902,6 +8952,23 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/rehype-slug": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/rehype-slug/-/rehype-slug-6.0.0.tgz", + "integrity": "sha512-lWyvf/jwu+oS5+hL5eClVd3hNdmwM1kAC0BUvEGD19pajQMIzcNUd/k9GsfQ+FfECvX+JE+e9/btsKH0EjJT6A==", + "dev": true, + "dependencies": { + "@types/hast": "^3.0.0", + "github-slugger": "^2.0.0", + "hast-util-heading-rank": "^3.0.0", + "hast-util-to-string": "^3.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/rehype-stringify": { "version": "10.0.0", "resolved": "https://registry.npmjs.org/rehype-stringify/-/rehype-stringify-10.0.0.tgz", diff --git a/docs/package.json b/docs/package.json index fe57db0cf..cc20f9c52 100644 --- a/docs/package.json +++ b/docs/package.json @@ -22,10 +22,12 @@ }, "devDependencies": { "@astrojs/starlight": "^0.21.2", - "zx": "^7.2.3", + "rehype-autolink-headings": "^7.1.0", + "rehype-external-links": "^3.0.0", + "rehype-slug": "^6.0.0", + "sharp": "^0.33.3", "tsx": "^4.7.1", "typescript": "^5.4.3", - "rehype-external-links": "^3.0.0", - "sharp": "^0.33.3" + "zx": "^7.2.3" } } diff --git a/docs/src/styles/custom.css b/docs/src/styles/custom.css index c1987a144..679a94021 100644 --- a/docs/src/styles/custom.css +++ b/docs/src/styles/custom.css @@ -11,6 +11,9 @@ --sl-color-gray-5: #35354c; --sl-color-gray-6: #24243a; --sl-color-black: #171721; + + /* heading anchor icon size */ + --icon-size: 0.75em; } /* Light mode colors. */ :root[data-theme='light'] { @@ -51,4 +54,42 @@ main::before { .external-link-icon { text-decoration: none; display: inline-block; -} \ No newline at end of file +} + +.heading-wrapper > :is(h2, h3, h4, h5, h6) { + display: inline; +} + +.heading-wrapper .anchor-link { + opacity: 0; + margin-inline-start: calc(var(--icon-size) / 2); + text-decoration: none; + &:hover { + text-decoration: underline; + } +} + +.heading-wrapper:hover .anchor-link, +.heading-wrapper .anchor-link:focus { + opacity: 1; +} + +.level-h2 { + font-size: var(--sl-text-h2); +} + +.level-h3 { + font-size: var(--sl-text-h3); +} + +.level-h4 { + font-size: var(--sl-text-h4); +} + +.level-h5 { + font-size: var(--sl-text-h5); +} + +.level-h6 { + font-size: var(--sl-text-h6); +}