Skip to content

Commit 174ddda

Browse files
feat: implement detail blocks
1 parent 38e4ffb commit 174ddda

File tree

8 files changed

+138
-65
lines changed

8 files changed

+138
-65
lines changed

src/components/templates/FuncTemplate.tsx

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import type { FC } from "hono/jsx";
22
import { Translation } from "../../translation/";
33
import type { Func, FuncBody, Page } from "../../types/model";
4+
import {
5+
normalizeDeprecation,
6+
normalizeDetailBlocks,
7+
} from "../../utils/normalizeModel.js";
48
import {
59
FunctionDefinition,
610
FunctionDisplay,
@@ -44,9 +48,26 @@ export const FuncTemplate: FC<FuncTemplateProps> = ({
4448

4549
{<DeprecationWarning item={content} level="top" />}
4650

47-
<div class="my-4 text-gray-700">
48-
<HtmlContent html={content.details} />
49-
</div>
51+
{normalizeDetailBlocks(content).map((block) => {
52+
switch (block.kind) {
53+
case "html":
54+
return (
55+
<div class="my-4 text-gray-700">
56+
<HtmlContent html={block.content} />
57+
</div>
58+
);
59+
case "example":
60+
// This will never reach for Typst v0.13.1 and v0.14.0-rc.1 documentations.
61+
return (
62+
<div class="my-6 bg-gray-50 p-4 rounded-md border border-gray-200">
63+
{block.content.title}
64+
<HtmlContent html={block.content.body} />
65+
</div>
66+
);
67+
default:
68+
return null;
69+
}
70+
})}
5071

5172
<h2 id="parameters" class="flex items-baseline gap-1">
5273
<Translation translationKey="parameters" />
@@ -57,12 +78,6 @@ export const FuncTemplate: FC<FuncTemplateProps> = ({
5778
<FunctionDefinition func={content} />
5879
</div>
5980

60-
{content.example && (
61-
<div class="my-6 bg-gray-50 p-4 rounded-md border border-gray-200">
62-
<HtmlContent html={content.example} />
63-
</div>
64-
)}
65-
6681
<div class="my-6">
6782
<FunctionParameters func={content} />
6883
</div>

src/components/ui/FunctionDisplay.tsx

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { FC } from "hono/jsx";
22
import { Translation } from "../../translation/";
33
import type { Func } from "../../types/model";
4+
import { normalizeDetailBlocks } from "../../utils/normalizeModel.js";
45
import { ChevronRightIcon } from "../icons";
56
import { FunctionDefinition } from "./FunctionDefinition";
67
import { FunctionParameters } from "./FunctionParameters";
@@ -24,32 +25,40 @@ export const FunctionDisplay: FC<FunctionDisplayProps> = ({
2425
}) => {
2526
return (
2627
<>
27-
<HtmlContent html={func.details} />
28+
{normalizeDetailBlocks(func).map((block) => {
29+
switch (block.kind) {
30+
case "html":
31+
return <HtmlContent html={block.content} />;
32+
case "example":
33+
return isExampleFolding ? (
34+
<details class="my-4 folding-example group">
35+
<summary class="flex items-center gap-1 text-sm font-medium text-blue-600 cursor-pointer hover:text-blue-800">
36+
<div class="w-4 h-4 text-gray-400 transform transition-transform duration-200 group-open:rotate-90">
37+
<ChevronRightIcon />
38+
</div>
39+
<Translation
40+
translationKey="showExample"
41+
title={block.content.title}
42+
/>
43+
</summary>
44+
<div class="mt-2 bg-white p-3 rounded-md border border-gray-200 text-sm">
45+
<HtmlContent html={block.content.body} />
46+
</div>
47+
</details>
48+
) : (
49+
<div class="my-6 bg-gray-50 p-4 rounded-md border border-gray-200">
50+
<HtmlContent html={block.content.body} />
51+
</div>
52+
);
53+
default:
54+
return null;
55+
}
56+
})}
2857

2958
<div class="my-4">
3059
<FunctionDefinition func={func} prefix={prefix} />
3160
</div>
3261

33-
{func.example && isExampleFolding && (
34-
<details class="my-4 folding-example group">
35-
<summary class="flex items-center gap-1 text-sm font-medium text-blue-600 cursor-pointer hover:text-blue-800">
36-
<div class="w-4 h-4 text-gray-400 transform transition-transform duration-200 group-open:rotate-90">
37-
<ChevronRightIcon />
38-
</div>
39-
<Translation translationKey="showExample" />
40-
</summary>
41-
<div class="mt-2 bg-white p-3 rounded-md border border-gray-200 text-sm">
42-
<HtmlContent html={func.example} />
43-
</div>
44-
</details>
45-
)}
46-
47-
{func.example && !isExampleFolding && (
48-
<div class="my-6 bg-gray-50 p-4 rounded-md border border-gray-200">
49-
<HtmlContent html={func.example} />
50-
</div>
51-
)}
52-
5362
<div class="my-4">
5463
<FunctionParameters func={func} prefix={prefix} />
5564
</div>

src/components/ui/FunctionParameters.tsx

Lines changed: 39 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type { FC } from "hono/jsx";
22
import { basePath } from "../../metadata";
33
import { Translation } from "../../translation/";
44
import type { Func } from "../../types/model";
5+
import { normalizeDetailBlocks } from "../../utils/normalizeModel";
56
import { joinPath } from "../../utils/path";
67
import { ChevronRightIcon } from "../icons";
78
import { HtmlContent } from "./HtmlContent";
@@ -58,22 +59,35 @@ export const FunctionParameters: FC<FunctionParametersProps> = ({
5859
</div>
5960
</h4>
6061

61-
<div class="mb-3 text-gray-700">
62-
<HtmlContent html={param.details} />
63-
</div>
64-
65-
{param.default && (
66-
<p class="mt-3 text-sm">
67-
<span class="font-medium">
68-
<Translation translationKey="defaultValue" />
69-
</span>{" "}
70-
<span class="text-gray-700">
71-
<HtmlContent html={param.default} />
72-
</span>
73-
</p>
74-
)}
75-
76-
{/* Put all collapsible blocks after non-collapsible blocks. */}
62+
{normalizeDetailBlocks(param).map((block) => {
63+
switch (block.kind) {
64+
case "html":
65+
return (
66+
<div class="mb-3 text-gray-700">
67+
<HtmlContent html={block.content} />
68+
</div>
69+
);
70+
case "example":
71+
return (
72+
<details class="my-4 folding-example group">
73+
<summary class="flex items-center gap-1 text-sm font-medium text-blue-600 cursor-pointer hover:text-blue-800">
74+
<div class="w-4 h-4 text-gray-400 transform transition-transform duration-200 group-open:rotate-90">
75+
<ChevronRightIcon />
76+
</div>
77+
<Translation
78+
translationKey="showExample"
79+
title={block.content.title}
80+
/>
81+
</summary>
82+
<div class="mt-2 bg-white p-3 rounded-md border border-gray-200 text-sm">
83+
<HtmlContent html={block.content.body} />
84+
</div>
85+
</details>
86+
);
87+
default:
88+
return null;
89+
}
90+
})}
7791

7892
{param.strings.length > 0 && (
7993
<details
@@ -104,18 +118,15 @@ export const FunctionParameters: FC<FunctionParametersProps> = ({
104118
</details>
105119
)}
106120

107-
{param.example && (
108-
<details class="my-4 folding-example group">
109-
<summary class="flex items-center gap-1 text-sm font-medium text-blue-600 cursor-pointer hover:text-blue-800">
110-
<div class="w-4 h-4 text-gray-400 transform transition-transform duration-200 group-open:rotate-90">
111-
<ChevronRightIcon />
112-
</div>
113-
<Translation translationKey="showExample" />
114-
</summary>
115-
<div class="mt-2 bg-white p-3 rounded-md border border-gray-200 text-sm">
116-
<HtmlContent html={param.example} />
117-
</div>
118-
</details>
121+
{param.default && (
122+
<p class="mt-3 text-sm">
123+
<span class="font-medium">
124+
<Translation translationKey="defaultValue" />
125+
</span>{" "}
126+
<span class="text-gray-700">
127+
<HtmlContent html={param.default} />
128+
</span>
129+
</p>
119130
)}
120131
</div>
121132
))}

src/translation/en-US.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,11 @@ export const Translation: TranslationComponent = (props) => {
4646
<Fragment>{props.message}</Fragment>
4747
);
4848
case "showExample":
49-
return <Fragment>Show example</Fragment>;
49+
return props.title ? (
50+
<Fragment>Show example: {props.title}</Fragment>
51+
) : (
52+
<Fragment>Show example</Fragment>
53+
);
5054
case "tableOfContents":
5155
return <Fragment>On this page</Fragment>;
5256
case "nextPage":

src/translation/index.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@ type TranslationComponentKey =
6060
| "globalAttributes"
6161
| "defaultValue"
6262
| "stringValues"
63-
| "showExample"
6463
// Translation statuses
6564
| "untranslated"
6665
| "untranslatedMessage"
@@ -94,7 +93,8 @@ export type TranslationComponentProps =
9493
message: string;
9594
/** A Typst version, e.g. "0.15.0". */
9695
until: string | null;
97-
};
96+
}
97+
| { translationKey: "showExample"; title: string | null };
9898

9999
/**
100100
* Translation component for UI text, descriptions, and other content to be embedded as JSX.

src/translation/ja-JP.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,11 @@ export const Translation: TranslationComponent = (props) => {
5252
<Fragment>{props.message}</Fragment>
5353
);
5454
case "showExample":
55-
return <Fragment>例を表示</Fragment>;
55+
return props.title ? (
56+
<Fragment>例を表示:{props.title}</Fragment>
57+
) : (
58+
<Fragment>例を表示</Fragment>
59+
);
5660
case "tableOfContents":
5761
return <Fragment>目次</Fragment>;
5862
case "nextPage":

src/types/model.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ type Param = {
9191
settable: boolean;
9292
} & WithDetailsBlocks;
9393

94-
type DetailsBlock =
94+
export type DetailsBlock =
9595
| {
9696
kind: "html";
9797
content: Html;
@@ -104,7 +104,7 @@ type DetailsBlock =
104104
};
105105
};
106106

107-
type WithDetailsBlocks =
107+
export type WithDetailsBlocks =
108108
// Format since Typst v0.14.0-rc.1 (typst/typst#7011)
109109
| { details: DetailsBlock[] }
110110
// Format for Typst v0.13.1

src/utils/normalizeModel.ts

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@
33
* @module
44
*/
55

6-
import type { WithDeprecation } from "../types/model";
6+
import type {
7+
DetailsBlock,
8+
WithDeprecation,
9+
WithDetailsBlocks,
10+
} from "../types/model";
711

812
/**
913
* Return deprecation info if deprecated, return null otherwise.
@@ -26,3 +30,29 @@ export function normalizeDeprecation(item: WithDeprecation): {
2630
}
2731
return null;
2832
}
33+
34+
export function normalizeDetailBlocks(item: WithDetailsBlocks): DetailsBlock[] {
35+
if ("example" in item) {
36+
// For v0.13.1
37+
const details: DetailsBlock[] = [
38+
{
39+
kind: "html",
40+
content: item.details,
41+
},
42+
];
43+
44+
if (item.example !== null) {
45+
details.push({
46+
kind: "example",
47+
content: {
48+
title: null,
49+
body: item.example,
50+
},
51+
});
52+
}
53+
54+
return details;
55+
}
56+
57+
return item.details;
58+
}

0 commit comments

Comments
 (0)