Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/website.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,10 @@ jobs:
java-version: 25
distribution: temurin
cache: 'maven'
- name: Set up Node.js 22
- name: Set up Node.js 24
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 22
node-version: 24.18.1
cache: 'npm'
cache-dependency-path: zookeeper-website/package-lock.json
- name: Show the first log message
Expand Down
3 changes: 2 additions & 1 deletion zookeeper-website/app/components/docs/layout/docs/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ export interface DocsLayoutProps extends BaseLayoutProps {
}

interface SidebarOptions
extends ComponentProps<"aside">,
extends
ComponentProps<"aside">,
Pick<ComponentProps<typeof Sidebar>, "defaultOpenLevel" | "prefetch"> {
enabled?: boolean;
component?: ReactNode;
Expand Down
24 changes: 14 additions & 10 deletions zookeeper-website/app/components/docs/layout/docs/page/client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ import {
} from "react";
import { ChevronDown, ChevronLeft, ChevronRight } from "lucide-react";
import Link from "fumadocs-core/link";
import { useI18n } from "fumadocs-ui/contexts/i18n";
import { useTreeContext, useTreePath } from "fumadocs-ui/contexts/tree";
import { T } from "@fuma-translate/react";
import type * as PageTree from "fumadocs-core/page-tree";
import { usePathname } from "fumadocs-core/framework";
import {
Expand Down Expand Up @@ -75,7 +75,7 @@ export function PageTOCPopover({
return () => {
window.removeEventListener("click", onClick);
};
}, [onClick]);
}, []);

