docusaurus-plugin-glossary 3.1.0 → 3.2.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 (50) hide show
  1. package/dist/chunk-4CUFUKUA.js +109 -0
  2. package/dist/chunk-4CUFUKUA.js.map +1 -0
  3. package/dist/chunk-PEB4Y6RI.js +311 -0
  4. package/dist/chunk-PEB4Y6RI.js.map +1 -0
  5. package/dist/chunk-SNP37IVL.js +212 -0
  6. package/dist/chunk-SNP37IVL.js.map +1 -0
  7. package/dist/client/index.cjs +55 -0
  8. package/dist/client/index.cjs.map +1 -0
  9. package/dist/client/index.js +10 -21
  10. package/dist/client/index.js.map +1 -0
  11. package/dist/components/GlossaryPage.cjs +130 -0
  12. package/dist/components/GlossaryPage.cjs.map +1 -0
  13. package/dist/components/GlossaryPage.js +74 -113
  14. package/dist/components/GlossaryPage.js.map +1 -0
  15. package/dist/index.cjs +659 -0
  16. package/dist/index.cjs.map +1 -0
  17. package/dist/index.d.cts +173 -0
  18. package/dist/index.d.ts +82 -11
  19. package/dist/index.js +23 -173
  20. package/dist/index.js.map +1 -0
  21. package/dist/preset.cjs +710 -0
  22. package/dist/preset.cjs.map +1 -0
  23. package/dist/preset.d.cts +98 -0
  24. package/dist/preset.d.ts +8 -7
  25. package/dist/preset.js +79 -143
  26. package/dist/preset.js.map +1 -0
  27. package/dist/remark/glossary-terms.cjs +345 -0
  28. package/dist/remark/glossary-terms.cjs.map +1 -0
  29. package/dist/remark/glossary-terms.js +9 -440
  30. package/dist/remark/glossary-terms.js.map +1 -0
  31. package/dist/theme/GlossaryTerm/index.cjs +138 -0
  32. package/dist/theme/GlossaryTerm/index.cjs.map +1 -0
  33. package/dist/theme/GlossaryTerm/index.js +56 -90
  34. package/dist/theme/GlossaryTerm/index.js.map +1 -0
  35. package/dist/validation.cjs +238 -0
  36. package/dist/validation.cjs.map +1 -0
  37. package/dist/validation.d.cts +2 -0
  38. package/dist/validation.d.ts +2 -44
  39. package/dist/validation.js +11 -256
  40. package/dist/validation.js.map +1 -0
  41. package/package.json +25 -30
  42. package/dist/components/GlossaryPage.test.js +0 -205
  43. package/dist/index.d.ts.map +0 -1
  44. package/dist/preset.d.ts.map +0 -1
  45. package/dist/remark/glossary-terms.d.ts +0 -28
  46. package/dist/remark/glossary-terms.d.ts.map +0 -1
  47. package/dist/theme/GlossaryTerm/index.test.js +0 -143
  48. package/dist/validation.d.ts.map +0 -1
  49. /package/dist/{components/GlossaryPage.module.css → GlossaryPage.module-M4DEUP4X.module.css} +0 -0
  50. /package/dist/{theme/GlossaryTerm/styles.module.css → styles.module-N7ME3MWS.module.css} +0 -0
