@tuwaio/docs-ui 0.5.7 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +93 -3
- package/bin/i18n-check.js +19 -0
- package/dist/components/DocsLayout.cjs +105 -0
- package/dist/components/DocsLayout.d.cts +93 -0
- package/dist/components/DocsLayout.d.ts +93 -0
- package/dist/components/DocsLayout.js +80 -0
- package/dist/components/Footer.cjs +1 -6
- package/dist/components/Footer.d.cts +3 -2
- package/dist/components/Footer.d.ts +3 -2
- package/dist/components/Footer.js +1 -6
- package/dist/components/LocalizedPage.cjs +42 -0
- package/dist/components/LocalizedPage.d.cts +37 -0
- package/dist/components/LocalizedPage.d.ts +37 -0
- package/dist/components/LocalizedPage.js +18 -0
- package/dist/docsI18n.cjs +33 -0
- package/dist/docsI18n.d.cts +16 -0
- package/dist/docsI18n.d.ts +16 -0
- package/dist/docsI18n.js +8 -0
- package/dist/docsLabels.cjs +140 -0
- package/dist/docsLabels.d.cts +72 -0
- package/dist/docsLabels.d.ts +72 -0
- package/dist/docsLabels.js +116 -0
- package/dist/docsPage.cjs +70 -0
- package/dist/docsPage.d.cts +56 -0
- package/dist/docsPage.d.ts +56 -0
- package/dist/docsPage.js +46 -0
- package/dist/i18n.d.cts +1 -1
- package/dist/i18n.d.ts +1 -1
- package/dist/index.cjs +4 -0
- package/dist/index.css +3 -0
- package/dist/index.d.cts +3 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +2 -0
- package/dist/nextra.cjs +26 -0
- package/dist/nextra.d.cts +11 -0
- package/dist/nextra.d.ts +11 -0
- package/dist/nextra.js +3 -0
- package/dist/pageMap.cjs +66 -0
- package/dist/pageMap.d.cts +33 -0
- package/dist/pageMap.d.ts +33 -0
- package/dist/pageMap.js +42 -0
- package/dist/translationCheck.cjs +191 -0
- package/dist/translationCheck.d.cts +90 -0
- package/dist/translationCheck.d.ts +90 -0
- package/dist/translationCheck.js +162 -0
- package/package.json +15 -3
package/README.md
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
- **Logo:** `RemoteLogo` is an async React Server Component that fetches an SVG (by default the TUWA logo) and renders it as React elements, so it takes `className` and `currentColor`.
|
|
14
14
|
- **Theme switch:** `ThemeSwitcher` is a light/dark switch for any theme state (for example `next-themes`).
|
|
15
15
|
- **Language select:** `LocaleSwitcher` is an accessible glassmorphic select dropdown for switching languages (English, Українська, 简体中文, etc.), styled to match `ThemeSwitcher`. Features zero layout shift, Nova UI Kit animated directional chevron, collision detection with auto-flip (`placement="auto"`), multi-layout Latin typeahead navigation (independent of user OS keyboard language), and an invisible native `<select>` overlay on touch devices (`pointer: coarse`) for native mobile system pickers (iOS wheel, Android sheet). Full WCAG 2.1/2.2 AA/AAA compliance. It renders an invisible placeholder during SSR to avoid hydration shifts.
|
|
16
|
+
- **Three languages (project sites):** `@tuwaio/docs-ui/nextra` and `@tuwaio/docs-ui/nextra/page` turn a Nextra site into an English, Ukrainian and Simplified Chinese site with one URL per page, as on the [docs hub](https://docs.tuwa.io). `DocsLayout` is the Nextra layout with the navbar (the language switch after the links; the theme switch stays in the Nextra sidebar and the mobile menu), the footer, the search, the table of contents, the edit, feedback and last-updated texts and the sidebar titles in the language of the reader (`docsLabels`, `localizePageMap`). `createDocsPage` creates the `[[...mdxPath]]` route: each page is prerendered in English and in the languages it is translated into, and `LocalizedPage` shows the reader's language without a request; pages without a translation (package READMEs, the generated API reference) show English with a note in the reader's language. The language is detected after mount (`tuwa-locale`, then the browser languages and the time zone; no cookie, no request). The `tuwa-docs-i18n-check` command keeps the translations in line with their English pages.
|
|
16
17
|
- **Interface settings for 30 days:** `PreferenceExpiry` is an inline script for the `<head>` of a site's root layout. It forgets the Local Storage values of the given keys (by default `theme`) 30 days after they were written, as the [Cookie Policy](https://tuwa.io/cookie) states, and dates each later write, whatever library writes it (`next-themes`, the `Tabs` of Nextra).
|
|
17
18
|
- **Decoration:** `Orb` (an animated sphere in the brand color of a TUWA project), `StarryBackground` (an animated star field on a canvas) and `NoSSR` (renders its children only on the client).
|
|
18
19
|
- **Policy pages:** `policies` lists the TUWA policies (Terms, Privacy, Cookie, Refund, Security, Data Processing Addendum) with their paths and whether they are in force (`publishedPolicies`; footers use `footerPolicies`). `loadPolicy` loads the text of a policy in a language, and `PolicyDocument` renders it with the date of the version, a Download PDF button, a language switch (English, Українська) when the policy is translated, anchored sections (the same anchors in every language) and a list of sections. The texts and PDFs come from [`TuwaIO/workflows/docs`](https://github.com/TuwaIO/workflows/tree/main/docs). Code that needs only the list or `loadPolicy` (footers, sitemaps, route handlers) imports them from `@tuwaio/docs-ui/policies`, which has no React, Next.js or Nextra imports.
|
|
@@ -27,7 +28,7 @@
|
|
|
27
28
|
pnpm add @tuwaio/docs-ui next nextra nextra-theme-docs react react-dom @heroicons/react
|
|
28
29
|
```
|
|
29
30
|
|
|
30
|
-
`nextra-theme-docs`
|
|
31
|
+
`nextra-theme-docs` is needed by `Navbar`, `Footer` and `DocsLayout`, `nextra` by `DocsLayout`, `LocalizedPage` and `createDocsPage`, `next` by `RemoteLogo` (a Server Component that uses the `fetch` cache of Next.js) and `createDocsPage`, and `@heroicons/react` by `ThemeSwitcher`.
|
|
31
32
|
|
|
32
33
|
Import the stylesheet after the Nextra theme:
|
|
33
34
|
|
|
@@ -122,6 +123,95 @@ export function PolicyLinks() {
|
|
|
122
123
|
|
|
123
124
|
Sections have stable anchors (`/refund#how-to-request-a-refund`), so hints and FAQ answers can link to a section.
|
|
124
125
|
|
|
126
|
+
### Languages of a project site
|
|
127
|
+
|
|
128
|
+
A TUWA project site (Orbit, SIWX, Satellite Connect, Pulsar, SDK) in English, Ukrainian and Simplified Chinese. The root layout renders `DocsLayout` around the page and keeps the language for 30 days:
|
|
129
|
+
|
|
130
|
+
```tsx
|
|
131
|
+
import { PreferenceExpiry, SiteLogo } from '@tuwaio/docs-ui';
|
|
132
|
+
import { DocsLayout } from '@tuwaio/docs-ui/nextra';
|
|
133
|
+
import { Head } from 'nextra/components';
|
|
134
|
+
import { getPageMap } from 'nextra/page-map';
|
|
135
|
+
import type { ReactNode } from 'react';
|
|
136
|
+
|
|
137
|
+
const logo = <SiteLogo width={126} height={40} />;
|
|
138
|
+
|
|
139
|
+
export default async function RootLayout({ children }: { children: ReactNode }) {
|
|
140
|
+
return (
|
|
141
|
+
<html lang="en" dir="ltr" suppressHydrationWarning>
|
|
142
|
+
<Head>
|
|
143
|
+
<PreferenceExpiry keys={['theme', 'tuwa-locale']} />
|
|
144
|
+
</Head>
|
|
145
|
+
<body>
|
|
146
|
+
<DocsLayout
|
|
147
|
+
logo={logo}
|
|
148
|
+
pageMap={await getPageMap()}
|
|
149
|
+
docsRepositoryBase="https://github.com/TuwaIO/pulsar-core/tree/main/apps/docs"
|
|
150
|
+
sidebarTitles={{ uk: { 'EVM Trackers Standalone': 'EVM-трекери окремо' } }}
|
|
151
|
+
>
|
|
152
|
+
{children}
|
|
153
|
+
</DocsLayout>
|
|
154
|
+
</body>
|
|
155
|
+
</html>
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
`src/app/[[...mdxPath]]/page.tsx` renders every page of `src/content` with its translations:
|
|
161
|
+
|
|
162
|
+
```tsx
|
|
163
|
+
import { createDocsPage } from '@tuwaio/docs-ui/nextra/page';
|
|
164
|
+
|
|
165
|
+
import { localizedPages } from '@/i18n/pages';
|
|
166
|
+
|
|
167
|
+
const { generateStaticParams, generateMetadata, Page } = createDocsPage({ localizedPages });
|
|
168
|
+
|
|
169
|
+
export { generateMetadata, generateStaticParams };
|
|
170
|
+
export default Page;
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
The translations are MDX files with the path of their English page under `src/i18n/<language>` (`src/i18n/uk/index.mdx` translates `src/content/index.mdx`), listed by route in `src/i18n/pages.ts`:
|
|
174
|
+
|
|
175
|
+
```ts
|
|
176
|
+
import type { LocalizedPageLoaders } from '@tuwaio/docs-ui/nextra/page';
|
|
177
|
+
|
|
178
|
+
export const localizedPages: Record<string, LocalizedPageLoaders> = {
|
|
179
|
+
'/': {
|
|
180
|
+
uk: () => import('./uk/index.mdx'),
|
|
181
|
+
'zh-CN': () => import('./zh-CN/index.mdx'),
|
|
182
|
+
},
|
|
183
|
+
};
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
TypeScript types the imported MDX files with a declaration next to it (`src/i18n/mdx.d.ts`):
|
|
187
|
+
|
|
188
|
+
```ts
|
|
189
|
+
declare module '*.mdx' {
|
|
190
|
+
import type { EvaluateResult } from 'nextra';
|
|
191
|
+
|
|
192
|
+
const MDXContent: EvaluateResult['default'];
|
|
193
|
+
export default MDXContent;
|
|
194
|
+
export const toc: EvaluateResult['toc'];
|
|
195
|
+
export const metadata: EvaluateResult['metadata'];
|
|
196
|
+
export const sourceCode: EvaluateResult['sourceCode'];
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
A translation keeps the structure of its English page: the same code blocks in the same order, the same heading levels with the English heading ids written as `## Встановлення [#-installation]` (so anchors work in every language) and the same links. `tuwa-docs-i18n-check`, run from the docs app, checks it and that every translated page exists in every language (it gives headings their ids with the `github-slugger` of the site's `nextra` and fails when that cannot be loaded); add it to the build and to the pre-commit hook:
|
|
201
|
+
|
|
202
|
+
```json
|
|
203
|
+
{
|
|
204
|
+
"scripts": {
|
|
205
|
+
"build": "tuwa-docs-i18n-check && next build && pnpm postbuild",
|
|
206
|
+
"i18n:check": "tuwa-docs-i18n-check"
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Client components inside `DocsLayout` read the language and the interface texts with `useDocsI18n()`.
|
|
212
|
+
|
|
213
|
+
`NextraDocsLayout` is the same layout without state: the language, its texts (`docsLabels[locale]`) and the page map come from props. The docs hub renders it with its own dictionaries and translates its sidebar by route with `localizePageMap(pageMap, {}, { routes })`.
|
|
214
|
+
|
|
125
215
|
### Search index
|
|
126
216
|
|
|
127
217
|
Run the command after `next build`. It uses the `pagefind` package of the site, so add it to the site's dependencies:
|
|
@@ -144,11 +234,11 @@ It writes the index to `public/_pagefind` (keep that directory in `.gitignore`)
|
|
|
144
234
|
|
|
145
235
|
## 🗄️ Browser Storage
|
|
146
236
|
|
|
147
|
-
`LocaleSwitcher` and `ThemeSwitcher` store nothing; they only call `onSelect` / `onToggle`, and the site keeps the choice. `PreferenceExpiry` stores `<key>:expires` (the time in epoch milliseconds) next to each key it is given, removes both once that time has passed, and wraps `Storage.prototype.setItem` on the page to date later writes of those keys.
|
|
237
|
+
`LocaleSwitcher` and `ThemeSwitcher` store nothing; they only call `onSelect` / `onToggle`, and the site keeps the choice. `DocsLayout`, `useLocaleState` and the providers of `createI18n` save the language the reader picks to `tuwa-locale` (`en`, `uk` or `zh-CN`) and read it on the next visit; list the key in `PreferenceExpiry` to forget it after 30 days. `PreferenceExpiry` stores `<key>:expires` (the time in epoch milliseconds) next to each key it is given, removes both once that time has passed, and wraps `Storage.prototype.setItem` on the page to date later writes of those keys.
|
|
148
238
|
|
|
149
239
|
## 🌐 External Services
|
|
150
240
|
|
|
151
|
-
`RemoteLogo` requests its `url` on the server (by default `tuwa.io/brand/logo_v2.svg`), cached by Next.js for 24 hours. `loadPolicy` requests `raw.githubusercontent.com/TuwaIO/workflows/main/docs/<slug>.json` (a translation: `docs/<language>/<slug>.json`, and the English file when it does not exist) on the server, cached by Next.js for an hour by default. The Download PDF button of `PolicyDocument` links to the PDF on the same host; the browser requests it only when it is clicked. The other components send no requests.
|
|
241
|
+
`RemoteLogo` requests its `url` on the server (by default `tuwa.io/brand/logo_v2.svg`), cached by Next.js for 24 hours. `loadPolicy` requests `raw.githubusercontent.com/TuwaIO/workflows/main/docs/<slug>.json` (a translation: `docs/<language>/<slug>.json`, and the English file when it does not exist) on the server, cached by Next.js for an hour by default. The Download PDF button of `PolicyDocument` links to the PDF on the same host; the browser requests it only when it is clicked. `createDocsPage` and `LocalizedPage` send no requests: the translations are part of the page. The other components send no requests.
|
|
152
242
|
|
|
153
243
|
---
|
|
154
244
|
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// `tuwa-docs-i18n-check`: checks the translated pages of a TUWA documentation site (src/i18n/<locale>) against their
|
|
3
|
+
// English pages (src/content), run from the docs app (see README)
|
|
4
|
+
import { checkSiteTranslations } from '../dist/translationCheck.js';
|
|
5
|
+
|
|
6
|
+
checkSiteTranslations().then(
|
|
7
|
+
({ files, issues }) => {
|
|
8
|
+
for (const { file, message } of issues) console.error(`${file}: ${message}`);
|
|
9
|
+
if (issues.length > 0) {
|
|
10
|
+
console.error(`Translations: ${issues.length} problem(s) in ${files} translated page(s)`);
|
|
11
|
+
process.exit(1);
|
|
12
|
+
}
|
|
13
|
+
console.log(`Translations: ${files} translated page(s) match their English pages`);
|
|
14
|
+
},
|
|
15
|
+
(error) => {
|
|
16
|
+
console.error(error instanceof Error ? error.message : error);
|
|
17
|
+
process.exit(1);
|
|
18
|
+
},
|
|
19
|
+
);
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
"use client";
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
|
+
var DocsLayout_exports = {};
|
|
21
|
+
__export(DocsLayout_exports, {
|
|
22
|
+
DocsLayout: () => DocsLayout,
|
|
23
|
+
NextraDocsLayout: () => NextraDocsLayout
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(DocsLayout_exports);
|
|
26
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
27
|
+
var import_components = require("nextra/components");
|
|
28
|
+
var import_nextra_theme_docs = require("nextra-theme-docs");
|
|
29
|
+
var import_react = require("react");
|
|
30
|
+
var import_docsI18n = require("../docsI18n");
|
|
31
|
+
var import_locale = require("../locale");
|
|
32
|
+
var import_pageMap = require("../pageMap");
|
|
33
|
+
var import_Footer = require("./Footer");
|
|
34
|
+
var import_LocaleSwitcher = require("./LocaleSwitcher");
|
|
35
|
+
var import_NavBar = require("./NavBar");
|
|
36
|
+
function NextraDocsLayout({
|
|
37
|
+
logo,
|
|
38
|
+
links,
|
|
39
|
+
footerLinks,
|
|
40
|
+
pageMap,
|
|
41
|
+
docsRepositoryBase,
|
|
42
|
+
locale,
|
|
43
|
+
onLocaleChange,
|
|
44
|
+
labels,
|
|
45
|
+
sidebar,
|
|
46
|
+
children
|
|
47
|
+
}) {
|
|
48
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
49
|
+
import_nextra_theme_docs.Layout,
|
|
50
|
+
{
|
|
51
|
+
navbar: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_NavBar.Navbar, { logo, links, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
52
|
+
import_LocaleSwitcher.LocaleSwitcher,
|
|
53
|
+
{
|
|
54
|
+
locale,
|
|
55
|
+
onSelect: (code) => {
|
|
56
|
+
const picked = (0, import_locale.normalizeLocale)(code);
|
|
57
|
+
if (picked) onLocaleChange(picked);
|
|
58
|
+
},
|
|
59
|
+
ariaLabel: labels.selectLanguage
|
|
60
|
+
}
|
|
61
|
+
) }),
|
|
62
|
+
footer: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_Footer.Footer, { logo, links: footerLinks, labels: labels.footer, policyLanguage: (0, import_locale.policyLanguageOf)(locale) }),
|
|
63
|
+
pageMap,
|
|
64
|
+
docsRepositoryBase,
|
|
65
|
+
navigation: { prev: true, next: true },
|
|
66
|
+
...sidebar && { sidebar },
|
|
67
|
+
editLink: labels.nextra.editThisPage,
|
|
68
|
+
feedback: { content: labels.nextra.feedback },
|
|
69
|
+
lastUpdated: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_nextra_theme_docs.LastUpdated, { locale, children: labels.nextra.lastUpdated }),
|
|
70
|
+
toc: { title: labels.nextra.onThisPage, backToTop: labels.nextra.scrollToTop },
|
|
71
|
+
themeSwitch: {
|
|
72
|
+
light: labels.nextra.themeLight,
|
|
73
|
+
dark: labels.nextra.themeDark,
|
|
74
|
+
system: labels.nextra.themeSystem
|
|
75
|
+
},
|
|
76
|
+
search: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
77
|
+
import_components.Search,
|
|
78
|
+
{
|
|
79
|
+
placeholder: labels.nextra.searchPlaceholder,
|
|
80
|
+
emptyResult: labels.nextra.searchEmpty,
|
|
81
|
+
errorText: labels.nextra.searchError,
|
|
82
|
+
loading: labels.nextra.searchLoading
|
|
83
|
+
}
|
|
84
|
+
),
|
|
85
|
+
children
|
|
86
|
+
}
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
function LocalizedLayout({ pageMap, sidebarTitles, ...props }) {
|
|
90
|
+
const { locale, setLocale, t } = (0, import_docsI18n.useDocsI18n)();
|
|
91
|
+
const siteTitles = locale === "en" ? void 0 : sidebarTitles?.[locale];
|
|
92
|
+
const localizedPageMap = (0, import_react.useMemo)(
|
|
93
|
+
() => (0, import_pageMap.localizePageMap)(pageMap, { ...t.sidebar, ...siteTitles }),
|
|
94
|
+
[pageMap, t.sidebar, siteTitles]
|
|
95
|
+
);
|
|
96
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(NextraDocsLayout, { ...props, pageMap: localizedPageMap, locale, onLocaleChange: setLocale, labels: t });
|
|
97
|
+
}
|
|
98
|
+
function DocsLayout({ initialLocale, ...props }) {
|
|
99
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_docsI18n.DocsI18nProvider, { initialLocale, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LocalizedLayout, { ...props }) });
|
|
100
|
+
}
|
|
101
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
102
|
+
0 && (module.exports = {
|
|
103
|
+
DocsLayout,
|
|
104
|
+
NextraDocsLayout
|
|
105
|
+
});
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode, ComponentProps } from 'react';
|
|
3
|
+
import { PageMapItem } from 'nextra';
|
|
4
|
+
import { Layout } from 'nextra-theme-docs';
|
|
5
|
+
import { DocsLabels } from '../docsLabels.cjs';
|
|
6
|
+
import { TuwaLocale } from '../locale.cjs';
|
|
7
|
+
import { SocialLink } from './NavBar.cjs';
|
|
8
|
+
import '../policies.cjs';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Props of {@link DocsLayout}.
|
|
12
|
+
*/
|
|
13
|
+
interface DocsLayoutProps {
|
|
14
|
+
/** Logo of the site, for example `SiteLogo`; rendered in the navbar and the footer. */
|
|
15
|
+
logo: ReactNode;
|
|
16
|
+
/** External links of the navbar (default: `baseNavLinks`). */
|
|
17
|
+
links?: SocialLink[];
|
|
18
|
+
/** External links of the footer (default: `baseFooterLinks`). */
|
|
19
|
+
footerLinks?: SocialLink[];
|
|
20
|
+
/** The page map of the site, the result of `getPageMap()` of `nextra/page-map`. */
|
|
21
|
+
pageMap: PageMapItem[];
|
|
22
|
+
/** URL of the docs app in the repository, for the edit links (`https://github.com/TuwaIO/<repo>/tree/main/apps/docs`). */
|
|
23
|
+
docsRepositoryBase: string;
|
|
24
|
+
/**
|
|
25
|
+
* Sidebar titles of the site's own pages, by language and English title (for example `{ uk: { 'EVM Trackers
|
|
26
|
+
* Standalone': '…' } }`). `Introduction`, `Packages`, `Guides` and `Overview` are translated already.
|
|
27
|
+
*/
|
|
28
|
+
sidebarTitles?: Partial<Record<Exclude<TuwaLocale, 'en'>, Record<string, string>>>;
|
|
29
|
+
/** Fixed language (tests, previews): detection and the stored choice are skipped. */
|
|
30
|
+
initialLocale?: TuwaLocale;
|
|
31
|
+
/** The page and anything rendered next to it, such as a top loading bar. */
|
|
32
|
+
children: ReactNode;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Props of {@link NextraDocsLayout}.
|
|
36
|
+
*/
|
|
37
|
+
interface NextraDocsLayoutProps {
|
|
38
|
+
/** Logo of the site, for example `SiteLogo`; rendered in the navbar and the footer. */
|
|
39
|
+
logo: ReactNode;
|
|
40
|
+
/** External links of the navbar (default: `baseNavLinks`). */
|
|
41
|
+
links?: SocialLink[];
|
|
42
|
+
/** External links of the footer (default: `baseFooterLinks`). */
|
|
43
|
+
footerLinks?: SocialLink[];
|
|
44
|
+
/** The page map, already in the language of the reader (`localizePageMap`); passed to Nextra as it is. */
|
|
45
|
+
pageMap: PageMapItem[];
|
|
46
|
+
/** URL of the docs app in the repository, for the edit links. */
|
|
47
|
+
docsRepositoryBase: string;
|
|
48
|
+
/** The language of the reader, shown in the language switch and used for the dates and the policy links. */
|
|
49
|
+
locale: TuwaLocale;
|
|
50
|
+
/**
|
|
51
|
+
* Called with the language the reader picks in the switch.
|
|
52
|
+
*
|
|
53
|
+
* @param locale - The picked language.
|
|
54
|
+
*/
|
|
55
|
+
onLocaleChange: (locale: TuwaLocale) => void;
|
|
56
|
+
/** The interface texts of that language, `docsLabels[locale]`. */
|
|
57
|
+
labels: DocsLabels;
|
|
58
|
+
/** Options of the Nextra sidebar (the `sidebar` prop of its `Layout`), for example `{ defaultMenuCollapseLevel: 1 }`. */
|
|
59
|
+
sidebar?: ComponentProps<typeof Layout>['sidebar'];
|
|
60
|
+
/** The page and anything rendered next to it. */
|
|
61
|
+
children: ReactNode;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* The Nextra `Layout` of a TUWA documentation site in a given language: the docs-ui {@link Navbar} with the language
|
|
65
|
+
* switch after the links (the theme switch stays in the Nextra sidebar and the mobile menu), the {@link Footer}, the
|
|
66
|
+
* search, the table of contents, the edit, feedback and last-updated texts and the theme switch options from
|
|
67
|
+
* `labels`. It keeps no state: {@link DocsLayout} renders it with the language of its provider, and the docs hub with
|
|
68
|
+
* its own dictionaries, so every site words and wires its chrome the same way.
|
|
69
|
+
*
|
|
70
|
+
* @param props - See {@link NextraDocsLayoutProps}.
|
|
71
|
+
* @returns The layout.
|
|
72
|
+
*/
|
|
73
|
+
declare function NextraDocsLayout({ logo, links, footerLinks, pageMap, docsRepositoryBase, locale, onLocaleChange, labels, sidebar, children, }: NextraDocsLayoutProps): react.JSX.Element;
|
|
74
|
+
/**
|
|
75
|
+
* The layout of a TUWA project documentation site in three languages (English, Ukrainian, Simplified Chinese):
|
|
76
|
+
* {@link NextraDocsLayout} (the Nextra `Layout` with the docs-ui {@link Navbar}, the language switch after the links,
|
|
77
|
+
* the theme switch in the Nextra sidebar and the mobile menu, the {@link Footer}, the search, the table of contents,
|
|
78
|
+
* the edit, feedback and last-updated texts) and the sidebar titles in the language of the reader. Render it in the
|
|
79
|
+
* `<body>` of the root layout, around the page; pages rendered with `createDocsPage` (`@tuwaio/docs-ui/nextra/page`)
|
|
80
|
+
* switch to their translation.
|
|
81
|
+
*
|
|
82
|
+
* The URL never changes with the language. The server renders English; after mount the language is read from
|
|
83
|
+
* `tuwa-locale` in Local Storage, then the browser languages and the time zone (no cookie, no request), and a pick in
|
|
84
|
+
* the switch is saved to `tuwa-locale` (add the key to `PreferenceExpiry`, so it is forgotten after 30 days) and sets
|
|
85
|
+
* `<html lang>`.
|
|
86
|
+
*
|
|
87
|
+
* @param props - See {@link DocsLayoutProps}.
|
|
88
|
+
* @returns The layout.
|
|
89
|
+
*/
|
|
90
|
+
declare function DocsLayout({ initialLocale, ...props }: DocsLayoutProps): react.JSX.Element;
|
|
91
|
+
|
|
92
|
+
export { DocsLayout, NextraDocsLayout };
|
|
93
|
+
export type { DocsLayoutProps, NextraDocsLayoutProps };
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode, ComponentProps } from 'react';
|
|
3
|
+
import { PageMapItem } from 'nextra';
|
|
4
|
+
import { Layout } from 'nextra-theme-docs';
|
|
5
|
+
import { DocsLabels } from '../docsLabels.js';
|
|
6
|
+
import { TuwaLocale } from '../locale.js';
|
|
7
|
+
import { SocialLink } from './NavBar.js';
|
|
8
|
+
import '../policies.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Props of {@link DocsLayout}.
|
|
12
|
+
*/
|
|
13
|
+
interface DocsLayoutProps {
|
|
14
|
+
/** Logo of the site, for example `SiteLogo`; rendered in the navbar and the footer. */
|
|
15
|
+
logo: ReactNode;
|
|
16
|
+
/** External links of the navbar (default: `baseNavLinks`). */
|
|
17
|
+
links?: SocialLink[];
|
|
18
|
+
/** External links of the footer (default: `baseFooterLinks`). */
|
|
19
|
+
footerLinks?: SocialLink[];
|
|
20
|
+
/** The page map of the site, the result of `getPageMap()` of `nextra/page-map`. */
|
|
21
|
+
pageMap: PageMapItem[];
|
|
22
|
+
/** URL of the docs app in the repository, for the edit links (`https://github.com/TuwaIO/<repo>/tree/main/apps/docs`). */
|
|
23
|
+
docsRepositoryBase: string;
|
|
24
|
+
/**
|
|
25
|
+
* Sidebar titles of the site's own pages, by language and English title (for example `{ uk: { 'EVM Trackers
|
|
26
|
+
* Standalone': '…' } }`). `Introduction`, `Packages`, `Guides` and `Overview` are translated already.
|
|
27
|
+
*/
|
|
28
|
+
sidebarTitles?: Partial<Record<Exclude<TuwaLocale, 'en'>, Record<string, string>>>;
|
|
29
|
+
/** Fixed language (tests, previews): detection and the stored choice are skipped. */
|
|
30
|
+
initialLocale?: TuwaLocale;
|
|
31
|
+
/** The page and anything rendered next to it, such as a top loading bar. */
|
|
32
|
+
children: ReactNode;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Props of {@link NextraDocsLayout}.
|
|
36
|
+
*/
|
|
37
|
+
interface NextraDocsLayoutProps {
|
|
38
|
+
/** Logo of the site, for example `SiteLogo`; rendered in the navbar and the footer. */
|
|
39
|
+
logo: ReactNode;
|
|
40
|
+
/** External links of the navbar (default: `baseNavLinks`). */
|
|
41
|
+
links?: SocialLink[];
|
|
42
|
+
/** External links of the footer (default: `baseFooterLinks`). */
|
|
43
|
+
footerLinks?: SocialLink[];
|
|
44
|
+
/** The page map, already in the language of the reader (`localizePageMap`); passed to Nextra as it is. */
|
|
45
|
+
pageMap: PageMapItem[];
|
|
46
|
+
/** URL of the docs app in the repository, for the edit links. */
|
|
47
|
+
docsRepositoryBase: string;
|
|
48
|
+
/** The language of the reader, shown in the language switch and used for the dates and the policy links. */
|
|
49
|
+
locale: TuwaLocale;
|
|
50
|
+
/**
|
|
51
|
+
* Called with the language the reader picks in the switch.
|
|
52
|
+
*
|
|
53
|
+
* @param locale - The picked language.
|
|
54
|
+
*/
|
|
55
|
+
onLocaleChange: (locale: TuwaLocale) => void;
|
|
56
|
+
/** The interface texts of that language, `docsLabels[locale]`. */
|
|
57
|
+
labels: DocsLabels;
|
|
58
|
+
/** Options of the Nextra sidebar (the `sidebar` prop of its `Layout`), for example `{ defaultMenuCollapseLevel: 1 }`. */
|
|
59
|
+
sidebar?: ComponentProps<typeof Layout>['sidebar'];
|
|
60
|
+
/** The page and anything rendered next to it. */
|
|
61
|
+
children: ReactNode;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* The Nextra `Layout` of a TUWA documentation site in a given language: the docs-ui {@link Navbar} with the language
|
|
65
|
+
* switch after the links (the theme switch stays in the Nextra sidebar and the mobile menu), the {@link Footer}, the
|
|
66
|
+
* search, the table of contents, the edit, feedback and last-updated texts and the theme switch options from
|
|
67
|
+
* `labels`. It keeps no state: {@link DocsLayout} renders it with the language of its provider, and the docs hub with
|
|
68
|
+
* its own dictionaries, so every site words and wires its chrome the same way.
|
|
69
|
+
*
|
|
70
|
+
* @param props - See {@link NextraDocsLayoutProps}.
|
|
71
|
+
* @returns The layout.
|
|
72
|
+
*/
|
|
73
|
+
declare function NextraDocsLayout({ logo, links, footerLinks, pageMap, docsRepositoryBase, locale, onLocaleChange, labels, sidebar, children, }: NextraDocsLayoutProps): react.JSX.Element;
|
|
74
|
+
/**
|
|
75
|
+
* The layout of a TUWA project documentation site in three languages (English, Ukrainian, Simplified Chinese):
|
|
76
|
+
* {@link NextraDocsLayout} (the Nextra `Layout` with the docs-ui {@link Navbar}, the language switch after the links,
|
|
77
|
+
* the theme switch in the Nextra sidebar and the mobile menu, the {@link Footer}, the search, the table of contents,
|
|
78
|
+
* the edit, feedback and last-updated texts) and the sidebar titles in the language of the reader. Render it in the
|
|
79
|
+
* `<body>` of the root layout, around the page; pages rendered with `createDocsPage` (`@tuwaio/docs-ui/nextra/page`)
|
|
80
|
+
* switch to their translation.
|
|
81
|
+
*
|
|
82
|
+
* The URL never changes with the language. The server renders English; after mount the language is read from
|
|
83
|
+
* `tuwa-locale` in Local Storage, then the browser languages and the time zone (no cookie, no request), and a pick in
|
|
84
|
+
* the switch is saved to `tuwa-locale` (add the key to `PreferenceExpiry`, so it is forgotten after 30 days) and sets
|
|
85
|
+
* `<html lang>`.
|
|
86
|
+
*
|
|
87
|
+
* @param props - See {@link DocsLayoutProps}.
|
|
88
|
+
* @returns The layout.
|
|
89
|
+
*/
|
|
90
|
+
declare function DocsLayout({ initialLocale, ...props }: DocsLayoutProps): react.JSX.Element;
|
|
91
|
+
|
|
92
|
+
export { DocsLayout, NextraDocsLayout };
|
|
93
|
+
export type { DocsLayoutProps, NextraDocsLayoutProps };
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import { Search } from "nextra/components";
|
|
4
|
+
import { LastUpdated, Layout } from "nextra-theme-docs";
|
|
5
|
+
import { useMemo } from "react";
|
|
6
|
+
import { DocsI18nProvider, useDocsI18n } from "../docsI18n";
|
|
7
|
+
import { normalizeLocale, policyLanguageOf } from "../locale";
|
|
8
|
+
import { localizePageMap } from "../pageMap";
|
|
9
|
+
import { Footer } from "./Footer";
|
|
10
|
+
import { LocaleSwitcher } from "./LocaleSwitcher";
|
|
11
|
+
import { Navbar } from "./NavBar";
|
|
12
|
+
function NextraDocsLayout({
|
|
13
|
+
logo,
|
|
14
|
+
links,
|
|
15
|
+
footerLinks,
|
|
16
|
+
pageMap,
|
|
17
|
+
docsRepositoryBase,
|
|
18
|
+
locale,
|
|
19
|
+
onLocaleChange,
|
|
20
|
+
labels,
|
|
21
|
+
sidebar,
|
|
22
|
+
children
|
|
23
|
+
}) {
|
|
24
|
+
return /* @__PURE__ */ jsx(
|
|
25
|
+
Layout,
|
|
26
|
+
{
|
|
27
|
+
navbar: /* @__PURE__ */ jsx(Navbar, { logo, links, children: /* @__PURE__ */ jsx(
|
|
28
|
+
LocaleSwitcher,
|
|
29
|
+
{
|
|
30
|
+
locale,
|
|
31
|
+
onSelect: (code) => {
|
|
32
|
+
const picked = normalizeLocale(code);
|
|
33
|
+
if (picked) onLocaleChange(picked);
|
|
34
|
+
},
|
|
35
|
+
ariaLabel: labels.selectLanguage
|
|
36
|
+
}
|
|
37
|
+
) }),
|
|
38
|
+
footer: /* @__PURE__ */ jsx(Footer, { logo, links: footerLinks, labels: labels.footer, policyLanguage: policyLanguageOf(locale) }),
|
|
39
|
+
pageMap,
|
|
40
|
+
docsRepositoryBase,
|
|
41
|
+
navigation: { prev: true, next: true },
|
|
42
|
+
...sidebar && { sidebar },
|
|
43
|
+
editLink: labels.nextra.editThisPage,
|
|
44
|
+
feedback: { content: labels.nextra.feedback },
|
|
45
|
+
lastUpdated: /* @__PURE__ */ jsx(LastUpdated, { locale, children: labels.nextra.lastUpdated }),
|
|
46
|
+
toc: { title: labels.nextra.onThisPage, backToTop: labels.nextra.scrollToTop },
|
|
47
|
+
themeSwitch: {
|
|
48
|
+
light: labels.nextra.themeLight,
|
|
49
|
+
dark: labels.nextra.themeDark,
|
|
50
|
+
system: labels.nextra.themeSystem
|
|
51
|
+
},
|
|
52
|
+
search: /* @__PURE__ */ jsx(
|
|
53
|
+
Search,
|
|
54
|
+
{
|
|
55
|
+
placeholder: labels.nextra.searchPlaceholder,
|
|
56
|
+
emptyResult: labels.nextra.searchEmpty,
|
|
57
|
+
errorText: labels.nextra.searchError,
|
|
58
|
+
loading: labels.nextra.searchLoading
|
|
59
|
+
}
|
|
60
|
+
),
|
|
61
|
+
children
|
|
62
|
+
}
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
function LocalizedLayout({ pageMap, sidebarTitles, ...props }) {
|
|
66
|
+
const { locale, setLocale, t } = useDocsI18n();
|
|
67
|
+
const siteTitles = locale === "en" ? void 0 : sidebarTitles?.[locale];
|
|
68
|
+
const localizedPageMap = useMemo(
|
|
69
|
+
() => localizePageMap(pageMap, { ...t.sidebar, ...siteTitles }),
|
|
70
|
+
[pageMap, t.sidebar, siteTitles]
|
|
71
|
+
);
|
|
72
|
+
return /* @__PURE__ */ jsx(NextraDocsLayout, { ...props, pageMap: localizedPageMap, locale, onLocaleChange: setLocale, labels: t });
|
|
73
|
+
}
|
|
74
|
+
function DocsLayout({ initialLocale, ...props }) {
|
|
75
|
+
return /* @__PURE__ */ jsx(DocsI18nProvider, { initialLocale, children: /* @__PURE__ */ jsx(LocalizedLayout, { ...props }) });
|
|
76
|
+
}
|
|
77
|
+
export {
|
|
78
|
+
DocsLayout,
|
|
79
|
+
NextraDocsLayout
|
|
80
|
+
};
|
|
@@ -82,12 +82,7 @@ function Footer({ links, logo, labels, policyLanguage = "en" }) {
|
|
|
82
82
|
}
|
|
83
83
|
)
|
|
84
84
|
] }),
|
|
85
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "tuwadocs:flex tuwadocs:flex-wrap tuwadocs:items-center tuwadocs:justify-center tuwadocs:gap-3 tuwadocs:mt-4 tuwadocs:pt-4 tuwa-footer-border", children: /* @__PURE__ */ (0, import_jsx_runtime.
|
|
86
|
-
"\xA9 2025 - ",
|
|
87
|
-
(/* @__PURE__ */ new Date()).getFullYear(),
|
|
88
|
-
" TUWA. ",
|
|
89
|
-
labels?.copyright ?? "All rights reserved."
|
|
90
|
-
] }) })
|
|
85
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "tuwadocs:flex tuwadocs:flex-wrap tuwadocs:items-center tuwadocs:justify-center tuwadocs:gap-3 tuwadocs:mt-4 tuwadocs:pt-4 tuwa-footer-border", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "tuwa-footer-copyright", suppressHydrationWarning: true, children: `\xA9 2025 - ${(/* @__PURE__ */ new Date()).getFullYear()} TUWA. ${labels?.copyright ?? "All rights reserved."}` }) })
|
|
91
86
|
] })
|
|
92
87
|
] }) });
|
|
93
88
|
}
|
|
@@ -31,8 +31,9 @@ interface FooterProps extends NavProps {
|
|
|
31
31
|
/**
|
|
32
32
|
* The footer of a TUWA documentation site: the `Footer` of `nextra-theme-docs` with the logo, external links, the
|
|
33
33
|
* TUWA description and the license on the left, links to the policies in force on tuwa.io (`footerPolicies`) and to
|
|
34
|
-
* the list of all policies on the docs hub on the right, and the copyright line (the current year is read on render
|
|
35
|
-
*
|
|
34
|
+
* the list of all policies on the docs hub on the right, and the copyright line (the current year is read on render;
|
|
35
|
+
* while a prerendered page hydrates, the year of its HTML stays without a hydration error) centered below; on narrow
|
|
36
|
+
* screens everything is centered. Render it in the `footer` prop of the Nextra `Layout`.
|
|
36
37
|
*
|
|
37
38
|
* @param props - See {@link FooterProps}.
|
|
38
39
|
* @returns The footer.
|
|
@@ -31,8 +31,9 @@ interface FooterProps extends NavProps {
|
|
|
31
31
|
/**
|
|
32
32
|
* The footer of a TUWA documentation site: the `Footer` of `nextra-theme-docs` with the logo, external links, the
|
|
33
33
|
* TUWA description and the license on the left, links to the policies in force on tuwa.io (`footerPolicies`) and to
|
|
34
|
-
* the list of all policies on the docs hub on the right, and the copyright line (the current year is read on render
|
|
35
|
-
*
|
|
34
|
+
* the list of all policies on the docs hub on the right, and the copyright line (the current year is read on render;
|
|
35
|
+
* while a prerendered page hydrates, the year of its HTML stays without a hydration error) centered below; on narrow
|
|
36
|
+
* screens everything is centered. Render it in the `footer` prop of the Nextra `Layout`.
|
|
36
37
|
*
|
|
37
38
|
* @param props - See {@link FooterProps}.
|
|
38
39
|
* @returns The footer.
|
|
@@ -63,12 +63,7 @@ function Footer({ links, logo, labels, policyLanguage = "en" }) {
|
|
|
63
63
|
}
|
|
64
64
|
)
|
|
65
65
|
] }),
|
|
66
|
-
/* @__PURE__ */ jsx("div", { className: "tuwadocs:flex tuwadocs:flex-wrap tuwadocs:items-center tuwadocs:justify-center tuwadocs:gap-3 tuwadocs:mt-4 tuwadocs:pt-4 tuwa-footer-border", children: /* @__PURE__ */
|
|
67
|
-
"\xA9 2025 - ",
|
|
68
|
-
(/* @__PURE__ */ new Date()).getFullYear(),
|
|
69
|
-
" TUWA. ",
|
|
70
|
-
labels?.copyright ?? "All rights reserved."
|
|
71
|
-
] }) })
|
|
66
|
+
/* @__PURE__ */ jsx("div", { className: "tuwadocs:flex tuwadocs:flex-wrap tuwadocs:items-center tuwadocs:justify-center tuwadocs:gap-3 tuwadocs:mt-4 tuwadocs:pt-4 tuwa-footer-border", children: /* @__PURE__ */ jsx("div", { className: "tuwa-footer-copyright", suppressHydrationWarning: true, children: `\xA9 2025 - ${(/* @__PURE__ */ new Date()).getFullYear()} TUWA. ${labels?.copyright ?? "All rights reserved."}` }) })
|
|
72
67
|
] })
|
|
73
68
|
] }) });
|
|
74
69
|
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
"use client";
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
|
+
var LocalizedPage_exports = {};
|
|
21
|
+
__export(LocalizedPage_exports, {
|
|
22
|
+
LocalizedPage: () => LocalizedPage
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(LocalizedPage_exports);
|
|
25
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
26
|
+
var import_components = require("nextra/components");
|
|
27
|
+
var import_nextra_theme_docs = require("nextra-theme-docs");
|
|
28
|
+
var import_docsI18n = require("../docsI18n");
|
|
29
|
+
function LocalizedPage({ variants }) {
|
|
30
|
+
const { locale, t } = (0, import_docsI18n.useDocsI18n)();
|
|
31
|
+
const Wrapper = (0, import_nextra_theme_docs.useMDXComponents)().wrapper;
|
|
32
|
+
const translated = variants[locale];
|
|
33
|
+
const page = translated ?? variants.en;
|
|
34
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Wrapper, { toc: page.toc, metadata: page.metadata, sourceCode: page.sourceCode, children: [
|
|
35
|
+
!translated && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "tuwadocs:clear-both", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_components.Callout, { type: "info", children: t.englishOnly }) }),
|
|
36
|
+
page.content
|
|
37
|
+
] });
|
|
38
|
+
}
|
|
39
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
40
|
+
0 && (module.exports = {
|
|
41
|
+
LocalizedPage
|
|
42
|
+
});
|