diff --git a/gatsby/__tests__/toc.test.ts b/gatsby/__tests__/toc.test.ts
new file mode 100644
index 00000000..db3e9544
--- /dev/null
+++ b/gatsby/__tests__/toc.test.ts
@@ -0,0 +1,102 @@
+import { mdxAstToToc } from "../toc";
+
+describe("mdxAstToToc tag query parsing", () => {
+ it("does not emit a bogus ?undefined query when the image URL has no query string", () => {
+ const toc = mdxAstToToc(
+ [
+ {
+ type: "list",
+ children: [
+ {
+ type: "listItem",
+ children: [
+ {
+ type: "paragraph",
+ children: [
+ { type: "text", value: "Data Service" },
+ {
+ type: "image",
+ alt: "PREVIEW",
+ url: "/media/tidb-cloud/blank_transparent_placeholder.png",
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ ] as any,
+ "en/tidbcloud/master/TOC"
+ );
+
+ expect(toc[0].tag).toEqual({
+ value: "PREVIEW",
+ query: undefined,
+ });
+ });
+
+ it("does not create a tag when the TOC image has no alt text", () => {
+ const toc = mdxAstToToc(
+ [
+ {
+ type: "list",
+ children: [
+ {
+ type: "listItem",
+ children: [
+ {
+ type: "paragraph",
+ children: [
+ { type: "text", value: "Data Service" },
+ {
+ type: "image",
+ alt: null,
+ url: "/media/tidb-cloud/blank_transparent_placeholder.png",
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ ] as any,
+ "en/tidbcloud/master/TOC"
+ );
+
+ expect(toc[0].tag).toBeUndefined();
+ });
+
+ it("keeps tag query params when the image URL includes them", () => {
+ const toc = mdxAstToToc(
+ [
+ {
+ type: "list",
+ children: [
+ {
+ type: "listItem",
+ children: [
+ {
+ type: "paragraph",
+ children: [
+ { type: "text", value: "Beta Feature" },
+ {
+ type: "image",
+ alt: "BETA",
+ url: "/media/tidb-cloud/blank_transparent_placeholder.png?color=%232d9cd2",
+ },
+ ],
+ },
+ ],
+ },
+ ],
+ },
+ ] as any,
+ "en/tidbcloud/master/TOC"
+ );
+
+ expect(toc[0].tag).toEqual({
+ value: "BETA",
+ query: "?color=%232d9cd2",
+ });
+ });
+});
diff --git a/gatsby/toc.ts b/gatsby/toc.ts
index fef4f3d3..c8c71f02 100644
--- a/gatsby/toc.ts
+++ b/gatsby/toc.ts
@@ -2,6 +2,7 @@ import {
ListItem,
List,
Link,
+ Image,
Paragraph,
Text,
Content,
@@ -157,11 +158,14 @@ function getContentFromLink(
const child = content.children[0] as Link | Text;
// use `image` as tag
- const image = content.children.find((n) => n.type === "image");
- const tag = image && {
- value: image.alt!,
- query: `?${image.url.split("?")[1]}`,
- };
+ const image = content.children.find((n): n is Image => n.type === "image");
+ const imageQuery = image?.url.split("?")[1];
+ const tag = image?.alt
+ ? {
+ value: image.alt,
+ query: imageQuery ? `?${imageQuery}` : undefined,
+ }
+ : undefined;
if (child.type === "link") {
if (child.children.length === 0) {
diff --git a/locale/en/translation.json b/locale/en/translation.json
index df468a63..0d64a522 100644
--- a/locale/en/translation.json
+++ b/locale/en/translation.json
@@ -43,8 +43,7 @@
"tidbOperatorReleases": "TiDB Operator Releases",
"tiupReleases": "TiUP Releases",
"badge": {
- "preview": "Preview",
- "beta": "Beta"
+ "preview": "Preview"
},
"appdev": "App Dev",
"asktug": "Forum",
diff --git a/locale/ja/translation.json b/locale/ja/translation.json
index d716614d..b536c5d9 100644
--- a/locale/ja/translation.json
+++ b/locale/ja/translation.json
@@ -43,8 +43,7 @@
"tidbOperatorReleases": "TiDB Operator リリース",
"tiupReleases": "TiUP リリース",
"badge": {
- "preview": "Preview",
- "beta": "Beta"
+ "preview": "Preview"
},
"appdev": "アプリ開発",
"asktug": "Forum",
diff --git a/locale/zh/translation.json b/locale/zh/translation.json
index a5e09239..bc6794a1 100644
--- a/locale/zh/translation.json
+++ b/locale/zh/translation.json
@@ -41,8 +41,7 @@
"tidbOperatorReleases": "TiDB Operator 版本发布记录",
"tiupReleases": "TiUP 版本发布记录",
"badge": {
- "preview": "Preview",
- "beta": "Beta"
+ "preview": "Preview"
},
"appdev": "开发指南",
"asktug": "社区",
diff --git a/src/components/Badge/PreviewBadge.tsx b/src/components/Badge/PreviewBadge.tsx
new file mode 100644
index 00000000..93470dfd
--- /dev/null
+++ b/src/components/Badge/PreviewBadge.tsx
@@ -0,0 +1,29 @@
+import Chip from "@mui/material/Chip";
+import { useTheme } from "@mui/material/styles";
+
+const PreviewBadge = (props: { label: string }) => {
+ const theme = useTheme();
+
+ return (
+
+ );
+};
+
+export default PreviewBadge;
diff --git a/src/components/Layout/Header/HeaderNavConfigData.tsx b/src/components/Layout/Header/HeaderNavConfigData.tsx
index 80f3beae..82701b8c 100644
--- a/src/components/Layout/Header/HeaderNavConfigData.tsx
+++ b/src/components/Layout/Header/HeaderNavConfigData.tsx
@@ -2,54 +2,11 @@ import { NavConfig } from "./HeaderNavConfigType";
import { CLOUD_MODE_KEY } from "shared/useCloudPlan";
import { CloudPlan, TOCNamespace } from "shared/interface";
import OpenInNewIcon from "@mui/icons-material/OpenInNew";
-import Chip from "@mui/material/Chip";
-import { useTheme } from "@mui/material/styles";
+import PreviewBadge from "components/Badge/PreviewBadge";
import TiDBCloudIcon from "media/icons/cloud-03.svg";
import TiDBIcon from "media/icons/layers-three-01.svg";
-const PreviewBadge = (props: { label: string }) => {
- const theme = useTheme();
- return (
-
- );
-};
-
-const BetaTagBadge = (props: { label: string }) => (
-
-);
-
/**
* Default navigation configuration
*/
@@ -167,7 +124,7 @@ const getDefaultNavConfig = (
leftNavLabel: (
<>
{t("navbar.tidbForAI")}
-
+
>
),
to: "/ai",
diff --git a/src/components/Layout/LeftNav/LeftNavTree.tsx b/src/components/Layout/LeftNav/LeftNavTree.tsx
index 5412d370..0766daac 100644
--- a/src/components/Layout/LeftNav/LeftNavTree.tsx
+++ b/src/components/Layout/LeftNav/LeftNavTree.tsx
@@ -7,9 +7,11 @@ import Stack from "@mui/material/Stack";
import Typography from "@mui/material/Typography";
import Divider from "@mui/material/Divider";
import { useTheme } from "@mui/material/styles";
+import { useTranslation } from "gatsby-plugin-react-i18next";
import { RepoNavLink, RepoNav } from "shared/interface";
import LinkComponent from "components/Link";
+import PreviewBadge from "components/Badge/PreviewBadge";
import { scrollToElementIfInView } from "shared/utils";
import { alpha, Chip } from "@mui/material";
@@ -190,6 +192,8 @@ export default function ControlledTreeView(props: {
});
const theme = useTheme();
+ const { t } = useTranslation();
+ const previewBadgeLabel = t("navbar.badge.preview");
const [disableTransition, setDisableTransition] = React.useState(false);
const previousUrlRef = React.useRef(null);
@@ -313,7 +317,7 @@ export default function ControlledTreeView(props: {
) : (
)}
- {generateItemLabel(item)}
+ {generateItemLabel(item, previewBadgeLabel)}
);
};
@@ -389,10 +393,22 @@ export default function ControlledTreeView(props: {
);
}
-const generateItemLabel = ({ content: contents, tag }: RepoNavLink) => {
- const tagQuery = new URLSearchParams(tag?.query);
- const tagColor = tagQuery.get("color");
- const tagColor02 = tagColor && alpha(tagColor, 0.2);
+const generateItemLabel = (
+ { content: contents, tag }: RepoNavLink,
+ previewBadgeLabel: string
+) => {
+ const normalizedTagValue = tag?.value?.trim().toUpperCase();
+ const isPreviewTag = normalizedTagValue === "PREVIEW";
+ let tagColor: string | null = null;
+ let tagColor02: string | null = null;
+
+ // PREVIEW intentionally ignores source color overrides to match shared badges.
+ if (tag && !isPreviewTag) {
+ const tagQuery = new URLSearchParams(tag.query ?? "");
+ tagColor = tagQuery.get("color");
+ tagColor02 = tagColor ? alpha(tagColor, 0.2) : null;
+ }
+
return (
{
);
})}
- {tag && (
+ {tag && isPreviewTag ? (
+
+ ) : tag ? (
{
fontWeight: 500,
}}
/>
- )}
+ ) : null}
);
};