docusaurus-plugin-glossary 1.1.2 → 1.3.1
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.
- package/README.md +116 -36
- package/lib/index.js +246 -0
- package/{remark → lib/remark}/glossary-terms.js +98 -49
- package/lib/theme/GlossaryTerm/index.js +130 -0
- package/{theme → lib/theme}/GlossaryTerm/index.test.js +19 -0
- package/{theme → lib/theme}/GlossaryTerm/styles.module.css +51 -13
- package/package.json +32 -9
- package/index.js +0 -158
- package/theme/GlossaryTerm/index.js +0 -69
- /package/{components → lib/components}/GlossaryPage.js +0 -0
- /package/{components → lib/components}/GlossaryPage.module.css +0 -0
- /package/{components → lib/components}/GlossaryPage.test.js +0 -0
package/index.js
DELETED
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
const path = require('path');
|
|
2
|
-
const fs = require('fs-extra');
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Docusaurus Glossary Plugin
|
|
6
|
-
*
|
|
7
|
-
* A plugin that provides glossary functionality with:
|
|
8
|
-
* - Glossary terms defined in a JSON file
|
|
9
|
-
* - Auto-generated glossary page
|
|
10
|
-
* - GlossaryTerm component for inline definitions
|
|
11
|
-
* - Tooltips on hover
|
|
12
|
-
* - Automatic glossary term detection in markdown files
|
|
13
|
-
*
|
|
14
|
-
* @param {object} context - Docusaurus context
|
|
15
|
-
* @param {object} options - Plugin options
|
|
16
|
-
* @param {string} options.glossaryPath - Path to glossary JSON file (default: 'glossary/glossary.json')
|
|
17
|
-
* @param {string} options.routePath - Route path for glossary page (default: '/glossary')
|
|
18
|
-
* @param {boolean} options.autoLinkTerms - Automatically link glossary terms in markdown (default: true)
|
|
19
|
-
* @returns {object} Plugin object
|
|
20
|
-
*/
|
|
21
|
-
function glossaryPlugin(context, options = {}) {
|
|
22
|
-
const {
|
|
23
|
-
glossaryPath = 'glossary/glossary.json',
|
|
24
|
-
routePath = '/glossary',
|
|
25
|
-
autoLinkTerms = true
|
|
26
|
-
} = options;
|
|
27
|
-
|
|
28
|
-
let glossaryDataCache = { terms: [] };
|
|
29
|
-
|
|
30
|
-
return {
|
|
31
|
-
name: 'docusaurus-plugin-glossary',
|
|
32
|
-
|
|
33
|
-
configureMarkdown(markdownConfig) {
|
|
34
|
-
// Automatically configure the remark plugin if autoLinkTerms is enabled
|
|
35
|
-
if (autoLinkTerms) {
|
|
36
|
-
if (!markdownConfig.remarkPlugins) {
|
|
37
|
-
markdownConfig.remarkPlugins = [];
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const remarkPlugin = require('./remark/glossary-terms');
|
|
41
|
-
|
|
42
|
-
// Check if the remark plugin is already configured
|
|
43
|
-
const isAlreadyConfigured = markdownConfig.remarkPlugins.some(
|
|
44
|
-
(plugin) => {
|
|
45
|
-
if (Array.isArray(plugin) && plugin[0]) {
|
|
46
|
-
// Check if it's our remark plugin by comparing the function reference
|
|
47
|
-
return plugin[0] === remarkPlugin;
|
|
48
|
-
}
|
|
49
|
-
// Also check if it's directly the remark plugin function
|
|
50
|
-
return plugin === remarkPlugin;
|
|
51
|
-
}
|
|
52
|
-
);
|
|
53
|
-
|
|
54
|
-
// Only add if not already configured
|
|
55
|
-
if (!isAlreadyConfigured) {
|
|
56
|
-
markdownConfig.remarkPlugins.push([
|
|
57
|
-
remarkPlugin,
|
|
58
|
-
{
|
|
59
|
-
glossaryPath,
|
|
60
|
-
routePath,
|
|
61
|
-
siteDir: context.siteDir,
|
|
62
|
-
}
|
|
63
|
-
]);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
},
|
|
67
|
-
|
|
68
|
-
async loadContent() {
|
|
69
|
-
// Load glossary terms from JSON file
|
|
70
|
-
const glossaryFilePath = path.resolve(context.siteDir, glossaryPath);
|
|
71
|
-
|
|
72
|
-
if (await fs.pathExists(glossaryFilePath)) {
|
|
73
|
-
const glossaryData = await fs.readJson(glossaryFilePath);
|
|
74
|
-
glossaryDataCache = glossaryData;
|
|
75
|
-
return glossaryData;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
console.warn(`Glossary file not found at ${glossaryFilePath}. Using empty glossary.`);
|
|
79
|
-
glossaryDataCache = { terms: [] };
|
|
80
|
-
return { terms: [] };
|
|
81
|
-
},
|
|
82
|
-
|
|
83
|
-
async contentLoaded({ content, actions }) {
|
|
84
|
-
const { createData, addRoute, setGlobalData } = actions;
|
|
85
|
-
|
|
86
|
-
// Create data file that can be imported by components
|
|
87
|
-
const glossaryDataPath = await createData('glossary-data.json', JSON.stringify(content));
|
|
88
|
-
|
|
89
|
-
// Create a data file for the remark plugin to access glossary terms
|
|
90
|
-
const remarkGlossaryDataPath = await createData(
|
|
91
|
-
'remark-glossary-data.json',
|
|
92
|
-
JSON.stringify({
|
|
93
|
-
terms: content.terms || [],
|
|
94
|
-
routePath: routePath,
|
|
95
|
-
})
|
|
96
|
-
);
|
|
97
|
-
|
|
98
|
-
// Add glossary page route
|
|
99
|
-
addRoute({
|
|
100
|
-
path: routePath,
|
|
101
|
-
component: path.join(__dirname, 'components/GlossaryPage.js'),
|
|
102
|
-
exact: true,
|
|
103
|
-
modules: {
|
|
104
|
-
glossaryData: glossaryDataPath,
|
|
105
|
-
},
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
// Expose global data for runtime lookups (used by GlossaryTerm)
|
|
109
|
-
setGlobalData({
|
|
110
|
-
terms: content.terms || [],
|
|
111
|
-
routePath,
|
|
112
|
-
});
|
|
113
|
-
},
|
|
114
|
-
|
|
115
|
-
getThemePath() {
|
|
116
|
-
return path.resolve(__dirname, './theme');
|
|
117
|
-
},
|
|
118
|
-
|
|
119
|
-
getPathsToWatch() {
|
|
120
|
-
return [path.resolve(context.siteDir, glossaryPath)];
|
|
121
|
-
},
|
|
122
|
-
|
|
123
|
-
async postBuild({ outDir }) {
|
|
124
|
-
// You can add any post-build steps here if needed
|
|
125
|
-
console.log('Glossary plugin: Build completed');
|
|
126
|
-
},
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
// Export remark plugin factory for use in markdown configuration
|
|
131
|
-
glossaryPlugin.remarkPlugin = require('./remark/glossary-terms');
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* Helper function to get the configured remark plugin
|
|
135
|
-
* This can be used in docusaurus.config.js markdown configuration
|
|
136
|
-
*
|
|
137
|
-
* @param {object} pluginOptions - Plugin options from docusaurus.config.js
|
|
138
|
-
* @param {object} context - Docusaurus context
|
|
139
|
-
* @returns {function} Configured remark plugin
|
|
140
|
-
*/
|
|
141
|
-
glossaryPlugin.getRemarkPlugin = function(pluginOptions, context) {
|
|
142
|
-
const {
|
|
143
|
-
glossaryPath = 'glossary/glossary.json',
|
|
144
|
-
routePath = '/glossary',
|
|
145
|
-
siteDir = context.siteDir
|
|
146
|
-
} = pluginOptions;
|
|
147
|
-
|
|
148
|
-
return [
|
|
149
|
-
require('./remark/glossary-terms'),
|
|
150
|
-
{
|
|
151
|
-
glossaryPath,
|
|
152
|
-
routePath,
|
|
153
|
-
siteDir,
|
|
154
|
-
}
|
|
155
|
-
];
|
|
156
|
-
};
|
|
157
|
-
|
|
158
|
-
module.exports = glossaryPlugin;
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import React, { useMemo, useState } from 'react';
|
|
2
|
-
import {usePluginData} from '@docusaurus/useGlobalData';
|
|
3
|
-
import styles from './styles.module.css';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* GlossaryTerm component - displays an inline term with tooltip
|
|
7
|
-
*
|
|
8
|
-
* Usage:
|
|
9
|
-
* import GlossaryTerm from '@theme/GlossaryTerm';
|
|
10
|
-
*
|
|
11
|
-
* <GlossaryTerm term="API" definition="Application Programming Interface" />
|
|
12
|
-
* or
|
|
13
|
-
* <GlossaryTerm term="API">custom display text</GlossaryTerm>
|
|
14
|
-
*
|
|
15
|
-
* @param {object} props
|
|
16
|
-
* @param {string} props.term - The glossary term
|
|
17
|
-
* @param {string} props.definition - The definition to show in tooltip
|
|
18
|
-
* @param {string} props.routePath - Route path to glossary page (default: '/glossary')
|
|
19
|
-
* @param {React.ReactNode} props.children - Optional custom display text
|
|
20
|
-
*/
|
|
21
|
-
export default function GlossaryTerm({ term, definition, routePath = '/glossary', children }) {
|
|
22
|
-
const [showTooltip, setShowTooltip] = useState(false);
|
|
23
|
-
|
|
24
|
-
// Pull definition/route from plugin global data if not provided
|
|
25
|
-
const pluginData = usePluginData('docusaurus-plugin-glossary');
|
|
26
|
-
const effectiveDefinition = useMemo(() => {
|
|
27
|
-
if (definition && typeof definition === 'string' && definition.length > 0) {
|
|
28
|
-
return definition;
|
|
29
|
-
}
|
|
30
|
-
const terms = (pluginData && pluginData.terms) || [];
|
|
31
|
-
const found = terms.find(
|
|
32
|
-
(t) => typeof t.term === 'string' && t.term.toLowerCase() === String(term).toLowerCase()
|
|
33
|
-
);
|
|
34
|
-
return found && found.definition ? found.definition : undefined;
|
|
35
|
-
}, [definition, pluginData, term]);
|
|
36
|
-
|
|
37
|
-
const effectiveRoutePath = useMemo(() => {
|
|
38
|
-
if (routePath && typeof routePath === 'string' && routePath.length > 0) return routePath;
|
|
39
|
-
return (pluginData && pluginData.routePath) || '/glossary';
|
|
40
|
-
}, [pluginData, routePath]);
|
|
41
|
-
|
|
42
|
-
const displayText = children || term;
|
|
43
|
-
const termId = term.toLowerCase().replace(/\s+/g, '-');
|
|
44
|
-
|
|
45
|
-
return (
|
|
46
|
-
<span className={styles.glossaryTermWrapper}>
|
|
47
|
-
<a
|
|
48
|
-
href={`${effectiveRoutePath}#${termId}`}
|
|
49
|
-
className={styles.glossaryTerm}
|
|
50
|
-
onMouseEnter={() => setShowTooltip(true)}
|
|
51
|
-
onMouseLeave={() => setShowTooltip(false)}
|
|
52
|
-
onFocus={() => setShowTooltip(true)}
|
|
53
|
-
onBlur={() => setShowTooltip(false)}
|
|
54
|
-
aria-describedby={`tooltip-${termId}`}
|
|
55
|
-
>
|
|
56
|
-
{displayText}
|
|
57
|
-
</a>
|
|
58
|
-
{effectiveDefinition && (
|
|
59
|
-
<span
|
|
60
|
-
id={`tooltip-${termId}`}
|
|
61
|
-
className={`${styles.tooltip} ${showTooltip ? styles.tooltipVisible : ''}`}
|
|
62
|
-
role="tooltip"
|
|
63
|
-
>
|
|
64
|
-
<strong>{term}:</strong> {effectiveDefinition}
|
|
65
|
-
</span>
|
|
66
|
-
)}
|
|
67
|
-
</span>
|
|
68
|
-
);
|
|
69
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|