diff --git a/docs/site/src/shared/components/ThemeToggle/index.tsx b/docs/site/src/shared/components/ThemeToggle/index.tsx index 51f9d90437..847f60e509 100644 --- a/docs/site/src/shared/components/ThemeToggle/index.tsx +++ b/docs/site/src/shared/components/ThemeToggle/index.tsx @@ -1,7 +1,6 @@ // Copyright (c) Walrus Foundation // SPDX-License-Identifier: Apache-2.0 - import React from "react"; import NavbarColorModeToggle from "@theme/Navbar/ColorModeToggle"; import { useLocation } from "@docusaurus/router"; @@ -9,7 +8,7 @@ import { useLocation } from "@docusaurus/router"; export default function ThemeToggle() { const location = useLocation(); return ( -
+
{location.pathname !== "/" && }
); diff --git a/docs/site/src/shared/plugins/remark-glossary.js b/docs/site/src/shared/plugins/remark-glossary.js index 029e84ad0a..e2ce4a0f4e 100644 --- a/docs/site/src/shared/plugins/remark-glossary.js +++ b/docs/site/src/shared/plugins/remark-glossary.js @@ -4,12 +4,11 @@ // plugins/remark-glossary.js // Auto-wraps glossary terms with in MDX content. // -// Requires: `js-yaml`, `unist-util-visit` +// Requires: `unist-util-visit` // pnpm add -D js-yaml unist-util-visit import fs from "fs"; import path from "path"; -import * as yaml from "js-yaml"; import { visit } from "unist-util-visit"; function escapeRegex(s) { @@ -17,7 +16,7 @@ function escapeRegex(s) { } function buildMatcher(entries) { - // Build alternation, longest-first to prefer “JSON API” over “API” + // Build alternation, longest-first to prefer "JSON API" over "API" const terms = entries.flatMap((e) => [e.label, ...(e.aliases || [])]).filter(Boolean); // De-duplicate (case-insensitive) @@ -33,7 +32,7 @@ function buildMatcher(entries) { unique.sort((a, b) => b.length - a.length); - // \b isn’t great for Unicode; use custom boundaries: start|non-word on left/right + // \b isn't great for Unicode; use custom boundaries: start|non-word on left/right // Also allow inside parentheses/quotes by treating those as boundaries too. const pattern = unique.map(escapeRegex).join("|"); // If no entries, make a regex that never matches @@ -41,13 +40,13 @@ function buildMatcher(entries) { // Left boundary: start or not letter/number/underscore // Right boundary: end or not letter/number/underscore - const regex = new RegExp(`(^|[^\\p{L}\\p{N}_])(${pattern})(?=([^\\p{L}\\p{N}_]|$))`, "giu"); + const regex = new RegExp(`(^|[^\\p{L}\\p{N}_])(${pattern})(?=[^\\p{L}\\p{N}_]|$)`, "giu"); return { regex, keys: unique }; } function loadGlossary(glossaryPath) { const raw = fs.readFileSync(glossaryPath, "utf8"); - const data = yaml.load(raw); + const data = JSON.parse(raw); /** @type {{label:string,definition:string,id?:string,aliases?:string[]}[]} */ const entries = []; @@ -75,6 +74,8 @@ function loadGlossary(glossaryPath) { * @param {{glossaryFile?: string}} options */ function remarkGlossary(options = {}) { + console.log(">>> remarkGlossary plugin loaded"); + const glossaryFile = options.glossaryFile || "static/glossary.json"; const absPath = path.isAbsolute(glossaryFile) ? glossaryFile @@ -93,10 +94,9 @@ function remarkGlossary(options = {}) { // Nodes we should NOT process beneath const BLOCK_SKIP = new Set(["code", "pre"]); const INLINE_SKIP = new Set(["inlineCode", "link", "linkReference"]); - // If author already used , skip inside it - const MDX_SKIP = new Set(["mdxJsxTextElement", "mdxJsxFlowElement"]); return function transformer(tree) { + // Track which terms have been processed on this page (case-insensitive) const processedTerms = new Set(); @@ -121,16 +121,25 @@ function remarkGlossary(options = {}) { /** @type {any[]} */ const nextChildren = []; + // Reset regex lastIndex for each node + regex.lastIndex = 0; + // Iterate all matches while preserving unmatched segments while ((m = regex.exec(value)) !== null) { const [full, leftBoundary, term] = m; - const start = m.index; - const before = value.slice(last, start); - if (before) - nextChildren.push({ - type: "text", - value: before + (leftBoundary || ""), - }); + const matchStart = m.index; + const termStart = matchStart + (leftBoundary?.length || 0); + + // Text before the match (not including leftBoundary) + const before = value.slice(last, matchStart); + if (before) { + nextChildren.push({ type: "text", value: before }); + } + + // Add leftBoundary as separate text if present + if (leftBoundary) { + nextChildren.push({ type: "text", value: leftBoundary }); + } const key = String(term).toLowerCase(); const entry = byKey.get(key); @@ -156,8 +165,6 @@ function remarkGlossary(options = {}) { name: "Term", attributes: [ { type: "mdxJsxAttribute", name: "lookup", value: entry.label }, - // You can also add data attributes if you want: - // {type: 'mdxJsxAttribute', name: 'data-term', value: entry.label}, ], children: [{ type: "text", value: term }], }); @@ -166,7 +173,9 @@ function remarkGlossary(options = {}) { nextChildren.push({ type: "text", value: term }); } } - last = start + full.length; + + // Move past the full match + last = matchStart + full.length; } if (last === 0) return; // no matches, keep node as-is