docusaurus-plugin-glossary 3.3.2 → 3.3.4
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 +23 -6
- package/dist/{chunk-MG34SMDE.js → chunk-CIAA7XR3.js} +23 -5
- package/dist/chunk-CIAA7XR3.js.map +1 -0
- package/dist/{chunk-33WWYCNA.js → chunk-EQBYCLUI.js} +9 -4
- package/dist/chunk-EQBYCLUI.js.map +1 -0
- package/dist/components/GlossaryPage.cjs +4 -3
- package/dist/components/GlossaryPage.cjs.map +1 -1
- package/dist/components/GlossaryPage.js +4 -3
- package/dist/components/GlossaryPage.js.map +1 -1
- package/dist/index.cjs +29 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +15 -97
- package/dist/index.d.ts +15 -97
- package/dist/index.js +2 -2
- package/dist/preset.cjs +38 -8
- package/dist/preset.cjs.map +1 -1
- package/dist/preset.d.cts +1 -1
- package/dist/preset.d.ts +1 -1
- package/dist/preset.js +11 -4
- package/dist/preset.js.map +1 -1
- package/dist/remark/glossary-terms.cjs +22 -4
- package/dist/remark/glossary-terms.cjs.map +1 -1
- package/dist/remark/glossary-terms.d.cts +10 -0
- package/dist/remark/glossary-terms.d.ts +10 -0
- package/dist/remark/glossary-terms.js +1 -1
- package/dist/theme/GlossaryTerm/index.cjs +22 -2
- package/dist/theme/GlossaryTerm/index.cjs.map +1 -1
- package/dist/theme/GlossaryTerm/index.js +22 -2
- package/dist/theme/GlossaryTerm/index.js.map +1 -1
- package/dist/types-B6LWPlBY.d.cts +54 -0
- package/dist/types-B6LWPlBY.d.ts +54 -0
- package/dist/validation.d.cts +46 -2
- package/dist/validation.d.ts +46 -2
- package/package.json +29 -12
- package/dist/chunk-33WWYCNA.js.map +0 -1
- package/dist/chunk-MG34SMDE.js.map +0 -1
package/dist/preset.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/preset.ts","../node_modules/tsup/assets/cjs_shims.js","../src/index.ts","../src/remark/glossary-terms.js","../src/validation.ts"],"sourcesContent":["import type { Preset, LoadContext } from '@docusaurus/types';\nimport glossaryPlugin, { getRemarkPlugin } from './index.js';\nimport type { GlossaryPluginOptions } from './index.js';\n\n/**\n * Configuration for @docusaurus/plugin-content-docs\n * Using Record<string, unknown> to allow any valid docs options without coupling to specific version\n */\ntype DocsConfig = Record<string, unknown> & {\n remarkPlugins?: unknown[];\n};\n\n/**\n * Configuration for @docusaurus/plugin-content-blog\n * Can be false to disable, or configuration object\n */\ntype BlogConfig =\n | false\n | (Record<string, unknown> & {\n remarkPlugins?: unknown[];\n });\n\n/**\n * Configuration for @docusaurus/plugin-content-pages\n */\ntype PagesConfig = Record<string, unknown> & {\n remarkPlugins?: unknown[];\n};\n\n/**\n * Configuration for @docusaurus/theme-classic\n */\ntype ThemeConfig = Record<string, unknown>;\n\n/**\n * Configuration for analytics plugins\n */\ntype AnalyticsConfig = Record<string, unknown>;\n\n/**\n * Configuration for @docusaurus/plugin-sitemap\n * Can be false to disable, or configuration object\n */\ntype SitemapConfig = false | Record<string, unknown>;\n\n/**\n * Classic preset options (simplified to avoid direct dependency on @docusaurus/preset-classic)\n * These mirror the options available in the classic preset\n */\nexport interface ClassicPresetOptions {\n docs?: DocsConfig;\n blog?: BlogConfig;\n pages?: PagesConfig;\n theme?: ThemeConfig;\n gtag?: AnalyticsConfig;\n googleAnalytics?: AnalyticsConfig;\n googleTagManager?: AnalyticsConfig;\n sitemap?: SitemapConfig;\n debug?: boolean;\n}\n\nexport interface GlossaryPresetOptions extends ClassicPresetOptions {\n glossary?: GlossaryPluginOptions;\n /** Internal: Docusaurus adds this, we need to exclude it from classic options */\n id?: string;\n}\n\n/**\n * Docusaurus Glossary Preset\n *\n * A preset that extends @docusaurus/preset-classic with automatic glossary functionality.\n * This preset automatically configures the remark plugin for docs and pages, so you don't\n * need to manually add it to remarkPlugins.\n *\n * @example\n * ```javascript\n * export default {\n * presets: [\n * [\n * 'docusaurus-plugin-glossary/preset',\n * {\n * // Glossary options\n * glossary: {\n * glossaryPath: 'glossary/glossary.json',\n * routePath: '/glossary',\n * },\n * // Classic preset options\n * docs: {\n * sidebarPath: './sidebars.js',\n * },\n * blog: {\n * showReadingTime: true,\n * },\n * theme: {\n * customCss: './src/css/custom.css',\n * },\n * },\n * ],\n * ],\n * };\n * ```\n *\n * @param context - Docusaurus context\n * @param options - Preset options including glossary and classic preset options\n * @returns Preset configuration\n */\nexport default function preset(context: LoadContext, options: GlossaryPresetOptions = {}): Preset {\n // Explicitly extract glossary and any Docusaurus-added properties that shouldn't go to classic preset\n const { glossary = {}, id: _id, ...restOptions } = options;\n\n // Extract only valid classic preset options\n // Explicitly type blog and sitemap to preserve union types (can be false)\n const { docs, pages, theme, gtag, googleAnalytics, googleTagManager, debug } = restOptions;\n const blog: BlogConfig | undefined = restOptions.blog;\n const sitemap: SitemapConfig | undefined = restOptions.sitemap;\n\n // Build classic options object with only defined properties\n const classicOptions: ClassicPresetOptions = {};\n if (docs !== undefined) classicOptions.docs = docs;\n if (blog !== undefined) classicOptions.blog = blog;\n if (pages !== undefined) classicOptions.pages = pages;\n if (theme !== undefined) classicOptions.theme = theme;\n if (gtag !== undefined) classicOptions.gtag = gtag;\n if (googleAnalytics !== undefined) classicOptions.googleAnalytics = googleAnalytics;\n if (googleTagManager !== undefined) classicOptions.googleTagManager = googleTagManager;\n if (sitemap !== undefined) classicOptions.sitemap = sitemap;\n if (debug !== undefined) classicOptions.debug = debug;\n\n const { glossaryPath = 'glossary/glossary.json', routePath = '/glossary' } = glossary;\n\n // Get the remark plugin configuration\n const remarkPlugin = getRemarkPlugin({ glossaryPath, routePath }, { siteDir: context.siteDir });\n\n // Extend docs configuration with glossary remark plugin\n const docsConfig = classicOptions.docs || {};\n const docsRemarkPlugins = docsConfig.remarkPlugins || [];\n const extendedDocsConfig = {\n ...docsConfig,\n remarkPlugins: [...docsRemarkPlugins, remarkPlugin],\n };\n\n // Extend pages configuration with glossary remark plugin\n const pagesConfig = classicOptions.pages || {};\n const pagesRemarkPlugins = pagesConfig.remarkPlugins || [];\n const extendedPagesConfig = {\n ...pagesConfig,\n remarkPlugins: [...pagesRemarkPlugins, remarkPlugin],\n };\n\n // Extend blog configuration with glossary remark plugin (optional)\n // Use typeof check for proper type narrowing (blog can be false, object, or undefined)\n let extendedBlogConfig: BlogConfig | undefined = blog;\n if (typeof blog === 'object' && blog !== null) {\n const blogRemarkPlugins = blog.remarkPlugins || [];\n extendedBlogConfig = {\n ...blog,\n remarkPlugins: [...blogRemarkPlugins, remarkPlugin],\n };\n }\n\n // Build the final classic preset options\n const finalClassicOptions: ClassicPresetOptions = {};\n if (extendedDocsConfig !== undefined) finalClassicOptions.docs = extendedDocsConfig;\n if (extendedBlogConfig !== undefined) finalClassicOptions.blog = extendedBlogConfig;\n if (extendedPagesConfig !== undefined) finalClassicOptions.pages = extendedPagesConfig;\n if (theme !== undefined) finalClassicOptions.theme = theme;\n if (gtag !== undefined) finalClassicOptions.gtag = gtag;\n if (googleAnalytics !== undefined) finalClassicOptions.googleAnalytics = googleAnalytics;\n if (googleTagManager !== undefined) finalClassicOptions.googleTagManager = googleTagManager;\n if (sitemap !== undefined) finalClassicOptions.sitemap = sitemap;\n if (debug !== undefined) finalClassicOptions.debug = debug;\n\n // Plugin tuple type: [plugin-name, options] or plugin function\n type PluginEntry =\n | [string, Record<string, unknown>]\n | ((ctx: LoadContext) => ReturnType<typeof glossaryPlugin>);\n\n const plugins: PluginEntry[] = [\n // Add the glossary plugin first\n function glossaryPluginWrapper(ctx: LoadContext) {\n return glossaryPlugin(ctx, glossary);\n },\n ];\n\n // Add classic preset plugins individually\n if (extendedDocsConfig) plugins.push(['@docusaurus/plugin-content-docs', extendedDocsConfig]);\n if (typeof extendedBlogConfig === 'object' && extendedBlogConfig !== null)\n plugins.push(['@docusaurus/plugin-content-blog', extendedBlogConfig]);\n if (extendedPagesConfig) plugins.push(['@docusaurus/plugin-content-pages', extendedPagesConfig]);\n if (gtag) plugins.push(['@docusaurus/plugin-google-gtag', gtag]);\n if (googleAnalytics) plugins.push(['@docusaurus/plugin-google-analytics', googleAnalytics]);\n if (googleTagManager) plugins.push(['@docusaurus/plugin-google-tag-manager', googleTagManager]);\n if (sitemap !== false) plugins.push(['@docusaurus/plugin-sitemap', sitemap || {}]);\n if (debug) plugins.push(['@docusaurus/plugin-debug', {}]);\n\n return {\n themes: [\n // Pass theme options (including customCss) to theme-classic\n ['@docusaurus/theme-classic', theme || {}],\n ],\n plugins,\n };\n}\n","// Shim globals in cjs bundle\n// There's a weird bug that esbuild will always inject importMetaUrl\n// if we export it as `const importMetaUrl = ... __filename ...`\n// But using a function will not cause this issue\n\nconst getImportMetaUrl = () => \n typeof document === \"undefined\" \n ? new URL(`file:${__filename}`).href \n : (document.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT') \n ? document.currentScript.src \n : new URL(\"main.js\", document.baseURI).href;\n\nexport const importMetaUrl = /* @__PURE__ */ getImportMetaUrl()\n","// @ts-ignore\nimport path from 'path';\n// @ts-ignore\nimport { fileURLToPath } from 'url';\nimport fs from 'fs-extra';\nimport type { LoadContext, Plugin } from '@docusaurus/types';\nimport validatePeerDependencies from 'validate-peer-dependencies';\nimport remarkGlossaryTerms from './remark/glossary-terms.js';\nimport { validateGlossaryData, GlossaryValidationError } from './validation.js';\n\n// Standard ES module directory resolution\nconst currentFilePath = fileURLToPath(import.meta.url);\nconst currentDir = path.dirname(currentFilePath);\n\n// Validate peer dependencies at module load time\nvalidatePeerDependencies(currentDir);\n\nexport interface GlossaryPluginOptions {\n glossaryPath?: string;\n routePath?: string;\n autoLinkTerms?: boolean;\n}\n\nexport interface GlossaryTerm {\n term: string;\n definition: string;\n abbreviation?: string;\n relatedTerms?: string[];\n id?: string;\n autoLink?: boolean;\n aliases?: string[];\n caseSensitive?: boolean;\n}\n\nexport interface GlossaryData {\n title?: string;\n description?: string;\n terms: GlossaryTerm[];\n}\n\n/**\n * Docusaurus Glossary Plugin\n *\n * A plugin that provides glossary functionality with:\n * - Glossary terms defined in a JSON file\n * - Auto-generated glossary page with term definitions\n * - GlossaryTerm component for inline definitions with interactive tooltips\n * - Automatic client-side initialization via getClientModules() (no manual imports needed)\n * - Optional automatic glossary term detection in markdown files via remark plugin\n *\n * ## Basic Usage (Manual Term Markup)\n *\n * Just install the plugin - the GlossaryTerm component is automatically available:\n * ```javascript\n * module.exports = {\n * plugins: [\n * ['docusaurus-plugin-glossary', {\n * glossaryPath: 'glossary/glossary.json',\n * routePath: '/glossary',\n * }],\n * ],\n * };\n * ```\n *\n * Then use `<GlossaryTerm>` in your MDX files without importing:\n * ```mdx\n * <GlossaryTerm term=\"API\">API</GlossaryTerm>\n * ```\n *\n * ## Advanced Usage (Automatic Term Detection)\n *\n * To automatically detect and link glossary terms in markdown, add the remark plugin:\n * ```javascript\n * const glossaryPlugin = require('docusaurus-plugin-glossary');\n *\n * module.exports = {\n * presets: [\n * ['@docusaurus/preset-classic', {\n * docs: {\n * remarkPlugins: [\n * glossaryPlugin.getRemarkPlugin({\n * glossaryPath: 'glossary/glossary.json',\n * routePath: '/glossary',\n * }, { siteDir: __dirname }),\n * ],\n * },\n * }],\n * ],\n * plugins: [\n * ['docusaurus-plugin-glossary', {\n * glossaryPath: 'glossary/glossary.json',\n * routePath: '/glossary',\n * }],\n * ],\n * };\n * ```\n *\n * @param context - Docusaurus context\n * @param options - Plugin options\n * @param options.glossaryPath - Path to glossary JSON file (default: 'glossary/glossary.json')\n * @param options.routePath - Route path for glossary page (default: '/glossary')\n * @param options.autoLinkTerms - Legacy option, kept for compatibility but no longer used (configure remark plugin manually instead)\n * @returns Plugin object\n */\nexport default function glossaryPlugin(\n context: LoadContext,\n options: GlossaryPluginOptions = {}\n): Plugin {\n const { glossaryPath = 'glossary/glossary.json', routePath = '/glossary' } = options;\n\n return {\n name: 'docusaurus-plugin-glossary',\n\n getClientModules() {\n return [path.resolve(currentDir, './client/index.js')];\n },\n\n async loadContent() {\n // Load glossary terms from JSON file\n const glossaryFilePath = path.resolve(context.siteDir, glossaryPath);\n\n if (await fs.pathExists(glossaryFilePath)) {\n try {\n const rawData = await fs.readJson(glossaryFilePath);\n\n // Validate glossary data structure\n const validationResult = validateGlossaryData(rawData, { throwOnError: false });\n\n if (!validationResult.valid) {\n console.warn(\n `[glossary-plugin] Glossary file has validation errors at ${glossaryFilePath}:`\n );\n validationResult.errors.forEach(err => {\n console.warn(` - [${err.field}] ${err.message}`);\n });\n console.warn('[glossary-plugin] Proceeding with valid terms only.');\n }\n\n return validationResult.data;\n } catch (error) {\n if (error instanceof GlossaryValidationError) {\n throw error;\n }\n // JSON parsing error\n throw new Error(\n `Failed to parse glossary file at ${glossaryFilePath}: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n }\n\n console.warn(`Glossary file not found at ${glossaryFilePath}. Using empty glossary.`);\n return { terms: [] };\n },\n\n async contentLoaded({ content, actions }) {\n const { createData, addRoute, setGlobalData } = actions;\n const glossaryContent = content as GlossaryData;\n\n // Create data file that can be imported by components\n const glossaryDataPath = await createData(\n 'glossary-data.json',\n JSON.stringify(glossaryContent)\n );\n\n // Create a data file for the remark plugin to access glossary terms\n await createData(\n 'remark-glossary-data.json',\n JSON.stringify({\n terms: glossaryContent.terms || [],\n routePath: routePath,\n })\n );\n\n // Add glossary page route\n addRoute({\n path: routePath,\n component: path.join(currentDir, 'components/GlossaryPage.js'),\n exact: true,\n modules: {\n glossaryData: glossaryDataPath,\n },\n });\n\n // Expose global data for runtime lookups (used by GlossaryTerm)\n setGlobalData({\n terms: glossaryContent.terms || [],\n routePath,\n });\n },\n\n getThemePath() {\n return path.resolve(currentDir, './theme');\n },\n\n getPathsToWatch() {\n return [path.resolve(context.siteDir, glossaryPath)];\n },\n\n async postBuild() {\n // You can add any post-build steps here if needed\n console.log('Glossary plugin: Build completed');\n },\n };\n}\n\n// Export remark plugin factory for use in markdown configuration\nexport const remarkPlugin = remarkGlossaryTerms;\n\n// Export cache clearing utility\nexport { clearGlossaryCache } from './remark/glossary-terms.js';\n\n// Export validation utilities\nexport {\n validateGlossaryData,\n GlossaryValidationError,\n formatValidationErrors,\n type ValidationError,\n type ValidationResult,\n} from './validation.js';\n\n/**\n * Helper function to get the configured remark plugin\n * This can be used in docusaurus.config.js markdown configuration\n *\n * @param pluginOptions - Plugin options from docusaurus.config.js\n * @param context - Context with siteDir\n * @returns Configured remark plugin\n */\nexport function getRemarkPlugin(\n pluginOptions: GlossaryPluginOptions,\n context?: { siteDir?: string }\n): [typeof remarkGlossaryTerms, { glossaryPath: string; routePath: string; siteDir?: string }] {\n const { glossaryPath = 'glossary/glossary.json', routePath = '/glossary' } = pluginOptions;\n\n const siteDir = context?.siteDir;\n\n return [\n remarkGlossaryTerms,\n {\n glossaryPath,\n routePath,\n siteDir,\n },\n ];\n}\n","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 represents a matchable phrase (canonical term or alias) and points\n // back to the canonical term object so tooltip/href always use the canonical form.\n // Key: lowercase phrase, Value: { termObj, phrase, caseSensitive } where\n // `phrase` preserves the original case (used for case-sensitive matching).\n const termMap = new Map();\n glossaryTerms.forEach(termObj => {\n if (!termObj.term || termObj.autoLink === false) return;\n const caseSensitive = termObj.caseSensitive === true;\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, phrase, caseSensitive });\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, phrase, caseSensitive }] of sortedTerms) {\n // Case-sensitive terms search the original text for the exact casing;\n // case-insensitive terms search the lowercased text for the lowercased phrase.\n const haystack = caseSensitive ? text : textLower;\n const needle = caseSensitive ? phrase : lowerPhrase;\n let searchIndex = 0;\n\n while (searchIndex < haystack.length) {\n const index = haystack.indexOf(needle, searchIndex);\n if (index === -1) break;\n\n // Check if it's a whole word match, with simple plural tolerance ('s' or 'es').\n // Word-boundary detection uses the lowercased text so letter-class checks\n // behave consistently regardless of the term's case-sensitivity setting.\n const beforeChar = index > 0 ? textLower[index - 1] : ' ';\n const afterIndex = index + needle.length;\n const afterChar = afterIndex < textLower.length ? textLower[afterIndex] : ' ';\n\n let matchLength = needle.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 = needle.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 = needle.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","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 // Optional: caseSensitive (boolean)\n if ('caseSensitive' in termObj && termObj.caseSensitive !== undefined) {\n if (typeof termObj.caseSensitive !== 'boolean') {\n errors.push({\n field: `${prefix}.caseSensitive`,\n message: `Field \"caseSensitive\" must be a boolean, got ${typeof termObj.caseSensitive}`,\n value: termObj.caseSensitive,\n });\n }\n }\n\n // Optional: aliases (string[])\n if ('aliases' in termObj && termObj.aliases !== undefined) {\n if (!Array.isArray(termObj.aliases)) {\n errors.push({\n field: `${prefix}.aliases`,\n message: `Field \"aliases\" must be an array, got ${typeof termObj.aliases}`,\n value: termObj.aliases,\n });\n } else {\n termObj.aliases.forEach((alias, aliasIndex) => {\n if (typeof alias !== 'string') {\n errors.push({\n field: `${prefix}.aliases[${aliasIndex}]`,\n message: `Alias must be a string, got ${typeof alias}`,\n value: alias,\n });\n } else if (alias.trim() === '') {\n errors.push({\n field: `${prefix}.aliases[${aliasIndex}]`,\n message: 'Alias cannot be empty',\n value: alias,\n });\n }\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 title\n if ('title' in glossaryData && typeof glossaryData.title !== 'string') {\n errors.push({\n field: 'title',\n message: 'The title property in the GlossaryData must be a string.',\n });\n\n if (throwOnError && errors.length > 0) {\n throw new GlossaryValidationError(errors);\n }\n }\n const validTitle = glossaryData.title as string;\n\n if ('description' in glossaryData && typeof glossaryData.description !== 'string') {\n errors.push({\n field: 'description',\n message: 'The description property in the GlossaryData must be a string.',\n });\n\n if (throwOnError && errors.length > 0) {\n throw new GlossaryValidationError(errors);\n }\n }\n\n const validDescription = glossaryData.description as string;\n\n if (!('terms' in glossaryData)) {\n // Check for terms array\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: { title: validTitle, description: validDescription, 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 // @ts-ignore\n if (Error.captureStackTrace) {\n // @ts-ignore\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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACKA,IAAM,mBAAmB,MACvB,OAAO,aAAa,cAChB,IAAI,IAAI,QAAQ,UAAU,EAAE,EAAE,OAC7B,SAAS,iBAAiB,SAAS,cAAc,QAAQ,YAAY,MAAM,WAC1E,SAAS,cAAc,MACvB,IAAI,IAAI,WAAW,SAAS,OAAO,EAAE;AAEtC,IAAM,gBAAgC,iCAAiB;;;ACX9D,IAAAA,eAAiB;AAEjB,iBAA8B;AAC9B,sBAAe;AAEf,wCAAqC;;;ACNrC,8BAAsB;AACtB,kBAAiB;AACjB,gBAAe;AAUf,SAAS,sBAAsB,MAAM,WAAW;AAC9C,QAAM,SAAS,CAAC;AAChB,QAAM,aAAa,CAAC;AAEpB,MAAI,SAAS,QAAQ,SAAS,QAAW;AACvC,WAAO,KAAK,oCAAoC;AAChD,WAAO,EAAE,OAAO,CAAC,GAAG,OAAO;AAAA,EAC7B;AAEA,MAAI,OAAO,SAAS,UAAU;AAC5B,WAAO,KAAK,wCAAwC,OAAO,IAAI,EAAE;AACjE,WAAO,EAAE,OAAO,CAAC,GAAG,OAAO;AAAA,EAC7B;AAEA,MAAI,EAAE,WAAW,OAAO;AACtB,WAAO,KAAK,4CAA4C;AACxD,WAAO,EAAE,OAAO,CAAC,GAAG,OAAO;AAAA,EAC7B;AAEA,MAAI,CAAC,MAAM,QAAQ,KAAK,KAAK,GAAG;AAC9B,WAAO,KAAK,uCAAuC,OAAO,KAAK,KAAK,EAAE;AACtE,WAAO,EAAE,OAAO,CAAC,GAAG,OAAO;AAAA,EAC7B;AAEA,OAAK,MAAM,QAAQ,CAAC,MAAM,UAAU;AAClC,QAAI,SAAS,QAAQ,SAAS,UAAa,OAAO,SAAS,UAAU;AACnE,aAAO,KAAK,SAAS,KAAK,2BAA2B;AACrD;AAAA,IACF;AAEA,QAAI,OAAO,KAAK,SAAS,YAAY,KAAK,KAAK,KAAK,MAAM,IAAI;AAC5D,aAAO,KAAK,SAAS,KAAK,oCAAoC;AAC9D;AAAA,IACF;AAEA,QAAI,OAAO,KAAK,eAAe,UAAU;AACvC,aAAO,KAAK,SAAS,KAAK,0CAA0C;AACpE;AAAA,IACF;AAEA,eAAW,KAAK,IAAI;AAAA,EACtB,CAAC;AAED,SAAO,EAAE,OAAO,YAAY,OAAO;AACrC;AAIA,IAAM,gBAAgB,oBAAI,IAAI;AAC9B,IAAM,YAAY;AAgBH,SAAR,oBAAqC;AAAA,EAC1C,QAAQ,CAAC;AAAA,EACT,eAAe;AAAA,EACf,YAAY;AAAA,EACZ,UAAU;AACZ,IAAI,CAAC,GAAG;AACN,MAAI,gBAAgB;AAGpB,MAAI,CAAC,cAAc,UAAU,gBAAgB,SAAS;AACpD,QAAI;AACF,YAAM,mBAAmB,YAAAC,QAAK,QAAQ,SAAS,YAAY;AAC3D,YAAM,MAAM,KAAK,IAAI;AAGrB,YAAM,SAAS,cAAc,IAAI,gBAAgB;AACjD,UAAI,UAAU,MAAM,OAAO,WAAW,WAAW;AAC/C,wBAAgB,OAAO;AAAA,MACzB,OAAO;AAIL,YAAI,UAAAC,QAAG,WAAW,gBAAgB,GAAG;AACnC,gBAAM,cAAc,UAAAA,QAAG,aAAa,kBAAkB,MAAM;AAC5D,cAAI;AACJ,cAAI;AACF,2BAAe,KAAK,MAAM,WAAW;AAAA,UACvC,SAAS,YAAY;AACnB,oBAAQ;AAAA,cACN,sDAAsD,YAAY;AAAA,cAClE,WAAW;AAAA,YACb;AACA,0BAAc,IAAI,kBAAkB;AAAA,cAClC,OAAO,CAAC;AAAA,cACR,UAAU;AAAA,YACZ,CAAC;AACD,mBAAO,UAAQ;AAAA,UACjB;AAGA,gBAAM,EAAE,OAAO,YAAY,OAAO,IAAI,sBAAsB,cAAc,YAAY;AAEtF,cAAI,OAAO,SAAS,GAAG;AACrB,oBAAQ,KAAK,mDAAmD,YAAY,GAAG;AAC/E,mBAAO,QAAQ,SAAO,QAAQ,KAAK,OAAO,GAAG,EAAE,CAAC;AAChD,gBAAI,WAAW,SAAS,GAAG;AACzB,sBAAQ,KAAK,qCAAqC,WAAW,MAAM,iBAAiB;AAAA,YACtF;AAAA,UACF;AAEA,0BAAgB;AAGhB,wBAAc,IAAI,kBAAkB;AAAA,YAClC,OAAO;AAAA,YACP,UAAU;AAAA,UACZ,CAAC;AAGD,cAAI,CAAC,UAAU,QAAQ,IAAI,aAAa,cAAc;AACpD,oBAAQ;AAAA,cACN,4BAA4B,cAAc,MAAM,eAAe,YAAY;AAAA,YAC7E;AAAA,UACF;AAAA,QACF,OAAO;AAEL,wBAAc,IAAI,kBAAkB;AAAA,YAClC,OAAO,CAAC;AAAA,YACR,UAAU;AAAA,UACZ,CAAC;AACD,cAAI,QAAQ,IAAI,aAAa,cAAc;AACzC,oBAAQ,KAAK,8CAA8C,YAAY,EAAE;AAAA,UAC3E;AAAA,QACF;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AACd,cAAQ;AAAA,QACN,kDAAkD,YAAY;AAAA,QAC9D,MAAM;AAAA,MACR;AAEA,UAAI,gBAAgB,SAAS;AAC3B,cAAM,mBAAmB,YAAAD,QAAK,QAAQ,SAAS,YAAY;AAC3D,sBAAc,IAAI,kBAAkB;AAAA,UAClC,OAAO,CAAC;AAAA,UACR,UAAU,KAAK,IAAI;AAAA,QACrB,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAOA,QAAM,UAAU,oBAAI,IAAI;AACxB,gBAAc,QAAQ,aAAW;AAC/B,QAAI,CAAC,QAAQ,QAAQ,QAAQ,aAAa,MAAO;AACjD,UAAM,gBAAgB,QAAQ,kBAAkB;AAEhD,UAAM,WAAW,YAAU;AACzB,UAAI,OAAO,WAAW,YAAY,OAAO,KAAK,MAAM,GAAI;AACxD,YAAM,MAAM,OAAO,YAAY;AAC/B,UAAI,CAAC,QAAQ,IAAI,GAAG,GAAG;AACrB,gBAAQ,IAAI,KAAK,EAAE,SAAS,QAAQ,cAAc,CAAC;AAAA,MACrD;AAAA,IACF;AAEA,aAAS,QAAQ,IAAI;AACrB,QAAI,MAAM,QAAQ,QAAQ,OAAO,GAAG;AAClC,cAAQ,QAAQ,QAAQ,QAAQ;AAAA,IAClC;AAAA,EACF,CAAC;AAID,QAAM,cAAc,MAAM,KAAK,QAAQ,QAAQ,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM;AAG1F,MAAI,YAAY,WAAW,GAAG;AAC5B,WAAO,UAAQ;AAAA,EACjB;AAMA,WAAS,mBAAmB,MAAM;AAChC,QAAI,CAAC,QAAQ,CAAC,YAAY,QAAQ;AAChC,aAAO,CAAC,EAAE,MAAM,QAAQ,OAAO,KAAK,CAAC;AAAA,IACvC;AAEA,UAAM,SAAS,CAAC;AAChB,QAAI,YAAY;AAChB,UAAM,YAAY,KAAK,YAAY;AAGnC,UAAM,UAAU,CAAC;AACjB,eAAW,CAAC,aAAa,EAAE,SAAS,QAAQ,cAAc,CAAC,KAAK,aAAa;AAG3E,YAAM,WAAW,gBAAgB,OAAO;AACxC,YAAM,SAAS,gBAAgB,SAAS;AACxC,UAAI,cAAc;AAElB,aAAO,cAAc,SAAS,QAAQ;AACpC,cAAM,QAAQ,SAAS,QAAQ,QAAQ,WAAW;AAClD,YAAI,UAAU,GAAI;AAKlB,cAAM,aAAa,QAAQ,IAAI,UAAU,QAAQ,CAAC,IAAI;AACtD,cAAM,aAAa,QAAQ,OAAO;AAClC,cAAM,YAAY,aAAa,UAAU,SAAS,UAAU,UAAU,IAAI;AAE1E,YAAI,cAAc,OAAO;AACzB,YAAI,iBAAiB,CAAC,KAAK,KAAK,UAAU,KAAK,CAAC,KAAK,KAAK,SAAS;AAGnE,YAAI,CAAC,kBAAkB,cAAc,KAAK;AACxC,gBAAM,WAAW,aAAa,IAAI,UAAU,SAAS,UAAU,aAAa,CAAC,IAAI;AACjF,cAAI,CAAC,KAAK,KAAK,QAAQ,GAAG;AACxB,6BAAiB;AACjB,0BAAc,OAAO,SAAS;AAAA,UAChC;AAAA,QACF;AAGA,YACE,CAAC,kBACD,cAAc,OACd,aAAa,IAAI,UAAU,UAC3B,UAAU,aAAa,CAAC,MAAM,KAC9B;AACA,gBAAM,WAAW,aAAa,IAAI,UAAU,SAAS,UAAU,aAAa,CAAC,IAAI;AACjF,cAAI,CAAC,KAAK,KAAK,QAAQ,GAAG;AACxB,6BAAiB;AACjB,0BAAc,OAAO,SAAS;AAAA,UAChC;AAAA,QACF;AAEA,YAAI,gBAAgB;AAClB,kBAAQ,KAAK;AAAA,YACX;AAAA,YACA,QAAQ;AAAA,YACR;AAAA;AAAA,YAEA,cAAc,KAAK,UAAU,OAAO,QAAQ,WAAW;AAAA,UACzD,CAAC;AAAA,QACH;AAEA,sBAAc,QAAQ;AAAA,MACxB;AAAA,IACF;AAGA,YAAQ,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AAGxC,UAAM,wBAAwB,CAAC;AAC/B,QAAI,eAAe;AACnB,eAAW,SAAS,SAAS;AAC3B,UAAI,MAAM,SAAS,cAAc;AAC/B,8BAAsB,KAAK,KAAK;AAChC,uBAAe,MAAM,QAAQ,MAAM;AAAA,MACrC;AAAA,IACF;AAGA,eAAW,SAAS,uBAAuB;AAEzC,UAAI,MAAM,QAAQ,WAAW;AAC3B,eAAO,KAAK;AAAA,UACV,MAAM;AAAA,UACN,OAAO,KAAK,UAAU,WAAW,MAAM,KAAK;AAAA,QAC9C,CAAC;AAAA,MACH;AAGA,aAAO,KAAK;AAAA,QACV,MAAM;AAAA,QACN,MAAM;AAAA,QACN,YAAY;AAAA,UACV;AAAA,YACE,MAAM;AAAA,YACN,MAAM;AAAA,YACN,OAAO,MAAM,QAAQ;AAAA,UACvB;AAAA,UACA;AAAA,YACE,MAAM;AAAA,YACN,MAAM;AAAA,YACN,OAAO,MAAM,QAAQ,cAAc;AAAA,UACrC;AAAA,UACA;AAAA,YACE,MAAM;AAAA,YACN,MAAM;AAAA,YACN,OAAO;AAAA,UACT;AAAA,QACF;AAAA,QACA,UAAU;AAAA,UACR;AAAA,YACE,MAAM;AAAA,YACN,OAAO,MAAM;AAAA,UACf;AAAA,QACF;AAAA,MACF,CAAC;AAED,kBAAY,MAAM,QAAQ,MAAM;AAAA,IAClC;AAGA,QAAI,YAAY,KAAK,QAAQ;AAC3B,aAAO,KAAK;AAAA,QACV,MAAM;AAAA,QACN,OAAO,KAAK,UAAU,SAAS;AAAA,MACjC,CAAC;AAAA,IACH;AAEA,WAAO,OAAO,SAAS,IAAI,SAAS,CAAC,EAAE,MAAM,QAAQ,OAAO,KAAK,CAAC;AAAA,EACpE;AAKA,WAAS,wBAAwB,MAAM;AACrC,UAAM,OAAO,oBAAI,QAAQ;AACzB,uCAAM,MAAM,WAAW,iBAAe;AACpC,yCAAM,aAAa,QAAQ,cAAY;AACrC,aAAK,IAAI,QAAQ;AAAA,MACnB,CAAC;AAAA,IACH,CAAC;AACD,WAAO;AAAA,EACT;AAGA,QAAM,cAAc,UAAQ;AAC1B,QAAI,mBAAmB;AACvB,UAAM,sBAAsB,wBAAwB,IAAI;AACxD,uCAAM,MAAM,QAAQ,CAAC,MAAM,OAAO,WAAW;AAE3C,UACE,OAAO,SAAS,UAChB,OAAO,SAAS,gBAChB,OAAO,SAAS,UAChB,OAAO,SAAS,uBAChB,OAAO,SAAS,qBAChB;AACA;AAAA,MACF;AAGA,UAAI,oBAAoB,IAAI,IAAI,GAAG;AACjC;AAAA,MACF;AAGA,YAAM,eAAe,mBAAmB,KAAK,KAAK;AAGlD,UACE,aAAa,SAAS,KACrB,aAAa,WAAW,KAAK,aAAa,CAAC,EAAE,SAAS,QACvD;AAEA,cAAM,WAAW,aAAa,IAAI,iBAAe;AAC/C,cAAI,YAAY,SAAS,qBAAqB;AAE5C,gBAAI,OAAO,SAAS,aAAa;AAC/B,iCAAmB;AACnB,qBAAO;AAAA,gBACL,MAAM;AAAA,gBACN,MAAM,YAAY;AAAA,gBAClB,YAAY,YAAY;AAAA,gBACxB,UAAU,YAAY;AAAA,cACxB;AAAA,YACF;AACA,+BAAmB;AAAA,UACrB;AACA,iBAAO;AAAA,QACT,CAAC;AAGD,eAAO,SAAS,OAAO,OAAO,GAAG,GAAG,QAAQ;AAC5C,eAAO,QAAQ,SAAS,SAAS;AAAA,MACnC;AAAA,IACF,CAAC;AAID,QAAI,kBAAkB;AACpB,YAAM,aAAa;AAAA,QACjB,MAAM;AAAA,QACN,OAAO;AAAA,QACP,MAAM;AAAA,UACJ,QAAQ;AAAA,YACN,MAAM;AAAA,YACN,YAAY;AAAA,YACZ,MAAM;AAAA,cACJ;AAAA,gBACE,MAAM;AAAA,gBACN,YAAY;AAAA,kBACV;AAAA,oBACE,MAAM;AAAA,oBACN,OAAO,EAAE,MAAM,cAAc,MAAM,eAAe;AAAA,kBACpD;AAAA,gBACF;AAAA,gBACA,QAAQ;AAAA,kBACN,MAAM;AAAA,kBACN,OAAO;AAAA,kBACP,KAAK;AAAA,gBACP;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAGA,YAAM,YACJ,MAAM,QAAQ,KAAK,QAAQ,KAC3B,KAAK,SAAS;AAAA,QACZ,OACE,EAAE,SAAS,eACV,EAAE,OAAO,SAAS,qBAAqB,KACtC,EAAE,MAAM,QAAQ,MAAM,KAAK,OAAK,EAAE,QAAQ,UAAU,qBAAqB;AAAA,MAC/E;AAEF,UAAI,CAAC,WAAW;AACd,YAAI,CAAC,MAAM,QAAQ,KAAK,QAAQ,EAAG,MAAK,WAAW,CAAC;AACpD,YAAI,cAAc;AAClB,iBAAS,IAAI,GAAG,IAAI,KAAK,SAAS,QAAQ,KAAK;AAC7C,gBAAM,OAAO,KAAK,SAAS,CAAC;AAC5B,cAAI,KAAK,SAAS,UAAU,KAAK,SAAS,QAAQ;AAChD,0BAAc,IAAI;AAAA,UACpB,OAAO;AACL;AAAA,UACF;AAAA,QACF;AACA,aAAK,SAAS,OAAO,aAAa,GAAG,UAAU;AAAA,MACjD;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;;;AC1bA,SAAS,aAAa,MAAe,OAAkC;AACrE,QAAM,SAA4B,CAAC;AACnC,QAAM,SAAS,SAAS,KAAK;AAE7B,MAAI,SAAS,QAAQ,SAAS,QAAW;AACvC,WAAO,KAAK;AAAA,MACV,OAAO;AAAA,MACP,SAAS;AAAA,MACT,OAAO;AAAA,IACT,CAAC;AACD,WAAO;AAAA,EACT;AAEA,MAAI,OAAO,SAAS,UAAU;AAC5B,WAAO,KAAK;AAAA,MACV,OAAO;AAAA,MACP,SAAS,+BAA+B,OAAO,IAAI;AAAA,MACnD,OAAO;AAAA,IACT,CAAC;AACD,WAAO;AAAA,EACT;AAEA,QAAM,UAAU;AAGhB,MAAI,EAAE,UAAU,UAAU;AACxB,WAAO,KAAK;AAAA,MACV,OAAO,GAAG,MAAM;AAAA,MAChB,SAAS;AAAA,IACX,CAAC;AAAA,EACH,WAAW,OAAO,QAAQ,SAAS,UAAU;AAC3C,WAAO,KAAK;AAAA,MACV,OAAO,GAAG,MAAM;AAAA,MAChB,SAAS,sCAAsC,OAAO,QAAQ,IAAI;AAAA,MAClE,OAAO,QAAQ;AAAA,IACjB,CAAC;AAAA,EACH,WAAW,QAAQ,KAAK,KAAK,MAAM,IAAI;AACrC,WAAO,KAAK;AAAA,MACV,OAAO,GAAG,MAAM;AAAA,MAChB,SAAS;AAAA,MACT,OAAO,QAAQ;AAAA,IACjB,CAAC;AAAA,EACH;AAGA,MAAI,EAAE,gBAAgB,UAAU;AAC9B,WAAO,KAAK;AAAA,MACV,OAAO,GAAG,MAAM;AAAA,MAChB,SAAS;AAAA,IACX,CAAC;AAAA,EACH,WAAW,OAAO,QAAQ,eAAe,UAAU;AACjD,WAAO,KAAK;AAAA,MACV,OAAO,GAAG,MAAM;AAAA,MAChB,SAAS,4CAA4C,OAAO,QAAQ,UAAU;AAAA,MAC9E,OAAO,QAAQ;AAAA,IACjB,CAAC;AAAA,EACH;AAGA,MAAI,kBAAkB,WAAW,QAAQ,iBAAiB,QAAW;AACnE,QAAI,OAAO,QAAQ,iBAAiB,UAAU;AAC5C,aAAO,KAAK;AAAA,QACV,OAAO,GAAG,MAAM;AAAA,QAChB,SAAS,8CAA8C,OAAO,QAAQ,YAAY;AAAA,QAClF,OAAO,QAAQ;AAAA,MACjB,CAAC;AAAA,IACH;AAAA,EACF;AAGA,MAAI,kBAAkB,WAAW,QAAQ,iBAAiB,QAAW;AACnE,QAAI,CAAC,MAAM,QAAQ,QAAQ,YAAY,GAAG;AACxC,aAAO,KAAK;AAAA,QACV,OAAO,GAAG,MAAM;AAAA,QAChB,SAAS,8CAA8C,OAAO,QAAQ,YAAY;AAAA,QAClF,OAAO,QAAQ;AAAA,MACjB,CAAC;AAAA,IACH,OAAO;AACL,cAAQ,aAAa,QAAQ,CAAC,aAAa,iBAAiB;AAC1D,YAAI,OAAO,gBAAgB,UAAU;AACnC,iBAAO,KAAK;AAAA,YACV,OAAO,GAAG,MAAM,iBAAiB,YAAY;AAAA,YAC7C,SAAS,sCAAsC,OAAO,WAAW;AAAA,YACjE,OAAO;AAAA,UACT,CAAC;AAAA,QACH;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAGA,MAAI,QAAQ,WAAW,QAAQ,OAAO,QAAW;AAC/C,QAAI,OAAO,QAAQ,OAAO,UAAU;AAClC,aAAO,KAAK;AAAA,QACV,OAAO,GAAG,MAAM;AAAA,QAChB,SAAS,oCAAoC,OAAO,QAAQ,EAAE;AAAA,QAC9D,OAAO,QAAQ;AAAA,MACjB,CAAC;AAAA,IACH;AAAA,EACF;AAGA,MAAI,cAAc,WAAW,QAAQ,aAAa,QAAW;AAC3D,QAAI,OAAO,QAAQ,aAAa,WAAW;AACzC,aAAO,KAAK;AAAA,QACV,OAAO,GAAG,MAAM;AAAA,QAChB,SAAS,2CAA2C,OAAO,QAAQ,QAAQ;AAAA,QAC3E,OAAO,QAAQ;AAAA,MACjB,CAAC;AAAA,IACH;AAAA,EACF;AAGA,MAAI,mBAAmB,WAAW,QAAQ,kBAAkB,QAAW;AACrE,QAAI,OAAO,QAAQ,kBAAkB,WAAW;AAC9C,aAAO,KAAK;AAAA,QACV,OAAO,GAAG,MAAM;AAAA,QAChB,SAAS,gDAAgD,OAAO,QAAQ,aAAa;AAAA,QACrF,OAAO,QAAQ;AAAA,MACjB,CAAC;AAAA,IACH;AAAA,EACF;AAGA,MAAI,aAAa,WAAW,QAAQ,YAAY,QAAW;AACzD,QAAI,CAAC,MAAM,QAAQ,QAAQ,OAAO,GAAG;AACnC,aAAO,KAAK;AAAA,QACV,OAAO,GAAG,MAAM;AAAA,QAChB,SAAS,yCAAyC,OAAO,QAAQ,OAAO;AAAA,QACxE,OAAO,QAAQ;AAAA,MACjB,CAAC;AAAA,IACH,OAAO;AACL,cAAQ,QAAQ,QAAQ,CAAC,OAAO,eAAe;AAC7C,YAAI,OAAO,UAAU,UAAU;AAC7B,iBAAO,KAAK;AAAA,YACV,OAAO,GAAG,MAAM,YAAY,UAAU;AAAA,YACtC,SAAS,+BAA+B,OAAO,KAAK;AAAA,YACpD,OAAO;AAAA,UACT,CAAC;AAAA,QACH,WAAW,MAAM,KAAK,MAAM,IAAI;AAC9B,iBAAO,KAAK;AAAA,YACV,OAAO,GAAG,MAAM,YAAY,UAAU;AAAA,YACtC,SAAS;AAAA,YACT,OAAO;AAAA,UACT,CAAC;AAAA,QACH;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO;AACT;AAgBO,SAAS,qBACd,MACA,UAAsC,CAAC,GACrB;AAClB,QAAM,EAAE,eAAe,KAAK,IAAI;AAChC,QAAM,SAA4B,CAAC;AAGnC,MAAI,SAAS,QAAQ,SAAS,QAAW;AACvC,WAAO,KAAK;AAAA,MACV,OAAO;AAAA,MACP,SAAS;AAAA,MACT,OAAO;AAAA,IACT,CAAC;AAED,QAAI,gBAAgB,OAAO,SAAS,GAAG;AACrC,YAAM,IAAI,wBAAwB,MAAM;AAAA,IAC1C;AAEA,WAAO,EAAE,OAAO,OAAO,QAAQ,MAAM,EAAE,OAAO,CAAC,EAAE,EAAE;AAAA,EACrD;AAGA,MAAI,OAAO,SAAS,UAAU;AAC5B,WAAO,KAAK;AAAA,MACV,OAAO;AAAA,MACP,SAAS,wCAAwC,OAAO,IAAI;AAAA,MAC5D,OAAO;AAAA,IACT,CAAC;AAED,QAAI,gBAAgB,OAAO,SAAS,GAAG;AACrC,YAAM,IAAI,wBAAwB,MAAM;AAAA,IAC1C;AAEA,WAAO,EAAE,OAAO,OAAO,QAAQ,MAAM,EAAE,OAAO,CAAC,EAAE,EAAE;AAAA,EACrD;AAEA,QAAM,eAAe;AAGrB,MAAI,WAAW,gBAAgB,OAAO,aAAa,UAAU,UAAU;AACrE,WAAO,KAAK;AAAA,MACV,OAAO;AAAA,MACP,SAAS;AAAA,IACX,CAAC;AAED,QAAI,gBAAgB,OAAO,SAAS,GAAG;AACrC,YAAM,IAAI,wBAAwB,MAAM;AAAA,IAC1C;AAAA,EACF;AACA,QAAM,aAAa,aAAa;AAEhC,MAAI,iBAAiB,gBAAgB,OAAO,aAAa,gBAAgB,UAAU;AACjF,WAAO,KAAK;AAAA,MACV,OAAO;AAAA,MACP,SAAS;AAAA,IACX,CAAC;AAED,QAAI,gBAAgB,OAAO,SAAS,GAAG;AACrC,YAAM,IAAI,wBAAwB,MAAM;AAAA,IAC1C;AAAA,EACF;AAEA,QAAM,mBAAmB,aAAa;AAEtC,MAAI,EAAE,WAAW,eAAe;AAE9B,WAAO,KAAK;AAAA,MACV,OAAO;AAAA,MACP,SAAS;AAAA,IACX,CAAC;AAED,QAAI,gBAAgB,OAAO,SAAS,GAAG;AACrC,YAAM,IAAI,wBAAwB,MAAM;AAAA,IAC1C;AAEA,WAAO,EAAE,OAAO,OAAO,QAAQ,MAAM,EAAE,OAAO,CAAC,EAAE,EAAE;AAAA,EACrD;AAEA,MAAI,CAAC,MAAM,QAAQ,aAAa,KAAK,GAAG;AACtC,WAAO,KAAK;AAAA,MACV,OAAO;AAAA,MACP,SAAS,uCAAuC,OAAO,aAAa,KAAK;AAAA,MACzE,OAAO,aAAa;AAAA,IACtB,CAAC;AAED,QAAI,gBAAgB,OAAO,SAAS,GAAG;AACrC,YAAM,IAAI,wBAAwB,MAAM;AAAA,IAC1C;AAEA,WAAO,EAAE,OAAO,OAAO,QAAQ,MAAM,EAAE,OAAO,CAAC,EAAE,EAAE;AAAA,EACrD;AAGA,QAAM,aAA6B,CAAC;AACpC,eAAa,MAAM,QAAQ,CAAC,MAAM,UAAU;AAC1C,UAAM,aAAa,aAAa,MAAM,KAAK;AAC3C,QAAI,WAAW,SAAS,GAAG;AACzB,aAAO,KAAK,GAAG,UAAU;AAAA,IAC3B,OAAO;AAEL,iBAAW,KAAK,IAAoB;AAAA,IACtC;AAAA,EACF,CAAC;AAGD,QAAM,YAAY,oBAAI,IAAoB;AAC1C,aAAW,QAAQ,CAAC,MAAM,UAAU;AAClC,UAAM,YAAY,KAAK,KAAK,YAAY;AACxC,QAAI,UAAU,IAAI,SAAS,GAAG;AAC5B,aAAO,KAAK;AAAA,QACV,OAAO,SAAS,KAAK;AAAA,QACrB,SAAS,mBAAmB,KAAK,IAAI,gCAAgC,UAAU,IAAI,SAAS,CAAC;AAAA,QAC7F,OAAO,KAAK;AAAA,MACd,CAAC;AAAA,IACH,OAAO;AACL,gBAAU,IAAI,WAAW,KAAK;AAAA,IAChC;AAAA,EACF,CAAC;AAED,MAAI,gBAAgB,OAAO,SAAS,GAAG;AACrC,UAAM,IAAI,wBAAwB,MAAM;AAAA,EAC1C;AAEA,SAAO;AAAA,IACL,OAAO,OAAO,WAAW;AAAA,IACzB;AAAA,IACA,MAAM,EAAE,OAAO,YAAY,aAAa,kBAAkB,OAAO,WAAW;AAAA,EAC9E;AACF;AAMO,IAAM,0BAAN,MAAM,iCAAgC,MAAM;AAAA,EAGjD,YAAY,QAA2B;AACrC,UAAM,UAAU,uBAAuB,MAAM;AAC7C,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,SAAS;AAId,QAAI,MAAM,mBAAmB;AAE3B,YAAM,kBAAkB,MAAM,wBAAuB;AAAA,IACvD;AAAA,EACF;AACF;AAQO,SAAS,uBAAuB,QAAmC;AACxE,MAAI,OAAO,WAAW,GAAG;AACvB,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,mCAAmC,OAAO,MAAM,SAAS,OAAO,SAAS,IAAI,MAAM,EAAE;AACpG,QAAM,YAAY,OACf,IAAI,CAAC,KAAK,UAAU;AACnB,QAAI,MAAM,KAAK,QAAQ,CAAC,MAAM,IAAI,KAAK,KAAK,IAAI,OAAO;AACvD,QAAI,IAAI,UAAU,QAAW;AAC3B,YAAM,WACJ,OAAO,IAAI,UAAU,WAAW,KAAK,UAAU,IAAI,KAAK,IAAI,OAAO,IAAI,KAAK;AAE9E,YAAM,YAAY,SAAS,SAAS,KAAK,SAAS,UAAU,GAAG,EAAE,IAAI,QAAQ;AAC7E,aAAO,UAAU,SAAS;AAAA,IAC5B;AACA,WAAO;AAAA,EACT,CAAC,EACA,KAAK,IAAI;AAEZ,SAAO,GAAG,MAAM;AAAA,EAAK,SAAS;AAChC;;;AFrWA,IAAM,sBAAkB,0BAAc,aAAe;AACrD,IAAM,aAAa,aAAAE,QAAK,QAAQ,eAAe;AAAA,IAG/C,kCAAAC,SAAyB,UAAU;AAyFpB,SAAR,eACL,SACA,UAAiC,CAAC,GAC1B;AACR,QAAM,EAAE,eAAe,0BAA0B,YAAY,YAAY,IAAI;AAE7E,SAAO;AAAA,IACL,MAAM;AAAA,IAEN,mBAAmB;AACjB,aAAO,CAAC,aAAAD,QAAK,QAAQ,YAAY,mBAAmB,CAAC;AAAA,IACvD;AAAA,IAEA,MAAM,cAAc;AAElB,YAAM,mBAAmB,aAAAA,QAAK,QAAQ,QAAQ,SAAS,YAAY;AAEnE,UAAI,MAAM,gBAAAE,QAAG,WAAW,gBAAgB,GAAG;AACzC,YAAI;AACF,gBAAM,UAAU,MAAM,gBAAAA,QAAG,SAAS,gBAAgB;AAGlD,gBAAM,mBAAmB,qBAAqB,SAAS,EAAE,cAAc,MAAM,CAAC;AAE9E,cAAI,CAAC,iBAAiB,OAAO;AAC3B,oBAAQ;AAAA,cACN,4DAA4D,gBAAgB;AAAA,YAC9E;AACA,6BAAiB,OAAO,QAAQ,SAAO;AACrC,sBAAQ,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,OAAO,EAAE;AAAA,YAClD,CAAC;AACD,oBAAQ,KAAK,qDAAqD;AAAA,UACpE;AAEA,iBAAO,iBAAiB;AAAA,QAC1B,SAAS,OAAO;AACd,cAAI,iBAAiB,yBAAyB;AAC5C,kBAAM;AAAA,UACR;AAEA,gBAAM,IAAI;AAAA,YACR,oCAAoC,gBAAgB,KAAK,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,UACjH;AAAA,QACF;AAAA,MACF;AAEA,cAAQ,KAAK,8BAA8B,gBAAgB,yBAAyB;AACpF,aAAO,EAAE,OAAO,CAAC,EAAE;AAAA,IACrB;AAAA,IAEA,MAAM,cAAc,EAAE,SAAS,QAAQ,GAAG;AACxC,YAAM,EAAE,YAAY,UAAU,cAAc,IAAI;AAChD,YAAM,kBAAkB;AAGxB,YAAM,mBAAmB,MAAM;AAAA,QAC7B;AAAA,QACA,KAAK,UAAU,eAAe;AAAA,MAChC;AAGA,YAAM;AAAA,QACJ;AAAA,QACA,KAAK,UAAU;AAAA,UACb,OAAO,gBAAgB,SAAS,CAAC;AAAA,UACjC;AAAA,QACF,CAAC;AAAA,MACH;AAGA,eAAS;AAAA,QACP,MAAM;AAAA,QACN,WAAW,aAAAF,QAAK,KAAK,YAAY,4BAA4B;AAAA,QAC7D,OAAO;AAAA,QACP,SAAS;AAAA,UACP,cAAc;AAAA,QAChB;AAAA,MACF,CAAC;AAGD,oBAAc;AAAA,QACZ,OAAO,gBAAgB,SAAS,CAAC;AAAA,QACjC;AAAA,MACF,CAAC;AAAA,IACH;AAAA,IAEA,eAAe;AACb,aAAO,aAAAA,QAAK,QAAQ,YAAY,SAAS;AAAA,IAC3C;AAAA,IAEA,kBAAkB;AAChB,aAAO,CAAC,aAAAA,QAAK,QAAQ,QAAQ,SAAS,YAAY,CAAC;AAAA,IACrD;AAAA,IAEA,MAAM,YAAY;AAEhB,cAAQ,IAAI,kCAAkC;AAAA,IAChD;AAAA,EACF;AACF;AAyBO,SAAS,gBACd,eACA,SAC6F;AAC7F,QAAM,EAAE,eAAe,0BAA0B,YAAY,YAAY,IAAI;AAE7E,QAAM,UAAU,SAAS;AAEzB,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;;;AF1Ie,SAAR,OAAwB,SAAsB,UAAiC,CAAC,GAAW;AAEhG,QAAM,EAAE,WAAW,CAAC,GAAG,IAAI,KAAK,GAAG,YAAY,IAAI;AAInD,QAAM,EAAE,MAAM,OAAO,OAAO,MAAM,iBAAiB,kBAAkB,MAAM,IAAI;AAC/E,QAAM,OAA+B,YAAY;AACjD,QAAM,UAAqC,YAAY;AAGvD,QAAM,iBAAuC,CAAC;AAC9C,MAAI,SAAS,OAAW,gBAAe,OAAO;AAC9C,MAAI,SAAS,OAAW,gBAAe,OAAO;AAC9C,MAAI,UAAU,OAAW,gBAAe,QAAQ;AAChD,MAAI,UAAU,OAAW,gBAAe,QAAQ;AAChD,MAAI,SAAS,OAAW,gBAAe,OAAO;AAC9C,MAAI,oBAAoB,OAAW,gBAAe,kBAAkB;AACpE,MAAI,qBAAqB,OAAW,gBAAe,mBAAmB;AACtE,MAAI,YAAY,OAAW,gBAAe,UAAU;AACpD,MAAI,UAAU,OAAW,gBAAe,QAAQ;AAEhD,QAAM,EAAE,eAAe,0BAA0B,YAAY,YAAY,IAAI;AAG7E,QAAM,eAAe,gBAAgB,EAAE,cAAc,UAAU,GAAG,EAAE,SAAS,QAAQ,QAAQ,CAAC;AAG9F,QAAM,aAAa,eAAe,QAAQ,CAAC;AAC3C,QAAM,oBAAoB,WAAW,iBAAiB,CAAC;AACvD,QAAM,qBAAqB;AAAA,IACzB,GAAG;AAAA,IACH,eAAe,CAAC,GAAG,mBAAmB,YAAY;AAAA,EACpD;AAGA,QAAM,cAAc,eAAe,SAAS,CAAC;AAC7C,QAAM,qBAAqB,YAAY,iBAAiB,CAAC;AACzD,QAAM,sBAAsB;AAAA,IAC1B,GAAG;AAAA,IACH,eAAe,CAAC,GAAG,oBAAoB,YAAY;AAAA,EACrD;AAIA,MAAI,qBAA6C;AACjD,MAAI,OAAO,SAAS,YAAY,SAAS,MAAM;AAC7C,UAAM,oBAAoB,KAAK,iBAAiB,CAAC;AACjD,yBAAqB;AAAA,MACnB,GAAG;AAAA,MACH,eAAe,CAAC,GAAG,mBAAmB,YAAY;AAAA,IACpD;AAAA,EACF;AAGA,QAAM,sBAA4C,CAAC;AACnD,MAAI,uBAAuB,OAAW,qBAAoB,OAAO;AACjE,MAAI,uBAAuB,OAAW,qBAAoB,OAAO;AACjE,MAAI,wBAAwB,OAAW,qBAAoB,QAAQ;AACnE,MAAI,UAAU,OAAW,qBAAoB,QAAQ;AACrD,MAAI,SAAS,OAAW,qBAAoB,OAAO;AACnD,MAAI,oBAAoB,OAAW,qBAAoB,kBAAkB;AACzE,MAAI,qBAAqB,OAAW,qBAAoB,mBAAmB;AAC3E,MAAI,YAAY,OAAW,qBAAoB,UAAU;AACzD,MAAI,UAAU,OAAW,qBAAoB,QAAQ;AAOrD,QAAM,UAAyB;AAAA;AAAA,IAE7B,SAAS,sBAAsB,KAAkB;AAC/C,aAAO,eAAe,KAAK,QAAQ;AAAA,IACrC;AAAA,EACF;AAGA,MAAI,mBAAoB,SAAQ,KAAK,CAAC,mCAAmC,kBAAkB,CAAC;AAC5F,MAAI,OAAO,uBAAuB,YAAY,uBAAuB;AACnE,YAAQ,KAAK,CAAC,mCAAmC,kBAAkB,CAAC;AACtE,MAAI,oBAAqB,SAAQ,KAAK,CAAC,oCAAoC,mBAAmB,CAAC;AAC/F,MAAI,KAAM,SAAQ,KAAK,CAAC,kCAAkC,IAAI,CAAC;AAC/D,MAAI,gBAAiB,SAAQ,KAAK,CAAC,uCAAuC,eAAe,CAAC;AAC1F,MAAI,iBAAkB,SAAQ,KAAK,CAAC,yCAAyC,gBAAgB,CAAC;AAC9F,MAAI,YAAY,MAAO,SAAQ,KAAK,CAAC,8BAA8B,WAAW,CAAC,CAAC,CAAC;AACjF,MAAI,MAAO,SAAQ,KAAK,CAAC,4BAA4B,CAAC,CAAC,CAAC;AAExD,SAAO;AAAA,IACL,QAAQ;AAAA;AAAA,MAEN,CAAC,6BAA6B,SAAS,CAAC,CAAC;AAAA,IAC3C;AAAA,IACA;AAAA,EACF;AACF;","names":["import_path","path","fs","path","validatePeerDependencies","fs"]}
|
|
1
|
+
{"version":3,"sources":["../src/preset.ts","../node_modules/tsup/assets/cjs_shims.js","../src/index.ts","../src/remark/glossary-terms.js","../src/validation.ts"],"sourcesContent":["import type { Preset, LoadContext } from '@docusaurus/types';\nimport glossaryPlugin, { getRemarkPlugin } from './index.js';\nimport type { GlossaryPluginOptions } from './index.js';\n\n/**\n * Configuration for @docusaurus/plugin-content-docs\n * Using Record<string, unknown> to allow any valid docs options without coupling to specific version\n */\ntype DocsConfig = Record<string, unknown> & {\n remarkPlugins?: unknown[];\n};\n\n/**\n * Configuration for @docusaurus/plugin-content-blog\n * Can be false to disable, or configuration object\n */\ntype BlogConfig =\n | false\n | (Record<string, unknown> & {\n remarkPlugins?: unknown[];\n });\n\n/**\n * Configuration for @docusaurus/plugin-content-pages\n */\ntype PagesConfig = Record<string, unknown> & {\n remarkPlugins?: unknown[];\n};\n\n/**\n * Configuration for @docusaurus/theme-classic\n */\ntype ThemeConfig = Record<string, unknown>;\n\n/**\n * Configuration for analytics plugins\n */\ntype AnalyticsConfig = Record<string, unknown>;\n\n/**\n * Configuration for @docusaurus/plugin-sitemap\n * Can be false to disable, or configuration object\n */\ntype SitemapConfig = false | Record<string, unknown>;\n\n/**\n * Classic preset options (simplified to avoid direct dependency on @docusaurus/preset-classic)\n * These mirror the options available in the classic preset\n */\nexport interface ClassicPresetOptions {\n docs?: DocsConfig;\n blog?: BlogConfig;\n pages?: PagesConfig;\n theme?: ThemeConfig;\n gtag?: AnalyticsConfig;\n googleAnalytics?: AnalyticsConfig;\n googleTagManager?: AnalyticsConfig;\n sitemap?: SitemapConfig;\n debug?: boolean;\n}\n\nexport interface GlossaryPresetOptions extends ClassicPresetOptions {\n glossary?: GlossaryPluginOptions;\n /** Internal: Docusaurus adds this, we need to exclude it from classic options */\n id?: string;\n}\n\n/**\n * Docusaurus Glossary Preset\n *\n * A preset that extends @docusaurus/preset-classic with automatic glossary functionality.\n * This preset automatically configures the remark plugin for docs and pages, so you don't\n * need to manually add it to remarkPlugins.\n *\n * @example\n * ```javascript\n * export default {\n * presets: [\n * [\n * 'docusaurus-plugin-glossary/preset',\n * {\n * // Glossary options\n * glossary: {\n * glossaryPath: 'glossary/glossary.json',\n * routePath: '/glossary',\n * },\n * // Classic preset options\n * docs: {\n * sidebarPath: './sidebars.js',\n * },\n * blog: {\n * showReadingTime: true,\n * },\n * theme: {\n * customCss: './src/css/custom.css',\n * },\n * },\n * ],\n * ],\n * };\n * ```\n *\n * @param context - Docusaurus context\n * @param options - Preset options including glossary and classic preset options\n * @returns Preset configuration\n */\nexport default function preset(context: LoadContext, options: GlossaryPresetOptions = {}): Preset {\n // Explicitly extract glossary and any Docusaurus-added properties that shouldn't go to classic preset\n const { glossary = {}, id: _id, ...restOptions } = options;\n\n // Extract only valid classic preset options\n // Explicitly type blog and sitemap to preserve union types (can be false)\n const { docs, pages, theme, gtag, googleAnalytics, googleTagManager, debug } = restOptions;\n const blog: BlogConfig | undefined = restOptions.blog;\n const sitemap: SitemapConfig | undefined = restOptions.sitemap;\n\n // Build classic options object with only defined properties\n const classicOptions: ClassicPresetOptions = {};\n if (docs !== undefined) classicOptions.docs = docs;\n if (blog !== undefined) classicOptions.blog = blog;\n if (pages !== undefined) classicOptions.pages = pages;\n if (theme !== undefined) classicOptions.theme = theme;\n if (gtag !== undefined) classicOptions.gtag = gtag;\n if (googleAnalytics !== undefined) classicOptions.googleAnalytics = googleAnalytics;\n if (googleTagManager !== undefined) classicOptions.googleTagManager = googleTagManager;\n if (sitemap !== undefined) classicOptions.sitemap = sitemap;\n if (debug !== undefined) classicOptions.debug = debug;\n\n const {\n glossaryPath = 'glossary/glossary.json',\n routePath = '/glossary',\n expandAcronymsOnFirstUse = false,\n } = glossary;\n\n // Get the remark plugin configuration\n const remarkPlugin = getRemarkPlugin(\n { glossaryPath, routePath, expandAcronymsOnFirstUse },\n { siteDir: context.siteDir }\n );\n\n // Extend docs configuration with glossary remark plugin\n const docsConfig = classicOptions.docs || {};\n const docsRemarkPlugins = docsConfig.remarkPlugins || [];\n const extendedDocsConfig = {\n ...docsConfig,\n remarkPlugins: [...docsRemarkPlugins, remarkPlugin],\n };\n\n // Extend pages configuration with glossary remark plugin\n const pagesConfig = classicOptions.pages || {};\n const pagesRemarkPlugins = pagesConfig.remarkPlugins || [];\n const extendedPagesConfig = {\n ...pagesConfig,\n remarkPlugins: [...pagesRemarkPlugins, remarkPlugin],\n };\n\n // Extend blog configuration with glossary remark plugin (optional)\n // Use typeof check for proper type narrowing (blog can be false, object, or undefined)\n let extendedBlogConfig: BlogConfig | undefined = blog;\n if (typeof blog === 'object' && blog !== null) {\n const blogRemarkPlugins = blog.remarkPlugins || [];\n extendedBlogConfig = {\n ...blog,\n remarkPlugins: [...blogRemarkPlugins, remarkPlugin],\n };\n }\n\n // Build the final classic preset options\n const finalClassicOptions: ClassicPresetOptions = {};\n if (extendedDocsConfig !== undefined) finalClassicOptions.docs = extendedDocsConfig;\n if (extendedBlogConfig !== undefined) finalClassicOptions.blog = extendedBlogConfig;\n if (extendedPagesConfig !== undefined) finalClassicOptions.pages = extendedPagesConfig;\n if (theme !== undefined) finalClassicOptions.theme = theme;\n if (gtag !== undefined) finalClassicOptions.gtag = gtag;\n if (googleAnalytics !== undefined) finalClassicOptions.googleAnalytics = googleAnalytics;\n if (googleTagManager !== undefined) finalClassicOptions.googleTagManager = googleTagManager;\n if (sitemap !== undefined) finalClassicOptions.sitemap = sitemap;\n if (debug !== undefined) finalClassicOptions.debug = debug;\n\n // Plugin tuple type: [plugin-name, options] or plugin function\n type PluginEntry =\n | [string, Record<string, unknown>]\n | ((ctx: LoadContext) => ReturnType<typeof glossaryPlugin>);\n\n const plugins: PluginEntry[] = [\n // Add the glossary plugin first\n function glossaryPluginWrapper(ctx: LoadContext) {\n return glossaryPlugin(ctx, glossary);\n },\n ];\n\n // Add classic preset plugins individually\n if (extendedDocsConfig) plugins.push(['@docusaurus/plugin-content-docs', extendedDocsConfig]);\n if (typeof extendedBlogConfig === 'object' && extendedBlogConfig !== null)\n plugins.push(['@docusaurus/plugin-content-blog', extendedBlogConfig]);\n if (extendedPagesConfig) plugins.push(['@docusaurus/plugin-content-pages', extendedPagesConfig]);\n if (gtag) plugins.push(['@docusaurus/plugin-google-gtag', gtag]);\n if (googleAnalytics) plugins.push(['@docusaurus/plugin-google-analytics', googleAnalytics]);\n if (googleTagManager) plugins.push(['@docusaurus/plugin-google-tag-manager', googleTagManager]);\n if (sitemap !== false) plugins.push(['@docusaurus/plugin-sitemap', sitemap || {}]);\n if (debug) plugins.push(['@docusaurus/plugin-debug', {}]);\n\n return {\n themes: [\n // Pass theme options (including customCss) to theme-classic\n ['@docusaurus/theme-classic', theme || {}],\n ],\n plugins,\n };\n}\n","// Shim globals in cjs bundle\n// There's a weird bug that esbuild will always inject importMetaUrl\n// if we export it as `const importMetaUrl = ... __filename ...`\n// But using a function will not cause this issue\n\nconst getImportMetaUrl = () => \n typeof document === \"undefined\" \n ? new URL(`file:${__filename}`).href \n : (document.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT') \n ? document.currentScript.src \n : new URL(\"main.js\", document.baseURI).href;\n\nexport const importMetaUrl = /* @__PURE__ */ getImportMetaUrl()\n","// @ts-ignore\nimport path from 'path';\n// @ts-ignore\nimport { fileURLToPath } from 'url';\nimport fs from 'fs-extra';\nimport type { LoadContext, Plugin } from '@docusaurus/types';\nimport validatePeerDependencies from 'validate-peer-dependencies';\nimport remarkGlossaryTerms from './remark/glossary-terms.js';\nimport { validateGlossaryData, GlossaryValidationError } from './validation.js';\nimport type { GlossaryPluginOptions, GlossaryData } from './types.js';\n\n// Re-export the shared public types so existing\n// `import type { GlossaryTerm } from 'docusaurus-plugin-glossary'` imports keep working.\nexport type { GlossaryPluginOptions, GlossaryTerm, GlossaryData } from './types.js';\n\n// Standard ES module directory resolution\nconst currentFilePath = fileURLToPath(import.meta.url);\nconst currentDir = path.dirname(currentFilePath);\n\n// Validate peer dependencies at module load time\nvalidatePeerDependencies(currentDir);\n\n/**\n * Docusaurus Glossary Plugin\n *\n * A plugin that provides glossary functionality with:\n * - Glossary terms defined in a JSON file\n * - Auto-generated glossary page with term definitions\n * - GlossaryTerm component for inline definitions with interactive tooltips\n * - Automatic client-side initialization via getClientModules() (no manual imports needed)\n * - Optional automatic glossary term detection in markdown files via remark plugin\n *\n * ## Basic Usage (Manual Term Markup)\n *\n * Just install the plugin - the GlossaryTerm component is automatically available:\n * ```javascript\n * module.exports = {\n * plugins: [\n * ['docusaurus-plugin-glossary', {\n * glossaryPath: 'glossary/glossary.json',\n * routePath: '/glossary',\n * }],\n * ],\n * };\n * ```\n *\n * Then use `<GlossaryTerm>` in your MDX files without importing:\n * ```mdx\n * <GlossaryTerm term=\"API\">API</GlossaryTerm>\n * ```\n *\n * ## Advanced Usage (Automatic Term Detection)\n *\n * To automatically detect and link glossary terms in markdown, add the remark plugin:\n * ```javascript\n * const glossaryPlugin = require('docusaurus-plugin-glossary');\n *\n * module.exports = {\n * presets: [\n * ['@docusaurus/preset-classic', {\n * docs: {\n * remarkPlugins: [\n * glossaryPlugin.getRemarkPlugin({\n * glossaryPath: 'glossary/glossary.json',\n * routePath: '/glossary',\n * }, { siteDir: __dirname }),\n * ],\n * },\n * }],\n * ],\n * plugins: [\n * ['docusaurus-plugin-glossary', {\n * glossaryPath: 'glossary/glossary.json',\n * routePath: '/glossary',\n * }],\n * ],\n * };\n * ```\n *\n * @param context - Docusaurus context\n * @param options - Plugin options\n * @param options.glossaryPath - Path to glossary JSON file (default: 'glossary/glossary.json')\n * @param options.routePath - Route path for glossary page (default: '/glossary')\n * @param options.autoLinkTerms - Legacy option, kept for compatibility but no longer used (configure remark plugin manually instead)\n * @returns Plugin object\n */\nexport default function glossaryPlugin(\n context: LoadContext,\n options: GlossaryPluginOptions = {}\n): Plugin {\n const { glossaryPath = 'glossary/glossary.json', routePath = '/glossary' } = options;\n\n return {\n name: 'docusaurus-plugin-glossary',\n\n getClientModules() {\n return [path.resolve(currentDir, './client/index.js')];\n },\n\n async loadContent() {\n // Load glossary terms from JSON file\n const glossaryFilePath = path.resolve(context.siteDir, glossaryPath);\n\n if (await fs.pathExists(glossaryFilePath)) {\n try {\n const rawData = await fs.readJson(glossaryFilePath);\n\n // Validate glossary data structure\n const validationResult = validateGlossaryData(rawData, { throwOnError: false });\n\n if (!validationResult.valid) {\n console.warn(\n `[glossary-plugin] Glossary file has validation errors at ${glossaryFilePath}:`\n );\n validationResult.errors.forEach(err => {\n console.warn(` - [${err.field}] ${err.message}`);\n });\n console.warn('[glossary-plugin] Proceeding with valid terms only.');\n }\n\n return validationResult.data;\n } catch (error) {\n if (error instanceof GlossaryValidationError) {\n throw error;\n }\n // JSON parsing error\n throw new Error(\n `Failed to parse glossary file at ${glossaryFilePath}: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n }\n\n console.warn(`Glossary file not found at ${glossaryFilePath}. Using empty glossary.`);\n return { terms: [] };\n },\n\n async contentLoaded({ content, actions }) {\n const { createData, addRoute, setGlobalData } = actions;\n const glossaryContent = content as GlossaryData;\n\n // Create data file that can be imported by components\n const glossaryDataPath = await createData(\n 'glossary-data.json',\n JSON.stringify(glossaryContent)\n );\n\n // Create a data file for the remark plugin to access glossary terms\n await createData(\n 'remark-glossary-data.json',\n JSON.stringify({\n terms: glossaryContent.terms || [],\n routePath: routePath,\n })\n );\n\n // Add glossary page route\n addRoute({\n path: routePath,\n component: path.join(currentDir, 'components/GlossaryPage.js'),\n exact: true,\n modules: {\n glossaryData: glossaryDataPath,\n },\n });\n\n // Expose global data for runtime lookups (used by GlossaryTerm)\n setGlobalData({\n terms: glossaryContent.terms || [],\n routePath,\n });\n },\n\n getThemePath() {\n return path.resolve(currentDir, './theme');\n },\n\n getPathsToWatch() {\n return [path.resolve(context.siteDir, glossaryPath)];\n },\n\n async postBuild() {\n // You can add any post-build steps here if needed\n console.log('Glossary plugin: Build completed');\n },\n };\n}\n\n// Export remark plugin factory for use in markdown configuration\nexport const remarkPlugin = remarkGlossaryTerms;\n\n// Export cache clearing utility\nexport { clearGlossaryCache } from './remark/glossary-terms.js';\n\n// Export validation utilities\nexport {\n validateGlossaryData,\n GlossaryValidationError,\n formatValidationErrors,\n type ValidationError,\n type ValidationResult,\n} from './validation.js';\n\n/**\n * Helper function to get the configured remark plugin\n * This can be used in docusaurus.config.js markdown configuration\n *\n * @param pluginOptions - Plugin options from docusaurus.config.js\n * @param context - Context with siteDir\n * @returns Configured remark plugin\n */\nexport function getRemarkPlugin(\n pluginOptions: GlossaryPluginOptions,\n context?: { siteDir?: string }\n): [\n typeof remarkGlossaryTerms,\n {\n glossaryPath: string;\n routePath: string;\n siteDir?: string;\n expandAcronymsOnFirstUse: boolean;\n },\n] {\n const {\n glossaryPath = 'glossary/glossary.json',\n routePath = '/glossary',\n expandAcronymsOnFirstUse = false,\n } = pluginOptions;\n\n const siteDir = context?.siteDir;\n\n return [\n remarkGlossaryTerms,\n {\n glossaryPath,\n routePath,\n siteDir,\n expandAcronymsOnFirstUse,\n },\n ];\n}\n","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 * @param {boolean} options.expandAcronymsOnFirstUse - When true, the first canonical occurrence of a\n * term with an `abbreviation` is rendered as \"Long Form (Term)\" instead of just \"Term\".\n * Subsequent occurrences in the same file render unchanged. Default: false.\n * @returns {function} Remark plugin function\n */\nexport default function remarkGlossaryTerms({\n terms = [],\n glossaryPath = null,\n routePath = '/glossary',\n siteDir = null,\n expandAcronymsOnFirstUse = false,\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 represents a matchable phrase (canonical term or alias) and points\n // back to the canonical term object so tooltip/href always use the canonical form.\n // Key: lowercase phrase, Value: { termObj, phrase, caseSensitive } where\n // `phrase` preserves the original case (used for case-sensitive matching).\n const termMap = new Map();\n glossaryTerms.forEach(termObj => {\n if (!termObj.term || termObj.autoLink === false) return;\n const caseSensitive = termObj.caseSensitive === true;\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, phrase, caseSensitive });\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 * @param {string} text - Source text to scan\n * @param {Set<string>} seenTerms - Per-file set tracking which canonical terms have already been\n * rendered (used by expandAcronymsOnFirstUse to expand only on first occurrence).\n */\n function replaceTermsInText(text, seenTerms) {\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, phrase, caseSensitive }] of sortedTerms) {\n // Case-sensitive terms search the original text for the exact casing;\n // case-insensitive terms search the lowercased text for the lowercased phrase.\n const haystack = caseSensitive ? text : textLower;\n const needle = caseSensitive ? phrase : lowerPhrase;\n let searchIndex = 0;\n\n while (searchIndex < haystack.length) {\n const index = haystack.indexOf(needle, searchIndex);\n if (index === -1) break;\n\n // Check if it's a whole word match, with simple plural tolerance ('s' or 'es').\n // Word-boundary detection uses the lowercased text so letter-class checks\n // behave consistently regardless of the term's case-sensitivity setting.\n const beforeChar = index > 0 ? textLower[index - 1] : ' ';\n const afterIndex = index + needle.length;\n const afterChar = afterIndex < textLower.length ? textLower[afterIndex] : ' ';\n\n let matchLength = needle.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 = needle.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 = needle.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 const displayText = resolveDisplayText(match, text, seenTerms);\n // Mark this term as seen regardless of whether we expanded — once the reader\n // has encountered any occurrence (canonical or otherwise), the introduction\n // window has closed.\n seenTerms.add(match.termObj.term);\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: displayText,\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 // Decide what text to render inside the GlossaryTerm element.\n // Default: the text as written. When expandAcronymsOnFirstUse is enabled and this is the\n // first canonical occurrence of a term that has an `abbreviation`, expand to\n // \"Long Form (Term)\" — unless the long form already appears immediately before the match\n // (e.g. the author wrote \"Payment Service Provider (PSP)\" themselves).\n function resolveDisplayText(match, text, seenTerms) {\n const termObj = match.termObj;\n if (!expandAcronymsOnFirstUse) return match.originalText;\n if (!termObj.abbreviation) return match.originalText;\n if (seenTerms.has(termObj.term)) return match.originalText;\n\n // Only canonical matches — no aliases, no plural forms.\n const isCanonical =\n match.length === termObj.term.length &&\n match.originalText.toLowerCase() === termObj.term.toLowerCase();\n if (!isCanonical) return match.originalText;\n\n // If the long form is already present in the lookback window, skip expansion to\n // avoid \"Payment Service Provider (Payment Service Provider (PSP))\".\n const longForm = termObj.abbreviation;\n const lookbackWindow = longForm.length + 10;\n const lookbackStart = Math.max(0, match.index - lookbackWindow);\n const lookback = text.substring(lookbackStart, match.index).toLowerCase();\n if (lookback.includes(longForm.toLowerCase())) return match.originalText;\n\n return `${longForm} (${match.originalText})`;\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 // Per-file tracking: each transformer invocation gets a fresh Set so acronym\n // expansion fires at most once per term per file.\n const seenTerms = new Set();\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, seenTerms);\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","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 // Optional: caseSensitive (boolean)\n if ('caseSensitive' in termObj && termObj.caseSensitive !== undefined) {\n if (typeof termObj.caseSensitive !== 'boolean') {\n errors.push({\n field: `${prefix}.caseSensitive`,\n message: `Field \"caseSensitive\" must be a boolean, got ${typeof termObj.caseSensitive}`,\n value: termObj.caseSensitive,\n });\n }\n }\n\n // Optional: aliases (string[])\n if ('aliases' in termObj && termObj.aliases !== undefined) {\n if (!Array.isArray(termObj.aliases)) {\n errors.push({\n field: `${prefix}.aliases`,\n message: `Field \"aliases\" must be an array, got ${typeof termObj.aliases}`,\n value: termObj.aliases,\n });\n } else {\n termObj.aliases.forEach((alias, aliasIndex) => {\n if (typeof alias !== 'string') {\n errors.push({\n field: `${prefix}.aliases[${aliasIndex}]`,\n message: `Alias must be a string, got ${typeof alias}`,\n value: alias,\n });\n } else if (alias.trim() === '') {\n errors.push({\n field: `${prefix}.aliases[${aliasIndex}]`,\n message: 'Alias cannot be empty',\n value: alias,\n });\n }\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 title\n if ('title' in glossaryData && typeof glossaryData.title !== 'string') {\n errors.push({\n field: 'title',\n message: 'The title property in the GlossaryData must be a string.',\n });\n\n if (throwOnError && errors.length > 0) {\n throw new GlossaryValidationError(errors);\n }\n }\n const validTitle = glossaryData.title as string;\n\n if ('description' in glossaryData && typeof glossaryData.description !== 'string') {\n errors.push({\n field: 'description',\n message: 'The description property in the GlossaryData must be a string.',\n });\n\n if (throwOnError && errors.length > 0) {\n throw new GlossaryValidationError(errors);\n }\n }\n\n const validDescription = glossaryData.description as string;\n\n if (!('terms' in glossaryData)) {\n // Check for terms array\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: { title: validTitle, description: validDescription, 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 // @ts-ignore\n if (Error.captureStackTrace) {\n // @ts-ignore\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":["import_path","path","fs","path","validatePeerDependencies","fs"]}
|
package/dist/preset.d.cts
CHANGED
package/dist/preset.d.ts
CHANGED
package/dist/preset.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getRemarkPlugin,
|
|
3
3
|
glossaryPlugin
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-EQBYCLUI.js";
|
|
5
5
|
import "./chunk-FJKK57G2.js";
|
|
6
|
-
import "./chunk-
|
|
6
|
+
import "./chunk-CIAA7XR3.js";
|
|
7
7
|
|
|
8
8
|
// src/preset.ts
|
|
9
9
|
function preset(context, options = {}) {
|
|
@@ -21,8 +21,15 @@ function preset(context, options = {}) {
|
|
|
21
21
|
if (googleTagManager !== void 0) classicOptions.googleTagManager = googleTagManager;
|
|
22
22
|
if (sitemap !== void 0) classicOptions.sitemap = sitemap;
|
|
23
23
|
if (debug !== void 0) classicOptions.debug = debug;
|
|
24
|
-
const {
|
|
25
|
-
|
|
24
|
+
const {
|
|
25
|
+
glossaryPath = "glossary/glossary.json",
|
|
26
|
+
routePath = "/glossary",
|
|
27
|
+
expandAcronymsOnFirstUse = false
|
|
28
|
+
} = glossary;
|
|
29
|
+
const remarkPlugin = getRemarkPlugin(
|
|
30
|
+
{ glossaryPath, routePath, expandAcronymsOnFirstUse },
|
|
31
|
+
{ siteDir: context.siteDir }
|
|
32
|
+
);
|
|
26
33
|
const docsConfig = classicOptions.docs || {};
|
|
27
34
|
const docsRemarkPlugins = docsConfig.remarkPlugins || [];
|
|
28
35
|
const extendedDocsConfig = {
|
package/dist/preset.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/preset.ts"],"sourcesContent":["import type { Preset, LoadContext } from '@docusaurus/types';\nimport glossaryPlugin, { getRemarkPlugin } from './index.js';\nimport type { GlossaryPluginOptions } from './index.js';\n\n/**\n * Configuration for @docusaurus/plugin-content-docs\n * Using Record<string, unknown> to allow any valid docs options without coupling to specific version\n */\ntype DocsConfig = Record<string, unknown> & {\n remarkPlugins?: unknown[];\n};\n\n/**\n * Configuration for @docusaurus/plugin-content-blog\n * Can be false to disable, or configuration object\n */\ntype BlogConfig =\n | false\n | (Record<string, unknown> & {\n remarkPlugins?: unknown[];\n });\n\n/**\n * Configuration for @docusaurus/plugin-content-pages\n */\ntype PagesConfig = Record<string, unknown> & {\n remarkPlugins?: unknown[];\n};\n\n/**\n * Configuration for @docusaurus/theme-classic\n */\ntype ThemeConfig = Record<string, unknown>;\n\n/**\n * Configuration for analytics plugins\n */\ntype AnalyticsConfig = Record<string, unknown>;\n\n/**\n * Configuration for @docusaurus/plugin-sitemap\n * Can be false to disable, or configuration object\n */\ntype SitemapConfig = false | Record<string, unknown>;\n\n/**\n * Classic preset options (simplified to avoid direct dependency on @docusaurus/preset-classic)\n * These mirror the options available in the classic preset\n */\nexport interface ClassicPresetOptions {\n docs?: DocsConfig;\n blog?: BlogConfig;\n pages?: PagesConfig;\n theme?: ThemeConfig;\n gtag?: AnalyticsConfig;\n googleAnalytics?: AnalyticsConfig;\n googleTagManager?: AnalyticsConfig;\n sitemap?: SitemapConfig;\n debug?: boolean;\n}\n\nexport interface GlossaryPresetOptions extends ClassicPresetOptions {\n glossary?: GlossaryPluginOptions;\n /** Internal: Docusaurus adds this, we need to exclude it from classic options */\n id?: string;\n}\n\n/**\n * Docusaurus Glossary Preset\n *\n * A preset that extends @docusaurus/preset-classic with automatic glossary functionality.\n * This preset automatically configures the remark plugin for docs and pages, so you don't\n * need to manually add it to remarkPlugins.\n *\n * @example\n * ```javascript\n * export default {\n * presets: [\n * [\n * 'docusaurus-plugin-glossary/preset',\n * {\n * // Glossary options\n * glossary: {\n * glossaryPath: 'glossary/glossary.json',\n * routePath: '/glossary',\n * },\n * // Classic preset options\n * docs: {\n * sidebarPath: './sidebars.js',\n * },\n * blog: {\n * showReadingTime: true,\n * },\n * theme: {\n * customCss: './src/css/custom.css',\n * },\n * },\n * ],\n * ],\n * };\n * ```\n *\n * @param context - Docusaurus context\n * @param options - Preset options including glossary and classic preset options\n * @returns Preset configuration\n */\nexport default function preset(context: LoadContext, options: GlossaryPresetOptions = {}): Preset {\n // Explicitly extract glossary and any Docusaurus-added properties that shouldn't go to classic preset\n const { glossary = {}, id: _id, ...restOptions } = options;\n\n // Extract only valid classic preset options\n // Explicitly type blog and sitemap to preserve union types (can be false)\n const { docs, pages, theme, gtag, googleAnalytics, googleTagManager, debug } = restOptions;\n const blog: BlogConfig | undefined = restOptions.blog;\n const sitemap: SitemapConfig | undefined = restOptions.sitemap;\n\n // Build classic options object with only defined properties\n const classicOptions: ClassicPresetOptions = {};\n if (docs !== undefined) classicOptions.docs = docs;\n if (blog !== undefined) classicOptions.blog = blog;\n if (pages !== undefined) classicOptions.pages = pages;\n if (theme !== undefined) classicOptions.theme = theme;\n if (gtag !== undefined) classicOptions.gtag = gtag;\n if (googleAnalytics !== undefined) classicOptions.googleAnalytics = googleAnalytics;\n if (googleTagManager !== undefined) classicOptions.googleTagManager = googleTagManager;\n if (sitemap !== undefined) classicOptions.sitemap = sitemap;\n if (debug !== undefined) classicOptions.debug = debug;\n\n const { glossaryPath = 'glossary/glossary.json', routePath = '/glossary' } = glossary;\n\n // Get the remark plugin configuration\n const remarkPlugin = getRemarkPlugin({ glossaryPath, routePath }, { siteDir: context.siteDir });\n\n // Extend docs configuration with glossary remark plugin\n const docsConfig = classicOptions.docs || {};\n const docsRemarkPlugins = docsConfig.remarkPlugins || [];\n const extendedDocsConfig = {\n ...docsConfig,\n remarkPlugins: [...docsRemarkPlugins, remarkPlugin],\n };\n\n // Extend pages configuration with glossary remark plugin\n const pagesConfig = classicOptions.pages || {};\n const pagesRemarkPlugins = pagesConfig.remarkPlugins || [];\n const extendedPagesConfig = {\n ...pagesConfig,\n remarkPlugins: [...pagesRemarkPlugins, remarkPlugin],\n };\n\n // Extend blog configuration with glossary remark plugin (optional)\n // Use typeof check for proper type narrowing (blog can be false, object, or undefined)\n let extendedBlogConfig: BlogConfig | undefined = blog;\n if (typeof blog === 'object' && blog !== null) {\n const blogRemarkPlugins = blog.remarkPlugins || [];\n extendedBlogConfig = {\n ...blog,\n remarkPlugins: [...blogRemarkPlugins, remarkPlugin],\n };\n }\n\n // Build the final classic preset options\n const finalClassicOptions: ClassicPresetOptions = {};\n if (extendedDocsConfig !== undefined) finalClassicOptions.docs = extendedDocsConfig;\n if (extendedBlogConfig !== undefined) finalClassicOptions.blog = extendedBlogConfig;\n if (extendedPagesConfig !== undefined) finalClassicOptions.pages = extendedPagesConfig;\n if (theme !== undefined) finalClassicOptions.theme = theme;\n if (gtag !== undefined) finalClassicOptions.gtag = gtag;\n if (googleAnalytics !== undefined) finalClassicOptions.googleAnalytics = googleAnalytics;\n if (googleTagManager !== undefined) finalClassicOptions.googleTagManager = googleTagManager;\n if (sitemap !== undefined) finalClassicOptions.sitemap = sitemap;\n if (debug !== undefined) finalClassicOptions.debug = debug;\n\n // Plugin tuple type: [plugin-name, options] or plugin function\n type PluginEntry =\n | [string, Record<string, unknown>]\n | ((ctx: LoadContext) => ReturnType<typeof glossaryPlugin>);\n\n const plugins: PluginEntry[] = [\n // Add the glossary plugin first\n function glossaryPluginWrapper(ctx: LoadContext) {\n return glossaryPlugin(ctx, glossary);\n },\n ];\n\n // Add classic preset plugins individually\n if (extendedDocsConfig) plugins.push(['@docusaurus/plugin-content-docs', extendedDocsConfig]);\n if (typeof extendedBlogConfig === 'object' && extendedBlogConfig !== null)\n plugins.push(['@docusaurus/plugin-content-blog', extendedBlogConfig]);\n if (extendedPagesConfig) plugins.push(['@docusaurus/plugin-content-pages', extendedPagesConfig]);\n if (gtag) plugins.push(['@docusaurus/plugin-google-gtag', gtag]);\n if (googleAnalytics) plugins.push(['@docusaurus/plugin-google-analytics', googleAnalytics]);\n if (googleTagManager) plugins.push(['@docusaurus/plugin-google-tag-manager', googleTagManager]);\n if (sitemap !== false) plugins.push(['@docusaurus/plugin-sitemap', sitemap || {}]);\n if (debug) plugins.push(['@docusaurus/plugin-debug', {}]);\n\n return {\n themes: [\n // Pass theme options (including customCss) to theme-classic\n ['@docusaurus/theme-classic', theme || {}],\n ],\n plugins,\n };\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/preset.ts"],"sourcesContent":["import type { Preset, LoadContext } from '@docusaurus/types';\nimport glossaryPlugin, { getRemarkPlugin } from './index.js';\nimport type { GlossaryPluginOptions } from './index.js';\n\n/**\n * Configuration for @docusaurus/plugin-content-docs\n * Using Record<string, unknown> to allow any valid docs options without coupling to specific version\n */\ntype DocsConfig = Record<string, unknown> & {\n remarkPlugins?: unknown[];\n};\n\n/**\n * Configuration for @docusaurus/plugin-content-blog\n * Can be false to disable, or configuration object\n */\ntype BlogConfig =\n | false\n | (Record<string, unknown> & {\n remarkPlugins?: unknown[];\n });\n\n/**\n * Configuration for @docusaurus/plugin-content-pages\n */\ntype PagesConfig = Record<string, unknown> & {\n remarkPlugins?: unknown[];\n};\n\n/**\n * Configuration for @docusaurus/theme-classic\n */\ntype ThemeConfig = Record<string, unknown>;\n\n/**\n * Configuration for analytics plugins\n */\ntype AnalyticsConfig = Record<string, unknown>;\n\n/**\n * Configuration for @docusaurus/plugin-sitemap\n * Can be false to disable, or configuration object\n */\ntype SitemapConfig = false | Record<string, unknown>;\n\n/**\n * Classic preset options (simplified to avoid direct dependency on @docusaurus/preset-classic)\n * These mirror the options available in the classic preset\n */\nexport interface ClassicPresetOptions {\n docs?: DocsConfig;\n blog?: BlogConfig;\n pages?: PagesConfig;\n theme?: ThemeConfig;\n gtag?: AnalyticsConfig;\n googleAnalytics?: AnalyticsConfig;\n googleTagManager?: AnalyticsConfig;\n sitemap?: SitemapConfig;\n debug?: boolean;\n}\n\nexport interface GlossaryPresetOptions extends ClassicPresetOptions {\n glossary?: GlossaryPluginOptions;\n /** Internal: Docusaurus adds this, we need to exclude it from classic options */\n id?: string;\n}\n\n/**\n * Docusaurus Glossary Preset\n *\n * A preset that extends @docusaurus/preset-classic with automatic glossary functionality.\n * This preset automatically configures the remark plugin for docs and pages, so you don't\n * need to manually add it to remarkPlugins.\n *\n * @example\n * ```javascript\n * export default {\n * presets: [\n * [\n * 'docusaurus-plugin-glossary/preset',\n * {\n * // Glossary options\n * glossary: {\n * glossaryPath: 'glossary/glossary.json',\n * routePath: '/glossary',\n * },\n * // Classic preset options\n * docs: {\n * sidebarPath: './sidebars.js',\n * },\n * blog: {\n * showReadingTime: true,\n * },\n * theme: {\n * customCss: './src/css/custom.css',\n * },\n * },\n * ],\n * ],\n * };\n * ```\n *\n * @param context - Docusaurus context\n * @param options - Preset options including glossary and classic preset options\n * @returns Preset configuration\n */\nexport default function preset(context: LoadContext, options: GlossaryPresetOptions = {}): Preset {\n // Explicitly extract glossary and any Docusaurus-added properties that shouldn't go to classic preset\n const { glossary = {}, id: _id, ...restOptions } = options;\n\n // Extract only valid classic preset options\n // Explicitly type blog and sitemap to preserve union types (can be false)\n const { docs, pages, theme, gtag, googleAnalytics, googleTagManager, debug } = restOptions;\n const blog: BlogConfig | undefined = restOptions.blog;\n const sitemap: SitemapConfig | undefined = restOptions.sitemap;\n\n // Build classic options object with only defined properties\n const classicOptions: ClassicPresetOptions = {};\n if (docs !== undefined) classicOptions.docs = docs;\n if (blog !== undefined) classicOptions.blog = blog;\n if (pages !== undefined) classicOptions.pages = pages;\n if (theme !== undefined) classicOptions.theme = theme;\n if (gtag !== undefined) classicOptions.gtag = gtag;\n if (googleAnalytics !== undefined) classicOptions.googleAnalytics = googleAnalytics;\n if (googleTagManager !== undefined) classicOptions.googleTagManager = googleTagManager;\n if (sitemap !== undefined) classicOptions.sitemap = sitemap;\n if (debug !== undefined) classicOptions.debug = debug;\n\n const {\n glossaryPath = 'glossary/glossary.json',\n routePath = '/glossary',\n expandAcronymsOnFirstUse = false,\n } = glossary;\n\n // Get the remark plugin configuration\n const remarkPlugin = getRemarkPlugin(\n { glossaryPath, routePath, expandAcronymsOnFirstUse },\n { siteDir: context.siteDir }\n );\n\n // Extend docs configuration with glossary remark plugin\n const docsConfig = classicOptions.docs || {};\n const docsRemarkPlugins = docsConfig.remarkPlugins || [];\n const extendedDocsConfig = {\n ...docsConfig,\n remarkPlugins: [...docsRemarkPlugins, remarkPlugin],\n };\n\n // Extend pages configuration with glossary remark plugin\n const pagesConfig = classicOptions.pages || {};\n const pagesRemarkPlugins = pagesConfig.remarkPlugins || [];\n const extendedPagesConfig = {\n ...pagesConfig,\n remarkPlugins: [...pagesRemarkPlugins, remarkPlugin],\n };\n\n // Extend blog configuration with glossary remark plugin (optional)\n // Use typeof check for proper type narrowing (blog can be false, object, or undefined)\n let extendedBlogConfig: BlogConfig | undefined = blog;\n if (typeof blog === 'object' && blog !== null) {\n const blogRemarkPlugins = blog.remarkPlugins || [];\n extendedBlogConfig = {\n ...blog,\n remarkPlugins: [...blogRemarkPlugins, remarkPlugin],\n };\n }\n\n // Build the final classic preset options\n const finalClassicOptions: ClassicPresetOptions = {};\n if (extendedDocsConfig !== undefined) finalClassicOptions.docs = extendedDocsConfig;\n if (extendedBlogConfig !== undefined) finalClassicOptions.blog = extendedBlogConfig;\n if (extendedPagesConfig !== undefined) finalClassicOptions.pages = extendedPagesConfig;\n if (theme !== undefined) finalClassicOptions.theme = theme;\n if (gtag !== undefined) finalClassicOptions.gtag = gtag;\n if (googleAnalytics !== undefined) finalClassicOptions.googleAnalytics = googleAnalytics;\n if (googleTagManager !== undefined) finalClassicOptions.googleTagManager = googleTagManager;\n if (sitemap !== undefined) finalClassicOptions.sitemap = sitemap;\n if (debug !== undefined) finalClassicOptions.debug = debug;\n\n // Plugin tuple type: [plugin-name, options] or plugin function\n type PluginEntry =\n | [string, Record<string, unknown>]\n | ((ctx: LoadContext) => ReturnType<typeof glossaryPlugin>);\n\n const plugins: PluginEntry[] = [\n // Add the glossary plugin first\n function glossaryPluginWrapper(ctx: LoadContext) {\n return glossaryPlugin(ctx, glossary);\n },\n ];\n\n // Add classic preset plugins individually\n if (extendedDocsConfig) plugins.push(['@docusaurus/plugin-content-docs', extendedDocsConfig]);\n if (typeof extendedBlogConfig === 'object' && extendedBlogConfig !== null)\n plugins.push(['@docusaurus/plugin-content-blog', extendedBlogConfig]);\n if (extendedPagesConfig) plugins.push(['@docusaurus/plugin-content-pages', extendedPagesConfig]);\n if (gtag) plugins.push(['@docusaurus/plugin-google-gtag', gtag]);\n if (googleAnalytics) plugins.push(['@docusaurus/plugin-google-analytics', googleAnalytics]);\n if (googleTagManager) plugins.push(['@docusaurus/plugin-google-tag-manager', googleTagManager]);\n if (sitemap !== false) plugins.push(['@docusaurus/plugin-sitemap', sitemap || {}]);\n if (debug) plugins.push(['@docusaurus/plugin-debug', {}]);\n\n return {\n themes: [\n // Pass theme options (including customCss) to theme-classic\n ['@docusaurus/theme-classic', theme || {}],\n ],\n plugins,\n };\n}\n"],"mappings":"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","names":[]}
|
|
@@ -79,7 +79,8 @@ function remarkGlossaryTerms({
|
|
|
79
79
|
terms = [],
|
|
80
80
|
glossaryPath = null,
|
|
81
81
|
routePath = "/glossary",
|
|
82
|
-
siteDir = null
|
|
82
|
+
siteDir = null,
|
|
83
|
+
expandAcronymsOnFirstUse = false
|
|
83
84
|
} = {}) {
|
|
84
85
|
let glossaryTerms = terms;
|
|
85
86
|
if (!glossaryTerms.length && glossaryPath && siteDir) {
|
|
@@ -168,7 +169,7 @@ function remarkGlossaryTerms({
|
|
|
168
169
|
if (sortedTerms.length === 0) {
|
|
169
170
|
return (tree) => tree;
|
|
170
171
|
}
|
|
171
|
-
function replaceTermsInText(text) {
|
|
172
|
+
function replaceTermsInText(text, seenTerms) {
|
|
172
173
|
if (!text || !sortedTerms.length) {
|
|
173
174
|
return [{ type: "text", value: text }];
|
|
174
175
|
}
|
|
@@ -230,6 +231,8 @@ function remarkGlossaryTerms({
|
|
|
230
231
|
value: text.substring(lastIndex, match.index)
|
|
231
232
|
});
|
|
232
233
|
}
|
|
234
|
+
const displayText = resolveDisplayText(match, text, seenTerms);
|
|
235
|
+
seenTerms.add(match.termObj.term);
|
|
233
236
|
result.push({
|
|
234
237
|
type: "mdxJsxFlowElement",
|
|
235
238
|
name: "GlossaryTerm",
|
|
@@ -253,7 +256,7 @@ function remarkGlossaryTerms({
|
|
|
253
256
|
children: [
|
|
254
257
|
{
|
|
255
258
|
type: "text",
|
|
256
|
-
value:
|
|
259
|
+
value: displayText
|
|
257
260
|
}
|
|
258
261
|
]
|
|
259
262
|
});
|
|
@@ -267,6 +270,20 @@ function remarkGlossaryTerms({
|
|
|
267
270
|
}
|
|
268
271
|
return result.length > 0 ? result : [{ type: "text", value: text }];
|
|
269
272
|
}
|
|
273
|
+
function resolveDisplayText(match, text, seenTerms) {
|
|
274
|
+
const termObj = match.termObj;
|
|
275
|
+
if (!expandAcronymsOnFirstUse) return match.originalText;
|
|
276
|
+
if (!termObj.abbreviation) return match.originalText;
|
|
277
|
+
if (seenTerms.has(termObj.term)) return match.originalText;
|
|
278
|
+
const isCanonical = match.length === termObj.term.length && match.originalText.toLowerCase() === termObj.term.toLowerCase();
|
|
279
|
+
if (!isCanonical) return match.originalText;
|
|
280
|
+
const longForm = termObj.abbreviation;
|
|
281
|
+
const lookbackWindow = longForm.length + 10;
|
|
282
|
+
const lookbackStart = Math.max(0, match.index - lookbackWindow);
|
|
283
|
+
const lookback = text.substring(lookbackStart, match.index).toLowerCase();
|
|
284
|
+
if (lookback.includes(longForm.toLowerCase())) return match.originalText;
|
|
285
|
+
return `${longForm} (${match.originalText})`;
|
|
286
|
+
}
|
|
270
287
|
function collectHeadingTextNodes(tree) {
|
|
271
288
|
const skip = /* @__PURE__ */ new WeakSet();
|
|
272
289
|
(0, import_unist_util_visit.visit)(tree, "heading", (headingNode) => {
|
|
@@ -279,6 +296,7 @@ function remarkGlossaryTerms({
|
|
|
279
296
|
const transformer = (tree) => {
|
|
280
297
|
let usedGlossaryTerm = false;
|
|
281
298
|
const textNodesInHeadings = collectHeadingTextNodes(tree);
|
|
299
|
+
const seenTerms = /* @__PURE__ */ new Set();
|
|
282
300
|
(0, import_unist_util_visit.visit)(tree, "text", (node, index, parent) => {
|
|
283
301
|
if (parent.type === "code" || parent.type === "inlineCode" || parent.type === "link" || parent.type === "mdxJsxFlowElement" || parent.type === "mdxJsxTextElement") {
|
|
284
302
|
return;
|
|
@@ -286,7 +304,7 @@ function remarkGlossaryTerms({
|
|
|
286
304
|
if (textNodesInHeadings.has(node)) {
|
|
287
305
|
return;
|
|
288
306
|
}
|
|
289
|
-
const replacements = replaceTermsInText(node.value);
|
|
307
|
+
const replacements = replaceTermsInText(node.value, seenTerms);
|
|
290
308
|
if (replacements.length > 1 || replacements.length === 1 && replacements[0].type !== "text") {
|
|
291
309
|
const newNodes = replacements.map((replacement) => {
|
|
292
310
|
if (replacement.type === "mdxJsxFlowElement") {
|