docusaurus-plugin-glossary 3.1.0 → 3.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/README.md +5 -0
  2. package/dist/chunk-22LFZL7L.js +109 -0
  3. package/dist/chunk-22LFZL7L.js.map +1 -0
  4. package/dist/chunk-7Z37JEHW.js +257 -0
  5. package/dist/chunk-7Z37JEHW.js.map +1 -0
  6. package/dist/chunk-WYKSBP3X.js +331 -0
  7. package/dist/chunk-WYKSBP3X.js.map +1 -0
  8. package/dist/client/index.cjs +55 -0
  9. package/dist/client/index.cjs.map +1 -0
  10. package/dist/client/index.js +10 -21
  11. package/dist/client/index.js.map +1 -0
  12. package/dist/components/GlossaryPage.cjs +131 -0
  13. package/dist/components/GlossaryPage.cjs.map +1 -0
  14. package/dist/components/GlossaryPage.js +75 -113
  15. package/dist/components/GlossaryPage.js.map +1 -0
  16. package/dist/index.cjs +724 -0
  17. package/dist/index.cjs.map +1 -0
  18. package/dist/index.d.cts +176 -0
  19. package/dist/index.d.ts +85 -11
  20. package/dist/index.js +23 -173
  21. package/dist/index.js.map +1 -0
  22. package/dist/preset.cjs +775 -0
  23. package/dist/preset.cjs.map +1 -0
  24. package/dist/preset.d.cts +98 -0
  25. package/dist/preset.d.ts +8 -7
  26. package/dist/preset.js +79 -143
  27. package/dist/preset.js.map +1 -0
  28. package/dist/remark/glossary-terms.cjs +365 -0
  29. package/dist/remark/glossary-terms.cjs.map +1 -0
  30. package/dist/remark/glossary-terms.js +9 -440
  31. package/dist/remark/glossary-terms.js.map +1 -0
  32. package/dist/{theme/GlossaryTerm/styles.module.css → styles.module-QQW7ISLV.module.css} +2 -4
  33. package/dist/theme/GlossaryTerm/index.cjs +138 -0
  34. package/dist/theme/GlossaryTerm/index.cjs.map +1 -0
  35. package/dist/theme/GlossaryTerm/index.js +56 -90
  36. package/dist/theme/GlossaryTerm/index.js.map +1 -0
  37. package/dist/validation.cjs +283 -0
  38. package/dist/validation.cjs.map +1 -0
  39. package/dist/validation.d.cts +2 -0
  40. package/dist/validation.d.ts +2 -44
  41. package/dist/validation.js +11 -256
  42. package/dist/validation.js.map +1 -0
  43. package/package.json +27 -32
  44. package/dist/components/GlossaryPage.test.js +0 -205
  45. package/dist/index.d.ts.map +0 -1
  46. package/dist/preset.d.ts.map +0 -1
  47. package/dist/remark/glossary-terms.d.ts +0 -28
  48. package/dist/remark/glossary-terms.d.ts.map +0 -1
  49. package/dist/theme/GlossaryTerm/index.test.js +0 -143
  50. package/dist/validation.d.ts.map +0 -1
  51. /package/dist/{components/GlossaryPage.module.css → GlossaryPage.module-M4DEUP4X.module.css} +0 -0
