Skip to content

Commit 55e54d3

Browse files
committed
Update styles on heading anchor links
1 parent 80ac5c7 commit 55e54d3

12 files changed

Lines changed: 191 additions & 177 deletions

File tree

_TODO.md

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -128,16 +128,19 @@ Need a tooltip component for consistency. List to add tooltips to:
128128

129129
## Support Pages to Style
130130

131-
- /offline
131+
- /
132132
- /404
133-
- Bug reporter modal
134-
- /search
133+
- /about
135134
- /consent
135+
- /contact
136+
- /downloads/[slug]
137+
- /newsletter/confirm/[token]
138+
- /offline
136139
- /privacy
140+
- /privacy/my-data
141+
- /search
137142
- /tags/[tag]
138-
- /about
139-
- /contact
140-
- /
143+
- Bug reporter modal
141144

142145
## Image generation models
143146

src/components/Layout/Markdown/Tags/index.astro

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ const resolveTagMeta = (rawTag: string) => {
5858
href={href}
5959
rel="tag"
6060
itemprop="keywords"
61-
class="uppercase inline-block pr-2 sm:pr-3 py-0.5 text-xs sm:text-sm no-underline transition-colors hover:text-secondary focus:bg-spotlight focus:text-secondary"
61+
class="uppercase inline-block pr-2 sm:pr-3 py-0.5 text-xs sm:text-sm no-underline transition-colors hover:text-secondary focus-visible:px-2 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-spotlight focus-visible:text-secondary"
6262
>
6363
{label}
6464
</a>

src/components/Test/Demo.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@
55
*/
66
---
77

8-
Just some included text.
8+
And a [link]('/about') to included text.

src/content/articles/demo/index.mdx

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import Demo from '@components/Test/Demo.mdx'
1313

1414
## Components
1515

16-
### Includes from other Markdown files
16+
### Includes from [other Markdown]('/articles/demo') files
1717

1818
```markdown
1919
import Demo from '@components/Test/Demo.mdx'
@@ -23,12 +23,6 @@ import Demo from '@components/Test/Demo.mdx'
2323

2424
<Demo />
2525

26-
### Search
27-
28-
import SearchBar from '@components/Search/SearchBar/index.astro'
29-
30-
<SearchBar />
31-
3226
### Avatar Component
3327

3428
```markdown

src/lib/config/markdown.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,11 +186,24 @@ export const rehypeMermaidConfig = {
186186
/** rehype-autolink-headings plugin */
187187
export const rehypeAutolinkHeadingsConfig: RehypeAutolinkHeadingsOptions = {
188188
behavior: 'append',
189+
/**
190+
* Set explicit classes on the injected <a> so we can style heading anchors
191+
* independently from the generic <a> handling in rehypeTailwindClasses.
192+
*/
193+
properties: {
194+
className: [
195+
'heading-anchor',
196+
'no-underline',
197+
'hover:no-underline',
198+
'focus-visible:no-underline',
199+
'transition-colors',
200+
],
201+
},
189202
content: {
190203
type: 'element',
191204
tagName: 'span',
192205
properties: {
193-
className: 'anchor-link',
206+
className: ['anchor-link', 'text-md', 'sm:text-lg'],
194207
ariaHidden: 'true',
195208
},
196209
children: [

src/lib/markdown/__tests__/integration/rehype-autolink-headings-astro.spec.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ describe('rehype-autolink-headings (Layer 2: With Astro Pipeline)', () => {
2323

2424
expect(html).toContain('<h2')
2525
expect(html).toContain('🔗')
26-
expect(html).toContain('class="anchor-link"')
26+
expect(html).toContain('class="anchor-link')
27+
expect(html).toContain('class="heading-anchor')
2728
expect(html).toContain('<table')
2829
})
2930

@@ -118,7 +119,7 @@ Content[^1]
118119
stage: 'rehype',
119120
})
120121

121-
const anchorCount = (html.match(/class="anchor-link"/g) || []).length
122+
const anchorCount = (html.match(/class="anchor-link\b/g) || []).length
122123
expect(anchorCount).toBe(4) // All 4 headings should have anchors
123124
})
124125

src/lib/markdown/__tests__/integration/rehype-tailwind-astro.spec.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { describe, it, expect } from 'vitest'
22
import { rehypeTailwindClasses } from '@lib/markdown/plugins/rehype-tailwind'
3-
import { processWithAstroSettings } from '@lib/markdown/helpers/processors'
3+
import { processWithAstroSettings, processWithFullPipeline } from '@lib/markdown/helpers/processors'
44

55
describe('rehype-tailwind-classes (Layer 2: With Astro Pipeline)', () => {
66
describe('Tailwind classes with GFM', () => {
@@ -63,6 +63,8 @@ describe('rehype-tailwind-classes (Layer 2: With Astro Pipeline)', () => {
6363

6464
expect(html).toContain('<a')
6565
expect(html).toContain('https://example.com')
66+
expect(html).toContain('hover:decoration-content-active')
67+
expect(html).toContain('focus-visible:outline-none')
6668
})
6769
})
6870

@@ -151,5 +153,21 @@ Content text
151153
expect(html).toContain('<h1')
152154
expect(html).toContain('Content text')
153155
})
156+
157+
it('should not apply generic link classes to heading anchors', async () => {
158+
const markdown = `
159+
## Components
160+
161+
Paragraph with a [regular link](https://example.com)
162+
`.trim()
163+
164+
const html = await processWithFullPipeline(markdown)
165+
166+
// Heading anchors are created by rehype-autolink-headings and should be styled via its config.
167+
expect(html).toContain('class="heading-anchor')
168+
// Regular links should not be marked as heading anchors.
169+
expect(html).toContain('href="https://example.com"')
170+
expect(html).not.toMatch(/href="https:\/\/example\.com"[^>]*class="[^"]*heading-anchor/)
171+
})
154172
})
155173
})

src/lib/markdown/__tests__/units/rehype-autolink-headings.spec.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ describe('rehype-autolink-headings (Layer 1: Isolated)', () => {
3333
})
3434

3535
expect(html).toContain('🔗')
36-
expect(html).toContain('class="anchor-link"')
36+
expect(html).toContain('class="anchor-link')
37+
expect(html).toContain('class="heading-anchor')
3738
})
3839

3940
it('should add aria-hidden to anchor content', async () => {
@@ -74,7 +75,7 @@ describe('rehype-autolink-headings (Layer 1: Isolated)', () => {
7475
expect(html).toContain('<h6')
7576

7677
// Should have anchor links for each
77-
const anchorCount = (html.match(/class="anchor-link"/g) || []).length
78+
const anchorCount = (html.match(/class="anchor-link\b/g) || []).length
7879
expect(anchorCount).toBe(6)
7980
})
8081
})

0 commit comments

Comments
 (0)