return (
<TocPopoverContext
Expand Down Expand Up @@ -116,7 +116,6 @@ export function PageTOCPopoverTrigger({
className,
...props
}: ComponentProps<"button">) {
const { text } = useI18n();
const { open } = use(TocPopoverContext)!;
const items = useTOCItems();
const active = useActiveAnchor();
Expand Down Expand Up @@ -149,7 +148,7 @@ export function PageTOCPopoverTrigger({
showItem && "pointer-events-none -translate-y-full opacity-0"
)}
>
{path?.name ?? text.toc}
{path?.name ?? <T text="On this page" note="table of contents" />}
</span>
<span
className={cn(
Expand All @@ -170,8 +169,10 @@ export function PageTOCPopoverTrigger({
);
}

interface ProgressCircleProps
extends Omit<React.ComponentProps<"svg">, "strokeWidth"> {
interface ProgressCircleProps extends Omit<
React.ComponentProps<"svg">,
"strokeWidth"
> {
value: number;
strokeWidth?: number;
size?: number;
Expand Down Expand Up @@ -244,7 +245,6 @@ export function PageLastUpdate({
date: value,
...props
}: Omit<ComponentProps<"p">, "children"> & { date: Date }) {
const { text } = useI18n();
const [date, setDate] = useState("");

useEffect(() => {
Expand All @@ -257,7 +257,7 @@ export function PageLastUpdate({
{...props}
className={cn("text-fd-muted-foreground text-sm", props.className)}
>
{text.lastUpdate} {date}
<T text="Last updated on" note="page footer" /> {date}
</p>
);
}
Expand Down Expand Up @@ -314,7 +314,6 @@ export function PageFooter({
}

function FooterItem({ item, index }: { item: Item; index: 0 | 1 }) {
const { text } = useI18n();
const Icon = index === 0 ? ChevronLeft : ChevronRight;

return (
Expand All @@ -335,7 +334,12 @@ function FooterItem({ item, index }: { item: Item; index: 0 | 1 }) {
<p>{item.name}</p>
</div>
<p className="text-fd-muted-foreground truncate">
{item.description ?? (index === 0 ? text.previousPage : text.nextPage)}
{item.description ??
(index === 0 ? (
<T text="Previous Page" note="pagination" />
) : (
<T text="Next Page" note="pagination" />
))}
</p>
</Link>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
import type { ComponentProps, ReactNode } from "react";
import { buttonVariants } from "../../../../../ui/button";
import { Edit, Text } from "lucide-react";
import { I18nLabel } from "fumadocs-ui/contexts/i18n";
import { T } from "@fuma-translate/react";
import {
type BreadcrumbProps,
type FooterProps,
Expand Down Expand Up @@ -193,7 +193,7 @@ export function DocsPage({
className="text-fd-muted-foreground inline-flex items-center gap-1.5 text-sm"
>
<Text className="size-4" />
<I18nLabel label="toc" />
<T text="On this page" note="table of contents" />
</h3>
<TOCScrollArea>
{tocOptions.style === "clerk" ? (
Expand Down Expand Up @@ -227,7 +227,7 @@ export function EditOnGitHub(props: ComponentProps<"a">) {
{props.children ?? (
<>
<Edit className="size-3.5" />
<I18nLabel label="editOnGithub" />
<T text="Edit on GitHub" note="edit page" />
</>
)}
</a>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import type { ComponentProps } from "react";
import { useI18n } from "fumadocs-ui/contexts/i18n";
import { T, useTranslations } from "@fuma-translate/react";
import { Popover, PopoverContent, PopoverTrigger } from "../../../ui/popover";
import { buttonVariants } from "../../../ui/button";
import { cn } from "@/lib/utils";
Expand All @@ -26,12 +27,13 @@ export type LanguageSelectProps = ComponentProps<"button">;

export function LanguageToggle(props: LanguageSelectProps): React.ReactElement {
const context = useI18n();
const t = useTranslations();
if (!context.locales) throw new Error("Missing `<I18nProvider />`");

return (
<Popover>
<PopoverTrigger
aria-label={context.text.chooseLanguage}
aria-label={t("Choose a language", { note: "language switcher" })}
{...props}
className={cn(
buttonVariants({
Expand All @@ -45,7 +47,7 @@ export function LanguageToggle(props: LanguageSelectProps): React.ReactElement {
</PopoverTrigger>
<PopoverContent className="flex flex-col overflow-x-hidden p-0">
<p className="text-fd-muted-foreground mb-1 p-2 text-xs font-medium">
{context.text.chooseLanguage}
<T text="Choose a language" note="language switcher" />
</p>
{context.locales.map((item) => (
<button
Expand Down
6 changes: 1 addition & 5 deletions zookeeper-website/app/components/docs/layout/link-item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,11 +105,7 @@ export interface CustomItemType extends Filterable {
}

export type LinkItemType =
| MainItemType
| IconItemType
| ButtonItemType
| MenuItemType
| CustomItemType;
MainItemType | IconItemType | ButtonItemType | MenuItemType | CustomItemType;

export function LinkItem({
ref,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,12 @@
import type { ComponentProps } from "react";
import { Search } from "lucide-react";
import { useSearchContext } from "fumadocs-ui/contexts/search";
import { useI18n } from "fumadocs-ui/contexts/i18n";
import { T } from "@fuma-translate/react";
import { type ButtonProps, buttonVariants } from "../../../ui/button";
import { cn } from "@/lib/utils";

interface SearchToggleProps
extends Omit<ComponentProps<"button">, "color">,
ButtonProps {
extends Omit<ComponentProps<"button">, "color">, ButtonProps {
hideIfDisabled?: boolean;
}

Expand Down Expand Up @@ -66,7 +65,6 @@ export function LargeSearchToggle({
hideIfDisabled?: boolean;
}) {
const { enabled, hotKey, setOpenSearch } = useSearchContext();
const { text } = useI18n();
if (hideIfDisabled && !enabled) return null;

return (
Expand All @@ -83,7 +81,7 @@ export function LargeSearchToggle({
}}
>
<Search className="size-4" />
{text.search}
<T text="Search" note="search trigger" />
<div className="ms-auto inline-flex gap-0.5">
{hotKey.map((k, i) => (
<kbd key={i} className="bg-fd-background rounded-md border px-1.5">
Expand Down
56 changes: 36 additions & 20 deletions zookeeper-website/app/components/docs/search/create-db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,39 +18,51 @@

import {
create,
insertMultiple,
type Orama,
insertMultipleAsync,
type PartialSchemaDeep,
type TypedDocument
} from "@orama/orama";
type TypedDocument,
type ZBSearch
} from "zbsearch";
import type { AdvancedOptions } from "fumadocs-core/search/server";

export type AdvancedDocument = TypedDocument<Orama<typeof advancedSchema>>;
export type AdvancedDocument = TypedDocument<ZBSearch<typeof advancedSchema>>;
export const advancedSchema = {
content: "string",
page_id: "string",
type: "string",
breadcrumbs: "string[]",
tags: "enum[]",
url: "string",
locale: "enum",
embeddings: "vector[512]"
} as const;

export async function createDB({
indexes,
tokenizer,
...rest
}: AdvancedOptions): Promise<Orama<typeof advancedSchema>> {
const DefaultLanguage = "multilingual";

export async function createDB(
options: AdvancedOptions
): Promise<ZBSearch<typeof advancedSchema>> {
const {
indexes,
tokenizer,
language = DefaultLanguage,
sort,
plugins,
components
} = options;
const items = typeof indexes === "function" ? await indexes() : indexes;
const resolvedTokenizer = tokenizer ?? components?.tokenizer;

const db = create({
schema: advancedSchema,
...rest,
language: resolvedTokenizer ? undefined : language,
sort,
plugins,
components: {
...rest.components,
tokenizer: tokenizer ?? rest.components?.tokenizer
...components,
tokenizer: resolvedTokenizer
}
}) as Orama<typeof advancedSchema>;
});

const mapTo: PartialSchemaDeep<AdvancedDocument>[] = [];
items.forEach((page) => {
Expand All @@ -66,7 +78,8 @@ export async function createDB({
content: page.title,
breadcrumbs: page.breadcrumbs,
tags,
url: page.url
url: page.url,
locale: page.locale
});

const nextId = () => `${page.id}-${id++}`;
Expand All @@ -78,7 +91,8 @@ export async function createDB({
tags,
type: "text",
url: page.url,
content: page.description
content: page.description,
locale: page.locale
});
}

Expand All @@ -89,7 +103,8 @@ export async function createDB({
type: "heading",
tags,
url: `${page.url}#${heading.id}`,
content: heading.content
content: heading.content,
locale: page.locale
});
}

Expand All @@ -100,11 +115,12 @@ export async function createDB({
tags,
type: "text",
url: content.heading ? `${page.url}#${content.heading}` : page.url,
content: content.content
content: content.content,
locale: page.locale
});
}
});

await insertMultiple(db, mapTo);
return db;
await insertMultipleAsync(db, mapTo);
return db as ZBSearch<typeof advancedSchema>;
}
21 changes: 10 additions & 11 deletions zookeeper-website/app/components/docs/search/create-from-source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ import {
createSearchAPI
} from "fumadocs-core/search/server";
import { PathUtils } from "fumadocs-core/source";
import type { Language } from "@orama/orama";
import type { LoaderConfig, LoaderOutput, Page } from "fumadocs-core/source";
import type { Language } from "zbsearch";
import type { LoaderConfig, LoaderOutput } from "fumadocs-core/source";
import type { I18nConfig } from "fumadocs-core/i18n";
import { findPath } from "fumadocs-core/page-tree";
import type { StructuredData } from "fumadocs-core/mdx-plugins";
Expand All @@ -35,12 +35,12 @@ type Awaitable<T> = T | Promise<T>;
function defaultBuildIndex<C extends LoaderConfig>(
source: LoaderOutput<C>,
tag?: (pageUrl: string) => string
) {
): (page: C["page"]) => Promise<AdvancedIndex> {
function isBreadcrumbItem(item: unknown): item is string {
return typeof item === "string" && item.length > 0;
}

return async (page: Page): Promise<AdvancedIndex> => {
return async (page) => {
let breadcrumbs: string[] | undefined;
let structuredData: StructuredData | undefined;

Expand Down Expand Up @@ -89,16 +89,15 @@ function defaultBuildIndex<C extends LoaderConfig>(
};
}

interface Options<C extends LoaderConfig>
extends Omit<AdvancedOptions, "indexes"> {
interface Options<C extends LoaderConfig> extends Omit<
AdvancedOptions,
"indexes"
> {
localeMap?: {
[K in C["i18n"] extends I18nConfig<infer Languages> ? Languages : string]?:
| Partial<AdvancedOptions>
| Language;
Partial<AdvancedOptions> | Language;
};
buildIndex?: (
page: Page<C["source"]["pageData"]>
) => Awaitable<AdvancedIndex>;
buildIndex?: (page: C["page"]) => Awaitable<AdvancedIndex>;
tag?: (pageUrl: string) => string;
}

Expand Down
Loading
Loading