@tuwaio/docs-ui 0.6.0 → 0.7.1
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 +3 -1
- package/dist/components/DocsLayout.cjs +45 -22
- package/dist/components/DocsLayout.d.cts +52 -9
- package/dist/components/DocsLayout.d.ts +52 -9
- package/dist/components/DocsLayout.js +44 -22
- 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/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/nextra.d.cts +4 -3
- package/dist/nextra.d.ts +4 -3
- package/dist/pageMap.cjs +27 -16
- package/dist/pageMap.d.cts +18 -5
- package/dist/pageMap.d.ts +18 -5
- package/dist/pageMap.js +27 -16
- package/dist/translationCheck.cjs +5 -0
- package/dist/translationCheck.d.cts +3 -2
- package/dist/translationCheck.d.ts +3 -2
- package/dist/translationCheck.js +5 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -197,7 +197,7 @@ declare module '*.mdx' {
|
|
|
197
197
|
}
|
|
198
198
|
```
|
|
199
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; add it to the build and to the pre-commit hook:
|
|
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
201
|
|
|
202
202
|
```json
|
|
203
203
|
{
|
|
@@ -210,6 +210,8 @@ A translation keeps the structure of its English page: the same code blocks in t
|
|
|
210
210
|
|
|
211
211
|
Client components inside `DocsLayout` read the language and the interface texts with `useDocsI18n()`.
|
|
212
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
|
+
|
|
213
215
|
### Search index
|
|
214
216
|
|
|
215
217
|
Run the command after `next build`. It uses the `pagefind` package of the site, so add it to the site's dependencies:
|
|
@@ -19,7 +19,8 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
19
19
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
20
|
var DocsLayout_exports = {};
|
|
21
21
|
__export(DocsLayout_exports, {
|
|
22
|
-
DocsLayout: () => DocsLayout
|
|
22
|
+
DocsLayout: () => DocsLayout,
|
|
23
|
+
NextraDocsLayout: () => NextraDocsLayout
|
|
23
24
|
});
|
|
24
25
|
module.exports = __toCommonJS(DocsLayout_exports);
|
|
25
26
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
@@ -32,51 +33,73 @@ var import_pageMap = require("../pageMap");
|
|
|
32
33
|
var import_Footer = require("./Footer");
|
|
33
34
|
var import_LocaleSwitcher = require("./LocaleSwitcher");
|
|
34
35
|
var import_NavBar = require("./NavBar");
|
|
35
|
-
function
|
|
36
|
+
function NextraDocsLayout({
|
|
36
37
|
logo,
|
|
37
38
|
links,
|
|
38
39
|
footerLinks,
|
|
39
40
|
pageMap,
|
|
40
41
|
docsRepositoryBase,
|
|
41
|
-
|
|
42
|
+
locale,
|
|
43
|
+
onLocaleChange,
|
|
44
|
+
labels,
|
|
45
|
+
sidebar,
|
|
42
46
|
children
|
|
43
47
|
}) {
|
|
44
|
-
const { locale, setLocale, t } = (0, import_docsI18n.useDocsI18n)();
|
|
45
|
-
const siteTitles = locale === "en" ? void 0 : sidebarTitles?.[locale];
|
|
46
|
-
const localizedPageMap = (0, import_react.useMemo)(
|
|
47
|
-
() => (0, import_pageMap.localizePageMap)(pageMap, { ...t.sidebar, ...siteTitles }),
|
|
48
|
-
[pageMap, t.sidebar, siteTitles]
|
|
49
|
-
);
|
|
50
48
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
51
49
|
import_nextra_theme_docs.Layout,
|
|
52
50
|
{
|
|
53
|
-
navbar: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_NavBar.Navbar, { logo, links, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
54
|
-
|
|
55
|
-
|
|
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,
|
|
56
64
|
docsRepositoryBase,
|
|
57
65
|
navigation: { prev: true, next: true },
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
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
|
+
},
|
|
63
76
|
search: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
64
77
|
import_components.Search,
|
|
65
78
|
{
|
|
66
|
-
placeholder:
|
|
67
|
-
emptyResult:
|
|
68
|
-
errorText:
|
|
69
|
-
loading:
|
|
79
|
+
placeholder: labels.nextra.searchPlaceholder,
|
|
80
|
+
emptyResult: labels.nextra.searchEmpty,
|
|
81
|
+
errorText: labels.nextra.searchError,
|
|
82
|
+
loading: labels.nextra.searchLoading
|
|
70
83
|
}
|
|
71
84
|
),
|
|
72
85
|
children
|
|
73
86
|
}
|
|
74
87
|
);
|
|
75
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
|
+
}
|
|
76
98
|
function DocsLayout({ initialLocale, ...props }) {
|
|
77
99
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_docsI18n.DocsI18nProvider, { initialLocale, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LocalizedLayout, { ...props }) });
|
|
78
100
|
}
|
|
79
101
|
// Annotate the CommonJS export names for ESM import in node:
|
|
80
102
|
0 && (module.exports = {
|
|
81
|
-
DocsLayout
|
|
103
|
+
DocsLayout,
|
|
104
|
+
NextraDocsLayout
|
|
82
105
|
});
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
|
-
import { ReactNode } from 'react';
|
|
2
|
+
import { ReactNode, ComponentProps } from 'react';
|
|
3
3
|
import { PageMapItem } from 'nextra';
|
|
4
|
+
import { Layout } from 'nextra-theme-docs';
|
|
5
|
+
import { DocsLabels } from '../docsLabels.cjs';
|
|
4
6
|
import { TuwaLocale } from '../locale.cjs';
|
|
5
7
|
import { SocialLink } from './NavBar.cjs';
|
|
8
|
+
import '../policies.cjs';
|
|
6
9
|
|
|
7
10
|
/**
|
|
8
11
|
* Props of {@link DocsLayout}.
|
|
@@ -29,12 +32,52 @@ interface DocsLayoutProps {
|
|
|
29
32
|
children: ReactNode;
|
|
30
33
|
}
|
|
31
34
|
/**
|
|
32
|
-
*
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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.
|
|
38
81
|
*
|
|
39
82
|
* The URL never changes with the language. The server renders English; after mount the language is read from
|
|
40
83
|
* `tuwa-locale` in Local Storage, then the browser languages and the time zone (no cookie, no request), and a pick in
|
|
@@ -46,5 +89,5 @@ interface DocsLayoutProps {
|
|
|
46
89
|
*/
|
|
47
90
|
declare function DocsLayout({ initialLocale, ...props }: DocsLayoutProps): react.JSX.Element;
|
|
48
91
|
|
|
49
|
-
export { DocsLayout };
|
|
50
|
-
export type { DocsLayoutProps };
|
|
92
|
+
export { DocsLayout, NextraDocsLayout };
|
|
93
|
+
export type { DocsLayoutProps, NextraDocsLayoutProps };
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
|
-
import { ReactNode } from 'react';
|
|
2
|
+
import { ReactNode, ComponentProps } from 'react';
|
|
3
3
|
import { PageMapItem } from 'nextra';
|
|
4
|
+
import { Layout } from 'nextra-theme-docs';
|
|
5
|
+
import { DocsLabels } from '../docsLabels.js';
|
|
4
6
|
import { TuwaLocale } from '../locale.js';
|
|
5
7
|
import { SocialLink } from './NavBar.js';
|
|
8
|
+
import '../policies.js';
|
|
6
9
|
|
|
7
10
|
/**
|
|
8
11
|
* Props of {@link DocsLayout}.
|
|
@@ -29,12 +32,52 @@ interface DocsLayoutProps {
|
|
|
29
32
|
children: ReactNode;
|
|
30
33
|
}
|
|
31
34
|
/**
|
|
32
|
-
*
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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.
|
|
38
81
|
*
|
|
39
82
|
* The URL never changes with the language. The server renders English; after mount the language is read from
|
|
40
83
|
* `tuwa-locale` in Local Storage, then the browser languages and the time zone (no cookie, no request), and a pick in
|
|
@@ -46,5 +89,5 @@ interface DocsLayoutProps {
|
|
|
46
89
|
*/
|
|
47
90
|
declare function DocsLayout({ initialLocale, ...props }: DocsLayoutProps): react.JSX.Element;
|
|
48
91
|
|
|
49
|
-
export { DocsLayout };
|
|
50
|
-
export type { DocsLayoutProps };
|
|
92
|
+
export { DocsLayout, NextraDocsLayout };
|
|
93
|
+
export type { DocsLayoutProps, NextraDocsLayoutProps };
|
|
@@ -4,55 +4,77 @@ import { Search } from "nextra/components";
|
|
|
4
4
|
import { LastUpdated, Layout } from "nextra-theme-docs";
|
|
5
5
|
import { useMemo } from "react";
|
|
6
6
|
import { DocsI18nProvider, useDocsI18n } from "../docsI18n";
|
|
7
|
-
import { policyLanguageOf } from "../locale";
|
|
7
|
+
import { normalizeLocale, policyLanguageOf } from "../locale";
|
|
8
8
|
import { localizePageMap } from "../pageMap";
|
|
9
9
|
import { Footer } from "./Footer";
|
|
10
10
|
import { LocaleSwitcher } from "./LocaleSwitcher";
|
|
11
11
|
import { Navbar } from "./NavBar";
|
|
12
|
-
function
|
|
12
|
+
function NextraDocsLayout({
|
|
13
13
|
logo,
|
|
14
14
|
links,
|
|
15
15
|
footerLinks,
|
|
16
16
|
pageMap,
|
|
17
17
|
docsRepositoryBase,
|
|
18
|
-
|
|
18
|
+
locale,
|
|
19
|
+
onLocaleChange,
|
|
20
|
+
labels,
|
|
21
|
+
sidebar,
|
|
19
22
|
children
|
|
20
23
|
}) {
|
|
21
|
-
const { locale, setLocale, t } = useDocsI18n();
|
|
22
|
-
const siteTitles = locale === "en" ? void 0 : sidebarTitles?.[locale];
|
|
23
|
-
const localizedPageMap = useMemo(
|
|
24
|
-
() => localizePageMap(pageMap, { ...t.sidebar, ...siteTitles }),
|
|
25
|
-
[pageMap, t.sidebar, siteTitles]
|
|
26
|
-
);
|
|
27
24
|
return /* @__PURE__ */ jsx(
|
|
28
25
|
Layout,
|
|
29
26
|
{
|
|
30
|
-
navbar: /* @__PURE__ */ jsx(Navbar, { logo, links, children: /* @__PURE__ */ jsx(
|
|
31
|
-
|
|
32
|
-
|
|
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,
|
|
33
40
|
docsRepositoryBase,
|
|
34
41
|
navigation: { prev: true, next: true },
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
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
|
+
},
|
|
40
52
|
search: /* @__PURE__ */ jsx(
|
|
41
53
|
Search,
|
|
42
54
|
{
|
|
43
|
-
placeholder:
|
|
44
|
-
emptyResult:
|
|
45
|
-
errorText:
|
|
46
|
-
loading:
|
|
55
|
+
placeholder: labels.nextra.searchPlaceholder,
|
|
56
|
+
emptyResult: labels.nextra.searchEmpty,
|
|
57
|
+
errorText: labels.nextra.searchError,
|
|
58
|
+
loading: labels.nextra.searchLoading
|
|
47
59
|
}
|
|
48
60
|
),
|
|
49
61
|
children
|
|
50
62
|
}
|
|
51
63
|
);
|
|
52
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
|
+
}
|
|
53
74
|
function DocsLayout({ initialLocale, ...props }) {
|
|
54
75
|
return /* @__PURE__ */ jsx(DocsI18nProvider, { initialLocale, children: /* @__PURE__ */ jsx(LocalizedLayout, { ...props }) });
|
|
55
76
|
}
|
|
56
77
|
export {
|
|
57
|
-
DocsLayout
|
|
78
|
+
DocsLayout,
|
|
79
|
+
NextraDocsLayout
|
|
58
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
|
}
|
package/dist/index.d.cts
CHANGED
|
@@ -10,7 +10,7 @@ export { ThemeSwitcher, ThemeSwitcherProps } from './components/ThemeSwitcher.cj
|
|
|
10
10
|
export { DocsLabels, docsLabels } from './docsLabels.cjs';
|
|
11
11
|
export { I18nContextValue, I18nKit, I18nProviderProps, LocaleState, LocaleStateOptions, LocaleVariant, createI18n, useLocaleState } from './i18n.cjs';
|
|
12
12
|
export { DEFAULT_LOCALE, LOCALE_STORAGE_KEY, LocaleSignals, TUWA_LOCALES, TuwaLocale, detectLocale, formatLabel, normalizeLocale, policyLanguageOf, resolveClientLocale } from './locale.cjs';
|
|
13
|
-
export { localizePageMap } from './pageMap.cjs';
|
|
13
|
+
export { LocalizePageMapOptions, localizePageMap } from './pageMap.cjs';
|
|
14
14
|
export { POLICIES_INDEX_URL, POLICY_DOCUMENT_LABELS, POLICY_LANGUAGES, POLICY_LANGUAGE_NAMES, POLICY_SITE_URL, POLICY_SOURCE, Policy, PolicyContent, PolicyDocumentLabels, PolicyLanguage, PolicySection, PolicySlug, footerPolicies, formatPolicyDate, getPolicyFileUrl, getPolicyPageUrl, loadPolicy, policies, policyLanguageFrom, publishedPolicies } from './policies.cjs';
|
|
15
15
|
export { PREFERENCE_DAYS, PreferenceExpiry, expireStoredPreferences } from './preferences.cjs';
|
|
16
16
|
export { baseFooterLinks, baseNavLinks } from './utils.cjs';
|
package/dist/index.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ export { ThemeSwitcher, ThemeSwitcherProps } from './components/ThemeSwitcher.js
|
|
|
10
10
|
export { DocsLabels, docsLabels } from './docsLabels.js';
|
|
11
11
|
export { I18nContextValue, I18nKit, I18nProviderProps, LocaleState, LocaleStateOptions, LocaleVariant, createI18n, useLocaleState } from './i18n.js';
|
|
12
12
|
export { DEFAULT_LOCALE, LOCALE_STORAGE_KEY, LocaleSignals, TUWA_LOCALES, TuwaLocale, detectLocale, formatLabel, normalizeLocale, policyLanguageOf, resolveClientLocale } from './locale.js';
|
|
13
|
-
export { localizePageMap } from './pageMap.js';
|
|
13
|
+
export { LocalizePageMapOptions, localizePageMap } from './pageMap.js';
|
|
14
14
|
export { POLICIES_INDEX_URL, POLICY_DOCUMENT_LABELS, POLICY_LANGUAGES, POLICY_LANGUAGE_NAMES, POLICY_SITE_URL, POLICY_SOURCE, Policy, PolicyContent, PolicyDocumentLabels, PolicyLanguage, PolicySection, PolicySlug, footerPolicies, formatPolicyDate, getPolicyFileUrl, getPolicyPageUrl, loadPolicy, policies, policyLanguageFrom, publishedPolicies } from './policies.js';
|
|
15
15
|
export { PREFERENCE_DAYS, PreferenceExpiry, expireStoredPreferences } from './preferences.js';
|
|
16
16
|
export { baseFooterLinks, baseNavLinks } from './utils.js';
|
package/dist/nextra.d.cts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
export { DocsLayout, DocsLayoutProps } from './components/DocsLayout.cjs';
|
|
1
|
+
export { DocsLayout, DocsLayoutProps, NextraDocsLayout, NextraDocsLayoutProps } from './components/DocsLayout.cjs';
|
|
2
2
|
export { LocalizedPage, LocalizedPageProps, LocalizedPageVariant } from './components/LocalizedPage.cjs';
|
|
3
3
|
export { DocsI18nProvider, useDocsI18n } from './docsI18n.cjs';
|
|
4
4
|
import 'react';
|
|
5
5
|
import 'nextra';
|
|
6
|
-
import '
|
|
7
|
-
import './components/NavBar.cjs';
|
|
6
|
+
import 'nextra-theme-docs';
|
|
8
7
|
import './docsLabels.cjs';
|
|
8
|
+
import './locale.cjs';
|
|
9
9
|
import './policies.cjs';
|
|
10
|
+
import './components/NavBar.cjs';
|
|
10
11
|
import './i18n.cjs';
|
package/dist/nextra.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
export { DocsLayout, DocsLayoutProps } from './components/DocsLayout.js';
|
|
1
|
+
export { DocsLayout, DocsLayoutProps, NextraDocsLayout, NextraDocsLayoutProps } from './components/DocsLayout.js';
|
|
2
2
|
export { LocalizedPage, LocalizedPageProps, LocalizedPageVariant } from './components/LocalizedPage.js';
|
|
3
3
|
export { DocsI18nProvider, useDocsI18n } from './docsI18n.js';
|
|
4
4
|
import 'react';
|
|
5
5
|
import 'nextra';
|
|
6
|
-
import '
|
|
7
|
-
import './components/NavBar.js';
|
|
6
|
+
import 'nextra-theme-docs';
|
|
8
7
|
import './docsLabels.js';
|
|
8
|
+
import './locale.js';
|
|
9
9
|
import './policies.js';
|
|
10
|
+
import './components/NavBar.js';
|
|
10
11
|
import './i18n.js';
|
package/dist/pageMap.cjs
CHANGED
|
@@ -21,34 +21,45 @@ __export(pageMap_exports, {
|
|
|
21
21
|
localizePageMap: () => localizePageMap
|
|
22
22
|
});
|
|
23
23
|
module.exports = __toCommonJS(pageMap_exports);
|
|
24
|
-
function localizeMetaValue(value, titles) {
|
|
25
|
-
if (typeof value === "string") return titles[value] ?? value;
|
|
26
|
-
if (value
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
30
|
-
return value;
|
|
24
|
+
function localizeMetaValue(value, routeTitle, titles) {
|
|
25
|
+
if (typeof value === "string") return routeTitle ?? titles[value] ?? value;
|
|
26
|
+
if (!value || typeof value !== "object" || !("title" in value)) return value;
|
|
27
|
+
const title = value.title;
|
|
28
|
+
const translated = routeTitle ?? (typeof title === "string" ? titles[title] : void 0);
|
|
29
|
+
return translated ? { ...value, title: translated } : value;
|
|
31
30
|
}
|
|
32
|
-
function
|
|
33
|
-
|
|
34
|
-
return
|
|
31
|
+
function localizeItems(items, titles, routes, parent) {
|
|
32
|
+
const routeTitle = (name) => routes[parent ? `${parent}/${name}` : name] ?? routes[name];
|
|
33
|
+
return items.map((item) => {
|
|
35
34
|
if ("data" in item) {
|
|
36
35
|
const data = Object.fromEntries(
|
|
37
|
-
Object.entries(item.data).map(([key, value]) => [key, localizeMetaValue(value, titles)])
|
|
36
|
+
Object.entries(item.data).map(([key, value]) => [key, localizeMetaValue(value, routeTitle(key), titles)])
|
|
38
37
|
);
|
|
39
38
|
return { ...item, data };
|
|
40
39
|
}
|
|
41
40
|
const copy = { ...item };
|
|
41
|
+
const name = item.name;
|
|
42
|
+
const route = typeof name === "string" ? parent ? `${parent}/${name}` : name : parent;
|
|
43
|
+
const byRoute = typeof name === "string" ? routeTitle(name) : void 0;
|
|
42
44
|
const title = item.title;
|
|
43
|
-
if (
|
|
44
|
-
if (
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
if (byRoute) copy.title = byRoute;
|
|
46
|
+
else if (typeof title === "string" && titles[title]) copy.title = titles[title];
|
|
47
|
+
if ("frontMatter" in item && item.frontMatter) {
|
|
48
|
+
const frontTitle = item.frontMatter.title;
|
|
49
|
+
const translated = byRoute ?? (typeof frontTitle === "string" ? titles[frontTitle] : void 0);
|
|
50
|
+
if (translated) copy.frontMatter = { ...item.frontMatter, title: translated };
|
|
51
|
+
}
|
|
52
|
+
if ("children" in item && Array.isArray(item.children)) {
|
|
53
|
+
copy.children = localizeItems(item.children, titles, routes, route);
|
|
47
54
|
}
|
|
48
|
-
if ("children" in item && Array.isArray(item.children)) copy.children = localizePageMap(item.children, titles);
|
|
49
55
|
return copy;
|
|
50
56
|
});
|
|
51
57
|
}
|
|
58
|
+
function localizePageMap(pageMap, titles, options = {}) {
|
|
59
|
+
const routes = options.routes ?? {};
|
|
60
|
+
if (Object.keys(titles).length === 0 && Object.keys(routes).length === 0) return pageMap;
|
|
61
|
+
return localizeItems(pageMap, titles, routes);
|
|
62
|
+
}
|
|
52
63
|
// Annotate the CommonJS export names for ESM import in node:
|
|
53
64
|
0 && (module.exports = {
|
|
54
65
|
localizePageMap
|
package/dist/pageMap.d.cts
CHANGED
|
@@ -1,20 +1,33 @@
|
|
|
1
1
|
import { PageMapItem } from 'nextra';
|
|
2
2
|
|
|
3
|
+
/** Options of {@link localizePageMap}. */
|
|
4
|
+
interface LocalizePageMapOptions {
|
|
5
|
+
/**
|
|
6
|
+
* Translated titles by route instead of English title: `<folder>/<name>` (for example `guides/full-stack-react`),
|
|
7
|
+
* then the bare `<name>` (`guides`, `index`). A route title wins over an English title and also replaces the front
|
|
8
|
+
* matter `title`. The docs hub keys its sidebar this way.
|
|
9
|
+
*/
|
|
10
|
+
routes?: Readonly<Record<string, string>>;
|
|
11
|
+
}
|
|
3
12
|
/**
|
|
4
13
|
* Translates the titles of a Nextra page map: the sidebar, the top-level menu, the breadcrumbs and the previous / next
|
|
5
|
-
* links all read them.
|
|
6
|
-
* front matter `title`), so a site lists each English title once, whatever the page; titles without a
|
|
7
|
-
* such as package names, stay as they are. The
|
|
14
|
+
* links all read them. The project sites match titles by their English text (the `_meta` titles, the `title` of each
|
|
15
|
+
* item and the front matter `title`), so a site lists each English title once, whatever the page; titles without a
|
|
16
|
+
* translation, such as package names, stay as they are. The docs hub matches them by route instead
|
|
17
|
+
* (`options.routes`). The page map is not modified: changed items are copied.
|
|
8
18
|
*
|
|
9
19
|
* @example
|
|
10
20
|
* ```ts
|
|
11
21
|
* localizePageMap(pageMap, { Introduction: 'Вступ', Packages: 'Пакети' });
|
|
22
|
+
* localizePageMap(pageMap, {}, { routes: { guides: 'Посібники', 'guides/starter-templates': 'Стартові шаблони' } });
|
|
12
23
|
* ```
|
|
13
24
|
*
|
|
14
25
|
* @param pageMap - The page map of the site, the result of `getPageMap()` of `nextra/page-map`.
|
|
15
26
|
* @param titles - Translated titles by English title.
|
|
16
|
-
* @
|
|
27
|
+
* @param options - See {@link LocalizePageMapOptions}.
|
|
28
|
+
* @returns The page map with translated titles, or `pageMap` itself when there is nothing to translate.
|
|
17
29
|
*/
|
|
18
|
-
declare function localizePageMap(pageMap: PageMapItem[], titles: Readonly<Record<string, string
|
|
30
|
+
declare function localizePageMap(pageMap: PageMapItem[], titles: Readonly<Record<string, string>>, options?: LocalizePageMapOptions): PageMapItem[];
|
|
19
31
|
|
|
20
32
|
export { localizePageMap };
|
|
33
|
+
export type { LocalizePageMapOptions };
|
package/dist/pageMap.d.ts
CHANGED
|
@@ -1,20 +1,33 @@
|
|
|
1
1
|
import { PageMapItem } from 'nextra';
|
|
2
2
|
|
|
3
|
+
/** Options of {@link localizePageMap}. */
|
|
4
|
+
interface LocalizePageMapOptions {
|
|
5
|
+
/**
|
|
6
|
+
* Translated titles by route instead of English title: `<folder>/<name>` (for example `guides/full-stack-react`),
|
|
7
|
+
* then the bare `<name>` (`guides`, `index`). A route title wins over an English title and also replaces the front
|
|
8
|
+
* matter `title`. The docs hub keys its sidebar this way.
|
|
9
|
+
*/
|
|
10
|
+
routes?: Readonly<Record<string, string>>;
|
|
11
|
+
}
|
|
3
12
|
/**
|
|
4
13
|
* Translates the titles of a Nextra page map: the sidebar, the top-level menu, the breadcrumbs and the previous / next
|
|
5
|
-
* links all read them.
|
|
6
|
-
* front matter `title`), so a site lists each English title once, whatever the page; titles without a
|
|
7
|
-
* such as package names, stay as they are. The
|
|
14
|
+
* links all read them. The project sites match titles by their English text (the `_meta` titles, the `title` of each
|
|
15
|
+
* item and the front matter `title`), so a site lists each English title once, whatever the page; titles without a
|
|
16
|
+
* translation, such as package names, stay as they are. The docs hub matches them by route instead
|
|
17
|
+
* (`options.routes`). The page map is not modified: changed items are copied.
|
|
8
18
|
*
|
|
9
19
|
* @example
|
|
10
20
|
* ```ts
|
|
11
21
|
* localizePageMap(pageMap, { Introduction: 'Вступ', Packages: 'Пакети' });
|
|
22
|
+
* localizePageMap(pageMap, {}, { routes: { guides: 'Посібники', 'guides/starter-templates': 'Стартові шаблони' } });
|
|
12
23
|
* ```
|
|
13
24
|
*
|
|
14
25
|
* @param pageMap - The page map of the site, the result of `getPageMap()` of `nextra/page-map`.
|
|
15
26
|
* @param titles - Translated titles by English title.
|
|
16
|
-
* @
|
|
27
|
+
* @param options - See {@link LocalizePageMapOptions}.
|
|
28
|
+
* @returns The page map with translated titles, or `pageMap` itself when there is nothing to translate.
|
|
17
29
|
*/
|
|
18
|
-
declare function localizePageMap(pageMap: PageMapItem[], titles: Readonly<Record<string, string
|
|
30
|
+
declare function localizePageMap(pageMap: PageMapItem[], titles: Readonly<Record<string, string>>, options?: LocalizePageMapOptions): PageMapItem[];
|
|
19
31
|
|
|
20
32
|
export { localizePageMap };
|
|
33
|
+
export type { LocalizePageMapOptions };
|
package/dist/pageMap.js
CHANGED
|
@@ -1,31 +1,42 @@
|
|
|
1
|
-
function localizeMetaValue(value, titles) {
|
|
2
|
-
if (typeof value === "string") return titles[value] ?? value;
|
|
3
|
-
if (value
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
}
|
|
7
|
-
return value;
|
|
1
|
+
function localizeMetaValue(value, routeTitle, titles) {
|
|
2
|
+
if (typeof value === "string") return routeTitle ?? titles[value] ?? value;
|
|
3
|
+
if (!value || typeof value !== "object" || !("title" in value)) return value;
|
|
4
|
+
const title = value.title;
|
|
5
|
+
const translated = routeTitle ?? (typeof title === "string" ? titles[title] : void 0);
|
|
6
|
+
return translated ? { ...value, title: translated } : value;
|
|
8
7
|
}
|
|
9
|
-
function
|
|
10
|
-
|
|
11
|
-
return
|
|
8
|
+
function localizeItems(items, titles, routes, parent) {
|
|
9
|
+
const routeTitle = (name) => routes[parent ? `${parent}/${name}` : name] ?? routes[name];
|
|
10
|
+
return items.map((item) => {
|
|
12
11
|
if ("data" in item) {
|
|
13
12
|
const data = Object.fromEntries(
|
|
14
|
-
Object.entries(item.data).map(([key, value]) => [key, localizeMetaValue(value, titles)])
|
|
13
|
+
Object.entries(item.data).map(([key, value]) => [key, localizeMetaValue(value, routeTitle(key), titles)])
|
|
15
14
|
);
|
|
16
15
|
return { ...item, data };
|
|
17
16
|
}
|
|
18
17
|
const copy = { ...item };
|
|
18
|
+
const name = item.name;
|
|
19
|
+
const route = typeof name === "string" ? parent ? `${parent}/${name}` : name : parent;
|
|
20
|
+
const byRoute = typeof name === "string" ? routeTitle(name) : void 0;
|
|
19
21
|
const title = item.title;
|
|
20
|
-
if (
|
|
21
|
-
if (
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
if (byRoute) copy.title = byRoute;
|
|
23
|
+
else if (typeof title === "string" && titles[title]) copy.title = titles[title];
|
|
24
|
+
if ("frontMatter" in item && item.frontMatter) {
|
|
25
|
+
const frontTitle = item.frontMatter.title;
|
|
26
|
+
const translated = byRoute ?? (typeof frontTitle === "string" ? titles[frontTitle] : void 0);
|
|
27
|
+
if (translated) copy.frontMatter = { ...item.frontMatter, title: translated };
|
|
28
|
+
}
|
|
29
|
+
if ("children" in item && Array.isArray(item.children)) {
|
|
30
|
+
copy.children = localizeItems(item.children, titles, routes, route);
|
|
24
31
|
}
|
|
25
|
-
if ("children" in item && Array.isArray(item.children)) copy.children = localizePageMap(item.children, titles);
|
|
26
32
|
return copy;
|
|
27
33
|
});
|
|
28
34
|
}
|
|
35
|
+
function localizePageMap(pageMap, titles, options = {}) {
|
|
36
|
+
const routes = options.routes ?? {};
|
|
37
|
+
if (Object.keys(titles).length === 0 && Object.keys(routes).length === 0) return pageMap;
|
|
38
|
+
return localizeItems(pageMap, titles, routes);
|
|
39
|
+
}
|
|
29
40
|
export {
|
|
30
41
|
localizePageMap
|
|
31
42
|
};
|
|
@@ -149,6 +149,11 @@ async function checkSiteTranslations(options = {}) {
|
|
|
149
149
|
throw new Error(`No ${contentDir} in ${cwd}: run the check from the docs app of the site`);
|
|
150
150
|
}
|
|
151
151
|
const createSlugger = options.createSlugger ?? await loadNextraSlugger(cwd);
|
|
152
|
+
if (!createSlugger) {
|
|
153
|
+
throw new Error(
|
|
154
|
+
`Cannot load github-slugger through nextra from ${cwd}: the heading ids of the translations cannot be checked`
|
|
155
|
+
);
|
|
156
|
+
}
|
|
152
157
|
const locales = import_locale.TUWA_LOCALES.filter((locale) => locale !== import_locale.DEFAULT_LOCALE);
|
|
153
158
|
const filesByLocale = new Map(locales.map((locale) => [locale, pageFiles((0, import_node_path.join)(cwd, i18nDir, locale))]));
|
|
154
159
|
const pages = [...new Set([...filesByLocale.values()].flat().map(withoutExtension))].sort();
|
|
@@ -68,7 +68,7 @@ interface CheckSiteTranslationsOptions {
|
|
|
68
68
|
contentDir?: string;
|
|
69
69
|
/** The translations, one folder per language, relative to `cwd` (default: `src/i18n`). */
|
|
70
70
|
i18nDir?: string;
|
|
71
|
-
/** The heading slugger (default: {@link loadNextraSlugger}). */
|
|
71
|
+
/** The heading slugger (default: {@link loadNextraSlugger}; the check fails when it cannot be loaded). */
|
|
72
72
|
createSlugger?: HeadingSlugger;
|
|
73
73
|
}
|
|
74
74
|
/**
|
|
@@ -78,7 +78,8 @@ interface CheckSiteTranslationsOptions {
|
|
|
78
78
|
*
|
|
79
79
|
* @param options - See {@link CheckSiteTranslationsOptions}.
|
|
80
80
|
* @returns The number of translated files and the issues found.
|
|
81
|
-
* @throws When `contentDir` does not exist (the check runs from the wrong directory)
|
|
81
|
+
* @throws When `contentDir` does not exist (the check runs from the wrong directory), or when no `createSlugger` is
|
|
82
|
+
* given and the slugger of Nextra cannot be loaded from `cwd` (the heading ids would go unchecked).
|
|
82
83
|
*/
|
|
83
84
|
declare function checkSiteTranslations(options?: CheckSiteTranslationsOptions): Promise<{
|
|
84
85
|
files: number;
|
|
@@ -68,7 +68,7 @@ interface CheckSiteTranslationsOptions {
|
|
|
68
68
|
contentDir?: string;
|
|
69
69
|
/** The translations, one folder per language, relative to `cwd` (default: `src/i18n`). */
|
|
70
70
|
i18nDir?: string;
|
|
71
|
-
/** The heading slugger (default: {@link loadNextraSlugger}). */
|
|
71
|
+
/** The heading slugger (default: {@link loadNextraSlugger}; the check fails when it cannot be loaded). */
|
|
72
72
|
createSlugger?: HeadingSlugger;
|
|
73
73
|
}
|
|
74
74
|
/**
|
|
@@ -78,7 +78,8 @@ interface CheckSiteTranslationsOptions {
|
|
|
78
78
|
*
|
|
79
79
|
* @param options - See {@link CheckSiteTranslationsOptions}.
|
|
80
80
|
* @returns The number of translated files and the issues found.
|
|
81
|
-
* @throws When `contentDir` does not exist (the check runs from the wrong directory)
|
|
81
|
+
* @throws When `contentDir` does not exist (the check runs from the wrong directory), or when no `createSlugger` is
|
|
82
|
+
* given and the slugger of Nextra cannot be loaded from `cwd` (the heading ids would go unchecked).
|
|
82
83
|
*/
|
|
83
84
|
declare function checkSiteTranslations(options?: CheckSiteTranslationsOptions): Promise<{
|
|
84
85
|
files: number;
|
package/dist/translationCheck.js
CHANGED
|
@@ -121,6 +121,11 @@ async function checkSiteTranslations(options = {}) {
|
|
|
121
121
|
throw new Error(`No ${contentDir} in ${cwd}: run the check from the docs app of the site`);
|
|
122
122
|
}
|
|
123
123
|
const createSlugger = options.createSlugger ?? await loadNextraSlugger(cwd);
|
|
124
|
+
if (!createSlugger) {
|
|
125
|
+
throw new Error(
|
|
126
|
+
`Cannot load github-slugger through nextra from ${cwd}: the heading ids of the translations cannot be checked`
|
|
127
|
+
);
|
|
128
|
+
}
|
|
124
129
|
const locales = TUWA_LOCALES.filter((locale) => locale !== DEFAULT_LOCALE);
|
|
125
130
|
const filesByLocale = new Map(locales.map((locale) => [locale, pageFiles(join(cwd, i18nDir, locale))]));
|
|
126
131
|
const pages = [...new Set([...filesByLocale.values()].flat().map(withoutExtension))].sort();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tuwaio/docs-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"author": "Oleksandr Tkach",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
}
|
|
83
83
|
],
|
|
84
84
|
"dependencies": {
|
|
85
|
-
"@tuwaio/nova-core": "^0.10.
|
|
85
|
+
"@tuwaio/nova-core": "^0.10.6",
|
|
86
86
|
"clsx": "^2.1.1",
|
|
87
87
|
"html-react-parser": "^6.1.9",
|
|
88
88
|
"tailwind-merge": "^3.7.0"
|