返回 CodeWhale
code-spans.tsx
根目录 / web / components / code-spans.tsx
1 import { Fragment, type ReactNode } from "react";
2 import { splitTokens } from "@/lib/i18n/dictionaries";
3
4 /**
5 * Typeset a dictionary template whose `{token}` placeholders stand for
6 * code-owned literals (commands, env names, config keys, job states). The
7 * literals stay in the page; the sentence stays one translated unit and a
8 * locale may reorder the tokens freely. An unknown token renders as
9 * `{token}` so template/literal drift is visible in review, never silent.
10 */
11 export function withCodeSpans(template: string, spans: Record<string, string>): ReactNode {
12 return splitTokens(template).map((part, i) =>
13 "token" in part ? (
14 <code key={`${i}-${part.token}`} className="inline">
15 {spans[part.token] ?? `{${part.token}}`}
16 </code>
17 ) : (
18 <Fragment key={`${i}-text`}>{part.text}</Fragment>
19 ),
20 );
21 }
22
23 /** A `[term, detail]` reference list, the docs pages' one table shape. */
24 export function RefRows({
25 rows,
26 spans = {},
27 termSpans = false,
28 }: {
29 rows: readonly (readonly [string, string])[];
30 spans?: Record<string, string>;
31 /** Typeset the term column as code (command tables). */
32 termSpans?: boolean;
33 }) {
34 return (
35 <dl className="docs-ref-rows">
36 {rows.map(([term, detail]) => (
37 <div key={term}>
38 <dt>{termSpans ? <code className="inline">{term}</code> : term}</dt>
39 <dd>{withCodeSpans(detail, spans)}</dd>
40 </div>
41 ))}
42 </dl>
43 );
44 }
45
45 lines Plain Text