@docusaurus/theme-classic 0.0.0-4290 → 0.0.0-4299
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/lib/theme-classic.d.ts +12 -0
- package/lib/translations.js +14 -5
- package/lib/validateThemeConfig.js +5 -3
- package/lib-next/theme/Admonition/index.js +101 -0
- package/lib-next/theme/Footer/index.js +73 -35
- package/lib-next/theme/Heading/index.js +0 -1
- package/package.json +12 -13
- package/src/theme/Admonition/index.tsx +106 -0
- package/src/theme/Footer/index.tsx +83 -37
- package/src/theme/Heading/index.tsx +0 -1
- package/src/theme-classic.d.ts +12 -0
- package/src/translations.ts +41 -21
- package/src/validateThemeConfig.ts +13 -8
package/lib/theme-classic.d.ts
CHANGED
|
@@ -11,6 +11,18 @@ declare module '@docusaurus/theme-classic' {
|
|
|
11
11
|
};
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
declare module '@theme/Admonition' {
|
|
15
|
+
import type {ReactNode} from 'react';
|
|
16
|
+
|
|
17
|
+
export interface Props {
|
|
18
|
+
readonly children: ReactNode;
|
|
19
|
+
readonly type: 'note' | 'tip' | 'danger' | 'info' | 'caution';
|
|
20
|
+
readonly icon?: ReactNode;
|
|
21
|
+
readonly title?: string;
|
|
22
|
+
}
|
|
23
|
+
export default function Admonition(props: Props): JSX.Element;
|
|
24
|
+
}
|
|
25
|
+
|
|
14
26
|
declare module '@theme/AnnouncementBar' {
|
|
15
27
|
const AnnouncementBar: () => JSX.Element | null;
|
|
16
28
|
export default AnnouncementBar;
|
package/lib/translations.js
CHANGED
|
@@ -68,13 +68,16 @@ function translateNavbar(navbar, navbarTranslations) {
|
|
|
68
68
|
};
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
+
function isMultiColumnFooterLinks(links) {
|
|
72
|
+
return 'title' in links[0];
|
|
73
|
+
}
|
|
74
|
+
|
|
71
75
|
function getFooterTranslationFile(footer) {
|
|
72
|
-
|
|
73
|
-
const footerLinkTitles = (0, _lodash.chain)(footer.links.filter(link => !!link.title)).keyBy(link => `link.title.${link.title}`).mapValues(link => ({
|
|
76
|
+
const footerLinkTitles = isMultiColumnFooterLinks(footer.links) ? (0, _lodash.chain)(footer.links.filter(link => !!link.title)).keyBy(link => `link.title.${link.title}`).mapValues(link => ({
|
|
74
77
|
message: link.title,
|
|
75
78
|
description: `The title of the footer links column with title=${link.title} in the footer`
|
|
76
|
-
})).value();
|
|
77
|
-
const footerLinkLabels = (0, _lodash.chain)(footer.links.flatMap(link => link.items).filter(link => !!link.label)).keyBy(linkItem => `link.item.label.${linkItem.label}`).mapValues(linkItem => {
|
|
79
|
+
})).value() : {};
|
|
80
|
+
const footerLinkLabels = (0, _lodash.chain)(isMultiColumnFooterLinks(footer.links) ? footer.links.flatMap(link => link.items).filter(link => !!link.label) : footer.links.filter(link => !!link.label)).keyBy(linkItem => `link.item.label.${linkItem.label}`).mapValues(linkItem => {
|
|
78
81
|
var _linkItem$to;
|
|
79
82
|
|
|
80
83
|
return {
|
|
@@ -94,7 +97,7 @@ function getFooterTranslationFile(footer) {
|
|
|
94
97
|
function translateFooter(footer, footerTranslations) {
|
|
95
98
|
var _footerTranslations$c, _footerTranslations$c2;
|
|
96
99
|
|
|
97
|
-
const links = footer.links.map(link => {
|
|
100
|
+
const links = isMultiColumnFooterLinks(footer.links) ? footer.links.map(link => {
|
|
98
101
|
var _footerTranslations$$, _footerTranslations$;
|
|
99
102
|
|
|
100
103
|
return { ...link,
|
|
@@ -107,6 +110,12 @@ function translateFooter(footer, footerTranslations) {
|
|
|
107
110
|
};
|
|
108
111
|
})
|
|
109
112
|
};
|
|
113
|
+
}) : footer.links.map(link => {
|
|
114
|
+
var _footerTranslations$$3, _footerTranslations$3;
|
|
115
|
+
|
|
116
|
+
return { ...link,
|
|
117
|
+
label: (_footerTranslations$$3 = (_footerTranslations$3 = footerTranslations[`link.item.label.${link.label}`]) === null || _footerTranslations$3 === void 0 ? void 0 : _footerTranslations$3.message) !== null && _footerTranslations$$3 !== void 0 ? _footerTranslations$$3 : link.label
|
|
118
|
+
};
|
|
110
119
|
});
|
|
111
120
|
const copyright = (_footerTranslations$c = (_footerTranslations$c2 = footerTranslations.copyright) === null || _footerTranslations$c2 === void 0 ? void 0 : _footerTranslations$c2.message) !== null && _footerTranslations$c !== void 0 ? _footerTranslations$c : footer.copyright;
|
|
112
121
|
return { ...footer,
|
|
@@ -260,10 +260,12 @@ const ThemeConfigSchema = _utilsValidation.Joi.object({
|
|
|
260
260
|
href: _utilsValidation.Joi.string()
|
|
261
261
|
}),
|
|
262
262
|
copyright: _utilsValidation.Joi.string(),
|
|
263
|
-
links: _utilsValidation.Joi.array().items(_utilsValidation.Joi.object({
|
|
264
|
-
title: _utilsValidation.Joi.string().allow(null),
|
|
263
|
+
links: _utilsValidation.Joi.alternatives(_utilsValidation.Joi.array().items(_utilsValidation.Joi.object({
|
|
264
|
+
title: _utilsValidation.Joi.string().allow(null).default(null),
|
|
265
265
|
items: _utilsValidation.Joi.array().items(FooterLinkItemSchema).default([])
|
|
266
|
-
})).default([])
|
|
266
|
+
})).default([]), _utilsValidation.Joi.array().items(FooterLinkItemSchema).default([])).messages({
|
|
267
|
+
'alternatives.match': `The footer must be either simple or multi-column, and not a mix of the two. See: https://docusaurus.io/docs/api/themes/configuration#footer-links`
|
|
268
|
+
})
|
|
267
269
|
}).optional(),
|
|
268
270
|
prism: _utilsValidation.Joi.object({
|
|
269
271
|
theme: _utilsValidation.Joi.object({
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
import React from 'react';
|
|
8
|
+
import clsx from 'clsx';
|
|
9
|
+
const icons = {
|
|
10
|
+
note: (
|
|
11
|
+
<svg
|
|
12
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
13
|
+
width="14"
|
|
14
|
+
height="16"
|
|
15
|
+
viewBox="0 0 14 16">
|
|
16
|
+
<path
|
|
17
|
+
fillRule="evenodd"
|
|
18
|
+
d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"
|
|
19
|
+
/>
|
|
20
|
+
</svg>
|
|
21
|
+
),
|
|
22
|
+
tip: (
|
|
23
|
+
<svg
|
|
24
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
25
|
+
width="12"
|
|
26
|
+
height="16"
|
|
27
|
+
viewBox="0 0 12 16">
|
|
28
|
+
<path
|
|
29
|
+
fillRule="evenodd"
|
|
30
|
+
d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"
|
|
31
|
+
/>
|
|
32
|
+
</svg>
|
|
33
|
+
),
|
|
34
|
+
danger: (
|
|
35
|
+
<svg
|
|
36
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
37
|
+
width="12"
|
|
38
|
+
height="16"
|
|
39
|
+
viewBox="0 0 12 16">
|
|
40
|
+
<path
|
|
41
|
+
fillRule="evenodd"
|
|
42
|
+
d="M5.05.31c.81 2.17.41 3.38-.52 4.31C3.55 5.67 1.98 6.45.9 7.98c-1.45 2.05-1.7 6.53 3.53 7.7-2.2-1.16-2.67-4.52-.3-6.61-.61 2.03.53 3.33 1.94 2.86 1.39-.47 2.3.53 2.27 1.67-.02.78-.31 1.44-1.13 1.81 3.42-.59 4.78-3.42 4.78-5.56 0-2.84-2.53-3.22-1.25-5.61-1.52.13-2.03 1.13-1.89 2.75.09 1.08-1.02 1.8-1.86 1.33-.67-.41-.66-1.19-.06-1.78C8.18 5.31 8.68 2.45 5.05.32L5.03.3l.02.01z"
|
|
43
|
+
/>
|
|
44
|
+
</svg>
|
|
45
|
+
),
|
|
46
|
+
info: (
|
|
47
|
+
<svg
|
|
48
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
49
|
+
width="14"
|
|
50
|
+
height="16"
|
|
51
|
+
viewBox="0 0 14 16">
|
|
52
|
+
<path
|
|
53
|
+
fillRule="evenodd"
|
|
54
|
+
d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"
|
|
55
|
+
/>
|
|
56
|
+
</svg>
|
|
57
|
+
),
|
|
58
|
+
caution: (
|
|
59
|
+
<svg
|
|
60
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
61
|
+
width="16"
|
|
62
|
+
height="16"
|
|
63
|
+
viewBox="0 0 16 16">
|
|
64
|
+
<path
|
|
65
|
+
fillRule="evenodd"
|
|
66
|
+
d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"
|
|
67
|
+
/>
|
|
68
|
+
</svg>
|
|
69
|
+
),
|
|
70
|
+
};
|
|
71
|
+
const ifmClassNames = {
|
|
72
|
+
note: 'secondary',
|
|
73
|
+
tip: 'success',
|
|
74
|
+
danger: 'danger',
|
|
75
|
+
info: 'info',
|
|
76
|
+
caution: 'warning',
|
|
77
|
+
};
|
|
78
|
+
export default function Admonition({
|
|
79
|
+
children,
|
|
80
|
+
type,
|
|
81
|
+
title = type,
|
|
82
|
+
icon = icons[type],
|
|
83
|
+
}) {
|
|
84
|
+
return (
|
|
85
|
+
<div
|
|
86
|
+
className={clsx(
|
|
87
|
+
'admonition',
|
|
88
|
+
`admonition-${type}`,
|
|
89
|
+
'alert',
|
|
90
|
+
`alert--${ifmClassNames[type]}`,
|
|
91
|
+
)}>
|
|
92
|
+
<div className="admonition-heading">
|
|
93
|
+
<h5>
|
|
94
|
+
<span className="admonition-icon">{icon}</span>
|
|
95
|
+
{title}
|
|
96
|
+
</h5>
|
|
97
|
+
</div>
|
|
98
|
+
<div className="admonition-content">{children}</div>
|
|
99
|
+
</div>
|
|
100
|
+
);
|
|
101
|
+
}
|
|
@@ -54,6 +54,66 @@ function FooterLogo({sources, alt, width, height}) {
|
|
|
54
54
|
);
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
+
function MultiColumnLinks({links}) {
|
|
58
|
+
return (
|
|
59
|
+
<>
|
|
60
|
+
{links.map((linkItem, i) => (
|
|
61
|
+
<div key={i} className="col footer__col">
|
|
62
|
+
<div className="footer__title">{linkItem.title}</div>
|
|
63
|
+
<ul className="footer__items">
|
|
64
|
+
{linkItem.items.map((item, key) =>
|
|
65
|
+
item.html ? (
|
|
66
|
+
<li
|
|
67
|
+
key={key}
|
|
68
|
+
className="footer__item" // Developer provided the HTML, so assume it's safe.
|
|
69
|
+
// eslint-disable-next-line react/no-danger
|
|
70
|
+
dangerouslySetInnerHTML={{
|
|
71
|
+
__html: item.html,
|
|
72
|
+
}}
|
|
73
|
+
/>
|
|
74
|
+
) : (
|
|
75
|
+
<li key={item.href || item.to} className="footer__item">
|
|
76
|
+
<FooterLink {...item} />
|
|
77
|
+
</li>
|
|
78
|
+
),
|
|
79
|
+
)}
|
|
80
|
+
</ul>
|
|
81
|
+
</div>
|
|
82
|
+
))}
|
|
83
|
+
</>
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function SimpleLinks({links}) {
|
|
88
|
+
return (
|
|
89
|
+
<div className="footer__links">
|
|
90
|
+
{links.map((item, key) => (
|
|
91
|
+
<>
|
|
92
|
+
{item.html ? (
|
|
93
|
+
<span
|
|
94
|
+
key={key}
|
|
95
|
+
className="footer__link-item" // Developer provided the HTML, so assume it's safe.
|
|
96
|
+
// eslint-disable-next-line react/no-danger
|
|
97
|
+
dangerouslySetInnerHTML={{
|
|
98
|
+
__html: item.html,
|
|
99
|
+
}}
|
|
100
|
+
/>
|
|
101
|
+
) : (
|
|
102
|
+
<FooterLink {...item} />
|
|
103
|
+
)}
|
|
104
|
+
{links.length !== key + 1 && (
|
|
105
|
+
<span className="footer__link-separator">·</span>
|
|
106
|
+
)}
|
|
107
|
+
</>
|
|
108
|
+
))}
|
|
109
|
+
</div>
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function isMultiColumnFooterLinks(links) {
|
|
114
|
+
return 'title' in links[0];
|
|
115
|
+
}
|
|
116
|
+
|
|
57
117
|
function Footer() {
|
|
58
118
|
const {footer} = useThemeConfig();
|
|
59
119
|
const {copyright, links = [], logo = {}} = footer || {};
|
|
@@ -71,40 +131,18 @@ function Footer() {
|
|
|
71
131
|
className={clsx('footer', {
|
|
72
132
|
'footer--dark': footer.style === 'dark',
|
|
73
133
|
})}>
|
|
74
|
-
<div className="container">
|
|
75
|
-
{links &&
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
{linkItem.items.map((item, key) =>
|
|
87
|
-
item.html ? (
|
|
88
|
-
<li
|
|
89
|
-
key={key}
|
|
90
|
-
className="footer__item" // Developer provided the HTML, so assume it's safe.
|
|
91
|
-
// eslint-disable-next-line react/no-danger
|
|
92
|
-
dangerouslySetInnerHTML={{
|
|
93
|
-
__html: item.html,
|
|
94
|
-
}}
|
|
95
|
-
/>
|
|
96
|
-
) : (
|
|
97
|
-
<li key={item.href || item.to} className="footer__item">
|
|
98
|
-
<FooterLink {...item} />
|
|
99
|
-
</li>
|
|
100
|
-
),
|
|
101
|
-
)}
|
|
102
|
-
</ul>
|
|
103
|
-
) : null}
|
|
104
|
-
</div>
|
|
105
|
-
))}
|
|
106
|
-
</div>
|
|
107
|
-
)}
|
|
134
|
+
<div className="container container-fluid">
|
|
135
|
+
{links &&
|
|
136
|
+
links.length > 0 &&
|
|
137
|
+
(isMultiColumnFooterLinks(links) ? (
|
|
138
|
+
<div className="row footer__links">
|
|
139
|
+
<MultiColumnLinks links={links} />
|
|
140
|
+
</div>
|
|
141
|
+
) : (
|
|
142
|
+
<div className="footer__links text--center">
|
|
143
|
+
<SimpleLinks links={links} />
|
|
144
|
+
</div>
|
|
145
|
+
))}
|
|
108
146
|
{(logo || copyright) && (
|
|
109
147
|
<div className="footer__bottom text--center">
|
|
110
148
|
{logo && (logo.src || logo.srcDark) && (
|
|
@@ -139,4 +177,4 @@ function Footer() {
|
|
|
139
177
|
);
|
|
140
178
|
}
|
|
141
179
|
|
|
142
|
-
export default Footer;
|
|
180
|
+
export default React.memo(Footer);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@docusaurus/theme-classic",
|
|
3
|
-
"version": "0.0.0-
|
|
3
|
+
"version": "0.0.0-4299",
|
|
4
4
|
"description": "Classic theme for Docusaurus",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "src/theme-classic.d.ts",
|
|
@@ -23,17 +23,16 @@
|
|
|
23
23
|
"update-code-translations": "node -e 'require(\"./update-code-translations.js\").run()'"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@docusaurus/core": "0.0.0-
|
|
27
|
-
"@docusaurus/plugin-content-blog": "0.0.0-
|
|
28
|
-
"@docusaurus/plugin-content-docs": "0.0.0-
|
|
29
|
-
"@docusaurus/plugin-content-pages": "0.0.0-
|
|
30
|
-
"@docusaurus/theme-common": "0.0.0-
|
|
31
|
-
"@docusaurus/theme-translations": "0.0.0-
|
|
32
|
-
"@docusaurus/utils": "0.0.0-
|
|
33
|
-
"@docusaurus/utils-validation": "0.0.0-
|
|
26
|
+
"@docusaurus/core": "0.0.0-4299",
|
|
27
|
+
"@docusaurus/plugin-content-blog": "0.0.0-4299",
|
|
28
|
+
"@docusaurus/plugin-content-docs": "0.0.0-4299",
|
|
29
|
+
"@docusaurus/plugin-content-pages": "0.0.0-4299",
|
|
30
|
+
"@docusaurus/theme-common": "0.0.0-4299",
|
|
31
|
+
"@docusaurus/theme-translations": "0.0.0-4299",
|
|
32
|
+
"@docusaurus/utils": "0.0.0-4299",
|
|
33
|
+
"@docusaurus/utils-validation": "0.0.0-4299",
|
|
34
34
|
"@mdx-js/mdx": "^1.6.21",
|
|
35
35
|
"@mdx-js/react": "^1.6.21",
|
|
36
|
-
"chalk": "^4.1.2",
|
|
37
36
|
"clsx": "^1.1.1",
|
|
38
37
|
"copy-text-to-clipboard": "^3.0.1",
|
|
39
38
|
"globby": "^11.0.2",
|
|
@@ -46,8 +45,8 @@
|
|
|
46
45
|
"rtlcss": "^3.3.0"
|
|
47
46
|
},
|
|
48
47
|
"devDependencies": {
|
|
49
|
-
"@docusaurus/module-type-aliases": "0.0.0-
|
|
50
|
-
"@docusaurus/types": "0.0.0-
|
|
48
|
+
"@docusaurus/module-type-aliases": "0.0.0-4299",
|
|
49
|
+
"@docusaurus/types": "0.0.0-4299",
|
|
51
50
|
"@types/mdx-js__react": "^1.5.4",
|
|
52
51
|
"@types/parse-numeric-range": "^0.0.1",
|
|
53
52
|
"@types/rtlcss": "^3.1.1",
|
|
@@ -62,5 +61,5 @@
|
|
|
62
61
|
"engines": {
|
|
63
62
|
"node": ">=14"
|
|
64
63
|
},
|
|
65
|
-
"gitHead": "
|
|
64
|
+
"gitHead": "57801f0f237dda31b5aae8c8fdddea45528f5bf1"
|
|
66
65
|
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import React from 'react';
|
|
9
|
+
import clsx from 'clsx';
|
|
10
|
+
import {Props} from '@theme/Admonition';
|
|
11
|
+
|
|
12
|
+
const icons = {
|
|
13
|
+
note: (
|
|
14
|
+
<svg
|
|
15
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
16
|
+
width="14"
|
|
17
|
+
height="16"
|
|
18
|
+
viewBox="0 0 14 16">
|
|
19
|
+
<path
|
|
20
|
+
fillRule="evenodd"
|
|
21
|
+
d="M6.3 5.69a.942.942 0 0 1-.28-.7c0-.28.09-.52.28-.7.19-.18.42-.28.7-.28.28 0 .52.09.7.28.18.19.28.42.28.7 0 .28-.09.52-.28.7a1 1 0 0 1-.7.3c-.28 0-.52-.11-.7-.3zM8 7.99c-.02-.25-.11-.48-.31-.69-.2-.19-.42-.3-.69-.31H6c-.27.02-.48.13-.69.31-.2.2-.3.44-.31.69h1v3c.02.27.11.5.31.69.2.2.42.31.69.31h1c.27 0 .48-.11.69-.31.2-.19.3-.42.31-.69H8V7.98v.01zM7 2.3c-3.14 0-5.7 2.54-5.7 5.68 0 3.14 2.56 5.7 5.7 5.7s5.7-2.55 5.7-5.7c0-3.15-2.56-5.69-5.7-5.69v.01zM7 .98c3.86 0 7 3.14 7 7s-3.14 7-7 7-7-3.12-7-7 3.14-7 7-7z"
|
|
22
|
+
/>
|
|
23
|
+
</svg>
|
|
24
|
+
),
|
|
25
|
+
tip: (
|
|
26
|
+
<svg
|
|
27
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
28
|
+
width="12"
|
|
29
|
+
height="16"
|
|
30
|
+
viewBox="0 0 12 16">
|
|
31
|
+
<path
|
|
32
|
+
fillRule="evenodd"
|
|
33
|
+
d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"
|
|
34
|
+
/>
|
|
35
|
+
</svg>
|
|
36
|
+
),
|
|
37
|
+
danger: (
|
|
38
|
+
<svg
|
|
39
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
40
|
+
width="12"
|
|
41
|
+
height="16"
|
|
42
|
+
viewBox="0 0 12 16">
|
|
43
|
+
<path
|
|
44
|
+
fillRule="evenodd"
|
|
45
|
+
d="M5.05.31c.81 2.17.41 3.38-.52 4.31C3.55 5.67 1.98 6.45.9 7.98c-1.45 2.05-1.7 6.53 3.53 7.7-2.2-1.16-2.67-4.52-.3-6.61-.61 2.03.53 3.33 1.94 2.86 1.39-.47 2.3.53 2.27 1.67-.02.78-.31 1.44-1.13 1.81 3.42-.59 4.78-3.42 4.78-5.56 0-2.84-2.53-3.22-1.25-5.61-1.52.13-2.03 1.13-1.89 2.75.09 1.08-1.02 1.8-1.86 1.33-.67-.41-.66-1.19-.06-1.78C8.18 5.31 8.68 2.45 5.05.32L5.03.3l.02.01z"
|
|
46
|
+
/>
|
|
47
|
+
</svg>
|
|
48
|
+
),
|
|
49
|
+
info: (
|
|
50
|
+
<svg
|
|
51
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
52
|
+
width="14"
|
|
53
|
+
height="16"
|
|
54
|
+
viewBox="0 0 14 16">
|
|
55
|
+
<path
|
|
56
|
+
fillRule="evenodd"
|
|
57
|
+
d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"
|
|
58
|
+
/>
|
|
59
|
+
</svg>
|
|
60
|
+
),
|
|
61
|
+
caution: (
|
|
62
|
+
<svg
|
|
63
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
64
|
+
width="16"
|
|
65
|
+
height="16"
|
|
66
|
+
viewBox="0 0 16 16">
|
|
67
|
+
<path
|
|
68
|
+
fillRule="evenodd"
|
|
69
|
+
d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"
|
|
70
|
+
/>
|
|
71
|
+
</svg>
|
|
72
|
+
),
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const ifmClassNames = {
|
|
76
|
+
note: 'secondary',
|
|
77
|
+
tip: 'success',
|
|
78
|
+
danger: 'danger',
|
|
79
|
+
info: 'info',
|
|
80
|
+
caution: 'warning',
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
export default function Admonition({
|
|
84
|
+
children,
|
|
85
|
+
type,
|
|
86
|
+
title = type,
|
|
87
|
+
icon = icons[type],
|
|
88
|
+
}: Props): JSX.Element {
|
|
89
|
+
return (
|
|
90
|
+
<div
|
|
91
|
+
className={clsx(
|
|
92
|
+
'admonition',
|
|
93
|
+
`admonition-${type}`,
|
|
94
|
+
'alert',
|
|
95
|
+
`alert--${ifmClassNames[type]}`,
|
|
96
|
+
)}>
|
|
97
|
+
<div className="admonition-heading">
|
|
98
|
+
<h5>
|
|
99
|
+
<span className="admonition-icon">{icon}</span>
|
|
100
|
+
{title}
|
|
101
|
+
</h5>
|
|
102
|
+
</div>
|
|
103
|
+
<div className="admonition-content">{children}</div>
|
|
104
|
+
</div>
|
|
105
|
+
);
|
|
106
|
+
}
|
|
@@ -9,7 +9,12 @@ import React from 'react';
|
|
|
9
9
|
import clsx from 'clsx';
|
|
10
10
|
|
|
11
11
|
import Link from '@docusaurus/Link';
|
|
12
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
FooterLinkItem,
|
|
14
|
+
useThemeConfig,
|
|
15
|
+
MultiColumnFooter,
|
|
16
|
+
SimpleFooter,
|
|
17
|
+
} from '@docusaurus/theme-common';
|
|
13
18
|
import useBaseUrl from '@docusaurus/useBaseUrl';
|
|
14
19
|
import isInternalUrl from '@docusaurus/isInternalUrl';
|
|
15
20
|
import styles from './styles.module.css';
|
|
@@ -66,6 +71,70 @@ function FooterLogo({
|
|
|
66
71
|
);
|
|
67
72
|
}
|
|
68
73
|
|
|
74
|
+
function MultiColumnLinks({links}: {links: MultiColumnFooter['links']}) {
|
|
75
|
+
return (
|
|
76
|
+
<>
|
|
77
|
+
{links.map((linkItem, i) => (
|
|
78
|
+
<div key={i} className="col footer__col">
|
|
79
|
+
<div className="footer__title">{linkItem.title}</div>
|
|
80
|
+
<ul className="footer__items">
|
|
81
|
+
{linkItem.items.map((item, key) =>
|
|
82
|
+
item.html ? (
|
|
83
|
+
<li
|
|
84
|
+
key={key}
|
|
85
|
+
className="footer__item"
|
|
86
|
+
// Developer provided the HTML, so assume it's safe.
|
|
87
|
+
// eslint-disable-next-line react/no-danger
|
|
88
|
+
dangerouslySetInnerHTML={{
|
|
89
|
+
__html: item.html,
|
|
90
|
+
}}
|
|
91
|
+
/>
|
|
92
|
+
) : (
|
|
93
|
+
<li key={item.href || item.to} className="footer__item">
|
|
94
|
+
<FooterLink {...item} />
|
|
95
|
+
</li>
|
|
96
|
+
),
|
|
97
|
+
)}
|
|
98
|
+
</ul>
|
|
99
|
+
</div>
|
|
100
|
+
))}
|
|
101
|
+
</>
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function SimpleLinks({links}: {links: SimpleFooter['links']}) {
|
|
106
|
+
return (
|
|
107
|
+
<div className="footer__links">
|
|
108
|
+
{links.map((item, key) => (
|
|
109
|
+
<>
|
|
110
|
+
{item.html ? (
|
|
111
|
+
<span
|
|
112
|
+
key={key}
|
|
113
|
+
className="footer__link-item"
|
|
114
|
+
// Developer provided the HTML, so assume it's safe.
|
|
115
|
+
// eslint-disable-next-line react/no-danger
|
|
116
|
+
dangerouslySetInnerHTML={{
|
|
117
|
+
__html: item.html,
|
|
118
|
+
}}
|
|
119
|
+
/>
|
|
120
|
+
) : (
|
|
121
|
+
<FooterLink {...item} />
|
|
122
|
+
)}
|
|
123
|
+
{links.length !== key + 1 && (
|
|
124
|
+
<span className="footer__link-separator">·</span>
|
|
125
|
+
)}
|
|
126
|
+
</>
|
|
127
|
+
))}
|
|
128
|
+
</div>
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function isMultiColumnFooterLinks(
|
|
133
|
+
links: MultiColumnFooter['links'] | SimpleFooter['links'],
|
|
134
|
+
): links is MultiColumnFooter['links'] {
|
|
135
|
+
return 'title' in links[0];
|
|
136
|
+
}
|
|
137
|
+
|
|
69
138
|
function Footer(): JSX.Element | null {
|
|
70
139
|
const {footer} = useThemeConfig();
|
|
71
140
|
|
|
@@ -84,41 +153,18 @@ function Footer(): JSX.Element | null {
|
|
|
84
153
|
className={clsx('footer', {
|
|
85
154
|
'footer--dark': footer.style === 'dark',
|
|
86
155
|
})}>
|
|
87
|
-
<div className="container">
|
|
88
|
-
{links &&
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
{linkItem.items.map((item, key) =>
|
|
100
|
-
item.html ? (
|
|
101
|
-
<li
|
|
102
|
-
key={key}
|
|
103
|
-
className="footer__item"
|
|
104
|
-
// Developer provided the HTML, so assume it's safe.
|
|
105
|
-
// eslint-disable-next-line react/no-danger
|
|
106
|
-
dangerouslySetInnerHTML={{
|
|
107
|
-
__html: item.html,
|
|
108
|
-
}}
|
|
109
|
-
/>
|
|
110
|
-
) : (
|
|
111
|
-
<li key={item.href || item.to} className="footer__item">
|
|
112
|
-
<FooterLink {...item} />
|
|
113
|
-
</li>
|
|
114
|
-
),
|
|
115
|
-
)}
|
|
116
|
-
</ul>
|
|
117
|
-
) : null}
|
|
118
|
-
</div>
|
|
119
|
-
))}
|
|
120
|
-
</div>
|
|
121
|
-
)}
|
|
156
|
+
<div className="container container-fluid">
|
|
157
|
+
{links &&
|
|
158
|
+
links.length > 0 &&
|
|
159
|
+
(isMultiColumnFooterLinks(links) ? (
|
|
160
|
+
<div className="row footer__links">
|
|
161
|
+
<MultiColumnLinks links={links} />
|
|
162
|
+
</div>
|
|
163
|
+
) : (
|
|
164
|
+
<div className="footer__links text--center">
|
|
165
|
+
<SimpleLinks links={links} />
|
|
166
|
+
</div>
|
|
167
|
+
))}
|
|
122
168
|
{(logo || copyright) && (
|
|
123
169
|
<div className="footer__bottom text--center">
|
|
124
170
|
{logo && (logo.src || logo.srcDark) && (
|
|
@@ -154,4 +200,4 @@ function Footer(): JSX.Element | null {
|
|
|
154
200
|
);
|
|
155
201
|
}
|
|
156
202
|
|
|
157
|
-
export default Footer;
|
|
203
|
+
export default React.memo(Footer);
|
package/src/theme-classic.d.ts
CHANGED
|
@@ -11,6 +11,18 @@ declare module '@docusaurus/theme-classic' {
|
|
|
11
11
|
};
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
declare module '@theme/Admonition' {
|
|
15
|
+
import type {ReactNode} from 'react';
|
|
16
|
+
|
|
17
|
+
export interface Props {
|
|
18
|
+
readonly children: ReactNode;
|
|
19
|
+
readonly type: 'note' | 'tip' | 'danger' | 'info' | 'caution';
|
|
20
|
+
readonly icon?: ReactNode;
|
|
21
|
+
readonly title?: string;
|
|
22
|
+
}
|
|
23
|
+
export default function Admonition(props: Props): JSX.Element;
|
|
24
|
+
}
|
|
25
|
+
|
|
14
26
|
declare module '@theme/AnnouncementBar' {
|
|
15
27
|
const AnnouncementBar: () => JSX.Element | null;
|
|
16
28
|
export default AnnouncementBar;
|
package/src/translations.ts
CHANGED
|
@@ -11,6 +11,8 @@ import {
|
|
|
11
11
|
Navbar,
|
|
12
12
|
NavbarItem,
|
|
13
13
|
Footer,
|
|
14
|
+
MultiColumnFooter,
|
|
15
|
+
SimpleFooter,
|
|
14
16
|
} from '@docusaurus/theme-common';
|
|
15
17
|
|
|
16
18
|
import {keyBy, chain} from 'lodash';
|
|
@@ -69,20 +71,31 @@ function translateNavbar(
|
|
|
69
71
|
};
|
|
70
72
|
}
|
|
71
73
|
|
|
74
|
+
function isMultiColumnFooterLinks(
|
|
75
|
+
links: MultiColumnFooter['links'] | SimpleFooter['links'],
|
|
76
|
+
): links is MultiColumnFooter['links'] {
|
|
77
|
+
return 'title' in links[0];
|
|
78
|
+
}
|
|
79
|
+
|
|
72
80
|
function getFooterTranslationFile(footer: Footer): TranslationFileContent {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
footer.links.filter((link) => !!link.title),
|
|
81
|
+
const footerLinkTitles: TranslationFileContent = isMultiColumnFooterLinks(
|
|
82
|
+
footer.links,
|
|
76
83
|
)
|
|
77
|
-
.
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
84
|
+
? chain(footer.links.filter((link) => !!link.title))
|
|
85
|
+
.keyBy((link) => `link.title.${link.title}`)
|
|
86
|
+
.mapValues((link) => ({
|
|
87
|
+
message: link.title!,
|
|
88
|
+
description: `The title of the footer links column with title=${link.title} in the footer`,
|
|
89
|
+
}))
|
|
90
|
+
.value()
|
|
91
|
+
: {};
|
|
83
92
|
|
|
84
93
|
const footerLinkLabels: TranslationFileContent = chain(
|
|
85
|
-
footer.links
|
|
94
|
+
isMultiColumnFooterLinks(footer.links)
|
|
95
|
+
? footer.links
|
|
96
|
+
.flatMap((link) => link.items)
|
|
97
|
+
.filter((link) => !!link.label)
|
|
98
|
+
: footer.links.filter((link) => !!link.label),
|
|
86
99
|
)
|
|
87
100
|
.keyBy((linkItem) => `link.item.label.${linkItem.label}`)
|
|
88
101
|
.mapValues((linkItem) => ({
|
|
@@ -108,17 +121,24 @@ function translateFooter(
|
|
|
108
121
|
footer: Footer,
|
|
109
122
|
footerTranslations: TranslationFileContent,
|
|
110
123
|
): Footer {
|
|
111
|
-
const links = footer.links
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
124
|
+
const links = isMultiColumnFooterLinks(footer.links)
|
|
125
|
+
? footer.links.map((link) => ({
|
|
126
|
+
...link,
|
|
127
|
+
title:
|
|
128
|
+
footerTranslations[`link.title.${link.title}`]?.message ?? link.title,
|
|
129
|
+
items: link.items.map((linkItem) => ({
|
|
130
|
+
...linkItem,
|
|
131
|
+
label:
|
|
132
|
+
footerTranslations[`link.item.label.${linkItem.label}`]?.message ??
|
|
133
|
+
linkItem.label,
|
|
134
|
+
})),
|
|
135
|
+
}))
|
|
136
|
+
: footer.links.map((link) => ({
|
|
137
|
+
...link,
|
|
138
|
+
label:
|
|
139
|
+
footerTranslations[`link.item.label.${link.label}`]?.message ??
|
|
140
|
+
link.label,
|
|
141
|
+
}));
|
|
122
142
|
|
|
123
143
|
const copyright = footerTranslations.copyright?.message ?? footer.copyright;
|
|
124
144
|
|
|
@@ -311,14 +311,19 @@ const ThemeConfigSchema = Joi.object({
|
|
|
311
311
|
href: Joi.string(),
|
|
312
312
|
}),
|
|
313
313
|
copyright: Joi.string(),
|
|
314
|
-
links: Joi.
|
|
315
|
-
.
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
314
|
+
links: Joi.alternatives(
|
|
315
|
+
Joi.array()
|
|
316
|
+
.items(
|
|
317
|
+
Joi.object({
|
|
318
|
+
title: Joi.string().allow(null).default(null),
|
|
319
|
+
items: Joi.array().items(FooterLinkItemSchema).default([]),
|
|
320
|
+
}),
|
|
321
|
+
)
|
|
322
|
+
.default([]),
|
|
323
|
+
Joi.array().items(FooterLinkItemSchema).default([]),
|
|
324
|
+
).messages({
|
|
325
|
+
'alternatives.match': `The footer must be either simple or multi-column, and not a mix of the two. See: https://docusaurus.io/docs/api/themes/configuration#footer-links`,
|
|
326
|
+
}),
|
|
322
327
|
}).optional(),
|
|
323
328
|
prism: Joi.object({
|
|
324
329
|
theme: Joi.object({
|