Skip to content
Open
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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 1 addition & 1 deletion apps/docs/next.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ const nextConfig: NextConfig = {
// https://github.com/vercel/next.js/issues/71638
sassOptions: {
logger: {
warn: function (message) {
warn: function (message: string) {
if (
message.includes("deprecat") ||
message.includes("declarations that appear after nested")
Expand Down
2 changes: 2 additions & 0 deletions apps/docs/source.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ const schema = z.custom<{
date?: string;
difficulty?: string;
index?: boolean;
featured?: boolean;
href?: string;
}>();

const docsData = defineDocs({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { CookbookPage, getMetadataFromSlug } from "../cookbook";
import { toStaticParams } from "@@/src/app/sources/utils";

type Props = {
params: Promise<{ slug?: string[]; locale: string }>;
params: Promise<{ slug: string[]; locale: string }>;
};

export default async function Page(props: Props) {
Expand Down
15 changes: 12 additions & 3 deletions apps/docs/src/app/[locale]/developers/developers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,23 @@

import DevelopersHeroSection from "@/components/developers/sections/DevelopersHeroSection/DevelopersHeroSection";
import DevelopersCoursesSection from "@/components/developers/sections/DevelopersCoursesSection/DevelopersCoursesSection";
import DevelopersResourcesSection from "@/components/developers/sections/DevelopersResourcesSection/DevelopersResourcesSection";
import DevelopersResourcesSection, {
DevelopersResourcesSectionProps,
} from "@/components/developers/sections/DevelopersResourcesSection/DevelopersResourcesSection";
import DevelopersDocumentsSection from "@/components/developers/sections/DevelopersDocumentsSection/DevelopersDocumentsSection";
import DevelopersContentSection from "@/components/developers/sections/DevelopersContentSection/DevelopersContentSection";
import heroImg from "@@/assets/developers/hero-geometry.png";
import { useTranslations } from "next-intl";
import StackExchangeIcon from "@@/assets/developers/stackexchange.inline.svg";
import { LatestChangelogVideo } from "@/components/developers/sections/DevelopersDocumentsSection/DevelopersChangelog";

export function DevelopersPage({ latestChangelogVideo, guides }) {
export function DevelopersPage({
latestChangelogVideo,
guides,
}: {
latestChangelogVideo?: LatestChangelogVideo;
guides?: DevelopersResourcesSectionProps["items"];
}) {
const t = useTranslations();
return (
<div className="overflow-hidden">
Expand All @@ -36,7 +45,7 @@ export function DevelopersPage({ latestChangelogVideo, guides }) {
/>
<DevelopersCoursesSection /* courses={courses} */ />
<DevelopersResourcesSection
items={guides}
items={guides ?? []}
baseHref={`/developers/guides`}
translationKey={"guides"}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"use client";

import type { ReactNode } from "react";
import Button from "@/components/shared/Button";
import RoundedDepthCard from "@/components/shared/RoundedDepthCard";
import DevelopersResources from "@/components/developers/DevelopersResources/DevelopersResources";
Expand All @@ -8,7 +9,21 @@ import { useTranslations } from "next-intl";
import classNames from "classnames";
import styles from "@/components/developers/DevelopersContentPage/DevelopersContentPage.module.scss";

export function GuidesIndex({ records, featured }) {
export type GuideRecord = {
href?: string;
title?: ReactNode;
description?: ReactNode;
difficulty?: string;
tags?: string[];
featured?: boolean;
};

type GuidesIndexProps = {
records: GuideRecord[];
featured: GuideRecord[];
};

export function GuidesIndex({ records, featured }: GuidesIndexProps) {
const t = useTranslations();

return (
Expand Down
2 changes: 1 addition & 1 deletion apps/docs/src/app/[locale]/developers/guides/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ type Props = {
export default async function Page(props: Props) {
const { locale } = await props.params;
const guides = getGuides(locale);
const featured = guides.filter((guide: any) => guide.featured).slice(0, 3);
const featured = guides.filter((guide) => guide.featured).slice(0, 3);
return (
<div className="my-12 px-6 max-w-[1120px] w-full mx-auto">
<GuidesIndex records={guides} featured={featured} />
Expand Down
9 changes: 5 additions & 4 deletions apps/docs/src/app/[locale]/developers/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ export default async function Page(props: Props) {
const { locale } = await props.params;
const latestChangelogVideo = await getLatestChangelogVideo();
const guides = getGuides(locale)
.filter((guide: any) => guide.featured)
.filter((guide) => guide.featured)
.slice(0, 6);
return (
<DevelopersPage
latestChangelogVideo={latestChangelogVideo}
guides={guides}
latestChangelogVideo={latestChangelogVideo ?? undefined}
guides={guides ?? undefined}
/>
);
}
Expand All @@ -27,7 +27,8 @@ async function getLatestChangelogVideo() {
let latestChangelogVideo = null;
const videos = await getYTVideos(undefined, YT_PLAYLIST_CHANGELOG);
if (videos.length) {
latestChangelogVideo = videos.sort((a: any, b: any) => {
latestChangelogVideo = videos.sort((a, b) => {
if (!b.snippet.publishedAt || !a.snippet.publishedAt) return 0;
return (
new Date(b.snippet.publishedAt).getTime() -
new Date(a.snippet.publishedAt).getTime()
Expand Down
2 changes: 1 addition & 1 deletion apps/docs/src/app/[locale]/docs/(main)/[...slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { getMetadataFromSlug, MainDocsPage } from "../docs";
import { toStaticParams } from "@@/src/app/sources/utils";

type Props = {
params: Promise<{ slug?: string[]; locale: string }>;
params: Promise<{ slug: string[]; locale: string }>;
};

export default async function Page(props: Props) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { getMetadataFromSlug, PaymentsDocsPage } from "../payments";
import { toStaticParams } from "@@/src/app/sources/utils";

type Props = {
params: Promise<{ slug?: string[]; locale: string }>;
params: Promise<{ slug: string[]; locale: string }>;
};

export default async function Page(props: Props) {
Expand Down
2 changes: 1 addition & 1 deletion apps/docs/src/app/[locale]/docs/rpc/[...slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { getMetadataFromSlug, RpcDocsPage } from "../rpc";
import { toStaticParams } from "@@/src/app/sources/utils";

type Props = {
params: Promise<{ slug?: string[]; locale: string }>;
params: Promise<{ slug: string[]; locale: string }>;
};

export default async function Page(props: Props) {
Expand Down
74 changes: 53 additions & 21 deletions apps/docs/src/app/components/api-method.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { isValidElement } from "react";
import { z } from "zod";
import { parseProps, Block, CodeBlock } from "codehike/blocks";
import { SingleCode, toCodeGroup } from "@@/src/app/components/code/code";
Expand Down Expand Up @@ -40,17 +41,45 @@ import {
ResizableHandle,
} from "@@/src/app/components/ui/resizable";

type ParamBlock = {
title?: string;
children?: React.ReactNode;
type: string;
required: boolean;
values?: string[];
default?: string;
blocks?: ParamBlock[];
};

type Result = ParamBlock & {
response?: RawCode;
};

type Method = {
title?: string;
children?: React.ReactNode;
request: RawCode[];
params: {
title?: string;
children?: React.ReactNode;
blocks?: ParamBlock[];
};
result: Result[];
};

const BaseParamSchema = Block.extend({
type: z.string(),
required: z.optional(z.string()).transform((val) => val != null),
values: z.optional(z.string()).transform((val) => val?.split(/\s+/)),
default: z.string().optional(),
});
const ParamSchema = BaseParamSchema.extend({

const ParamSchema: z.ZodType<ParamBlock> = BaseParamSchema.extend({
blocks: z.lazy(() => ParamSchema.array()).optional(),
});

const ResultSchema = ParamSchema.extend({
const ResultSchema: z.ZodType<Result> = BaseParamSchema.extend({
blocks: z.lazy(() => ParamSchema.array()).optional(),
response: CodeBlock.optional(),
});

Expand All @@ -63,11 +92,7 @@ const MethodSchema = Block.extend({
});

export function APIMethod(props: unknown) {
const method = parseProps(props, MethodSchema) as {
params?: { blocks: ParamBlock[] };
request: RawCode[];
result: { response: RawCode; title: string }[];
};
const method = parseProps(props, MethodSchema) as Method;
const paramsSection = <ParamsSection params={method.params?.blocks} />;
const resultHeader = (
<div className="flex gap-2 items-center">
Expand Down Expand Up @@ -202,10 +227,7 @@ function SmallLayout({
);
}

type ParamBlock = z.infer<typeof BaseParamSchema> & {
blocks?: ParamBlock[];
};
function ParamsSection({ params }: { params: ParamBlock[] }) {
function ParamsSection({ params }: { params?: ParamBlock[] }) {
return (
<>
<h4 className="mt-0 mb-2 font-mono">params</h4>
Expand All @@ -214,7 +236,7 @@ function ParamsSection({ params }: { params: ParamBlock[] }) {
{params?.map((param, i) => (
<Hoverable
key={i}
name={param.title}
name={param.title ?? ""}
className="tw-border border-ch-border p-2 rounded bg-ch-background data-[hovered=true]:border-sky-500/40 transition-colors duration-300 block"
>
<div className="[&>p]:inline">
Expand All @@ -241,9 +263,18 @@ function ParamsSection({ params }: { params: ParamBlock[] }) {
}

function ObjectParam({ block }: { block: ParamBlock }) {
const isEmpty = !(block.children as any)?.props.children;
const childElement = isValidElement<{ children?: React.ReactNode }>(
block.children,
)
? block.children
: null;
const isEmpty = !childElement?.props.children;
return (
<Hoverable key={block.title} name={block.title} className="block group">
<Hoverable
key={block.title}
name={block.title ?? ""}
className="block group"
>
<Collapsible
className="tw-border border-ch-border bg-ch-tabs-background rounded group-data-[hovered=true]:border-sky-500/40 transition-colors duration-300"
disabled={isEmpty}
Expand Down Expand Up @@ -271,6 +302,7 @@ function ObjectParam({ block }: { block: ParamBlock }) {
}

function ValuesTable({ block }: { block: ParamBlock }) {
if (!block.values) return null;
return (
<table className="w-full not-prose bg-fd-card">
<thead>
Expand Down Expand Up @@ -301,9 +333,6 @@ function ValuesTable({ block }: { block: ParamBlock }) {
);
}

type Result = ParamBlock & {
response?: RawCode;
};
function ResultSection({ result }: { result: Result }) {
return (
<Hoverable
Expand Down Expand Up @@ -372,10 +401,12 @@ async function getCurlTab(codeblock: RawCode) {
const lines = highlighted.code.split(/\r?\n/);
const params = highlighted.annotations
.filter(
(a: BlockAnnotation) =>
a.name == "hover" && a.fromLineNumber === a.toLineNumber,
(a): a is BlockAnnotation =>
a.name == "hover" &&
(a as BlockAnnotation).fromLineNumber ===
(a as BlockAnnotation).toLineNumber,
)
.map((a: BlockAnnotation) => {
.map((a) => {
let line = lines[a.fromLineNumber - 1];
// remove potential trailing commas
line = line.trim().replace(/,$/, "");
Expand Down Expand Up @@ -472,7 +503,8 @@ async function RequestBlock({ codeblocks }: { codeblocks: RawCode[] }) {
return <MultiCode group={group} className="flex-1 my-0 min-h-0 shrink-0" />;
}

async function ResponseBlock({ codeblock }: { codeblock: RawCode }) {
async function ResponseBlock({ codeblock }: { codeblock?: RawCode }) {
if (!codeblock) return null;
const highlighted = await highlight(codeblock, theme);
const handlers = [mark, tokenTransitions, hover, ...collapse];
const codeGroup = {
Expand Down
20 changes: 14 additions & 6 deletions apps/docs/src/app/components/blog-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@ export function BlogPage(props: {
tags?: string[];
date?: string;
difficulty?: string;
pageTree?: any;
pageTree?: Parameters<typeof findNeighbour>[0];
}) {
const record: ContentRecord = {
href: props.href,
title: props.title,
date: props.date,
date: props.date ?? "",
tags: props.tags,
difficulty: props.difficulty,
};
Expand All @@ -42,7 +42,7 @@ export function BlogPage(props: {
return (
<div className="mx-auto w-full px-5">
<div className="my-8">
<Breadcrumb root={props.baseHref} items={props.breadcrumb} />
<Breadcrumb root={props.baseHref ?? ""} items={props.breadcrumb} />
</div>
<div>
<HeroTitle record={record} baseHref={props.baseHref} />
Expand All @@ -57,21 +57,29 @@ export function BlogPage(props: {
<Text className="size-4" />
<TocLabel />
</h3>
<TOCItems items={props.toc} />
<TOCItems items={props.toc ?? []} />
<EditOnGithub href={href} />
<ScrollToTop />
</div>
</Toc>
<article className="min-w-0">
<DocsBody className="mb-8 text-lg">{props.children}</DocsBody>
<Footer pageTree={props.pageTree} pageUrl={props.href} />
{props.pageTree ? (
<Footer pageTree={props.pageTree} pageUrl={props.href} />
) : null}
</article>
</div>
</div>
);
}

function Footer({ pageTree, pageUrl }: { pageTree: any; pageUrl: string }) {
function Footer({
pageTree,
pageUrl,
}: {
pageTree: Parameters<typeof findNeighbour>[0];
pageUrl: string;
}) {
let { next, previous } = findNeighbour(pageTree, pageUrl);

// only if neighbours are in the same folder
Expand Down
2 changes: 1 addition & 1 deletion apps/docs/src/app/components/breadcrumb.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export function Breadcrumb({
className="truncate hover:text-fd-accent-foreground"
href={`/${rootParts.slice(0, index + 1).join("/")}`}
>
{roots[part]}
{roots[part as keyof typeof roots]}
</Link>
</React.Fragment>
))}
Expand Down
Loading
Loading