{"id":47628560,"url":"https://github.com/grnet/rspress-plugin-terminology","last_synced_at":"2026-04-01T23:03:24.203Z","repository":{"id":346621678,"uuid":"1179621102","full_name":"grnet/rspress-plugin-terminology","owner":"grnet","description":null,"archived":false,"fork":false,"pushed_at":"2026-03-24T17:07:02.000Z","size":215,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-25T21:56:11.147Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/grnet.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-12T07:56:49.000Z","updated_at":"2026-03-24T17:04:09.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/grnet/rspress-plugin-terminology","commit_stats":null,"previous_names":["grnet/rspress-plugin-terminology"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/grnet/rspress-plugin-terminology","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/grnet%2Frspress-plugin-terminology","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/grnet%2Frspress-plugin-terminology/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/grnet%2Frspress-plugin-terminology/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/grnet%2Frspress-plugin-terminology/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/grnet","download_url":"https://codeload.github.com/grnet/rspress-plugin-terminology/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/grnet%2Frspress-plugin-terminology/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31292789,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-01T21:15:39.731Z","status":"ssl_error","status_checked_at":"2026-04-01T21:15:34.046Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-04-01T23:03:06.438Z","updated_at":"2026-04-01T23:03:24.191Z","avatar_url":"https://github.com/grnet.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# rspress-terminology\n\n\u003e A plugin for Rspress that enables terminology management with hover tooltips and auto-generated glossaries.\n\nThis plugin is a port of [@grnet/docusaurus-terminology](https://github.com/grnet/docusaurus-terminology) for the Rspress static site generator.\n\n## Features\n\n- 🔤 **Term Definitions** - Define terms in markdown files with frontmatter\n- 🎯 **Hover Tooltips** - Display term definitions when hovering over links\n- 📚 **Auto-Generated Glossary** - Automatically create a glossary page with all terms\n- 🔗 **Link Transformation** - Automatically transform markdown links to interactive components\n- 🎨 **Customizable Components** - Use built-in components or provide your own\n- ⚡ **Fast \u0026 Efficient** - Pre-loads data during build, minimal runtime overhead\n- 🐛 **Debug Logging** - Built-in debug utility with namespace-based logging for troubleshooting\n- 🛡️ **Security** - Built-in XSS protection using DOMPurify sanitization\n\n## Installation\n\n```bash\nnpm install rspress-terminology --save\n# or\nyarn add rspress-terminology\n# or\npnpm add rspress-terminology\n```\n\n## Quick Start\n\n### Try the Example First!\n\nThe easiest way to see the plugin in action is to run the included example:\n\n```bash\ncd rspress-terminology\n\n# Build the plugin\nnpm run build\n\n# Install example dependencies\ncd example\nnpm install\n\n# Start the dev server\nnpm run dev\n```\n\nThen open `http://localhost:3000` and:\n- Hover over linked terms to see tooltips\n- Visit the Glossary page\n- Explore the source code in `docs/terms/`\n\n### Using in Your Project\n\n### 1. Configure the Plugin\n\nAdd the plugin to your `rspress.config.ts`:\n\n```typescript\nimport { defineConfig } from '@rspress/core';\nimport { terminologyPlugin } from 'rspress-terminology';\n\nexport default defineConfig({\n  // ... other config\n  plugins: [\n    terminologyPlugin({\n      termsDir: './docs/terms',           // Directory containing term definitions\n      docsDir: './docs/',                  // Root documentation directory\n      glossaryFilepath: './docs/glossary.md'  // Path to glossary page\n    })\n  ]\n});\n```\n\n### 2. Create Term Definitions\n\nCreate markdown files in your `docs/terms/` directory:\n\n```markdown\n---\nid: api-key\ntitle: API Key\nhoverText: A unique identifier used to authenticate a user or application.\n---\n\nAn API key is a secret token that identifies the calling application or user. API keys are used to track and control how the API is being used, prevent malicious use, and calculate usage fees.\n```\n\n### 3. Create Glossary Page\n\nCreate `docs/glossary.md`:\n\n```markdown\n---\ntitle: Glossary\n---\n\n# Glossary\n\nWelcome to the glossary. All terms from the documentation are listed below.\n\n```\n\nThe plugin will automatically inject the `\u003cGlossary /\u003e` component into this file.\n\n### 4. Use Terms in Your Documentation\n\nReference terms using standard markdown link syntax:\n\n```markdown\nTo use the API, you need an [API Key](./terms/api-key).\n```\n\nThis will automatically be transformed into an interactive link with a hover tooltip.\n\n## Configuration\n\n### Options\n\n| Option | Type | Required | Description |\n|--------|------|----------|-------------|\n| `termsDir` | `string` | Yes | Directory containing term definition files (e.g., `'./docs/terms'`) |\n| `docsDir` | `string` | Yes | Root documentation directory (e.g., `'./docs/'`) |\n| `glossaryFilepath` | `string` | Yes | Path to glossary markdown file (e.g., `'./docs/glossary.md'`) |\n| `basePath` | `string` | No | Base path for the site (e.g., `'/my-site'`). Useful when hosting in a subdirectory. |\n| `termPreviewComponentPath` | `string` | No | Custom path to Term preview component |\n| `glossaryComponentPath` | `string` | No | Custom path to Glossary view component |\n| `debug` | `boolean \\| object` | No | Enable debug logging. See [Debug Configuration](#debug-configuration) below. |\n\n### Example with Custom Components\n\n```typescript\nterminologyPlugin({\n  termsDir: './docs/terms',\n  docsDir: './docs/',\n  glossaryFilepath: './docs/glossary.md',\n  termPreviewComponentPath: './components/CustomTerm.tsx',\n  glossaryComponentPath: './components/CustomGlossary.tsx'\n})\n```\n\n### Example with Base Path\n\nIf your site is hosted in a subdirectory (e.g., `https://example.com/docs/`), use `basePath`:\n\n```typescript\nterminologyPlugin({\n  termsDir: './docs/terms',\n  docsDir: './docs/',\n  glossaryFilepath: './docs/glossary.md',\n  basePath: '/docs'  // Links will be /docs/terms/term instead of /terms/term\n})\n```\n\n### Debug Configuration\n\nThe plugin includes a built-in debug logging utility to help troubleshoot issues.\n\n#### Enable All Debug Logs\n\n```typescript\nterminologyPlugin({\n  termsDir: './docs/terms',\n  docsDir: './docs/',\n  glossaryFilepath: './docs/glossary.md',\n  debug: true  // Enable all debug logs\n})\n```\n\n#### Advanced Debug Configuration\n\n```typescript\nterminologyPlugin({\n  termsDir: './docs/terms',\n  docsDir: './docs/',\n  glossaryFilepath: './docs/glossary.md',\n  debug: {\n    enabled: true,\n    timestamps: true,  // Include timestamps in logs\n    namespaces: [      // Only log specific namespaces\n      'build:*',       // All build operations\n      'plugin:load'    // Plugin loading\n    ]\n  }\n})\n```\n\n#### Using Environment Variables\n\nYou can also control debug logging via environment variable:\n\n```bash\n# Enable all debug logs\nRSPRESS_TERMINOLOGY_DEBUG=1 npm run build\n\n# Enable specific namespaces\nRSPRESS_TERMINOLOGY_DEBUG=build:* npm run build\n\n# Enable multiple namespaces (comma-separated)\nRSPRESS_TERMINOLOGY_DEBUG=plugin:load,build:index npm run build\n```\n\n#### Available Namespaces\n\n- **`plugin`** - Main plugin lifecycle events\n  - `plugin:load` - Loading glossary JSON\n  - `plugin:build` - Build phase events\n  - `plugin:page` - Page data extension\n  - `plugin:inject` - HTML injection events\n- **`build`** - Build-time operations\n  - `build:index` - Term indexing operations\n  - `build:glossary` - Glossary JSON generation\n  - `build:inject` - Component injection\n  - `build:copy` - File copying operations\n\nFor more examples and detailed usage, see [DEBUG_EXAMPLES.md](DEBUG_EXAMPLES.md).\n\n## Term Definition Format\n\nEach term file should include:\n\n```markdown\n---\nid: unique-term-id        # Required: Unique identifier\ntitle: Term Title          # Required: Display title\nhoverText: Short definition shown on hover  # Optional: Hover text\n---\n\nFull term explanation and details here...\n```\n\n### Frontmatter Fields\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n| `id` | `string` | Yes | Unique identifier for the term |\n| `title` | `string` | Yes | Display title of the term |\n| `hoverText` | `string` | No | Short description shown on hover (supports markdown) |\n\n## Custom Components\n\n### Custom Term Component\n\nCreate a custom term preview component:\n\n```typescript\n// components/CustomTerm.tsx\nimport React from 'react';\nimport type { TermMetadata } from 'rspress-terminology';\n\ninterface CustomTermProps {\n  pathName: string;\n  children?: React.ReactNode;\n}\n\nexport default function CustomTerm({ pathName, children }: CustomTermProps) {\n  const [term, setTerm] = React.useState\u003cTermMetadata | null\u003e(null);\n\n  React.useEffect(() =\u003e {\n    fetch(`${pathName}.json`)\n      .then(res =\u003e res.json())\n      .then(setTerm);\n  }, [pathName]);\n\n  return (\n    \u003cspan className=\"custom-term\"\u003e\n      \u003ca href={pathName}\u003e{children || term?.title}\u003c/a\u003e\n      {/* Custom tooltip implementation */}\n    \u003c/span\u003e\n  );\n}\n```\n\n### Custom Glossary Component\n\n```typescript\n// components/CustomGlossary.tsx\nimport React from 'react';\nimport type { TermMetadata } from 'rspress-terminology';\n\nexport default function CustomGlossary() {\n  const [terms, setTerms] = React.useState\u003cRecord\u003cstring, TermMetadata\u003e\u003e({});\n\n  React.useEffect(() =\u003e {\n    fetch('/docs/glossary.json')\n      .then(res =\u003e res.json())\n      .then(setTerms);\n  }, []);\n\n  return (\n    \u003cdiv className=\"custom-glossary\"\u003e\n      \u003ch1\u003eGlossary\u003c/h1\u003e\n      {Object.entries(terms).map(([path, term]) =\u003e (\n        \u003cdiv key={path}\u003e\n          \u003ca href={path}\u003e{term.title}\u003c/a\u003e\n        \u003c/div\u003e\n      ))}\n    \u003c/div\u003e\n  );\n}\n```\n\n## Styling\n\nThe plugin includes default styles. To customize, override these CSS classes:\n\n### Term Link Classes\n\n- `.term-link` - Base term link style\n- `.term-link:hover` - Hover state\n- `.term-link-loading` - Loading state\n- `.term-link-error` - Error state\n\n### Tooltip Classes\n\n- `.rspress-terminology-tooltip` - Tooltip container\n- `.term-tooltip-content` - Tooltip content wrapper\n- `.term-title` - Term title in tooltip\n- `.term-hover-text` - Hover text content\n\n### Glossary Classes\n\n- `.glossary-container` - Glossary wrapper\n- `.glossary-item` - Individual glossary entry\n- `.glossary-term` - Term title\n- `.glossary-definition` - Term definition\n\n### Custom Styles\n\nAdd custom styles in your Rspress theme:\n\n```css\n/* src/styles/custom.css */\n.term-link {\n  text-decoration-style: dotted;\n  color: #3b82f6;\n}\n\n.rspress-terminology-tooltip {\n  max-width: 400px;\n  padding: 16px;\n}\n```\n\n## How It Works\n\n### Build Process\n\n1. **beforeBuild Hook**\n   - Scans `termsDir` for markdown files\n   - Parses frontmatter from each term file\n   - Builds term index\n   - Generates `glossary.json`\n   - Creates individual `.json` files for each term\n\n2. **extendPageData Hook**\n   - Attaches term index to page data\n   - Makes terms available via `usePageData()`\n\n3. **Remark Plugin**\n   - Transforms `[term](path/to/term.md)` links\n   - Converts to `\u003cTerm pathName=\"...\"\u003etext\u003c/Term\u003e` components\n   - Uses AST transformation for reliability\n\n### Runtime\n\n- **Term Component** - Fetches term data from JSON or uses pre-loaded data\n- **Glossary Component** - Displays all terms in a sorted list\n- **Tooltip** - Shows hover text using `rc-tooltip`\n\n## Migration from Docusaurus\n\nIf you're migrating from `@grnet/docusaurus-terminology`:\n\n### Configuration Changes\n\n**Docusaurus:**\n```javascript\nmodule.exports = {\n  plugins: [\n    ['@grnet/docusaurus-terminology', {\n      termsDir: './docs/terms',\n      docsDir: './docs/',\n      glossaryFilepath: './docs/glossary.md'\n    }]\n  ]\n};\n```\n\n**Rspress:**\n```typescript\nimport { terminologyPlugin } from 'rspress-terminology';\n\nexport default defineConfig({\n  plugins: [\n    terminologyPlugin({\n      termsDir: './docs/terms',\n      docsDir: './docs/',\n      glossaryFilepath: './docs/glossary.md'\n    })\n  ]\n});\n```\n\n### Component Changes\n\n- `@docusaurus/BrowserOnly` → No longer needed (client-side fetching handled internally)\n- `@docusaurus/useBaseUrl` → `usePageData()` from `rspress/runtime`\n- `@docusaurus/Link` → Standard `\u003ca\u003e` tags (Rspress handles routing)\n\n## Development\n\n### Building\n\n```bash\nnpm run build\n```\n\n### Watch Mode\n\n```bash\nnpm run dev\n```\n\n### Testing\n\nThe project includes comprehensive security tests to verify XSS prevention:\n\n```bash\n# Run tests\nnpm test\n\n# Run tests in watch mode\nnpm run test:watch\n\n# Run tests with coverage\nnpm run test:coverage\n```\n\nSee [SECURITY.md](SECURITY.md) for detailed security information.\n\n### Testing Locally\n\n```bash\n# Link your local version\nnpm link\n\n# In your rspress project\nnpm link rspress-terminology\n```\n\n## Troubleshooting\n\n### Terms Not Showing\n\n1. Check that term files are in the correct directory (`termsDir`)\n2. Verify each term has required frontmatter (`id`, `title`)\n3. Check browser console for fetch errors\n4. Ensure `glossary.json` is generated in your output\n\n### Tooltips Not Appearing\n\n1. Check that `mdxRs: false` is set (required for remark plugins)\n2. Verify links use correct relative paths\n3. Check browser console for JavaScript errors\n\n### Glossary Empty\n\n1. Ensure `glossary.md` exists at specified path\n2. Check that `\u003cGlossary /\u003e` component is injected\n3. Verify `glossary.json` is generated during build\n\n## License\n\nBSD-2-Clause\n\n## Credits\n\nPorted from [@grnet/docusaurus-terminology](https://github.com/grnet/docusaurus-terminology)\n\nOriginal implementation for Docusaurus by GRNET Developers.\n\n## Contributing\n\nContributions are welcome! Please feel free to submit issues or pull requests.\n\n---\n\n**Note:** This is the Rspress version of the terminology plugin. For Docusaurus, see [@grnet/docusaurus-terminology](https://github.com/grnet/docusaurus-terminology).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgrnet%2Frspress-plugin-terminology","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgrnet%2Frspress-plugin-terminology","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgrnet%2Frspress-plugin-terminology/lists"}