diff --git a/app/components/Article/Contents.tsx b/app/components/Article/Contents.tsx
index 56ffe5f3..2b9c54c6 100644
--- a/app/components/Article/Contents.tsx
+++ b/app/components/Article/Contents.tsx
@@ -1,4 +1,5 @@
import {useRef, useEffect} from 'react'
+import {questionUrl} from '~/routesMapper'
import type {Glossary, PageId, GlossaryEntry} from '~/server-utils/stampy'
const footnoteHTML = (el: HTMLDivElement, e: HTMLAnchorElement): string | null => {
@@ -56,27 +57,19 @@ const updateTextNodes = (el: Node, textProcessor: (node: Node) => Node) => {
* - use each glossary item only once
*/
const glossaryInjecter = (pageid: string, glossary: Glossary) => {
- const unusedGlossaryEntries = Object.values(glossary)
- .filter((item) => item.pageid != pageid)
- .map(({term}) => term)
- .sort((a, b) => b.length - a.length)
- .map(
- (term) =>
- [
- new RegExp(`(^|[^\\w-])(${term})($|[^\\w-])`, 'i'),
- '$1$2$3',
- ] as const
- )
-
- return (html: string) => {
- return unusedGlossaryEntries.reduce((html, [match, replacement], index) => {
- if (html.match(match)) {
- unusedGlossaryEntries.splice(index, 1)
- return html.replace(match, replacement)
- }
- return html
- }, html)
- }
+ const seen = new Set()
+ return (html: string) =>
+ Object.values(glossary)
+ .filter((item) => item.pageid != pageid)
+ .sort((a, b) => b.alias.length - a.alias.length)
+ .reduce((html, {term, alias}) => {
+ const match = new RegExp(`(^|[^\\w-])(${alias})($|[^\\w-])`, 'i')
+ if (!seen.has(term) && html.search(match) >= 0) {
+ seen.add(term)
+ return html.replace(match, '$1$2$3')
+ }
+ return html
+ }, html)
}
const insertGlossary = (pageid: string, glossary: Glossary) => {
@@ -101,6 +94,7 @@ const insertGlossary = (pageid: string, glossary: Glossary) => {
*/
const glossaryEntry = (e: Element) => {
const entry = e.textContent && glossary[e?.textContent.toLowerCase().trim()]
+ console.log(e.textContent, entry)
if (
// If the contents of this item aren't simply a glossary item word, then
// something has gone wrong and the glossary-entry should be removed
@@ -124,7 +118,7 @@ const insertGlossary = (pageid: string, glossary: Glossary) => {
if (!entry) return undefined
const link =
entry.pageid &&
- `View full definition`
+ `View full definition`
const image = entry.image && ``
addPopup(
e as HTMLSpanElement,
diff --git a/app/routesMapper.ts b/app/routesMapper.ts
index 5f65edea..79fe3063 100644
--- a/app/routesMapper.ts
+++ b/app/routesMapper.ts
@@ -1,5 +1,5 @@
export const questionUrl = ({pageid, title}: {pageid: string; title?: string}) =>
- `/questions/${pageid}/${title || ''}`
+ `/questions/${pageid}/${title?.replaceAll(' ', '-') || ''}`
export const tagUrl = ({tagId, name}: {tagId?: number | string; name: string}) =>
tagId ? `/tags/${tagId}/${name}` : `/tags/${name}`
diff --git a/app/server-utils/stampy.ts b/app/server-utils/stampy.ts
index f2757dcf..75e1b0c8 100644
--- a/app/server-utils/stampy.ts
+++ b/app/server-utils/stampy.ts
@@ -47,6 +47,7 @@ export type Banner = {
}
export type GlossaryEntry = {
term: string
+ alias: string
pageid: PageId
contents: string
image: string
@@ -328,13 +329,14 @@ export const loadGlossary = withCache('loadGlossary', async () => {
const phrases = [values.phrase, ...values.aliases.split('\n')]
const item = {
pageid,
+ term: extractText(values.phrase),
image: values.image?.url,
contents: renderText(pageid, extractText(values.definition)),
}
return phrases
.map((i) => extractText(i))
.filter(Boolean)
- .map((phrase) => [phrase.toLowerCase(), {term: phrase, ...item}])
+ .map((phrase) => [phrase.toLowerCase(), {alias: phrase, ...item}])
})
.flat()
)