@@ -0,0 +1,331 @@
1
+ // src/remark/glossary-terms.js
2
+ import { visit } from "unist-util-visit";
3
+ import path from "path";
4
+ import fs from "fs";
5
+ function validateGlossaryTerms(data, _filePath) {
6
+ const errors = [];
7
+ const validTerms = [];
8
+ if (data === null || data === void 0) {
9
+ errors.push(`Glossary data is null or undefined`);
10
+ return { terms: [], errors };
11
+ }
12
+ if (typeof data !== "object") {
13
+ errors.push(`Glossary data must be an object, got ${typeof data}`);
14
+ return { terms: [], errors };
15
+ }
16
+ if (!("terms" in data)) {
17
+ errors.push(`Glossary data must contain a "terms" array`);
18
+ return { terms: [], errors };
19
+ }
20
+ if (!Array.isArray(data.terms)) {
21
+ errors.push(`Field "terms" must be an array, got ${typeof data.terms}`);
22
+ return { terms: [], errors };
23
+ }
24
+ data.terms.forEach((term, index) => {
25
+ if (term === null || term === void 0 || typeof term !== "object") {
26
+ errors.push(`terms[${index}]: Term must be an object`);
27
+ return;
28
+ }
29
+ if (typeof term.term !== "string" || term.term.trim() === "") {
30
+ errors.push(`terms[${index}]: Missing or invalid "term" field`);
31
+ return;
32
+ }
33
+ if (typeof term.definition !== "string") {
34
+ errors.push(`terms[${index}]: Missing or invalid "definition" field`);
35
+ return;
36
+ }
37
+ validTerms.push(term);
38
+ });
39
+ return { terms: validTerms, errors };
40
+ }
41
+ var glossaryCache = /* @__PURE__ */ new Map();
42
+ var CACHE_TTL = 5e3;
43
+ function remarkGlossaryTerms({
44
+ terms = [],
45
+ glossaryPath = null,
46
+ routePath = "/glossary",
47
+ siteDir = null
48
+ } = {}) {
49
+ let glossaryTerms = terms;
50
+ if (!glossaryTerms.length && glossaryPath && siteDir) {
51
+ try {
52
+ const glossaryFilePath = path.resolve(siteDir, glossaryPath);
53
+ const now = Date.now();
54
+ const cached = glossaryCache.get(glossaryFilePath);
55
+ if (cached && now - cached.loadedAt < CACHE_TTL) {
56
+ glossaryTerms = cached.terms;
57
+ } else {
58
+ if (fs.existsSync(glossaryFilePath)) {
59
+ const fileContent = fs.readFileSync(glossaryFilePath, "utf8");
60
+ let glossaryData;
61
+ try {
62
+ glossaryData = JSON.parse(fileContent);
63
+ } catch (parseError) {
64
+ console.error(
65
+ `[glossary-plugin] Failed to parse glossary JSON at ${glossaryPath}:`,
66
+ parseError.message
67
+ );
68
+ glossaryCache.set(glossaryFilePath, {
69
+ terms: [],
70
+ loadedAt: now
71
+ });
72
+ return (tree) => tree;
73
+ }
74
+ const { terms: validTerms, errors } = validateGlossaryTerms(glossaryData, glossaryPath);
75
+ if (errors.length > 0) {
76
+ console.warn(`[glossary-plugin] Glossary validation errors in ${glossaryPath}:`);
77
+ errors.forEach((err) => console.warn(` - ${err}`));
78
+ if (validTerms.length > 0) {
79
+ console.warn(`[glossary-plugin] Proceeding with ${validTerms.length} valid term(s).`);
80
+ }
81
+ }
82
+ glossaryTerms = validTerms;
83
+ glossaryCache.set(glossaryFilePath, {
84
+ terms: glossaryTerms,
85
+ loadedAt: now
86
+ });
87
+ if (!cached && process.env.NODE_ENV !== "production") {
88
+ console.log(
89
+ `[glossary-plugin] Loaded ${glossaryTerms.length} terms from ${glossaryPath}`
90
+ );
91
+ }
92
+ } else {
93
+ glossaryCache.set(glossaryFilePath, {
94
+ terms: [],
95
+ loadedAt: now
96
+ });
97
+ if (process.env.NODE_ENV !== "production") {
98
+ console.warn(`[glossary-plugin] Glossary file not found: ${glossaryPath}`);
99
+ }
100
+ }
101
+ }
102
+ } catch (error) {
103
+ console.warn(
104
+ `[glossary-plugin] Failed to load glossary from ${glossaryPath}:`,
105
+ error.message
106
+ );
107
+ if (glossaryPath && siteDir) {
108
+ const glossaryFilePath = path.resolve(siteDir, glossaryPath);
109
+ glossaryCache.set(glossaryFilePath, {
110
+ terms: [],
111
+ loadedAt: Date.now()
112
+ });
113
+ }
114
+ }
115
+ }
116
+ const termMap = /* @__PURE__ */ new Map();
117
+ glossaryTerms.forEach((termObj) => {
118
+ if (!termObj.term || termObj.autoLink === false) return;
119
+ const register = (phrase) => {
120
+ if (typeof phrase !== "string" || phrase.trim() === "") return;
121
+ const key = phrase.toLowerCase();
122
+ if (!termMap.has(key)) {
123
+ termMap.set(key, { termObj, matchText: phrase });
124
+ }
125
+ };
126
+ register(termObj.term);
127
+ if (Array.isArray(termObj.aliases)) {
128
+ termObj.aliases.forEach(register);
129
+ }
130
+ });
131
+ const sortedTerms = Array.from(termMap.entries()).sort((a, b) => b[0].length - a[0].length);
132
+ if (sortedTerms.length === 0) {
133
+ return (tree) => tree;
134
+ }
135
+ function replaceTermsInText(text) {
136
+ if (!text || !sortedTerms.length) {
137
+ return [{ type: "text", value: text }];
138
+ }
139
+ const result = [];
140
+ let lastIndex = 0;
141
+ const textLower = text.toLowerCase();
142
+ const matches = [];
143
+ for (const [lowerPhrase, { termObj }] of sortedTerms) {
144
+ let searchIndex = 0;
145
+ while (searchIndex < textLower.length) {
146
+ const index = textLower.indexOf(lowerPhrase, searchIndex);
147
+ if (index === -1) break;
148
+ const beforeChar = index > 0 ? textLower[index - 1] : " ";
149
+ const afterIndex = index + lowerPhrase.length;
150
+ const afterChar = afterIndex < textLower.length ? textLower[afterIndex] : " ";
151
+ let matchLength = lowerPhrase.length;
152
+ let isWordBoundary = !/\w/.test(beforeChar) && !/\w/.test(afterChar);
153
+ if (!isWordBoundary && afterChar === "s") {
154
+ const nextChar = afterIndex + 1 < textLower.length ? textLower[afterIndex + 1] : " ";
155
+ if (!/\w/.test(nextChar)) {
156
+ isWordBoundary = true;
157
+ matchLength = lowerPhrase.length + 1;
158
+ }
159
+ }
160
+ if (!isWordBoundary && afterChar === "e" && afterIndex + 1 < textLower.length && textLower[afterIndex + 1] === "s") {
161
+ const nextChar = afterIndex + 2 < textLower.length ? textLower[afterIndex + 2] : " ";
162
+ if (!/\w/.test(nextChar)) {
163
+ isWordBoundary = true;
164
+ matchLength = lowerPhrase.length + 2;
165
+ }
166
+ }
167
+ if (isWordBoundary) {
168
+ matches.push({
169
+ index,
170
+ length: matchLength,
171
+ termObj,
172
+ // Store original case from the text (what the reader actually wrote)
173
+ originalText: text.substring(index, index + matchLength)
174
+ });
175
+ }
176
+ searchIndex = index + 1;
177
+ }
178
+ }
179
+ matches.sort((a, b) => a.index - b.index);
180
+ const nonOverlappingMatches = [];
181
+ let lastMatchEnd = 0;
182
+ for (const match of matches) {
183
+ if (match.index >= lastMatchEnd) {
184
+ nonOverlappingMatches.push(match);
185
+ lastMatchEnd = match.index + match.length;
186
+ }
187
+ }
188
+ for (const match of nonOverlappingMatches) {
189
+ if (match.index > lastIndex) {
190
+ result.push({
191
+ type: "text",
192
+ value: text.substring(lastIndex, match.index)
193
+ });
194
+ }
195
+ result.push({
196
+ type: "mdxJsxFlowElement",
197
+ name: "GlossaryTerm",
198
+ attributes: [
199
+ {
200
+ type: "mdxJsxAttribute",
201
+ name: "term",
202
+ value: match.termObj.term
203
+ },
204
+ {
205
+ type: "mdxJsxAttribute",
206
+ name: "definition",
207
+ value: match.termObj.definition || ""
208
+ },
209
+ {
210
+ type: "mdxJsxAttribute",
211
+ name: "routePath",
212
+ value: routePath
213
+ }
214
+ ],
215
+ children: [
216
+ {
217
+ type: "text",
218
+ value: match.originalText
219
+ }
220
+ ]
221
+ });
222
+ lastIndex = match.index + match.length;
223
+ }
224
+ if (lastIndex < text.length) {
225
+ result.push({
226
+ type: "text",
227
+ value: text.substring(lastIndex)
228
+ });
229
+ }
230
+ return result.length > 0 ? result : [{ type: "text", value: text }];
231
+ }
232
+ function collectHeadingTextNodes(tree) {
233
+ const skip = /* @__PURE__ */ new WeakSet();
234
+ visit(tree, "heading", (headingNode) => {
235
+ visit(headingNode, "text", (textNode) => {
236
+ skip.add(textNode);
237
+ });
238
+ });
239
+ return skip;
240
+ }
241
+ const transformer = (tree) => {
242
+ let usedGlossaryTerm = false;
243
+ const textNodesInHeadings = collectHeadingTextNodes(tree);
244
+ visit(tree, "text", (node, index, parent) => {
245
+ if (parent.type === "code" || parent.type === "inlineCode" || parent.type === "link" || parent.type === "mdxJsxFlowElement" || parent.type === "mdxJsxTextElement") {
246
+ return;
247
+ }
248
+ if (textNodesInHeadings.has(node)) {
249
+ return;
250
+ }
251
+ const replacements = replaceTermsInText(node.value);
252
+ if (replacements.length > 1 || replacements.length === 1 && replacements[0].type !== "text") {
253
+ const newNodes = replacements.map((replacement) => {
254
+ if (replacement.type === "mdxJsxFlowElement") {
255
+ if (parent.type === "paragraph") {
256
+ usedGlossaryTerm = true;
257
+ return {
258
+ type: "mdxJsxTextElement",
259
+ name: replacement.name,
260
+ attributes: replacement.attributes,
261
+ children: replacement.children
262
+ };
263
+ }
264
+ usedGlossaryTerm = true;
265
+ }
266
+ return replacement;
267
+ });
268
+ parent.children.splice(index, 1, ...newNodes);
269
+ return index + newNodes.length - 1;
270
+ }
271
+ });
272
+ if (usedGlossaryTerm) {
273
+ const importNode = {
274
+ type: "mdxjsEsm",
275
+ value: 'import GlossaryTerm from "@theme/GlossaryTerm";',
276
+ data: {
277
+ estree: {
278
+ type: "Program",
279
+ sourceType: "module",
280
+ body: [
281
+ {
282
+ type: "ImportDeclaration",
283
+ specifiers: [
284
+ {
285
+ type: "ImportDefaultSpecifier",
286
+ local: { type: "Identifier", name: "GlossaryTerm" }
287
+ }
288
+ ],
289
+ source: {
290
+ type: "Literal",
291
+ value: "@theme/GlossaryTerm",
292
+ raw: '"@theme/GlossaryTerm"'
293
+ }
294
+ }
295
+ ]
296
+ }
297
+ }
298
+ };
299
+ const hasImport = Array.isArray(tree.children) && tree.children.some(
300
+ (n) => n.type === "mdxjsEsm" && (n.value?.includes("@theme/GlossaryTerm") || n.data?.estree?.body?.some((s) => s.source?.value === "@theme/GlossaryTerm"))
301
+ );
302
+ if (!hasImport) {
303
+ if (!Array.isArray(tree.children)) tree.children = [];
304
+ let insertIndex = 0;
305
+ for (let i = 0; i < tree.children.length; i++) {
306
+ const node = tree.children[i];
307
+ if (node.type === "yaml" || node.type === "toml") {
308
+ insertIndex = i + 1;
309
+ } else {
310
+ break;
311
+ }
312
+ }
313
+ tree.children.splice(insertIndex, 0, importNode);
314
+ }
315
+ }
316
+ };
317
+ return transformer;
318
+ }
319
+ function clearGlossaryCache(filePath) {
320
+ if (filePath) {
321
+ glossaryCache.delete(filePath);
322
+ } else {
323
+ glossaryCache.clear();
324
+ }
325
+ }
326
+
327
+ export {
328
+ remarkGlossaryTerms,
329
+ clearGlossaryCache
330
+ };
331
+ //# sourceMappingURL=chunk-WYKSBP3X.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/remark/glossary-terms.js"],"sourcesContent":["import { visit } from 'unist-util-visit';\nimport path from 'path';\nimport fs from 'fs';\n\n/**\n * Simple validation for glossary terms loaded from file\n * Returns only valid terms with required fields\n *\n * @param {unknown} data - The parsed JSON data\n * @param {string} filePath - Path to the file (for error messages)\n * @returns {{ terms: Array<{term: string, definition: string}>, errors: string[] }}\n */\nfunction validateGlossaryTerms(data, _filePath) {\n const errors = [];\n const validTerms = [];\n\n if (data === null || data === undefined) {\n errors.push(`Glossary data is null or undefined`);\n return { terms: [], errors };\n }\n\n if (typeof data !== 'object') {\n errors.push(`Glossary data must be an object, got ${typeof data}`);\n return { terms: [], errors };\n }\n\n if (!('terms' in data)) {\n errors.push(`Glossary data must contain a \"terms\" array`);\n return { terms: [], errors };\n }\n\n if (!Array.isArray(data.terms)) {\n errors.push(`Field \"terms\" must be an array, got ${typeof data.terms}`);\n return { terms: [], errors };\n }\n\n data.terms.forEach((term, index) => {\n if (term === null || term === undefined || typeof term !== 'object') {\n errors.push(`terms[${index}]: Term must be an object`);\n return;\n }\n\n if (typeof term.term !== 'string' || term.term.trim() === '') {\n errors.push(`terms[${index}]: Missing or invalid \"term\" field`);\n return;\n }\n\n if (typeof term.definition !== 'string') {\n errors.push(`terms[${index}]: Missing or invalid \"definition\" field`);\n return;\n }\n\n validTerms.push(term);\n });\n\n return { terms: validTerms, errors };\n}\n\n// Cache for glossary data to avoid repeated synchronous file reads\n// Key: absolute file path, Value: { terms, loadedAt }\nconst glossaryCache = new Map();\nconst CACHE_TTL = 5000; // 5 seconds TTL to allow for file changes during dev\n\n/**\n * Creates a remark plugin that automatically detects and replaces glossary terms in markdown\n *\n * This plugin transforms plain text terms into <GlossaryTerm> JSX elements.\n * The GlossaryTerm component is globally available via the MDXComponents theme wrapper,\n * so no import injection is needed - MDX files can use it without explicit imports.\n *\n * @param {object} options - Plugin options\n * @param {Array} options.terms - Array of glossary term objects with {term, definition}\n * @param {string} options.glossaryPath - Path to glossary JSON file (optional, if terms not provided)\n * @param {string} options.routePath - Route path to glossary page (default: '/glossary')\n * @param {string} options.siteDir - Docusaurus site directory (required if using glossaryPath)\n * @returns {function} Remark plugin function\n */\nexport default function remarkGlossaryTerms({\n terms = [],\n glossaryPath = null,\n routePath = '/glossary',\n siteDir = null,\n} = {}) {\n let glossaryTerms = terms;\n\n // If terms not provided, try to load from glossaryPath with caching\n if (!glossaryTerms.length && glossaryPath && siteDir) {\n try {\n const glossaryFilePath = path.resolve(siteDir, glossaryPath);\n const now = Date.now();\n\n // Check cache first to avoid repeated file reads\n const cached = glossaryCache.get(glossaryFilePath);\n if (cached && now - cached.loadedAt < CACHE_TTL) {\n glossaryTerms = cached.terms;\n } else {\n // Cache miss or expired - load from file synchronously\n // Note: This is synchronous I/O which can block the build process\n // Consider passing terms directly to avoid this\n if (fs.existsSync(glossaryFilePath)) {\n const fileContent = fs.readFileSync(glossaryFilePath, 'utf8');\n let glossaryData;\n try {\n glossaryData = JSON.parse(fileContent);\n } catch (parseError) {\n console.error(\n `[glossary-plugin] Failed to parse glossary JSON at ${glossaryPath}:`,\n parseError.message\n );\n glossaryCache.set(glossaryFilePath, {\n terms: [],\n loadedAt: now,\n });\n return tree => tree;\n }\n\n // Validate glossary data\n const { terms: validTerms, errors } = validateGlossaryTerms(glossaryData, glossaryPath);\n\n if (errors.length > 0) {\n console.warn(`[glossary-plugin] Glossary validation errors in ${glossaryPath}:`);\n errors.forEach(err => console.warn(` - ${err}`));\n if (validTerms.length > 0) {\n console.warn(`[glossary-plugin] Proceeding with ${validTerms.length} valid term(s).`);\n }\n }\n\n glossaryTerms = validTerms;\n\n // Update cache\n glossaryCache.set(glossaryFilePath, {\n terms: glossaryTerms,\n loadedAt: now,\n });\n\n // Log only once per file (when cache is first populated)\n if (!cached && process.env.NODE_ENV !== 'production') {\n console.log(\n `[glossary-plugin] Loaded ${glossaryTerms.length} terms from ${glossaryPath}`\n );\n }\n } else {\n // File doesn't exist - cache empty result to avoid repeated checks\n glossaryCache.set(glossaryFilePath, {\n terms: [],\n loadedAt: now,\n });\n if (process.env.NODE_ENV !== 'production') {\n console.warn(`[glossary-plugin] Glossary file not found: ${glossaryPath}`);\n }\n }\n }\n } catch (error) {\n console.warn(\n `[glossary-plugin] Failed to load glossary from ${glossaryPath}:`,\n error.message\n );\n // Cache the error to avoid repeated attempts\n if (glossaryPath && siteDir) {\n const glossaryFilePath = path.resolve(siteDir, glossaryPath);\n glossaryCache.set(glossaryFilePath, {\n terms: [],\n loadedAt: Date.now(),\n });\n }\n }\n }\n\n // Build a map of terms for efficient lookup, skipping terms with autoLink: false.\n // Each entry in the map represents a matchable phrase (canonical term or alias)\n // and points back to the canonical term object so tooltip/href always use the canonical form.\n // Key: lowercase phrase, Value: { termObj, matchText } where matchText is what we matched in source\n const termMap = new Map();\n glossaryTerms.forEach(termObj => {\n if (!termObj.term || termObj.autoLink === false) return;\n\n const register = phrase => {\n if (typeof phrase !== 'string' || phrase.trim() === '') return;\n const key = phrase.toLowerCase();\n if (!termMap.has(key)) {\n termMap.set(key, { termObj, matchText: phrase });\n }\n };\n\n register(termObj.term);\n if (Array.isArray(termObj.aliases)) {\n termObj.aliases.forEach(register);\n }\n });\n\n // Sort terms by length (longest first) to avoid partial matches\n // e.g., \"Application Programming Interface\" should match before \"API\"\n const sortedTerms = Array.from(termMap.entries()).sort((a, b) => b[0].length - a[0].length);\n\n // If no terms, return a no-op transformer\n if (sortedTerms.length === 0) {\n return tree => tree;\n }\n\n /**\n * Recursively replace glossary terms in text\n * Returns an array of text nodes and MDX components\n */\n function replaceTermsInText(text) {\n if (!text || !sortedTerms.length) {\n return [{ type: 'text', value: text }];\n }\n\n const result = [];\n let lastIndex = 0;\n const textLower = text.toLowerCase();\n\n // Find all matches\n const matches = [];\n for (const [lowerPhrase, { termObj }] of sortedTerms) {\n let searchIndex = 0;\n\n while (searchIndex < textLower.length) {\n const index = textLower.indexOf(lowerPhrase, searchIndex);\n if (index === -1) break;\n\n // Check if it's a whole word match, with simple plural tolerance ('s' or 'es')\n const beforeChar = index > 0 ? textLower[index - 1] : ' ';\n const afterIndex = index + lowerPhrase.length;\n const afterChar = afterIndex < textLower.length ? textLower[afterIndex] : ' ';\n\n let matchLength = lowerPhrase.length;\n let isWordBoundary = !/\\w/.test(beforeChar) && !/\\w/.test(afterChar);\n\n // Allow trailing 's' plural (e.g., webhook -> webhooks)\n if (!isWordBoundary && afterChar === 's') {\n const nextChar = afterIndex + 1 < textLower.length ? textLower[afterIndex + 1] : ' ';\n if (!/\\w/.test(nextChar)) {\n isWordBoundary = true;\n matchLength = lowerPhrase.length + 1;\n }\n }\n\n // Allow trailing 'es' plural (e.g., API -> APIs, box -> boxes)\n if (\n !isWordBoundary &&\n afterChar === 'e' &&\n afterIndex + 1 < textLower.length &&\n textLower[afterIndex + 1] === 's'\n ) {\n const nextChar = afterIndex + 2 < textLower.length ? textLower[afterIndex + 2] : ' ';\n if (!/\\w/.test(nextChar)) {\n isWordBoundary = true;\n matchLength = lowerPhrase.length + 2;\n }\n }\n\n if (isWordBoundary) {\n matches.push({\n index,\n length: matchLength,\n termObj: termObj,\n // Store original case from the text (what the reader actually wrote)\n originalText: text.substring(index, index + matchLength),\n });\n }\n\n searchIndex = index + 1;\n }\n }\n\n // Sort matches by index\n matches.sort((a, b) => a.index - b.index);\n\n // Remove overlapping matches (keep the first one)\n const nonOverlappingMatches = [];\n let lastMatchEnd = 0;\n for (const match of matches) {\n if (match.index >= lastMatchEnd) {\n nonOverlappingMatches.push(match);\n lastMatchEnd = match.index + match.length;\n }\n }\n\n // Build result array\n for (const match of nonOverlappingMatches) {\n // Add text before match\n if (match.index > lastIndex) {\n result.push({\n type: 'text',\n value: text.substring(lastIndex, match.index),\n });\n }\n\n // Add MDX component for glossary term\n result.push({\n type: 'mdxJsxFlowElement',\n name: 'GlossaryTerm',\n attributes: [\n {\n type: 'mdxJsxAttribute',\n name: 'term',\n value: match.termObj.term,\n },\n {\n type: 'mdxJsxAttribute',\n name: 'definition',\n value: match.termObj.definition || '',\n },\n {\n type: 'mdxJsxAttribute',\n name: 'routePath',\n value: routePath,\n },\n ],\n children: [\n {\n type: 'text',\n value: match.originalText,\n },\n ],\n });\n\n lastIndex = match.index + match.length;\n }\n\n // Add remaining text\n if (lastIndex < text.length) {\n result.push({\n type: 'text',\n value: text.substring(lastIndex),\n });\n }\n\n return result.length > 0 ? result : [{ type: 'text', value: text }];\n }\n\n // Collect text nodes that live inside a heading (h1-h6) so we can skip them.\n // Headings are excluded from auto-linking because glossary anchors inside\n // headings clash with the heading's own link/anchor behavior and are noisy.\n function collectHeadingTextNodes(tree) {\n const skip = new WeakSet();\n visit(tree, 'heading', headingNode => {\n visit(headingNode, 'text', textNode => {\n skip.add(textNode);\n });\n });\n return skip;\n }\n\n // Return the transformer function\n const transformer = tree => {\n let usedGlossaryTerm = false;\n const textNodesInHeadings = collectHeadingTextNodes(tree);\n visit(tree, 'text', (node, index, parent) => {\n // Skip text nodes inside code blocks, links, or existing MDX components\n if (\n parent.type === 'code' ||\n parent.type === 'inlineCode' ||\n parent.type === 'link' ||\n parent.type === 'mdxJsxFlowElement' ||\n parent.type === 'mdxJsxTextElement'\n ) {\n return;\n }\n\n // Skip text nodes that are descendants of a heading (h1-h6)\n if (textNodesInHeadings.has(node)) {\n return;\n }\n\n // Replace terms in text node\n const replacements = replaceTermsInText(node.value);\n\n // If we have replacements, replace the single text node with multiple nodes\n if (\n replacements.length > 1 ||\n (replacements.length === 1 && replacements[0].type !== 'text')\n ) {\n // Convert to text elements for paragraph context if needed\n const newNodes = replacements.map(replacement => {\n if (replacement.type === 'mdxJsxFlowElement') {\n // In paragraph context, we need mdxJsxTextElement instead\n if (parent.type === 'paragraph') {\n usedGlossaryTerm = true;\n return {\n type: 'mdxJsxTextElement',\n name: replacement.name,\n attributes: replacement.attributes,\n children: replacement.children,\n };\n }\n usedGlossaryTerm = true;\n }\n return replacement;\n });\n\n // Replace the single node with multiple nodes\n parent.children.splice(index, 1, ...newNodes);\n return index + newNodes.length - 1; // Return new index to continue\n }\n });\n\n // Inject MDX import for GlossaryTerm if we used it\n // The component is available via theme path, so we just need to import it\n if (usedGlossaryTerm) {\n const importNode = {\n type: 'mdxjsEsm',\n value: 'import GlossaryTerm from \"@theme/GlossaryTerm\";',\n data: {\n estree: {\n type: 'Program',\n sourceType: 'module',\n body: [\n {\n type: 'ImportDeclaration',\n specifiers: [\n {\n type: 'ImportDefaultSpecifier',\n local: { type: 'Identifier', name: 'GlossaryTerm' },\n },\n ],\n source: {\n type: 'Literal',\n value: '@theme/GlossaryTerm',\n raw: '\"@theme/GlossaryTerm\"',\n },\n },\n ],\n },\n },\n };\n\n // Check for existing import\n const hasImport =\n Array.isArray(tree.children) &&\n tree.children.some(\n n =>\n n.type === 'mdxjsEsm' &&\n (n.value?.includes('@theme/GlossaryTerm') ||\n n.data?.estree?.body?.some(s => s.source?.value === '@theme/GlossaryTerm'))\n );\n\n if (!hasImport) {\n if (!Array.isArray(tree.children)) tree.children = [];\n let insertIndex = 0;\n for (let i = 0; i < tree.children.length; i++) {\n const node = tree.children[i];\n if (node.type === 'yaml' || node.type === 'toml') {\n insertIndex = i + 1;\n } else {\n break;\n }\n }\n tree.children.splice(insertIndex, 0, importNode);\n }\n }\n };\n\n return transformer;\n}\n\n/**\n * Clears the glossary cache\n * Useful for testing or when you want to force a reload of glossary data\n *\n * @param {string} [filePath] - Optional specific file path to clear. If not provided, clears entire cache.\n */\nexport function clearGlossaryCache(filePath) {\n if (filePath) {\n glossaryCache.delete(filePath);\n } else {\n glossaryCache.clear();\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/client/index.js
31
+ var client_exports = {};
32
+ __export(client_exports, {
33
+ default: () => client_default
34
+ });
35
+ module.exports = __toCommonJS(client_exports);
36
+ var import_ExecutionEnvironment = __toESM(require("@docusaurus/ExecutionEnvironment"), 1);
37
+ var client_default = (function() {
38
+ if (!import_ExecutionEnvironment.default.canUseDOM) {
39
+ return null;
40
+ }
41
+ return {
42
+ onRouteUpdate({ location }) {
43
+ if (process.env.NODE_ENV !== "production") {
44
+ const glossaryTerms = document.querySelectorAll("[data-glossary-term], .glossaryTerm");
45
+ if (glossaryTerms.length > 0) {
46
+ console.log(
47
+ `[glossary-plugin] Initialized ${glossaryTerms.length} glossary term(s) on route:`,
48
+ location.pathname
49
+ );
50
+ }
51
+ }
52
+ }
53
+ };
54
+ })();
55
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/client/index.js"],"sourcesContent":["import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment';\n\n/**\n * Client module for glossary plugin\n * This runs automatically on every page via getClientModules()\n * Similar to docusaurus-plugin-image-zoom approach\n */\nexport default (function () {\n // Only run in browser environment\n if (!ExecutionEnvironment.canUseDOM) {\n return null;\n }\n\n return {\n onRouteUpdate({ location }) {\n // GlossaryTerm components handle their own tooltips via React\n // This client module can handle any global initialization if needed\n\n // Optional: Log for debugging\n if (process.env.NODE_ENV !== 'production') {\n const glossaryTerms = document.querySelectorAll('[data-glossary-term], .glossaryTerm');\n if (glossaryTerms.length > 0) {\n console.log(\n `[glossary-plugin] Initialized ${glossaryTerms.length} glossary term(s) on route:`,\n location.pathname\n );\n }\n }\n\n // Future enhancement: Could add DOM-based term detection here\n // This would find plain text terms and add tooltips without requiring\n // the remark plugin, similar to how image-zoom finds and enhances <img> tags\n },\n };\n})();\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kCAAiC;AAOjC,IAAO,kBAAS,WAAY;AAE1B,MAAI,CAAC,4BAAAA,QAAqB,WAAW;AACnC,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL,cAAc,EAAE,SAAS,GAAG;AAK1B,UAAI,QAAQ,IAAI,aAAa,cAAc;AACzC,cAAM,gBAAgB,SAAS,iBAAiB,qCAAqC;AACrF,YAAI,cAAc,SAAS,GAAG;AAC5B,kBAAQ;AAAA,YACN,iCAAiC,cAAc,MAAM;AAAA,YACrD,SAAS;AAAA,UACX;AAAA,QACF;AAAA,MACF;AAAA,IAKF;AAAA,EACF;AACF,GAAG;","names":["ExecutionEnvironment"]}
@@ -1,24 +1,13 @@
1
- import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment';
2
-
3
- /**
4
- * Client module for glossary plugin
5
- * This runs automatically on every page via getClientModules()
6
- * Similar to docusaurus-plugin-image-zoom approach
7
- */
8
- export default (function () {
9
- // Only run in browser environment
1
+ // src/client/index.js
2
+ import ExecutionEnvironment from "@docusaurus/ExecutionEnvironment";
3
+ var client_default = (function() {
10
4
  if (!ExecutionEnvironment.canUseDOM) {
11
5
  return null;
12
6
  }
13
-
14
7
  return {
15
8
  onRouteUpdate({ location }) {
16
- // GlossaryTerm components handle their own tooltips via React
17
- // This client module can handle any global initialization if needed
18
-
19
- // Optional: Log for debugging
20
- if (process.env.NODE_ENV !== 'production') {
21
- const glossaryTerms = document.querySelectorAll('[data-glossary-term], .glossaryTerm');
9
+ if (process.env.NODE_ENV !== "production") {
10
+ const glossaryTerms = document.querySelectorAll("[data-glossary-term], .glossaryTerm");
22
11
  if (glossaryTerms.length > 0) {
23
12
  console.log(
24
13
  `[glossary-plugin] Initialized ${glossaryTerms.length} glossary term(s) on route:`,
@@ -26,10 +15,10 @@ export default (function () {
26
15
  );
27
16
  }
28
17
  }
29
-
30
- // Future enhancement: Could add DOM-based term detection here
31
- // This would find plain text terms and add tooltips without requiring
32
- // the remark plugin, similar to how image-zoom finds and enhances <img> tags
33
- },
18
+ }
34
19
  };
35
20
  })();
21
+ export {
22
+ client_default as default
23
+ };
24
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/client/index.js"],"sourcesContent":["import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment';\n\n/**\n * Client module for glossary plugin\n * This runs automatically on every page via getClientModules()\n * Similar to docusaurus-plugin-image-zoom approach\n */\nexport default (function () {\n // Only run in browser environment\n if (!ExecutionEnvironment.canUseDOM) {\n return null;\n }\n\n return {\n onRouteUpdate({ location }) {\n // GlossaryTerm components handle their own tooltips via React\n // This client module can handle any global initialization if needed\n\n // Optional: Log for debugging\n if (process.env.NODE_ENV !== 'production') {\n const glossaryTerms = document.querySelectorAll('[data-glossary-term], .glossaryTerm');\n if (glossaryTerms.length > 0) {\n console.log(\n `[glossary-plugin] Initialized ${glossaryTerms.length} glossary term(s) on route:`,\n location.pathname\n );\n }\n }\n\n // Future enhancement: Could add DOM-based term detection here\n // This would find plain text terms and add tooltips without requiring\n // the remark plugin, similar to how image-zoom finds and enhances <img> tags\n },\n };\n})();\n"],"mappings":";AAAA,OAAO,0BAA0B;AAOjC,IAAO,kBAAS,WAAY;AAE1B,MAAI,CAAC,qBAAqB,WAAW;AACnC,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL,cAAc,EAAE,SAAS,GAAG;AAK1B,UAAI,QAAQ,IAAI,aAAa,cAAc;AACzC,cAAM,gBAAgB,SAAS,iBAAiB,qCAAqC;AACrF,YAAI,cAAc,SAAS,GAAG;AAC5B,kBAAQ;AAAA,YACN,iCAAiC,cAAc,MAAM;AAAA,YACrD,SAAS;AAAA,UACX;AAAA,QACF;AAAA,MACF;AAAA,IAKF;AAAA,EACF;AACF,GAAG;","names":[]}
@@ -0,0 +1,131 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/components/GlossaryPage.js
31
+ var GlossaryPage_exports = {};
32
+ __export(GlossaryPage_exports, {
33
+ default: () => GlossaryPage
34
+ });
35
+ module.exports = __toCommonJS(GlossaryPage_exports);
36
+ var import_react = __toESM(require("react"), 1);
37
+ var import_Layout = __toESM(require("@theme/Layout"), 1);
38
+ var import_useDocusaurusContext = __toESM(require("@docusaurus/useDocusaurusContext"), 1);
39
+ var import_GlossaryPage = __toESM(require("../GlossaryPage.module-M4DEUP4X.module.css"), 1);
40
+ var import_jsx_runtime = require("react/jsx-runtime");
41
+ function groupTermsByLetter(terms) {
42
+ const grouped = {};
43
+ terms.forEach((term) => {
44
+ const firstLetter = term.term.charAt(0).toUpperCase();
45
+ if (!grouped[firstLetter]) {
46
+ grouped[firstLetter] = [];
47
+ }
48
+ grouped[firstLetter].push(term);
49
+ });
50
+ Object.keys(grouped).forEach((letter) => {
51
+ grouped[letter].sort((a, b) => a.term.localeCompare(b.term));
52
+ });
53
+ return grouped;
54
+ }
55
+ function GlossaryPage({ glossaryData }) {
56
+ (0, import_useDocusaurusContext.default)();
57
+ const [searchTerm, setSearchTerm] = (0, import_react.useState)("");
58
+ const terms = (0, import_react.useMemo)(() => glossaryData?.terms || [], [glossaryData?.terms]);
59
+ const filteredTerms = (0, import_react.useMemo)(() => {
60
+ if (!searchTerm) return terms;
61
+ const lowerSearch = searchTerm.toLowerCase();
62
+ return terms.filter(
63
+ (term) => term.term.toLowerCase().includes(lowerSearch) || term.definition.toLowerCase().includes(lowerSearch)
64
+ );
65
+ }, [terms, searchTerm]);
66
+ const groupedTerms = (0, import_react.useMemo)(() => {
67
+ return groupTermsByLetter(filteredTerms);
68
+ }, [filteredTerms]);
69
+ const letters = Object.keys(groupedTerms).sort();
70
+ const glossaryTitle = glossaryData?.title || "Glossary";
71
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_Layout.default, { title: glossaryTitle, description: "A glossary of terms and definitions", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: import_GlossaryPage.default.glossaryContainer, children: [
72
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("header", { className: import_GlossaryPage.default.glossaryHeader, children: [
73
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h1", { children: glossaryTitle }),
74
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: import_GlossaryPage.default.glossaryDescription, children: glossaryData?.description || "A collection of terms and their definitions" }),
75
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: import_GlossaryPage.default.searchContainer, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
76
+ "input",
77
+ {
78
+ type: "text",
79
+ placeholder: "Search terms...",
80
+ className: import_GlossaryPage.default.searchInput,
81
+ value: searchTerm,
82
+ onChange: (e) => setSearchTerm(e.target.value)
83
+ }
84
+ ) })
85
+ ] }),
86
+ filteredTerms.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: import_GlossaryPage.default.noResults, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { children: [
87
+ 'No terms found matching "',
88
+ searchTerm,
89
+ '"'
90
+ ] }) }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: import_GlossaryPage.default.glossaryContent, children: [
91
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("nav", { className: import_GlossaryPage.default.letterNav, children: letters.map((letter) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { href: `#letter-${letter}`, className: import_GlossaryPage.default.letterLink, children: letter }, letter)) }),
92
+ letters.map((letter) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { id: `letter-${letter}`, className: import_GlossaryPage.default.letterSection, children: [
93
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { className: import_GlossaryPage.default.letterHeading, children: letter }),
94
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("dl", { className: import_GlossaryPage.default.termList, children: groupedTerms[letter].map((term, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
95
+ "div",
96
+ {
97
+ className: import_GlossaryPage.default.termItem,
98
+ id: term.id || term.term.toLowerCase().replace(/\s+/g, "-"),
99
+ children: [
100
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("dt", { className: import_GlossaryPage.default.termName, children: [
101
+ term.term,
102
+ term.abbreviation && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: import_GlossaryPage.default.abbreviation, children: [
103
+ " (",
104
+ term.abbreviation,
105
+ ")"
106
+ ] })
107
+ ] }),
108
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("dd", { className: import_GlossaryPage.default.termDefinition, children: [
109
+ term.definition,
110
+ term.relatedTerms && term.relatedTerms.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: import_GlossaryPage.default.relatedTerms, children: [
111
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: "Related terms:" }),
112
+ " ",
113
+ term.relatedTerms.map((related, idx) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react.default.Fragment, { children: [
114
+ idx > 0 && ", ",
115
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { href: `#${related.toLowerCase().replace(/\s+/g, "-")}`, children: related })
116
+ ] }, idx))
117
+ ] })
118
+ ] })
119
+ ]
120
+ },
121
+ `${letter}-${index}`
122
+ )) })
123
+ ] }, letter))
124
+ ] }),
125
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("footer", { className: import_GlossaryPage.default.glossaryFooter, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { children: [
126
+ "Total terms: ",
127
+ terms.length
128
+ ] }) })
129
+ ] }) });
130
+ }
131
+ //# sourceMappingURL=GlossaryPage.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/GlossaryPage.js"],"sourcesContent":["import React, { useState, useMemo } from 'react';\nimport Layout from '@theme/Layout';\nimport useDocusaurusContext from '@docusaurus/useDocusaurusContext';\nimport styles from './GlossaryPage.module.css';\n\n/**\n * Groups glossary terms by their first letter\n */\nfunction groupTermsByLetter(terms) {\n const grouped = {};\n\n terms.forEach(term => {\n const firstLetter = term.term.charAt(0).toUpperCase();\n if (!grouped[firstLetter]) {\n grouped[firstLetter] = [];\n }\n grouped[firstLetter].push(term);\n });\n\n // Sort each group alphabetically\n Object.keys(grouped).forEach(letter => {\n grouped[letter].sort((a, b) => a.term.localeCompare(b.term));\n });\n\n return grouped;\n}\n\n/**\n * GlossaryPage component - displays all glossary terms\n */\nexport default function GlossaryPage({ glossaryData }) {\n useDocusaurusContext();\n const [searchTerm, setSearchTerm] = useState('');\n\n const terms = useMemo(() => glossaryData?.terms || [], [glossaryData?.terms]);\n\n // Filter terms based on search\n const filteredTerms = useMemo(() => {\n if (!searchTerm) return terms;\n\n const lowerSearch = searchTerm.toLowerCase();\n return terms.filter(\n term =>\n term.term.toLowerCase().includes(lowerSearch) ||\n term.definition.toLowerCase().includes(lowerSearch)\n );\n }, [terms, searchTerm]);\n\n // Group terms by first letter\n const groupedTerms = useMemo(() => {\n return groupTermsByLetter(filteredTerms);\n }, [filteredTerms]);\n\n const letters = Object.keys(groupedTerms).sort();\n\n const glossaryTitle = glossaryData?.title || 'Glossary';\n\n return (\n <Layout title={glossaryTitle} description=\"A glossary of terms and definitions\">\n <div className={styles.glossaryContainer}>\n <header className={styles.glossaryHeader}>\n <h1>{glossaryTitle}</h1>\n <p className={styles.glossaryDescription}>\n {glossaryData?.description || 'A collection of terms and their definitions'}\n </p>\n\n <div className={styles.searchContainer}>\n <input\n type=\"text\"\n placeholder=\"Search terms...\"\n className={styles.searchInput}\n value={searchTerm}\n onChange={e => setSearchTerm(e.target.value)}\n />\n </div>\n </header>\n\n {filteredTerms.length === 0 ? (\n <div className={styles.noResults}>\n <p>No terms found matching \"{searchTerm}\"</p>\n </div>\n ) : (\n <div className={styles.glossaryContent}>\n {/* Letter navigation */}\n <nav className={styles.letterNav}>\n {letters.map(letter => (\n <a key={letter} href={`#letter-${letter}`} className={styles.letterLink}>\n {letter}\n </a>\n ))}\n </nav>\n\n {/* Terms grouped by letter */}\n {letters.map(letter => (\n <section key={letter} id={`letter-${letter}`} className={styles.letterSection}>\n <h2 className={styles.letterHeading}>{letter}</h2>\n <dl className={styles.termList}>\n {groupedTerms[letter].map((term, index) => (\n <div\n key={`${letter}-${index}`}\n className={styles.termItem}\n id={term.id || term.term.toLowerCase().replace(/\\s+/g, '-')}\n >\n <dt className={styles.termName}>\n {term.term}\n {term.abbreviation && (\n <span className={styles.abbreviation}> ({term.abbreviation})</span>\n )}\n </dt>\n <dd className={styles.termDefinition}>\n {term.definition}\n {term.relatedTerms && term.relatedTerms.length > 0 && (\n <div className={styles.relatedTerms}>\n <strong>Related terms:</strong>{' '}\n {term.relatedTerms.map((related, idx) => (\n <React.Fragment key={idx}>\n {idx > 0 && ', '}\n <a href={`#${related.toLowerCase().replace(/\\s+/g, '-')}`}>\n {related}\n </a>\n </React.Fragment>\n ))}\n </div>\n )}\n </dd>\n </div>\n ))}\n </dl>\n </section>\n ))}\n </div>\n )}\n\n <footer className={styles.glossaryFooter}>\n <p>Total terms: {terms.length}</p>\n </footer>\n </div>\n </Layout>\n );\n}\n"],"mappings":"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","names":["useDocusaurusContext","Layout","styles","React"]}