docusaurus-plugin-glossary 3.0.2 → 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 +83 -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 -246
  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
@@ -1,246 +1,11 @@
1
- /**
2
- * Validates a single glossary term object
3
- *
4
- * @param term - The term object to validate
5
- * @param index - The index in the terms array (for error messages)
6
- * @returns Array of validation errors (empty if valid)
7
- */
8
- function validateTerm(term, index) {
9
- const errors = [];
10
- const prefix = `terms[${index}]`;
11
- if (term === null || term === undefined) {
12
- errors.push({
13
- field: prefix,
14
- message: 'Term cannot be null or undefined',
15
- value: term,
16
- });
17
- return errors;
18
- }
19
- if (typeof term !== 'object') {
20
- errors.push({
21
- field: prefix,
22
- message: `Term must be an object, got ${typeof term}`,
23
- value: term,
24
- });
25
- return errors;
26
- }
27
- const termObj = term;
28
- // Required: term (string)
29
- if (!('term' in termObj)) {
30
- errors.push({
31
- field: `${prefix}.term`,
32
- message: 'Missing required field "term"',
33
- });
34
- }
35
- else if (typeof termObj.term !== 'string') {
36
- errors.push({
37
- field: `${prefix}.term`,
38
- message: `Field "term" must be a string, got ${typeof termObj.term}`,
39
- value: termObj.term,
40
- });
41
- }
42
- else if (termObj.term.trim() === '') {
43
- errors.push({
44
- field: `${prefix}.term`,
45
- message: 'Field "term" cannot be empty',
46
- value: termObj.term,
47
- });
48
- }
49
- // Required: definition (string)
50
- if (!('definition' in termObj)) {
51
- errors.push({
52
- field: `${prefix}.definition`,
53
- message: 'Missing required field "definition"',
54
- });
55
- }
56
- else if (typeof termObj.definition !== 'string') {
57
- errors.push({
58
- field: `${prefix}.definition`,
59
- message: `Field "definition" must be a string, got ${typeof termObj.definition}`,
60
- value: termObj.definition,
61
- });
62
- }
63
- // Optional: abbreviation (string)
64
- if ('abbreviation' in termObj && termObj.abbreviation !== undefined) {
65
- if (typeof termObj.abbreviation !== 'string') {
66
- errors.push({
67
- field: `${prefix}.abbreviation`,
68
- message: `Field "abbreviation" must be a string, got ${typeof termObj.abbreviation}`,
69
- value: termObj.abbreviation,
70
- });
71
- }
72
- }
73
- // Optional: relatedTerms (string[])
74
- if ('relatedTerms' in termObj && termObj.relatedTerms !== undefined) {
75
- if (!Array.isArray(termObj.relatedTerms)) {
76
- errors.push({
77
- field: `${prefix}.relatedTerms`,
78
- message: `Field "relatedTerms" must be an array, got ${typeof termObj.relatedTerms}`,
79
- value: termObj.relatedTerms,
80
- });
81
- }
82
- else {
83
- termObj.relatedTerms.forEach((relatedTerm, relatedIndex) => {
84
- if (typeof relatedTerm !== 'string') {
85
- errors.push({
86
- field: `${prefix}.relatedTerms[${relatedIndex}]`,
87
- message: `Related term must be a string, got ${typeof relatedTerm}`,
88
- value: relatedTerm,
89
- });
90
- }
91
- });
92
- }
93
- }
94
- // Optional: id (string)
95
- if ('id' in termObj && termObj.id !== undefined) {
96
- if (typeof termObj.id !== 'string') {
97
- errors.push({
98
- field: `${prefix}.id`,
99
- message: `Field "id" must be a string, got ${typeof termObj.id}`,
100
- value: termObj.id,
101
- });
102
- }
103
- }
104
- return errors;
105
- }
106
- /**
107
- * Validates glossary data structure
108
- *
109
- * Ensures the glossary data conforms to the expected schema:
110
- * - Must be an object with a "terms" array
111
- * - Each term must have "term" (string) and "definition" (string)
112
- * - Optional fields: abbreviation (string), relatedTerms (string[]), id (string)
113
- *
114
- * @param data - The data to validate
115
- * @param options - Validation options
116
- * @param options.throwOnError - If true, throws an error on validation failure (default: true)
117
- * @returns Validation result with errors and sanitized data
118
- * @throws Error if data is invalid and throwOnError is true
119
- */
120
- export function validateGlossaryData(data, options = {}) {
121
- const { throwOnError = true } = options;
122
- const errors = [];
123
- // Check if data is null or undefined
124
- if (data === null || data === undefined) {
125
- errors.push({
126
- field: 'root',
127
- message: 'Glossary data cannot be null or undefined',
128
- value: data,
129
- });
130
- if (throwOnError && errors.length > 0) {
131
- throw new GlossaryValidationError(errors);
132
- }
133
- return { valid: false, errors, data: { terms: [] } };
134
- }
135
- // Check if data is an object
136
- if (typeof data !== 'object') {
137
- errors.push({
138
- field: 'root',
139
- message: `Glossary data must be an object, got ${typeof data}`,
140
- value: data,
141
- });
142
- if (throwOnError && errors.length > 0) {
143
- throw new GlossaryValidationError(errors);
144
- }
145
- return { valid: false, errors, data: { terms: [] } };
146
- }
147
- const glossaryData = data;
148
- // Check for terms array
149
- if (!('terms' in glossaryData)) {
150
- errors.push({
151
- field: 'terms',
152
- message: 'Glossary data must contain a "terms" array',
153
- });
154
- if (throwOnError && errors.length > 0) {
155
- throw new GlossaryValidationError(errors);
156
- }
157
- return { valid: false, errors, data: { terms: [] } };
158
- }
159
- if (!Array.isArray(glossaryData.terms)) {
160
- errors.push({
161
- field: 'terms',
162
- message: `Field "terms" must be an array, got ${typeof glossaryData.terms}`,
163
- value: glossaryData.terms,
164
- });
165
- if (throwOnError && errors.length > 0) {
166
- throw new GlossaryValidationError(errors);
167
- }
168
- return { valid: false, errors, data: { terms: [] } };
169
- }
170
- // Validate each term
171
- const validTerms = [];
172
- glossaryData.terms.forEach((term, index) => {
173
- const termErrors = validateTerm(term, index);
174
- if (termErrors.length > 0) {
175
- errors.push(...termErrors);
176
- }
177
- else {
178
- // Term is valid, add to valid terms
179
- validTerms.push(term);
180
- }
181
- });
182
- // Check for duplicate terms
183
- const termNames = new Map();
184
- validTerms.forEach((term, index) => {
185
- const lowerName = term.term.toLowerCase();
186
- if (termNames.has(lowerName)) {
187
- errors.push({
188
- field: `terms[${index}].term`,
189
- message: `Duplicate term "${term.term}" (first occurrence at index ${termNames.get(lowerName)})`,
190
- value: term.term,
191
- });
192
- }
193
- else {
194
- termNames.set(lowerName, index);
195
- }
196
- });
197
- if (throwOnError && errors.length > 0) {
198
- throw new GlossaryValidationError(errors);
199
- }
200
- return {
201
- valid: errors.length === 0,
202
- errors,
203
- data: { terms: validTerms },
204
- };
205
- }
206
- /**
207
- * Custom error class for glossary validation errors
208
- * Provides detailed error messages for debugging
209
- */
210
- export class GlossaryValidationError extends Error {
211
- constructor(errors) {
212
- const message = formatValidationErrors(errors);
213
- super(message);
214
- this.name = 'GlossaryValidationError';
215
- this.errors = errors;
216
- // Maintains proper stack trace for where error was thrown (V8 engines)
217
- if (Error.captureStackTrace) {
218
- Error.captureStackTrace(this, GlossaryValidationError);
219
- }
220
- }
221
- }
222
- /**
223
- * Formats validation errors into a readable string
224
- *
225
- * @param errors - Array of validation errors
226
- * @returns Formatted error message
227
- */
228
- export function formatValidationErrors(errors) {
229
- if (errors.length === 0) {
230
- return 'No validation errors';
231
- }
232
- const header = `Glossary validation failed with ${errors.length} error${errors.length > 1 ? 's' : ''}:`;
233
- const errorList = errors
234
- .map((err, index) => {
235
- let msg = ` ${index + 1}. [${err.field}] ${err.message}`;
236
- if (err.value !== undefined) {
237
- const valueStr = typeof err.value === 'object' ? JSON.stringify(err.value) : String(err.value);
238
- // Truncate long values
239
- const truncated = valueStr.length > 50 ? valueStr.substring(0, 50) + '...' : valueStr;
240
- msg += ` (got: ${truncated})`;
241
- }
242
- return msg;
243
- })
244
- .join('\n');
245
- return `${header}\n${errorList}`;
246
- }
1
+ import {
2
+ GlossaryValidationError,
3
+ formatValidationErrors,
4
+ validateGlossaryData
5
+ } from "./chunk-SNP37IVL.js";
6
+ export {
7
+ GlossaryValidationError,
8
+ formatValidationErrors,
9
+ validateGlossaryData
10
+ };
11
+ //# sourceMappingURL=validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
package/package.json CHANGED
@@ -1,24 +1,26 @@
1
1
  {
2
2
  "name": "docusaurus-plugin-glossary",
3
- "version": "3.0.2",
3
+ "version": "3.2.0",
4
4
  "description": "A Docusaurus plugin for creating and managing glossary terms with auto-generated pages and inline tooltips",
5
5
  "type": "module",
6
- "main": "dist/index.js",
6
+ "main": "dist/index.cjs",
7
+ "module": "dist/index.js",
8
+ "types": "dist/index.d.ts",
7
9
  "exports": {
8
10
  ".": {
11
+ "types": "./dist/index.d.ts",
9
12
  "import": "./dist/index.js",
10
- "require": "./dist/index.js",
11
- "default": "./dist/index.js"
13
+ "require": "./dist/index.cjs"
12
14
  },
13
15
  "./preset": {
16
+ "types": "./dist/preset.d.ts",
14
17
  "import": "./dist/preset.js",
15
- "require": "./dist/preset.js",
16
- "default": "./dist/preset.js"
18
+ "require": "./dist/preset.cjs"
17
19
  },
18
20
  "./remark/glossary-terms": {
21
+ "types": "./dist/remark/glossary-terms.d.ts",
19
22
  "import": "./dist/remark/glossary-terms.js",
20
- "require": "./dist/remark/glossary-terms.js",
21
- "default": "./dist/remark/glossary-terms.js"
23
+ "require": "./dist/remark/glossary-terms.cjs"
22
24
  }
23
25
  },
24
26
  "files": [
@@ -27,8 +29,11 @@
27
29
  "LICENSE"
28
30
  ],
29
31
  "scripts": {
30
- "build": "tsc && node scripts/build.js",
31
- "watch": "tsc && node scripts/watch.js",
32
+ "build": "tsup",
33
+ "dev": "tsup --watch",
34
+ "watch": "npm run dev",
35
+ "clean": "rimraf dist",
36
+ "typecheck": "tsc --noEmit",
32
37
  "test": "jest",
33
38
  "test:watch": "jest --watch",
34
39
  "test:coverage": "jest --coverage",
@@ -40,7 +45,6 @@
40
45
  "example:clear": "npm --prefix examples/docusaurus-v3 run clear",
41
46
  "prepare": "husky",
42
47
  "prepublishOnly": "npm run build && npm test",
43
- "version": "npm version",
44
48
  "format": "prettier --write \"**/*.{js,jsx,ts,tsx,json,css,md}\"",
45
49
  "format:check": "prettier --check \"**/*.{js,jsx,ts,tsx,json,css,md}\"",
46
50
  "lint": "eslint \"src/**/*.{js,jsx,ts,tsx}\" \"__tests__/**/*.js\"",
@@ -82,25 +86,28 @@
82
86
  "@babel/preset-env": "^7.28.5",
83
87
  "@babel/preset-react": "^7.28.5",
84
88
  "@babel/preset-typescript": "^7.28.5",
85
- "@eslint/js": "^9.28.0",
86
- "@typescript-eslint/eslint-plugin": "^8.33.0",
87
- "@typescript-eslint/parser": "^8.33.0",
88
- "eslint": "^9.28.0",
89
- "eslint-plugin-react": "^7.37.5",
90
- "eslint-plugin-react-hooks": "^5.2.0",
91
89
  "@docusaurus/tsconfig": "^3.9.2",
92
90
  "@docusaurus/types": "^3.9.2",
91
+ "@eslint/js": "^9.28.0",
93
92
  "@playwright/test": "^1.56.1",
94
93
  "@testing-library/jest-dom": "^6.9.1",
95
94
  "@testing-library/react": "^16.3.0",
96
95
  "@testing-library/user-event": "^14.6.1",
96
+ "@types/fs-extra": "^11.0.4",
97
+ "@typescript-eslint/eslint-plugin": "^8.33.0",
98
+ "@typescript-eslint/parser": "^8.33.0",
97
99
  "babel-jest": "^30.2.0",
100
+ "eslint": "^9.28.0",
101
+ "eslint-plugin-react": "^7.37.5",
102
+ "eslint-plugin-react-hooks": "^5.2.0",
103
+ "husky": "^9.1.7",
98
104
  "identity-obj-proxy": "^3.0.0",
99
105
  "jest": "^30.2.0",
100
106
  "jest-environment-jsdom": "^30.2.0",
101
- "husky": "^9.1.7",
102
107
  "lint-staged": "^15.5.1",
103
108
  "prettier": "^3.6.2",
109
+ "rimraf": "^6.0.1",
110
+ "tsup": "^8.0.1",
104
111
  "typescript": "^5.7.3"
105
112
  },
106
113
  "lint-staged": {
@@ -111,17 +118,5 @@
111
118
  "*.{json,css,md}": [
112
119
  "prettier --write"
113
120
  ]
114
- },
115
- "browser": {
116
- "path": false,
117
- "url": false,
118
- "fs": false,
119
- "fs-extra": false,
120
- "graceful-fs": false,
121
- "jsonfile": false,
122
- "util": false,
123
- "assert": false,
124
- "stream": false,
125
- "constants": false
126
121
  }
127
122
  }
