Skip to content

Commit 22ee2c0

Browse files
committed
fixed comment from Copilot Review
1 parent 474c758 commit 22ee2c0

1 file changed

Lines changed: 28 additions & 12 deletions

File tree

website/src/components/Glossary/GlossaryTable.tsx

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useCallback, useEffect, useMemo, useState } from 'react';
1+
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
22
import Fuse from 'fuse.js';
33
import clsx from 'clsx';
44
import { marked } from 'marked';
@@ -31,29 +31,34 @@ const slugify = (text: string): string =>
3131
.replace(/[^a-z0-9]+/g, '-')
3232
.replace(/(^-+|-+$)/g, '');
3333

34-
const sanitizeMarkdown = (markdown: string, purify: typeof DOMPurify | null): string => {
35-
const html = marked.parse(markdown || '', { async: false }) as string;
36-
return purify ? purify.sanitize(html) : html;
37-
};
38-
3934
const GlossaryTable: React.FC = () => {
4035
const [termQuery, setTermQuery] = useState('');
4136
const [textQuery, setTextQuery] = useState('');
4237
const [activeSlug, setActiveSlug] = useState('');
38+
const [entries, setEntries] = useState<DisplayEntry[]>([]);
39+
const [aliasToCanonicalSlug, setAliasToCanonicalSlug] = useState<Map<string, string>>(new Map());
40+
const purifyRef = useRef<typeof DOMPurify | null>(null);
41+
const [purifyReady, setPurifyReady] = useState(false);
4342

44-
const purify = useMemo(() => (typeof window === 'undefined' ? null : DOMPurify), []);
43+
useEffect(() => {
44+
if (typeof window !== 'undefined') {
45+
purifyRef.current = DOMPurify;
46+
setPurifyReady(true);
47+
}
48+
}, []);
4549

46-
const { entries, aliasToCanonicalSlug } = useMemo(() => {
50+
useEffect(() => {
4751
const glossaryItems = glossaryData as GlossaryItem[];
4852
const termSet = new Set(glossaryItems.map((item) => item.term));
4953

5054
const canonicalEntries: DisplayEntry[] = glossaryItems.map((item) => {
5155
const slug = slugify(item.term);
56+
const html = marked.parse(item.definition || '', { async: false }) as string;
5257
return {
5358
term: item.term,
5459
abbreviation: item.abbreviation,
5560
definition: item.definition,
56-
definitionHtml: sanitizeMarkdown(item.definition, purify),
61+
definitionHtml: html,
5762
canonicalTerm: item.term,
5863
isAlias: false,
5964
slug,
@@ -70,7 +75,7 @@ const GlossaryTable: React.FC = () => {
7075
term: alias,
7176
abbreviation: '',
7277
definition: `See ${item.term}`,
73-
definitionHtml: '', // Alias entries don't need HTML since they use a link
78+
definitionHtml: '',
7479
canonicalTerm: item.term,
7580
isAlias: true,
7681
slug: slugify(alias),
@@ -84,8 +89,19 @@ const GlossaryTable: React.FC = () => {
8489
aliasEntries.forEach((entry) => aliasMap.set(entry.slug, entry.targetSlug));
8590

8691
const combined = [...canonicalEntries, ...aliasEntries].sort((a, b) => a.term.localeCompare(b.term));
87-
return { entries: combined, aliasToCanonicalSlug: aliasMap };
88-
}, [purify]);
92+
setEntries(combined);
93+
setAliasToCanonicalSlug(aliasMap);
94+
}, []);
95+
96+
useEffect(() => {
97+
if (!purifyReady || !purifyRef.current) return;
98+
setEntries((prev) =>
99+
prev.map((entry) => {
100+
if (entry.isAlias || !entry.definitionHtml) return entry;
101+
return { ...entry, definitionHtml: purifyRef.current!.sanitize(entry.definitionHtml) };
102+
})
103+
);
104+
}, [purifyReady]);
89105

90106
const fuse = useMemo(
91107
() =>

0 commit comments

Comments
 (0)