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: 4 additions & 0 deletions astro.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import starlightLlmsTxt from "starlight-llms-txt";
import { loadEnv } from "vite";
import { readFile } from "node:fs/promises";
import satteriExternalLinks from "./src/plugins/satteri/external-links";
import satteriCallouts from "./src/plugins/satteri/callouts";

import { defineConfig } from "astro/config";
import type { HeadUserConfig } from "node_modules/@astrojs/starlight/schemas/head";
Expand Down Expand Up @@ -194,9 +195,11 @@ export default defineConfig({
markdown: {
processor: satteri({
features: {
directive: true,
gfm: true,
smartPunctuation: true,
},
mdastPlugins: [satteriCallouts],
hastPlugins: [satteriExternalLinks],
}),
},
Expand Down Expand Up @@ -334,6 +337,7 @@ export default defineConfig({
"./src/styles/theme-light.css",
"./src/styles/starlight-vars.css",
"./src/styles/utilities.css",
"./src/styles/callout.css",
],
pagination: false,
lastUpdated: true,
Expand Down
2 changes: 1 addition & 1 deletion ec.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { pluginLineNumbers } from "@expressive-code/plugin-line-numbers";

export default defineEcConfig({
plugins: [pluginCollapsibleSections(), pluginLineNumbers()],
themes: ["github-dark-dimmed", "github-light-default"],
themes: ["github-dark-default", "github-light-default"],
styleOverrides: {
codeFontSize: "0.8rem",
borderColor: "var(--cui-border-subtle)",
Expand Down
29 changes: 25 additions & 4 deletions src/components/ApiDocs/Operation.astro
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@
import { Badge, Tabs, TabItem } from "@astrojs/starlight/components";
import Callout from "@components/content/Callout";
import Markdown from "@components/Markdown.astro";
import MarkdownContent from "@components/MarkdownContent.astro";
import { formatSlug } from "@lib/helpers";
import { resolveReference } from "@lib/openapi";
import { getOperationDescriptionId } from "@lib/openapiContent";
import { Headline, Body, Anchor } from "@sumup-oss/circuit-ui";
import type { HTMLAttributes } from "astro/types";
import { getEntry, render } from "astro:content";
import type { OpenAPIV3_1 } from "openapi-types";
import type {
OperationObject,
Expand All @@ -26,6 +29,24 @@ interface Props extends HTMLAttributes<"section"> {
}

const { operation, coreObjects = [], ...props } = Astro.props;
// OpenAPI descriptions are content entries so they use the same configured
// Markdown pipeline as authored docs instead of a component-local parser.
const descriptionEntry = operation.operationId
? await getEntry(
"apiDescriptions",
getOperationDescriptionId(operation.operationId),
)
: undefined;

if (operation.description && !descriptionEntry) {
throw new Error(
`Missing Markdown content entry for operation ${operation.operationId ?? "without an operationId"}`,
);
}

const Description = descriptionEntry
? (await render(descriptionEntry)).Content
: undefined;

const isParameterObject = (
object: OpenAPIV3_1.ParameterObject | OpenAPIV3_1.ReferenceObject,
Expand Down Expand Up @@ -260,10 +281,10 @@ const formattedPermissions = (operation["x-permissions"] || [])
)
}
{
operation.description && (
<div class="description">
<Markdown>{operation.description}</Markdown>
</div>
operation.description && Description && (
<MarkdownContent class="description">
<Description />
</MarkdownContent>
)
}
{
Expand Down
25 changes: 24 additions & 1 deletion src/components/ApiDocs/TagSection.astro
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
---
import Callout from "@components/content/Callout";
import Markdown from "@components/Markdown.astro";
import MarkdownContent from "@components/MarkdownContent.astro";
import { formatSlug } from "@lib/helpers";
import { getTagDescriptionId } from "@lib/openapiContent";
import type { HTMLAttributes } from "astro/types";
import { getEntry, render } from "astro:content";
import type { OperationObject, TagObject } from "src/types/openapi";
import EndpointList from "./EndpointList";
import LRGrid from "./LRGrid.astro";
Expand All @@ -28,6 +31,20 @@ const {
} = Astro.props;

const slug = formatSlug(name);
// Tag descriptions are content entries so they use the configured Satteri
// pipeline, matching operation descriptions and authored documentation.
const descriptionEntry = await getEntry(
"apiDescriptions",
getTagDescriptionId(name),
);

if (description && !descriptionEntry) {
throw new Error(`Missing Markdown content entry for tag ${name}`);
}

const Description = descriptionEntry
? (await render(descriptionEntry)).Content
: undefined;
const [targetTag, targetOp] = (target || "").split("/");
const tagIsTarget = !targetOp && targetTag === slug;
const objectPagefindAttributes = tagIsTarget
Expand Down Expand Up @@ -80,7 +97,13 @@ const coreObjectSections = coreObjects.map((schema, index) => {
</div>
)
}
<Markdown>{description}</Markdown>
{
description && Description && (
<MarkdownContent>
<Description />
</MarkdownContent>
)
}
</div>
{
operations.length > 0 && (
Expand Down
17 changes: 9 additions & 8 deletions src/components/ApiDocs/TopSections.astro
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
---
import MarkdownContent from "@components/MarkdownContent.astro";
import { CodeBlock, MultiCode } from "@components/Code";
import Markdown from "@components/Markdown.astro";
import type { ApiTopSection } from "@lib/openapi/routes";
Expand Down Expand Up @@ -72,14 +73,14 @@ const sectionAttrs = (id: ApiTopSection) =>
<section id="sdks" {...sectionAttrs("sdks")}>
<LRGrid class="sdks">
<div>
<div class="info sl-markdown-content">
<MarkdownContent class="info">
<SectionHeading as="h2" id="sdks-heading">SDKs</SectionHeading>
<p>
The SumUp SDKs reduce the amount of work required to use our REST
APIs. SumUp maintains SDKs for PHP, JavaScript, Python, Java, Go, Rust,
and .NET.
APIs. SumUp maintains SDKs for PHP, JavaScript, Python, Java, Go,
Rust, and .NET.
</p>
</div>
</MarkdownContent>
<SDKList />
</div>
<div>
Expand Down Expand Up @@ -167,7 +168,7 @@ uv add sumup`,

<section id="authentication" {...sectionAttrs("authentication")}>
<LRGrid>
<div class="info sl-markdown-content">
<MarkdownContent class="info">
<SectionHeading as="h2" id="authentication-heading">
Authentication
</SectionHeading>
Expand All @@ -185,7 +186,7 @@ uv add sumup`,
All API requests must be made over HTTPS and authenticated. Calls made
over plain HTTP or calls without authentication will fail.
</p>
</div>
</MarkdownContent>
<div class="servers">
<MultiCode
data-pagefind-ignore="all"
Expand Down Expand Up @@ -266,7 +267,7 @@ let client = Client::default().with_authorization("sup_sk_MvxmLOl0...");`,

<section id="errors" {...sectionAttrs("errors")}>
<LRGrid>
<div class="info sl-markdown-content">
<MarkdownContent class="info">
<SectionHeading as="h2" id="errors-heading"> Errors </SectionHeading>
<p>
Newer APIs use{" "}
Expand Down Expand Up @@ -381,7 +382,7 @@ let client = Client::default().with_authorization("sup_sk_MvxmLOl0...");`,
</div>
)
}
</div>
</MarkdownContent>
<div class="errors-panel api-docs-codeblock-stack">
<CodeBlock
data-pagefind-ignore="all"
Expand Down
5 changes: 3 additions & 2 deletions src/components/Markdown.astro
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
---
import { markdownToHtml } from "satteri";
import MarkdownContent from "@components/MarkdownContent.astro";

interface Props {
class?: string;
Expand All @@ -12,6 +13,6 @@ const slot = await Astro.slots.render("default");
const { html } = markdownToHtml(slot);
---

<div class:list={["sl-markdown-content", className]}>
<MarkdownContent class={className}>
<Fragment set:html={html} />
</div>
</MarkdownContent>
12 changes: 12 additions & 0 deletions src/components/MarkdownContent.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
import type { HTMLAttributes } from "astro/types";
import "@astrojs/starlight/style/markdown.css";

type Props = HTMLAttributes<"div">;

const { class: className, ...attrs } = Astro.props;
---

<div {...attrs} class:list={["sl-markdown-content", className]}>
<slot />
</div>
20 changes: 0 additions & 20 deletions src/components/content/Callout.module.css

This file was deleted.

48 changes: 25 additions & 23 deletions src/components/content/Callout.tsx
Original file line number Diff line number Diff line change
@@ -1,49 +1,51 @@
import {
Callout as CircuitCallout,
type CalloutColor,
} from "@sumup-oss/circuit-ui";
import {
Confirm,
Info,
Notify,
Sparkles,
type IconComponentType,
} from "@sumup-oss/icons";
import type { ComponentProps, ReactNode } from "react";
import styles from "./Callout.module.css";

type CalloutType = "note" | "tip" | "caution" | "success" | "promo";
import type { HTMLAttributes, ReactNode } from "react";
import type { CalloutType } from "./calloutTypes";

type Props = Omit<ComponentProps<typeof CircuitCallout>, "body" | "color"> & {
type Props = HTMLAttributes<HTMLDivElement> & {
children: ReactNode;
type?: CalloutType;
};

const calloutConfig: Record<
CalloutType,
{
color: CalloutColor;
icon: IconComponentType<"24">;
iconLabel: string;
}
> = {
note: { color: "neutral", icon: Info, iconLabel: "Note" },
tip: { color: "promo", icon: Sparkles, iconLabel: "Tip" },
caution: { color: "alert", icon: Notify, iconLabel: "Caution" },
success: { color: "confirm", icon: Confirm, iconLabel: "Success" },
promo: { color: "promo", icon: Sparkles, iconLabel: "Promo" },
note: { icon: Info, iconLabel: "Note" },
tip: { icon: Sparkles, iconLabel: "Tip" },
caution: { icon: Notify, iconLabel: "Caution" },
success: { icon: Confirm, iconLabel: "Success" },
promo: { icon: Sparkles, iconLabel: "Promo" },
};

export default function Callout({ children, type = "note", ...props }: Props) {
export default function Callout({
children,
className,
type = "note",
...props
}: Props) {
const config = calloutConfig[type];
const className = [styles.callout, props.className].filter(Boolean).join(" ");
const classes = ["sumup-callout", `sumup-callout--${type}`, className]
.filter(Boolean)
.join(" ");
const Icon = config.icon;

return (
<CircuitCallout
{...config}
{...props}
className={className}
body={children}
/>
<div {...props} className={classes}>
<div className="sumup-callout__icon">
<Icon aria-hidden="true" size="24" />
</div>
<span className="visually-hidden">{config.iconLabel}</span>
<div className="sumup-callout__content">{children}</div>
</div>
);
}
12 changes: 12 additions & 0 deletions src/components/content/calloutTypes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export const CALLOUT_TYPES = [
"note",
"tip",
"caution",
"success",
"promo",
] as const;

export type CalloutType = (typeof CALLOUT_TYPES)[number];

export const isCalloutType = (value: string): value is CalloutType =>
CALLOUT_TYPES.includes(value as CalloutType);
18 changes: 18 additions & 0 deletions src/content.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { docsLoader } from "@astrojs/starlight/loaders";
import { docsSchema } from "@astrojs/starlight/schema";
import { glob } from "astro/loaders";
import { defineCollection, z } from "astro:content";
import { openapiDescriptionsLoader } from "./loaders/openapiDescriptions";

const help = defineCollection({
loader: glob({ pattern: "**/*.{md,mdx}", base: "./src/content/help" }),
Expand All @@ -19,6 +20,22 @@ const changelog = defineCollection({
}),
});

const apiDescriptions = defineCollection({
loader: openapiDescriptionsLoader(),
schema: z.discriminatedUnion("kind", [
z.object({
kind: z.literal("tag"),
name: z.string(),
}),
z.object({
kind: z.literal("operation"),
name: z.string(),
method: z.string(),
path: z.string(),
}),
]),
});

export const collections = {
docs: defineCollection({
schema: docsSchema({
Expand All @@ -38,4 +55,5 @@ export const collections = {
}),
help,
changelog,
apiDescriptions,
};
Loading