@@ -1,205 +0,0 @@
1
- import React from 'react';
2
- import { render, screen } from '@testing-library/react';
3
- import userEvent from '@testing-library/user-event';
4
- import GlossaryPage from './GlossaryPage';
5
-
6
- // Mock CSS modules
7
- jest.mock('./GlossaryPage.module.css', () => ({
8
- glossaryContainer: 'glossaryContainer',
9
- glossaryHeader: 'glossaryHeader',
10
- glossaryDescription: 'glossaryDescription',
11
- searchContainer: 'searchContainer',
12
- searchInput: 'searchInput',
13
- noResults: 'noResults',
14
- glossaryContent: 'glossaryContent',
15
- letterNav: 'letterNav',
16
- letterLink: 'letterLink',
17
- letterSection: 'letterSection',
18
- letterHeading: 'letterHeading',
19
- termList: 'termList',
20
- termItem: 'termItem',
21
- termName: 'termName',
22
- abbreviation: 'abbreviation',
23
- termDefinition: 'termDefinition',
24
- relatedTerms: 'relatedTerms',
25
- glossaryFooter: 'glossaryFooter',
26
- }));
27
-
28
- const mockGlossaryData = {
29
- description: 'Test glossary',
30
- terms: [
31
- {
32
- id: 'api',
33
- term: 'API',
34
- definition: 'Application Programming Interface',
35
- abbreviation: 'API',
36
- relatedTerms: ['REST'],
37
- },
38
- {
39
- id: 'rest',
40
- term: 'REST',
41
- definition: 'Representational State Transfer',
42
- abbreviation: 'REST',
43
- relatedTerms: ['API'],
44
- },
45
- {
46
- id: 'ml',
47
- term: 'Machine Learning',
48
- definition: 'A type of artificial intelligence',
49
- },
50
- ],
51
- };
52
-
53
- describe('GlossaryPage', () => {
54
- it('should render glossary with all terms', () => {
55
- render(<GlossaryPage glossaryData={mockGlossaryData} />);
56
-
57
- expect(screen.getByText('Glossary')).toBeInTheDocument();
58
- expect(screen.getByText('Test glossary')).toBeInTheDocument();
59
- // Use getAllBy since terms can appear multiple times (in term names and related links)
60
- expect(screen.getAllByText('API').length).toBeGreaterThan(0);
61
- expect(screen.getAllByText('REST').length).toBeGreaterThan(0);
62
- expect(screen.getByText('Machine Learning')).toBeInTheDocument();
63
- });
64
-
65
- it('should show search input', () => {
66
- render(<GlossaryPage glossaryData={mockGlossaryData} />);
67
-
68
- const searchInput = screen.getByPlaceholderText('Search terms...');
69
- expect(searchInput).toBeInTheDocument();
70
- });
71
-
72
- it('should filter terms by search query', async () => {
73
- const user = userEvent.setup();
74
- render(<GlossaryPage glossaryData={mockGlossaryData} />);
75
-
76
- const searchInput = screen.getByPlaceholderText('Search terms...');
77
- await user.type(searchInput, 'API');
78
-
79
- expect(screen.getByText('API')).toBeInTheDocument();
80
- expect(screen.queryByText('Machine Learning')).not.toBeInTheDocument();
81
- });
82
-
83
- it('should filter by definition text', async () => {
84
- const user = userEvent.setup();
85
- render(<GlossaryPage glossaryData={mockGlossaryData} />);
86
-
87
- const searchInput = screen.getByPlaceholderText('Search terms...');
88
- await user.type(searchInput, 'artificial');
89
-
90
- expect(screen.getByText('Machine Learning')).toBeInTheDocument();
91
- expect(screen.queryByText('API')).not.toBeInTheDocument();
92
- expect(screen.queryByText('REST')).not.toBeInTheDocument();
93
- });
94
-
95
- it('should show no results message when no matches', async () => {
96
- const user = userEvent.setup();
97
- render(<GlossaryPage glossaryData={mockGlossaryData} />);
98
-
99
- const searchInput = screen.getByPlaceholderText('Search terms...');
100
- await user.type(searchInput, 'NonexistentTerm');
101
-
102
- expect(screen.getByText(/No terms found matching/)).toBeInTheDocument();
103
- });
104
-
105
- it('should group terms by first letter', () => {
106
- render(<GlossaryPage glossaryData={mockGlossaryData} />);
107
-
108
- // Check that terms are grouped under their first letter (multiple elements per letter)
109
- expect(screen.getAllByText('A').length).toBeGreaterThan(0);
110
- expect(screen.getAllByText('M').length).toBeGreaterThan(0);
111
- expect(screen.getAllByText('R').length).toBeGreaterThan(0);
112
- });
113
-
114
- it('should sort terms alphabetically within groups', () => {
115
- const dataWithMultipleTerms = {
116
- ...mockGlossaryData,
117
- terms: [
118
- { id: 'zebra', term: 'Zebra', definition: 'An animal' },
119
- { id: 'alpha', term: 'Alpha', definition: 'First letter' },
120
- { id: 'beta', term: 'Beta', definition: 'Second letter' },
121
- ],
122
- };
123
-
124
- render(<GlossaryPage glossaryData={dataWithMultipleTerms} />);
125
-
126
- const terms = screen.getAllByText(/Zebra|Alpha|Beta/);
127
- expect(terms).toHaveLength(3);
128
- // Check Alpha is before Beta, and Beta is before Zebra
129
- expect(terms[0]).toHaveTextContent('Alpha');
130
- expect(terms[1]).toHaveTextContent('Beta');
131
- expect(terms[2]).toHaveTextContent('Zebra');
132
- });
133
-
134
- it('should display abbreviations', () => {
135
- render(<GlossaryPage glossaryData={mockGlossaryData} />);
136
-
137
- // Check abbreviation appears in document
138
- expect(screen.getAllByText('(API)').length).toBeGreaterThan(0);
139
- expect(screen.getAllByText('(REST)').length).toBeGreaterThan(0);
140
- });
141
-
142
- it('should display related terms', () => {
143
- render(<GlossaryPage glossaryData={mockGlossaryData} />);
144
-
145
- // Related terms header appears multiple times (once per term with related terms)
146
- expect(screen.getAllByText('Related terms:').length).toBeGreaterThan(0);
147
- // REST appears as a term and in related links
148
- expect(screen.getAllByText('REST').length).toBeGreaterThan(0);
149
- });
150
-
151
- it('should show total term count in footer', () => {
152
- render(<GlossaryPage glossaryData={mockGlossaryData} />);
153
-
154
- expect(screen.getByText('Total terms: 3')).toBeInTheDocument();
155
- });
156
-
157
- it('should handle empty terms array', () => {
158
- const emptyData = { terms: [] };
159
- render(<GlossaryPage glossaryData={emptyData} />);
160
-
161
- expect(screen.getByText('Glossary')).toBeInTheDocument();
162
- expect(screen.getByText('Total terms: 0')).toBeInTheDocument();
163
- });
164
-
165
- it('should handle missing glossaryData gracefully', () => {
166
- render(<GlossaryPage glossaryData={null} />);
167
-
168
- expect(screen.getByText('Glossary')).toBeInTheDocument();
169
- expect(screen.getByText('Total terms: 0')).toBeInTheDocument();
170
- });
171
-
172
- it('should handle missing description gracefully', () => {
173
- const dataWithoutDescription = {
174
- terms: mockGlossaryData.terms,
175
- };
176
- render(<GlossaryPage glossaryData={dataWithoutDescription} />);
177
-
178
- expect(screen.getByText(/A collection of terms and their definitions/)).toBeInTheDocument();
179
- });
180
-
181
- it('should generate correct anchor links for terms', () => {
182
- render(<GlossaryPage glossaryData={mockGlossaryData} />);
183
-
184
- // Check navigation links are generated
185
- const navLinks = screen.getAllByRole('link', { name: /^[AMR]$/ });
186
- expect(navLinks.length).toBeGreaterThan(0);
187
- expect(navLinks[0]).toHaveAttribute('href', '#letter-A');
188
- });
189
-
190
- it('should clear search when input is cleared', async () => {
191
- const user = userEvent.setup();
192
- render(<GlossaryPage glossaryData={mockGlossaryData} />);
193
-
194
- const searchInput = screen.getByPlaceholderText('Search terms...');
195
- await user.type(searchInput, 'Machine');
196
-
197
- expect(screen.getByText('Machine Learning')).toBeInTheDocument();
198
-
199
- await user.clear(searchInput);
200
-
201
- expect(screen.getAllByText('API').length).toBeGreaterThan(0);
202
- expect(screen.getAllByText('REST').length).toBeGreaterThan(0);
203
- expect(screen.getByText('Machine Learning')).toBeInTheDocument();
204
- });
205
- });
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAE7D,OAAO,mBAAmB,MAAM,4BAA4B,CAAC;AAU7D,MAAM,WAAW,qBAAqB;IACpC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,YAAY,EAAE,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+DG;AACH,MAAM,CAAC,OAAO,UAAU,cAAc,CACpC,OAAO,EAAE,WAAW,EACpB,OAAO,GAAE,qBAA0B,GAClC,MAAM,CAgGR;AAGD,eAAO,MAAM,YAAY,4BAAsB,CAAC;AAGhD,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAGhE,OAAO,EACL,oBAAoB,EACpB,uBAAuB,EACvB,sBAAsB,EACtB,KAAK,eAAe,EACpB,KAAK,gBAAgB,GACtB,MAAM,iBAAiB,CAAC;AAEzB;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,aAAa,EAAE,qBAAqB,EACpC,OAAO,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7B,CAAC,OAAO,mBAAmB,EAAE;IAAE,YAAY,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAa7F"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"preset.d.ts","sourceRoot":"","sources":["../src/preset.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAE7D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAExD;;;GAGG;AACH,KAAK,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;IAC1C,aAAa,CAAC,EAAE,OAAO,EAAE,CAAC;CAC3B,CAAC;AAEF;;;GAGG;AACH,KAAK,UAAU,GACX,KAAK,GACL,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;IACzB,aAAa,CAAC,EAAE,OAAO,EAAE,CAAC;CAC3B,CAAC,CAAC;AAEP;;GAEG;AACH,KAAK,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;IAC3C,aAAa,CAAC,EAAE,OAAO,EAAE,CAAC;CAC3B,CAAC;AAEF;;GAEG;AACH,KAAK,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE3C;;GAEG;AACH,KAAK,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE/C;;;GAGG;AACH,KAAK,aAAa,GAAG,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAErD;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,IAAI,CAAC,EAAE,eAAe,CAAC;IACvB,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,gBAAgB,CAAC,EAAE,eAAe,CAAC;IACnC,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,qBAAsB,SAAQ,oBAAoB;IACjE,QAAQ,CAAC,EAAE,qBAAqB,CAAC;IACjC,iFAAiF;IACjF,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,MAAM,CAAC,OAAO,UAAU,MAAM,CAAC,OAAO,EAAE,WAAW,EAAE,OAAO,GAAE,qBAA0B,GAAG,MAAM,CAgGhG"}
@@ -1,28 +0,0 @@
1
- /**
2
- * Creates a remark plugin that automatically detects and replaces glossary terms in markdown
3
- *
4
- * This plugin transforms plain text terms into <GlossaryTerm> JSX elements.
5
- * The GlossaryTerm component is globally available via the MDXComponents theme wrapper,
6
- * so no import injection is needed - MDX files can use it without explicit imports.
7
- *
8
- * @param {object} options - Plugin options
9
- * @param {Array} options.terms - Array of glossary term objects with {term, definition}
10
- * @param {string} options.glossaryPath - Path to glossary JSON file (optional, if terms not provided)
11
- * @param {string} options.routePath - Route path to glossary page (default: '/glossary')
12
- * @param {string} options.siteDir - Docusaurus site directory (required if using glossaryPath)
13
- * @returns {function} Remark plugin function
14
- */
15
- export default function remarkGlossaryTerms({ terms, glossaryPath, routePath, siteDir, }?: {
16
- terms: any[];
17
- glossaryPath: string;
18
- routePath: string;
19
- siteDir: string;
20
- }): Function;
21
- /**
22
- * Clears the glossary cache
23
- * Useful for testing or when you want to force a reload of glossary data
24
- *
25
- * @param {string} [filePath] - Optional specific file path to clear. If not provided, clears entire cache.
26
- */
27
- export function clearGlossaryCache(filePath?: string): void;
28
- //# sourceMappingURL=glossary-terms.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"glossary-terms.d.ts","sourceRoot":"","sources":["../../src/remark/glossary-terms.js"],"names":[],"mappings":"AA+DA;;;;;;;;;;;;;GAaG;AACH,2FANG;IAAuB,KAAK;IACJ,YAAY,EAA5B,MAAM;IACU,SAAS,EAAzB,MAAM;IACU,OAAO,EAAvB,MAAM;CACd,YA8VF;AAED;;;;;GAKG;AACH,8CAFW,MAAM,QAQhB"}