@@ -0,0 +1,212 @@
1
+ // src/validation.ts
2
+ function validateTerm(term, index) {
3
+ const errors = [];
4
+ const prefix = `terms[${index}]`;
5
+ if (term === null || term === void 0) {
6
+ errors.push({
7
+ field: prefix,
8
+ message: "Term cannot be null or undefined",
9
+ value: term
10
+ });
11
+ return errors;
12
+ }
13
+ if (typeof term !== "object") {
14
+ errors.push({
15
+ field: prefix,
16
+ message: `Term must be an object, got ${typeof term}`,
17
+ value: term
18
+ });
19
+ return errors;
20
+ }
21
+ const termObj = term;
22
+ if (!("term" in termObj)) {
23
+ errors.push({
24
+ field: `${prefix}.term`,
25
+ message: 'Missing required field "term"'
26
+ });
27
+ } else if (typeof termObj.term !== "string") {
28
+ errors.push({
29
+ field: `${prefix}.term`,
30
+ message: `Field "term" must be a string, got ${typeof termObj.term}`,
31
+ value: termObj.term
32
+ });
33
+ } else if (termObj.term.trim() === "") {
34
+ errors.push({
35
+ field: `${prefix}.term`,
36
+ message: 'Field "term" cannot be empty',
37
+ value: termObj.term
38
+ });
39
+ }
40
+ if (!("definition" in termObj)) {
41
+ errors.push({
42
+ field: `${prefix}.definition`,
43
+ message: 'Missing required field "definition"'
44
+ });
45
+ } else if (typeof termObj.definition !== "string") {
46
+ errors.push({
47
+ field: `${prefix}.definition`,
48
+ message: `Field "definition" must be a string, got ${typeof termObj.definition}`,
49
+ value: termObj.definition
50
+ });
51
+ }
52
+ if ("abbreviation" in termObj && termObj.abbreviation !== void 0) {
53
+ if (typeof termObj.abbreviation !== "string") {
54
+ errors.push({
55
+ field: `${prefix}.abbreviation`,
56
+ message: `Field "abbreviation" must be a string, got ${typeof termObj.abbreviation}`,
57
+ value: termObj.abbreviation
58
+ });
59
+ }
60
+ }
61
+ if ("relatedTerms" in termObj && termObj.relatedTerms !== void 0) {
62
+ if (!Array.isArray(termObj.relatedTerms)) {
63
+ errors.push({
64
+ field: `${prefix}.relatedTerms`,
65
+ message: `Field "relatedTerms" must be an array, got ${typeof termObj.relatedTerms}`,
66
+ value: termObj.relatedTerms
67
+ });
68
+ } else {
69
+ termObj.relatedTerms.forEach((relatedTerm, relatedIndex) => {
70
+ if (typeof relatedTerm !== "string") {
71
+ errors.push({
72
+ field: `${prefix}.relatedTerms[${relatedIndex}]`,
73
+ message: `Related term must be a string, got ${typeof relatedTerm}`,
74
+ value: relatedTerm
75
+ });
76
+ }
77
+ });
78
+ }
79
+ }
80
+ if ("id" in termObj && termObj.id !== void 0) {
81
+ if (typeof termObj.id !== "string") {
82
+ errors.push({
83
+ field: `${prefix}.id`,
84
+ message: `Field "id" must be a string, got ${typeof termObj.id}`,
85
+ value: termObj.id
86
+ });
87
+ }
88
+ }
89
+ if ("autoLink" in termObj && termObj.autoLink !== void 0) {
90
+ if (typeof termObj.autoLink !== "boolean") {
91
+ errors.push({
92
+ field: `${prefix}.autoLink`,
93
+ message: `Field "autoLink" must be a boolean, got ${typeof termObj.autoLink}`,
94
+ value: termObj.autoLink
95
+ });
96
+ }
97
+ }
98
+ return errors;
99
+ }
100
+ function validateGlossaryData(data, options = {}) {
101
+ const { throwOnError = true } = options;
102
+ const errors = [];
103
+ if (data === null || data === void 0) {
104
+ errors.push({
105
+ field: "root",
106
+ message: "Glossary data cannot be null or undefined",
107
+ value: data
108
+ });
109
+ if (throwOnError && errors.length > 0) {
110
+ throw new GlossaryValidationError(errors);
111
+ }
112
+ return { valid: false, errors, data: { terms: [] } };
113
+ }
114
+ if (typeof data !== "object") {
115
+ errors.push({
116
+ field: "root",
117
+ message: `Glossary data must be an object, got ${typeof data}`,
118
+ value: data
119
+ });
120
+ if (throwOnError && errors.length > 0) {
121
+ throw new GlossaryValidationError(errors);
122
+ }
123
+ return { valid: false, errors, data: { terms: [] } };
124
+ }
125
+ const glossaryData = data;
126
+ if (!("terms" in glossaryData)) {
127
+ errors.push({
128
+ field: "terms",
129
+ message: 'Glossary data must contain a "terms" array'
130
+ });
131
+ if (throwOnError && errors.length > 0) {
132
+ throw new GlossaryValidationError(errors);
133
+ }
134
+ return { valid: false, errors, data: { terms: [] } };
135
+ }
136
+ if (!Array.isArray(glossaryData.terms)) {
137
+ errors.push({
138
+ field: "terms",
139
+ message: `Field "terms" must be an array, got ${typeof glossaryData.terms}`,
140
+ value: glossaryData.terms
141
+ });
142
+ if (throwOnError && errors.length > 0) {
143
+ throw new GlossaryValidationError(errors);
144
+ }
145
+ return { valid: false, errors, data: { terms: [] } };
146
+ }
147
+ const validTerms = [];
148
+ glossaryData.terms.forEach((term, index) => {
149
+ const termErrors = validateTerm(term, index);
150
+ if (termErrors.length > 0) {
151
+ errors.push(...termErrors);
152
+ } else {
153
+ validTerms.push(term);
154
+ }
155
+ });
156
+ const termNames = /* @__PURE__ */ new Map();
157
+ validTerms.forEach((term, index) => {
158
+ const lowerName = term.term.toLowerCase();
159
+ if (termNames.has(lowerName)) {
160
+ errors.push({
161
+ field: `terms[${index}].term`,
162
+ message: `Duplicate term "${term.term}" (first occurrence at index ${termNames.get(lowerName)})`,
163
+ value: term.term
164
+ });
165
+ } else {
166
+ termNames.set(lowerName, index);
167
+ }
168
+ });
169
+ if (throwOnError && errors.length > 0) {
170
+ throw new GlossaryValidationError(errors);
171
+ }
172
+ return {
173
+ valid: errors.length === 0,
174
+ errors,
175
+ data: { terms: validTerms }
176
+ };
177
+ }
178
+ var GlossaryValidationError = class _GlossaryValidationError extends Error {
179
+ constructor(errors) {
180
+ const message = formatValidationErrors(errors);
181
+ super(message);
182
+ this.name = "GlossaryValidationError";
183
+ this.errors = errors;
184
+ if (Error.captureStackTrace) {
185
+ Error.captureStackTrace(this, _GlossaryValidationError);
186
+ }
187
+ }
188
+ };
189
+ function formatValidationErrors(errors) {
190
+ if (errors.length === 0) {
191
+ return "No validation errors";
192
+ }
193
+ const header = `Glossary validation failed with ${errors.length} error${errors.length > 1 ? "s" : ""}:`;
194
+ const errorList = errors.map((err, index) => {
195
+ let msg = ` ${index + 1}. [${err.field}] ${err.message}`;
196
+ if (err.value !== void 0) {
197
+ const valueStr = typeof err.value === "object" ? JSON.stringify(err.value) : String(err.value);
198
+ const truncated = valueStr.length > 50 ? valueStr.substring(0, 50) + "..." : valueStr;
199
+ msg += ` (got: ${truncated})`;
200
+ }
201
+ return msg;
202
+ }).join("\n");
203
+ return `${header}
204
+ ${errorList}`;
205
+ }
206
+
207
+ export {
208
+ validateGlossaryData,
209
+ GlossaryValidationError,
210
+ formatValidationErrors
211
+ };
212
+ //# sourceMappingURL=chunk-SNP37IVL.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/validation.ts"],"sourcesContent":["import type { GlossaryData, GlossaryTerm } from './index.js';\n\nexport interface ValidationError {\n field: string;\n message: string;\n value?: unknown;\n}\n\nexport interface ValidationResult {\n valid: boolean;\n errors: ValidationError[];\n data: GlossaryData;\n}\n\n/**\n * Validates a single glossary term object\n *\n * @param term - The term object to validate\n * @param index - The index in the terms array (for error messages)\n * @returns Array of validation errors (empty if valid)\n */\nfunction validateTerm(term: unknown, index: number): ValidationError[] {\n const errors: ValidationError[] = [];\n const prefix = `terms[${index}]`;\n\n if (term === null || term === undefined) {\n errors.push({\n field: prefix,\n message: 'Term cannot be null or undefined',\n value: term,\n });\n return errors;\n }\n\n if (typeof term !== 'object') {\n errors.push({\n field: prefix,\n message: `Term must be an object, got ${typeof term}`,\n value: term,\n });\n return errors;\n }\n\n const termObj = term as Record<string, unknown>;\n\n // Required: term (string)\n if (!('term' in termObj)) {\n errors.push({\n field: `${prefix}.term`,\n message: 'Missing required field \"term\"',\n });\n } else if (typeof termObj.term !== 'string') {\n errors.push({\n field: `${prefix}.term`,\n message: `Field \"term\" must be a string, got ${typeof termObj.term}`,\n value: termObj.term,\n });\n } else if (termObj.term.trim() === '') {\n errors.push({\n field: `${prefix}.term`,\n message: 'Field \"term\" cannot be empty',\n value: termObj.term,\n });\n }\n\n // Required: definition (string)\n if (!('definition' in termObj)) {\n errors.push({\n field: `${prefix}.definition`,\n message: 'Missing required field \"definition\"',\n });\n } else if (typeof termObj.definition !== 'string') {\n errors.push({\n field: `${prefix}.definition`,\n message: `Field \"definition\" must be a string, got ${typeof termObj.definition}`,\n value: termObj.definition,\n });\n }\n\n // Optional: abbreviation (string)\n if ('abbreviation' in termObj && termObj.abbreviation !== undefined) {\n if (typeof termObj.abbreviation !== 'string') {\n errors.push({\n field: `${prefix}.abbreviation`,\n message: `Field \"abbreviation\" must be a string, got ${typeof termObj.abbreviation}`,\n value: termObj.abbreviation,\n });\n }\n }\n\n // Optional: relatedTerms (string[])\n if ('relatedTerms' in termObj && termObj.relatedTerms !== undefined) {\n if (!Array.isArray(termObj.relatedTerms)) {\n errors.push({\n field: `${prefix}.relatedTerms`,\n message: `Field \"relatedTerms\" must be an array, got ${typeof termObj.relatedTerms}`,\n value: termObj.relatedTerms,\n });\n } else {\n termObj.relatedTerms.forEach((relatedTerm, relatedIndex) => {\n if (typeof relatedTerm !== 'string') {\n errors.push({\n field: `${prefix}.relatedTerms[${relatedIndex}]`,\n message: `Related term must be a string, got ${typeof relatedTerm}`,\n value: relatedTerm,\n });\n }\n });\n }\n }\n\n // Optional: id (string)\n if ('id' in termObj && termObj.id !== undefined) {\n if (typeof termObj.id !== 'string') {\n errors.push({\n field: `${prefix}.id`,\n message: `Field \"id\" must be a string, got ${typeof termObj.id}`,\n value: termObj.id,\n });\n }\n }\n\n // Optional: autoLink (boolean)\n if ('autoLink' in termObj && termObj.autoLink !== undefined) {\n if (typeof termObj.autoLink !== 'boolean') {\n errors.push({\n field: `${prefix}.autoLink`,\n message: `Field \"autoLink\" must be a boolean, got ${typeof termObj.autoLink}`,\n value: termObj.autoLink,\n });\n }\n }\n\n return errors;\n}\n\n/**\n * Validates glossary data structure\n *\n * Ensures the glossary data conforms to the expected schema:\n * - Must be an object with a \"terms\" array\n * - Each term must have \"term\" (string) and \"definition\" (string)\n * - Optional fields: abbreviation (string), relatedTerms (string[]), id (string)\n *\n * @param data - The data to validate\n * @param options - Validation options\n * @param options.throwOnError - If true, throws an error on validation failure (default: true)\n * @returns Validation result with errors and sanitized data\n * @throws Error if data is invalid and throwOnError is true\n */\nexport function validateGlossaryData(\n data: unknown,\n options: { throwOnError?: boolean } = {}\n): ValidationResult {\n const { throwOnError = true } = options;\n const errors: ValidationError[] = [];\n\n // Check if data is null or undefined\n if (data === null || data === undefined) {\n errors.push({\n field: 'root',\n message: 'Glossary data cannot be null or undefined',\n value: data,\n });\n\n if (throwOnError && errors.length > 0) {\n throw new GlossaryValidationError(errors);\n }\n\n return { valid: false, errors, data: { terms: [] } };\n }\n\n // Check if data is an object\n if (typeof data !== 'object') {\n errors.push({\n field: 'root',\n message: `Glossary data must be an object, got ${typeof data}`,\n value: data,\n });\n\n if (throwOnError && errors.length > 0) {\n throw new GlossaryValidationError(errors);\n }\n\n return { valid: false, errors, data: { terms: [] } };\n }\n\n const glossaryData = data as Record<string, unknown>;\n\n // Check for terms array\n if (!('terms' in glossaryData)) {\n errors.push({\n field: 'terms',\n message: 'Glossary data must contain a \"terms\" array',\n });\n\n if (throwOnError && errors.length > 0) {\n throw new GlossaryValidationError(errors);\n }\n\n return { valid: false, errors, data: { terms: [] } };\n }\n\n if (!Array.isArray(glossaryData.terms)) {\n errors.push({\n field: 'terms',\n message: `Field \"terms\" must be an array, got ${typeof glossaryData.terms}`,\n value: glossaryData.terms,\n });\n\n if (throwOnError && errors.length > 0) {\n throw new GlossaryValidationError(errors);\n }\n\n return { valid: false, errors, data: { terms: [] } };\n }\n\n // Validate each term\n const validTerms: GlossaryTerm[] = [];\n glossaryData.terms.forEach((term, index) => {\n const termErrors = validateTerm(term, index);\n if (termErrors.length > 0) {\n errors.push(...termErrors);\n } else {\n // Term is valid, add to valid terms\n validTerms.push(term as GlossaryTerm);\n }\n });\n\n // Check for duplicate terms\n const termNames = new Map<string, number>();\n validTerms.forEach((term, index) => {\n const lowerName = term.term.toLowerCase();\n if (termNames.has(lowerName)) {\n errors.push({\n field: `terms[${index}].term`,\n message: `Duplicate term \"${term.term}\" (first occurrence at index ${termNames.get(lowerName)})`,\n value: term.term,\n });\n } else {\n termNames.set(lowerName, index);\n }\n });\n\n if (throwOnError && errors.length > 0) {\n throw new GlossaryValidationError(errors);\n }\n\n return {\n valid: errors.length === 0,\n errors,\n data: { terms: validTerms },\n };\n}\n\n/**\n * Custom error class for glossary validation errors\n * Provides detailed error messages for debugging\n */\nexport class GlossaryValidationError extends Error {\n public readonly errors: ValidationError[];\n\n constructor(errors: ValidationError[]) {\n const message = formatValidationErrors(errors);\n super(message);\n this.name = 'GlossaryValidationError';\n this.errors = errors;\n\n // Maintains proper stack trace for where error was thrown (V8 engines)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, GlossaryValidationError);\n }\n }\n}\n\n/**\n * Formats validation errors into a readable string\n *\n * @param errors - Array of validation errors\n * @returns Formatted error message\n */\nexport function formatValidationErrors(errors: ValidationError[]): string {\n if (errors.length === 0) {\n return 'No validation errors';\n }\n\n const header = `Glossary validation failed with ${errors.length} error${errors.length > 1 ? 's' : ''}:`;\n const errorList = errors\n .map((err, index) => {\n let msg = ` ${index + 1}. [${err.field}] ${err.message}`;\n if (err.value !== undefined) {\n const valueStr =\n typeof err.value === 'object' ? JSON.stringify(err.value) : String(err.value);\n // Truncate long values\n const truncated = valueStr.length > 50 ? valueStr.substring(0, 50) + '...' : valueStr;\n msg += ` (got: ${truncated})`;\n }\n return msg;\n })\n .join('\\n');\n\n return `${header}\\n${errorList}`;\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,130 @@
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
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_Layout.default, { title: "Glossary", description: "A glossary of terms and definitions", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: import_GlossaryPage.default.glossaryContainer, children: [
71
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("header", { className: import_GlossaryPage.default.glossaryHeader, children: [
72
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h1", { children: "Glossary" }),
73
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: import_GlossaryPage.default.glossaryDescription, children: glossaryData?.description || "A collection of terms and their definitions" }),
74
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: import_GlossaryPage.default.searchContainer, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
75
+ "input",
76
+ {
77
+ type: "text",
78
+ placeholder: "Search terms...",
79
+ className: import_GlossaryPage.default.searchInput,
80
+ value: searchTerm,
81
+ onChange: (e) => setSearchTerm(e.target.value)
82
+ }
83
+ ) })
84
+ ] }),
85
+ filteredTerms.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: import_GlossaryPage.default.noResults, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { children: [
86
+ 'No terms found matching "',
87
+ searchTerm,
88
+ '"'
89
+ ] }) }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: import_GlossaryPage.default.glossaryContent, children: [
90
+ /* @__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)) }),
91
+ letters.map((letter) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { id: `letter-${letter}`, className: import_GlossaryPage.default.letterSection, children: [
92
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { className: import_GlossaryPage.default.letterHeading, children: letter }),
93
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("dl", { className: import_GlossaryPage.default.termList, children: groupedTerms[letter].map((term, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
94
+ "div",
95
+ {
96
+ className: import_GlossaryPage.default.termItem,
97
+ id: term.id || term.term.toLowerCase().replace(/\s+/g, "-"),
98
+ children: [
99
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("dt", { className: import_GlossaryPage.default.termName, children: [
100
+ term.term,
101
+ term.abbreviation && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: import_GlossaryPage.default.abbreviation, children: [
102
+ " (",
103
+ term.abbreviation,
104
+ ")"
105
+ ] })
106
+ ] }),
107
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("dd", { className: import_GlossaryPage.default.termDefinition, children: [
108
+ term.definition,
109
+ term.relatedTerms && term.relatedTerms.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: import_GlossaryPage.default.relatedTerms, children: [
110
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: "Related terms:" }),
111
+ " ",
112
+ term.relatedTerms.map((related, idx) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react.default.Fragment, { children: [
113
+ idx > 0 && ", ",
114
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { href: `#${related.toLowerCase().replace(/\s+/g, "-")}`, children: related })
115
+ ] }, idx))
116
+ ] })
117
+ ] })
118
+ ]
119
+ },
120
+ `${letter}-${index}`
121
+ )) })
122
+ ] }, letter))
123
+ ] }),
124
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("footer", { className: import_GlossaryPage.default.glossaryFooter, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { children: [
125
+ "Total terms: ",
126
+ terms.length
127
+ ] }) })
128
+ ] }) });
129
+ }
130
+ //# 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 return (\n <Layout title=\"Glossary\" description=\"A glossary of terms and definitions\">\n <div className={styles.glossaryContainer}>\n <header className={styles.glossaryHeader}>\n <h1>Glossary</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"]}