Skip to content

Commit 74ee7f6

Browse files
authored
Add linkable anchors to past security advisories (#17303)
Each past advisory now has a stable id matching its PSA code and a copy-link icon in its summary. Linking to the anchor (e.g. #PSA-2026-00001) auto-expands the advisory via ReaderView's existing hash handling.
1 parent 7406a3a commit 74ee7f6

3 files changed

Lines changed: 46 additions & 4 deletions

File tree

contents/handbook/company/security-advisories.md

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ Currently, there are no active security advisories or CVEs. All is well.
4848

4949
## Past advisories
5050

51-
<details>
52-
<summary>June 2, 2026 / PSA-2026-00001</summary>
51+
<details id="PSA-2026-00001">
52+
<summary>June 2, 2026 / PSA-2026-00001 <AdvisoryAnchor id="PSA-2026-00001" /></summary>
5353

5454
<p><strong>Date:</strong> June 2, 2026<br />
5555
<strong>Advisory:</strong> PSA-2026-00001<br />
@@ -101,8 +101,8 @@ Currently, there are no active security advisories or CVEs. All is well.
101101

102102
</details>
103103

104-
<details>
105-
<summary>August 15, 2025 / PSA-2025-00001</summary>
104+
<details id="PSA-2025-00001">
105+
<summary>August 15, 2025 / PSA-2025-00001 <AdvisoryAnchor id="PSA-2025-00001" /></summary>
106106

107107
<p><strong>Date:</strong> August 15, 2025<br />
108108
<strong>Advisory:</strong> PSA-2025-00001<br />
@@ -144,7 +144,12 @@ Currently, there are no active security advisories or CVEs. All is well.
144144

145145
### Advisory template
146146

147+
Use the advisory code as the `<details>` `id` (and the matching `<AdvisoryAnchor>` `id`) so it can be linked directly. Linking to the anchor (e.g. `/handbook/company/security-advisories#PSA-2025-XXXXX`) auto-expands the advisory.
148+
147149
```
150+
<details id="PSA-2025-XXXXX">
151+
<summary>August 15, 2025 / PSA-2025-XXXXX <AdvisoryAnchor id="PSA-2025-XXXXX" /></summary>
152+
148153
<p><strong>Date:</strong> August 15, 2025<br />
149154
<strong>Advisory:</strong> PSA-2025-XXXXX<br />
150155
<strong>Severity:</strong> Low / Medium / Critical<br />
@@ -173,6 +178,8 @@ Currently, there are no active security advisories or CVEs. All is well.
173178
<li><strong>Fixed:</strong> January 10, 2024, 00:00 UTC</li>
174179
<li><strong>Disclosed:</strong> January 10, 2024, 00:00 UTC</li>
175180
</ul>
181+
182+
</details>
176183
```
177184

178185

src/components/Heading/index.tsx

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,39 @@ export const CopyAnchor = ({ id = '', hovered }: { id: string; hovered: boolean
3939
)
4040
}
4141

42+
export const AdvisoryAnchor = ({ id = '' }: { id: string }): JSX.Element => {
43+
const [copied, setCopied] = useState(false)
44+
const { href } = useLocation()
45+
// Copy the shareable link without toggling the parent <details>. Stopping propagation and
46+
// the default action keeps the surrounding <summary> from opening/closing on click.
47+
const handleClick = (e: React.MouseEvent) => {
48+
e.stopPropagation()
49+
e.preventDefault()
50+
const url = `${href.replace(/#.*/, '')}#${id}`
51+
window.history.replaceState(null, '', `#${id}`)
52+
navigator.clipboard?.writeText(url)
53+
setCopied(true)
54+
setTimeout(() => {
55+
setCopied(false)
56+
}, 1000)
57+
}
58+
59+
return (
60+
<span className="inline-flex items-center align-middle">
61+
<button
62+
type="button"
63+
onClick={handleClick}
64+
aria-label="Copy link to this advisory"
65+
title="Copy link to this advisory"
66+
className="inline-flex opacity-40 hover:opacity-100 transition-opacity ml-2"
67+
>
68+
<IconLink className="size-4" />
69+
</button>
70+
{copied && <span className="ml-1.5 text-sm font-normal">Copied!</span>}
71+
</span>
72+
)
73+
}
74+
4275
export const Heading = ({
4376
as = 'h1',
4477
children,

src/mdxGlobalComponents.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import { FeatureAvailability } from './components/FeatureAvailability'
2525
import FeatureOwnershipTable from './components/FeatureOwnershipTable'
2626
import { FormulaScreenshot } from './components/FormulaScreenshot'
2727
import { GDPRForm } from './components/GDPRForm'
28+
import { AdvisoryAnchor } from './components/Heading'
2829
import { HiddenSection } from './components/HiddenSection'
2930
import { HubSpotForm } from './components/HubSpotForm'
3031
import ImageSlider from './components/ImageSlider'
@@ -96,6 +97,7 @@ export const shortcodes = {
9697
FeatureAvailability,
9798
FormulaScreenshot,
9899
GDPRForm,
100+
AdvisoryAnchor,
99101
HiddenSection,
100102
HubSpotForm,
101103
KeyboardShortcut,

0 commit comments

Comments
 (0)