diff --git a/src/layouts/sidebar/DocsNavMenu.astro b/src/layouts/sidebar/DocsNavMenu.astro
index 01fb0a1fe..1849c65bb 100644
--- a/src/layouts/sidebar/DocsNavMenu.astro
+++ b/src/layouts/sidebar/DocsNavMenu.astro
@@ -89,7 +89,7 @@ const serverSystemVersion = readServerSystemVersion();
);
}
- if (item.slug === "===") {
+ if (item.path === "===") {
return (
diff --git a/src/layouts/sidebar/LeftSidebarItem.tsx b/src/layouts/sidebar/LeftSidebarItem.tsx
index eac027e0d..b1fbcddb0 100644
--- a/src/layouts/sidebar/LeftSidebarItem.tsx
+++ b/src/layouts/sidebar/LeftSidebarItem.tsx
@@ -8,14 +8,21 @@ import type { SystemVersion } from "~/type";
function LeftSidebarItem(props: NavMenuPage) {
const systemVersion = useSystemVersion();
if (props.items.length > 0) return ;
- const { title, slug } = props;
+ const { title, path } = props;
const pageSlug = slugSignal.value;
- const isActive = pageSlug === slug;
- const href = `/docs${slug}`;
+ const isActive = pageSlug === path;
+ const [href, isExternal] = (() => {
+ try {
+ return [new URL(path).toString(), true];
+ } catch (e) {
+ return [`/docs${path}`, false];
+ }
+ })();
return (
@@ -23,11 +30,11 @@ function LeftSidebarItem(props: NavMenuPage) {
}
export default LeftSidebarItem;
-function FolderLink({ title, slug, items, systemVersion }: NavMenuPage) {
- const openSignal = useComputed(() => !!navOpenStatesSignal.value[slug]);
+function FolderLink({ title, path, items, systemVersion }: NavMenuPage) {
+ const openSignal = useComputed(() => !!navOpenStatesSignal.value[path]);
const open = openSignal.value;
const pageSlug = slugSignal.value;
- const isActive = pageSlug === slug;
+ const isActive = pageSlug === path;
return (
{
navOpenStatesSignal.value = {
...navOpenStatesSignal.value,
- [slug]: !open,
+ [path]: !open,
};
}}
>
@@ -63,7 +70,7 @@ function FolderLink({ title, slug, items, systemVersion }: NavMenuPage) {
{items.map((item) => (
- -
+
-
))}
@@ -76,6 +83,7 @@ function FolderLink({ title, slug, items, systemVersion }: NavMenuPage) {
export interface JustLinkProps {
title: string;
href: string;
+ isExternal?: boolean;
isActive: boolean;
systemVersion?: SystemVersion | undefined;
event?: {
@@ -86,6 +94,7 @@ export interface JustLinkProps {
export function JustLink({
title,
href,
+ isExternal,
isActive,
systemVersion,
event,
@@ -93,12 +102,13 @@ export function JustLink({
return (
event && trackEvent(event.name, event.props)}
+ target={isExternal ? "_blank" : "_self"}
>
-
+
);
}
@@ -113,11 +123,15 @@ export function getLinkStyle(isActive: boolean): string {
interface LinkTitleProps {
title: string;
+ isExternal?: boolean | undefined;
}
-function LinkTitle({ title }: LinkTitleProps) {
+function LinkTitle({ title, isExternal }: LinkTitleProps) {
return (
-
+
{title || (unknown page)}
+ {isExternal && (
+
+ )}
);
}
diff --git a/src/state/server-only/nav.ts b/src/state/server-only/nav.ts
index a41d36941..6608b3179 100644
--- a/src/state/server-only/nav.ts
+++ b/src/state/server-only/nav.ts
@@ -28,7 +28,7 @@ export interface NavMenu {
export type NavMenuItem = NavMenuPage | NavMenuGroup;
export interface NavMenuPage {
type: "page";
- slug: string;
+ path: string;
title: string;
items: NavMenuPage[];
systemVersion?: SystemVersion | undefined;
@@ -50,15 +50,15 @@ export const navMenuItemsKo = toNavMenuItems(
export const navMenu = { en: navMenuItemsEn, ko: navMenuItemsKo };
export interface NavMenuSystemVersions {
- [slug: string]: SystemVersion;
+ [path: string]: SystemVersion;
}
export function calcNavMenuSystemVersions(
navMenuItems: NavMenuItem[],
): NavMenuSystemVersions {
const result: NavMenuSystemVersions = {};
for (const item of iterNavMenuItems(navMenuItems)) {
- if (!("slug" in item)) continue;
- if (item.systemVersion) result[item.slug] = item.systemVersion;
+ if (!("path" in item)) continue;
+ if (item.systemVersion) result[item.path] = item.systemVersion;
}
return result;
}
@@ -84,7 +84,7 @@ function* iterNavMenuAncestors(
if (item.type === "group") {
yield* iterNavMenuAncestors(item.items, ancestors);
} else if (item.type === "page") {
- const { slug, items } = item;
+ const { path: slug, items } = item;
yield { slug, ancestors };
yield* iterNavMenuAncestors(items, [...ancestors, slug]);
}
@@ -107,7 +107,7 @@ function toNavMenuItems(
if (typeof item === "string") {
return {
type: "page",
- slug: item,
+ path: item,
title: frontmatters[item]?.["title"] || "",
items: [],
systemVersion,
@@ -116,7 +116,7 @@ function toNavMenuItems(
const _systemVersion = item.systemVersion || systemVersion;
return {
type: "page",
- slug: item.slug,
+ path: item.slug,
title: frontmatters[item.slug]?.["title"] || "",
items: item.items
? (toNavMenuItems(
@@ -127,6 +127,21 @@ function toNavMenuItems(
: [],
systemVersion: _systemVersion,
};
+ } else if ("href" in item) {
+ const _systemVersion = item.systemVersion || systemVersion;
+ return {
+ type: "page",
+ path: item.href,
+ title: item.label,
+ items: item.items
+ ? (toNavMenuItems(
+ item.items,
+ frontmatters,
+ _systemVersion,
+ ) as NavMenuPage[])
+ : [],
+ systemVersion: _systemVersion,
+ };
} else {
const _systemVersion = item.systemVersion || systemVersion;
return {
diff --git a/src/type.ts b/src/type.ts
index e8efde501..748ffc49f 100644
--- a/src/type.ts
+++ b/src/type.ts
@@ -12,14 +12,24 @@ export type SystemVersion = z.infer;
export type YamlNavMenuToplevelItem =
| YamlNavMenuPageSugar
| YamlNavMenuPage
+ | YamlNavMenuExternalPage
| YamlNavMenuGroup;
-export type YamlNavMenuItem = YamlNavMenuPageSugar | YamlNavMenuPage;
+export type YamlNavMenuItem =
+ | YamlNavMenuPageSugar
+ | YamlNavMenuPage
+ | YamlNavMenuExternalPage;
type YamlNavMenuPageSugar = string;
interface YamlNavMenuPage {
slug: string;
items: YamlNavMenuItem[];
systemVersion?: SystemVersion;
}
+interface YamlNavMenuExternalPage {
+ label: string;
+ href: string;
+ items?: YamlNavMenuItem[];
+ systemVersion?: SystemVersion;
+}
interface YamlNavMenuGroup {
label: string;
items: YamlNavMenuItem[];