xs-dev 0.14.3 → 0.15.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 +4 -0
- package/build/toolbox/setup/esp32.js +2 -2
- package/build/toolbox/update/esp32.js +2 -2
- package/docs/astro.config.mjs +13 -0
- package/docs/public/favicon.ico +0 -0
- package/docs/public/make-scrollable-code-focusable.js +3 -0
- package/docs/src/components/Footer/AvatarList.astro +149 -0
- package/docs/src/components/Footer/Footer.astro +16 -0
- package/docs/src/components/HeadCommon.astro +41 -0
- package/docs/src/components/HeadSEO.astro +34 -0
- package/docs/src/components/Header/Header.astro +133 -0
- package/docs/src/components/Header/LanguageSelect.css +47 -0
- package/docs/src/components/Header/LanguageSelect.tsx +49 -0
- package/docs/src/components/Header/Search.css +39 -0
- package/docs/src/components/Header/Search.tsx +65 -0
- package/docs/src/components/Header/SidebarToggle.tsx +44 -0
- package/docs/src/components/Header/SkipToContent.astro +22 -0
- package/docs/src/components/LeftSidebar/LeftSidebar.astro +118 -0
- package/docs/src/components/PageContent/PageContent.astro +41 -0
- package/docs/src/components/RightSidebar/MoreMenu.astro +70 -0
- package/docs/src/components/RightSidebar/RightSidebar.astro +27 -0
- package/docs/src/components/RightSidebar/TableOfContents.tsx +49 -0
- package/docs/src/components/RightSidebar/ThemeToggleButton.css +37 -0
- package/docs/src/components/RightSidebar/ThemeToggleButton.tsx +83 -0
- package/docs/src/config.ts +43 -0
- package/docs/src/languages.ts +10 -0
- package/docs/src/layouts/MainLayout.astro +122 -0
- package/docs/src/pages/en/features/include.md +48 -0
- package/docs/src/pages/en/features/init.md +57 -0
- package/docs/src/pages/en/features/run.md +63 -0
- package/docs/src/pages/en/features/scan.md +28 -0
- package/docs/src/pages/en/features/setup.md +55 -0
- package/docs/src/pages/en/features/teardown.md +13 -0
- package/docs/src/pages/en/features/update.md +21 -0
- package/docs/src/pages/en/introduction.md +68 -0
- package/docs/src/pages/index.astro +5 -0
- package/docs/src/pages/search-index.json.ts +18 -0
- package/docs/src/styles/index.css +382 -0
- package/docs/src/styles/theme.css +125 -0
- package/docs/tailwind.config.cjs +7 -0
- package/docs/tsconfig.json +15 -0
- package/package.json +18 -5
- package/docs/commands.md +0 -3
- package/docs/plugins.md +0 -47
package/README.md
CHANGED
|
@@ -334,3 +334,7 @@ To maintain the alias between shell sessions, for example I use zsh:
|
|
|
334
334
|
```
|
|
335
335
|
echo "alias local-xs-dev=$PWD/bin/xs-dev" >> ~/.zshrc
|
|
336
336
|
```
|
|
337
|
+
|
|
338
|
+
## Docs
|
|
339
|
+
|
|
340
|
+
The documentation site is built with [Astro](https://astro.build) and can be found in the `docs/` directory. When working on them locally, run `pnpm start:docs` to start the development server that watches for file changes and reloads the page.
|
|
@@ -13,7 +13,7 @@ const linux_1 = require("./esp32/linux");
|
|
|
13
13
|
async function default_1() {
|
|
14
14
|
const OS = (0, os_1.type)().toLowerCase();
|
|
15
15
|
const ESP_IDF_REPO = 'https://github.com/espressif/esp-idf.git';
|
|
16
|
-
const ESP_BRANCH = 'v4.4';
|
|
16
|
+
const ESP_BRANCH = 'v4.4.2';
|
|
17
17
|
const ESP32_DIR = gluegun_1.filesystem.resolve(constants_1.INSTALL_DIR, 'esp32');
|
|
18
18
|
const IDF_PATH = gluegun_1.filesystem.resolve(ESP32_DIR, 'esp-idf');
|
|
19
19
|
const spinner = gluegun_1.print.spin();
|
|
@@ -67,4 +67,4 @@ async function default_1() {
|
|
|
67
67
|
`);
|
|
68
68
|
}
|
|
69
69
|
exports.default = default_1;
|
|
70
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
70
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXNwMzIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvdG9vbGJveC9zZXR1cC9lc3AzMi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLHFDQUFtRDtBQUNuRCwyQkFBeUM7QUFDekMsMkNBQTREO0FBQzVELHlDQUEyQztBQUMzQyxnRUFBdUM7QUFDdkMscUNBQTJEO0FBQzNELHlDQUErRDtBQUVoRCxLQUFLO0lBQ2xCLE1BQU0sRUFBRSxHQUFHLElBQUEsU0FBWSxHQUFFLENBQUMsV0FBVyxFQUFFLENBQUE7SUFDdkMsTUFBTSxZQUFZLEdBQUcsMENBQTBDLENBQUE7SUFDL0QsTUFBTSxVQUFVLEdBQUcsUUFBUSxDQUFBO0lBQzNCLE1BQU0sU0FBUyxHQUFHLG9CQUFVLENBQUMsT0FBTyxDQUFDLHVCQUFXLEVBQUUsT0FBTyxDQUFDLENBQUE7SUFDMUQsTUFBTSxRQUFRLEdBQUcsb0JBQVUsQ0FBQyxPQUFPLENBQUMsU0FBUyxFQUFFLFNBQVMsQ0FBQyxDQUFBO0lBRXpELE1BQU0sT0FBTyxHQUFHLGVBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQTtJQUM1QixPQUFPLENBQUMsS0FBSyxDQUFDLHdCQUF3QixDQUFDLENBQUE7SUFFdkMsNEJBQTRCO0lBQzVCLElBQUksQ0FBQyxJQUFBLHlCQUFjLEdBQUUsRUFBRTtRQUNyQixPQUFPLENBQUMsSUFBSSxDQUNWLG9FQUFvRSxDQUNyRSxDQUFBO1FBQ0QsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQTtLQUNoQjtJQUVELDJDQUEyQztJQUMzQyxPQUFPLENBQUMsSUFBSSxDQUFDLGtDQUFrQyxDQUFDLENBQUE7SUFDaEQsb0JBQVUsQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLENBQUE7SUFFekIscURBQXFEO0lBQ3JELElBQUksb0JBQVUsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLEtBQUssS0FBSyxFQUFFO1FBQ3pDLE9BQU8sQ0FBQyxLQUFLLENBQUMsc0JBQXNCLENBQUMsQ0FBQTtRQUNyQyxNQUFNLGdCQUFNLENBQUMsS0FBSyxDQUNoQixnQkFBZ0IsVUFBVSxnQkFBZ0IsWUFBWSxJQUFJLFFBQVEsRUFBRSxDQUNyRSxDQUFBO1FBQ0QsT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFBO0tBQ2xCO0lBRUQsd0NBQXdDO0lBQ3hDLE9BQU8sQ0FBQyxLQUFLLENBQUMsK0JBQStCLENBQUMsQ0FBQTtJQUU5QyxJQUFJLEVBQUUsS0FBSyxRQUFRLEVBQUU7UUFDbkIsTUFBTSxJQUFBLGlCQUFjLEVBQUMsT0FBTyxDQUFDLENBQUE7S0FDOUI7SUFFRCxJQUFJLEVBQUUsS0FBSyxPQUFPLEVBQUU7UUFDbEIsTUFBTSxJQUFBLG1CQUFnQixFQUFDLE9BQU8sQ0FBQyxDQUFBO0tBQ2hDO0lBRUQsaURBQWlEO0lBQ2pELElBQUksT0FBTyxDQUFDLEdBQUcsQ0FBQyxRQUFRLEtBQUssU0FBUyxFQUFFO1FBQ3RDLE9BQU8sQ0FBQyxJQUFJLENBQUMsdUJBQXVCLENBQUMsQ0FBQTtRQUNyQyxPQUFPLENBQUMsR0FBRyxDQUFDLFFBQVEsR0FBRyxRQUFRLENBQUE7UUFDL0IsTUFBTSxJQUFBLGdCQUFNLEVBQUMsNkJBQWlCLEVBQUUsbUJBQW1CLFFBQVEsRUFBRSxDQUFDLENBQUE7S0FDL0Q7SUFFRCxvQ0FBb0M7SUFDcEMsT0FBTyxDQUFDLEtBQUssQ0FBQyw0QkFBNEIsQ0FBQyxDQUFBO0lBQzNDLE1BQU0sZ0JBQU0sQ0FBQyxJQUFJLENBQUMsY0FBYyxFQUFFO1FBQ2hDLEdBQUcsRUFBRSxRQUFRO1FBQ2IsS0FBSyxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsS0FBSztRQUN4QixNQUFNLEVBQUUsT0FBTyxDQUFDLE1BQU07S0FDdkIsQ0FBQyxDQUFBO0lBQ0YsT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFBO0lBRWpCLDBEQUEwRDtJQUMxRCxPQUFPLENBQUMsSUFBSSxDQUFDLDhCQUE4QixDQUFDLENBQUE7SUFDNUMsTUFBTSxJQUFBLGdCQUFNLEVBQUMsNkJBQWlCLEVBQUUseUNBQXlDLENBQUMsQ0FBQTtJQUMxRSxNQUFNLGdCQUFNLENBQUMsSUFBSSxDQUFDLDRCQUE0QixFQUFFO1FBQzlDLEtBQUssRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLEtBQUs7S0FDekIsQ0FBQyxDQUFBO0lBRUYsT0FBTyxDQUFDLE9BQU8sQ0FBQzs7OztHQUlmLENBQUMsQ0FBQTtBQUNKLENBQUM7QUF0RUQsNEJBc0VDIn0=
|
|
@@ -13,7 +13,7 @@ const linux_1 = require("../setup/esp32/linux");
|
|
|
13
13
|
async function default_1() {
|
|
14
14
|
var _a, _b;
|
|
15
15
|
const OS = (0, os_1.type)().toLowerCase();
|
|
16
|
-
const ESP_BRANCH = 'v4.4';
|
|
16
|
+
const ESP_BRANCH = 'v4.4.2';
|
|
17
17
|
const ESP32_DIR = gluegun_1.filesystem.resolve(constants_1.INSTALL_DIR, 'esp32');
|
|
18
18
|
const IDF_PATH = gluegun_1.filesystem.resolve(ESP32_DIR, 'esp-idf');
|
|
19
19
|
const spinner = gluegun_1.print.spin();
|
|
@@ -86,4 +86,4 @@ async function default_1() {
|
|
|
86
86
|
`);
|
|
87
87
|
}
|
|
88
88
|
exports.default = default_1;
|
|
89
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
89
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXNwMzIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvdG9vbGJveC91cGRhdGUvZXNwMzIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSxxQ0FBNkQ7QUFDN0QsMkJBQXlDO0FBQ3pDLGtEQUFtRTtBQUNuRSxnREFBa0Q7QUFDbEQsZ0VBQXVDO0FBQ3ZDLDRDQUFrRTtBQUNsRSxnREFBc0U7QUFFdkQsS0FBSzs7SUFDbEIsTUFBTSxFQUFFLEdBQUcsSUFBQSxTQUFZLEdBQUUsQ0FBQyxXQUFXLEVBQUUsQ0FBQTtJQUN2QyxNQUFNLFVBQVUsR0FBRyxRQUFRLENBQUE7SUFDM0IsTUFBTSxTQUFTLEdBQUcsb0JBQVUsQ0FBQyxPQUFPLENBQUMsdUJBQVcsRUFBRSxPQUFPLENBQUMsQ0FBQTtJQUMxRCxNQUFNLFFBQVEsR0FBRyxvQkFBVSxDQUFDLE9BQU8sQ0FBQyxTQUFTLEVBQUUsU0FBUyxDQUFDLENBQUE7SUFFekQsTUFBTSxPQUFPLEdBQUcsZUFBSyxDQUFDLElBQUksRUFBRSxDQUFBO0lBQzVCLE9BQU8sQ0FBQyxLQUFLLENBQUMseUJBQXlCLENBQUMsQ0FBQTtJQUV4Qyw0QkFBNEI7SUFDNUIsSUFBSSxDQUFDLElBQUEseUJBQWMsR0FBRSxFQUFFO1FBQ3JCLE9BQU8sQ0FBQyxJQUFJLENBQ1Ysb0VBQW9FLENBQ3JFLENBQUE7UUFDRCxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFBO0tBQ2hCO0lBRUQsMkNBQTJDO0lBQzNDLE9BQU8sQ0FBQyxJQUFJLENBQUMsa0NBQWtDLENBQUMsQ0FBQTtJQUNoRCxJQUNFLG9CQUFVLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxLQUFLLEtBQUs7UUFDdEMsb0JBQVUsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLEtBQUssS0FBSyxFQUNyQztRQUNBLE9BQU8sQ0FBQyxJQUFJLENBQ1YsZ0ZBQWdGLENBQ2pGLENBQUE7UUFDRCxPQUFPLENBQUMsSUFB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
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { defineConfig } from 'astro/config'
|
|
2
|
+
|
|
3
|
+
import lit from '@astrojs/lit'
|
|
4
|
+
import preact from '@astrojs/preact'
|
|
5
|
+
import tailwind from '@astrojs/tailwind'
|
|
6
|
+
import sitemap from '@astrojs/sitemap'
|
|
7
|
+
|
|
8
|
+
// https://astro.build/config
|
|
9
|
+
export default defineConfig({
|
|
10
|
+
integrations: [preact(), lit(), tailwind(), sitemap()],
|
|
11
|
+
site: 'https://hipsterbrown.github.io',
|
|
12
|
+
base: '/xs-dev',
|
|
13
|
+
})
|
|
Binary file
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
---
|
|
2
|
+
// fetch all commits for just this page's path
|
|
3
|
+
const path = 'docs/' + Astro.props.path;
|
|
4
|
+
const url = `https://api.github.com/repos/hipsterbrown/xs-dev/commits?path=${path}`;
|
|
5
|
+
const commitsURL = `https://github.com/hipsterbrown/xs-dev/commits/main/${path}`;
|
|
6
|
+
|
|
7
|
+
async function getCommits(url) {
|
|
8
|
+
try {
|
|
9
|
+
const token = import.meta.env.PUBLIC_GITHUB_TOKEN;
|
|
10
|
+
if (!token) {
|
|
11
|
+
throw new Error('Cannot find "PUBLIC_GITHUB_TOKEN" used for escaping rate-limiting.');
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const auth = `Basic ${Buffer.from(token, 'binary').toString('base64')}`;
|
|
15
|
+
|
|
16
|
+
const res = await fetch(url, {
|
|
17
|
+
method: 'GET',
|
|
18
|
+
headers: {
|
|
19
|
+
Authorization: auth,
|
|
20
|
+
'User-Agent': 'astro-docs/1.0',
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const data = await res.json();
|
|
25
|
+
|
|
26
|
+
if (!res.ok) {
|
|
27
|
+
throw new Error(
|
|
28
|
+
`Request to fetch commits failed. Reason: ${res.statusText}
|
|
29
|
+
Message: ${data.message}`
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return data;
|
|
34
|
+
} catch (e) {
|
|
35
|
+
console.warn(`[error] /src/components/AvatarList.astro
|
|
36
|
+
${e?.message ?? e}`);
|
|
37
|
+
return new Array();
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function removeDups(arr) {
|
|
42
|
+
if (!arr) {
|
|
43
|
+
return new Array();
|
|
44
|
+
}
|
|
45
|
+
let map = new Map();
|
|
46
|
+
|
|
47
|
+
for (let item of arr) {
|
|
48
|
+
let author = item.author;
|
|
49
|
+
// Deduplicate based on author.id
|
|
50
|
+
map.set(author.id, { login: author.login, id: author.id });
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return Array.from(map.values());
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const data = await getCommits(url);
|
|
57
|
+
const unique = removeDups(data);
|
|
58
|
+
const recentContributors = unique.slice(0, 3); // only show avatars for the 3 most recent contributors
|
|
59
|
+
const additionalContributors = unique.length - recentContributors.length; // list the rest of them as # of extra contributors
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
<!-- Thanks to @5t3ph for https://smolcss.dev/#smol-avatar-list! -->
|
|
63
|
+
<div class="contributors">
|
|
64
|
+
<ul class="avatar-list" style={`--avatar-count: ${recentContributors.length}`}>
|
|
65
|
+
{recentContributors.map((item) => (
|
|
66
|
+
<li>
|
|
67
|
+
<a href={`https://github.com/${item.login}`}>
|
|
68
|
+
<img alt={`Contributor ${item.login}`} title={`Contributor ${item.login}`} width="64" height="64" src={`https://avatars.githubusercontent.com/u/${item.id}`} />
|
|
69
|
+
</a>
|
|
70
|
+
</li>
|
|
71
|
+
))}
|
|
72
|
+
</ul>
|
|
73
|
+
{additionalContributors > 0 && (
|
|
74
|
+
<span>
|
|
75
|
+
<a href={commitsURL}>{`and ${additionalContributors} additional contributor${additionalContributors > 1 ? 's' : ''}.`}</a>
|
|
76
|
+
</span>
|
|
77
|
+
)}
|
|
78
|
+
{unique.length === 0 && <a href={commitsURL}>Contributors</a>}
|
|
79
|
+
</div>
|
|
80
|
+
|
|
81
|
+
<style>
|
|
82
|
+
.avatar-list {
|
|
83
|
+
--avatar-size: 2.5rem;
|
|
84
|
+
--avatar-count: 3;
|
|
85
|
+
|
|
86
|
+
display: grid;
|
|
87
|
+
list-style: none;
|
|
88
|
+
/* Default to displaying most of the avatar to
|
|
89
|
+
enable easier access on touch devices, ensuring
|
|
90
|
+
the WCAG touch target size is met or exceeded */
|
|
91
|
+
grid-template-columns: repeat(var(--avatar-count), max(44px, calc(var(--avatar-size) / 1.15)));
|
|
92
|
+
/* `padding` matches added visual dimensions of
|
|
93
|
+
the `box-shadow` to help create a more accurate
|
|
94
|
+
computed component size */
|
|
95
|
+
padding: 0.08em;
|
|
96
|
+
font-size: var(--avatar-size);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
@media (any-hover: hover) and (any-pointer: fine) {
|
|
100
|
+
.avatar-list {
|
|
101
|
+
/* We create 1 extra cell to enable the computed
|
|
102
|
+
width to match the final visual width */
|
|
103
|
+
grid-template-columns: repeat(calc(var(--avatar-count) + 1), calc(var(--avatar-size) / 1.75));
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.avatar-list li {
|
|
108
|
+
width: var(--avatar-size);
|
|
109
|
+
height: var(--avatar-size);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.avatar-list li:hover ~ li a,
|
|
113
|
+
.avatar-list li:focus-within ~ li a {
|
|
114
|
+
transform: translateX(33%);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.avatar-list img,
|
|
118
|
+
.avatar-list a {
|
|
119
|
+
display: block;
|
|
120
|
+
border-radius: 50%;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.avatar-list a {
|
|
124
|
+
transition: transform 180ms ease-in-out;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.avatar-list img {
|
|
128
|
+
width: 100%;
|
|
129
|
+
height: 100%;
|
|
130
|
+
object-fit: cover;
|
|
131
|
+
background-color: #fff;
|
|
132
|
+
box-shadow: 0 0 0 0.05em #fff, 0 0 0 0.08em rgba(0, 0, 0, 0.15);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
.avatar-list a:focus {
|
|
136
|
+
outline: 2px solid transparent;
|
|
137
|
+
/* Double-layer trick to work for dark and light backgrounds */
|
|
138
|
+
box-shadow: 0 0 0 0.08em var(--theme-accent), 0 0 0 0.12em white;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.contributors {
|
|
142
|
+
display: flex;
|
|
143
|
+
align-items: center;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.contributors > * + * {
|
|
147
|
+
margin-left: 0.75rem;
|
|
148
|
+
}
|
|
149
|
+
</style>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
import AvatarList from './AvatarList.astro';
|
|
3
|
+
const { path } = Astro.props;
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
<footer>
|
|
7
|
+
<AvatarList {path} />
|
|
8
|
+
</footer>
|
|
9
|
+
|
|
10
|
+
<style>
|
|
11
|
+
footer {
|
|
12
|
+
margin-top: auto;
|
|
13
|
+
padding: 2rem 0;
|
|
14
|
+
border-top: 3px solid var(--theme-divider);
|
|
15
|
+
}
|
|
16
|
+
</style>
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
import '../styles/theme.css';
|
|
3
|
+
import '../styles/index.css';
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
<!-- Global Metadata -->
|
|
7
|
+
<meta charset="utf-8" />
|
|
8
|
+
<meta name="viewport" content="width=device-width" />
|
|
9
|
+
|
|
10
|
+
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
|
11
|
+
<link rel="alternate icon" type="image/x-icon" href="/favicon.ico" />
|
|
12
|
+
|
|
13
|
+
<link rel="sitemap" href="/sitemap.xml" />
|
|
14
|
+
|
|
15
|
+
<!-- Preload Fonts -->
|
|
16
|
+
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
17
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
18
|
+
<link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:ital@0;1&display=swap" rel="stylesheet" />
|
|
19
|
+
|
|
20
|
+
<!-- Scrollable a11y code helper -->
|
|
21
|
+
<script src="/make-scrollable-code-focusable.js" is:inline></script>
|
|
22
|
+
|
|
23
|
+
<!-- This is intentionally inlined to avoid FOUC -->
|
|
24
|
+
<script is:inline>
|
|
25
|
+
const root = document.documentElement;
|
|
26
|
+
const theme = localStorage.getItem('theme');
|
|
27
|
+
if (theme === 'dark' || (!theme && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
|
|
28
|
+
root.classList.add('theme-dark');
|
|
29
|
+
} else {
|
|
30
|
+
root.classList.remove('theme-dark');
|
|
31
|
+
}
|
|
32
|
+
</script>
|
|
33
|
+
|
|
34
|
+
<!-- Global site tag (gtag.js) - Google Analytics -->
|
|
35
|
+
<!-- <script async src="https://www.googletagmanager.com/gtag/js?id=G-TEL60V1WM9" is:inline></script>
|
|
36
|
+
<script>
|
|
37
|
+
window.dataLayer = window.dataLayer || [];
|
|
38
|
+
function gtag(){dataLayer.push(arguments);}
|
|
39
|
+
gtag('js', new Date());
|
|
40
|
+
gtag('config', 'G-TEL60V1WM9');
|
|
41
|
+
</script> -->
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { SITE, OPEN_GRAPH } from '../config.ts';
|
|
3
|
+
export interface Props {
|
|
4
|
+
content: any;
|
|
5
|
+
site: any;
|
|
6
|
+
canonicalURL: URL | string;
|
|
7
|
+
}
|
|
8
|
+
const { content = {}, canonicalURL } = Astro.props;
|
|
9
|
+
const formattedContentTitle = content.title ? `${content.title} 🚀 ${SITE.title}` : SITE.title;
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
<!-- Page Metadata -->
|
|
13
|
+
<link rel="canonical" href={canonicalURL} />
|
|
14
|
+
|
|
15
|
+
<!-- OpenGraph Tags -->
|
|
16
|
+
<meta property="og:title" content={formattedContentTitle} />
|
|
17
|
+
<meta property="og:type" content="article" />
|
|
18
|
+
<meta property="og:url" content={canonicalURL} />
|
|
19
|
+
<meta property="og:locale" content={content.ogLocale ?? SITE.defaultLanguage} />
|
|
20
|
+
<meta name="description" property="og:description" content={content.description ? content.description : SITE.description} />
|
|
21
|
+
<meta property="og:site_name" content={SITE.title} />
|
|
22
|
+
|
|
23
|
+
<!-- Twitter Tags -->
|
|
24
|
+
<meta name="twitter:card" content="summary_large_image" />
|
|
25
|
+
<meta name="twitter:site" content={OPEN_GRAPH.twitter} />
|
|
26
|
+
<meta name="twitter:title" content={formattedContentTitle} />
|
|
27
|
+
<meta name="twitter:description" content={content.description ? content.description : SITE.description} />
|
|
28
|
+
|
|
29
|
+
<!--
|
|
30
|
+
TODO: Add json+ld data, maybe https://schema.org/APIReference makes sense?
|
|
31
|
+
Docs: https://developers.google.com/search/docs/advanced/structured-data/intro-structured-data
|
|
32
|
+
https://www.npmjs.com/package/schema-dts seems like a great resource for implementing this.
|
|
33
|
+
Even better, there's a React component that integrates with `schema-dts`: https://github.com/google/react-schemaorg
|
|
34
|
+
-->
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { getLanguageFromURL, KNOWN_LANGUAGE_CODES } from '../../languages.ts';
|
|
3
|
+
import * as CONFIG from '../../config.ts';
|
|
4
|
+
import SkipToContent from './SkipToContent.astro';
|
|
5
|
+
import SidebarToggle from './SidebarToggle.tsx';
|
|
6
|
+
import LanguageSelect from './LanguageSelect.tsx';
|
|
7
|
+
import Search from './Search.tsx';
|
|
8
|
+
|
|
9
|
+
const { currentPage } = Astro.props;
|
|
10
|
+
const lang = currentPage && getLanguageFromURL(currentPage);
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
<header>
|
|
14
|
+
<SkipToContent />
|
|
15
|
+
<nav class="nav-wrapper" title="Top Navigation">
|
|
16
|
+
<div class="menu-toggle">
|
|
17
|
+
<SidebarToggle client:idle />
|
|
18
|
+
</div>
|
|
19
|
+
<div class="logo flex">
|
|
20
|
+
<a href={Astro.site}>
|
|
21
|
+
<h1>{CONFIG.SITE.title ?? "Documentation"}</h1>
|
|
22
|
+
</a>
|
|
23
|
+
</div>
|
|
24
|
+
<div style="flex-grow: 1;"></div>
|
|
25
|
+
{KNOWN_LANGUAGE_CODES.length > 1 && <LanguageSelect lang={lang} client:idle />}
|
|
26
|
+
</nav>
|
|
27
|
+
<Search client:idle />
|
|
28
|
+
</header>
|
|
29
|
+
|
|
30
|
+
<style>
|
|
31
|
+
header {
|
|
32
|
+
z-index: 11;
|
|
33
|
+
height: var(--theme-navbar-height);
|
|
34
|
+
width: 100%;
|
|
35
|
+
background-color: var(--theme-navbar-bg);
|
|
36
|
+
display: flex;
|
|
37
|
+
align-items: center;
|
|
38
|
+
justify-content: center;
|
|
39
|
+
position: sticky;
|
|
40
|
+
top: 0;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.logo {
|
|
44
|
+
flex: 1;
|
|
45
|
+
display: flex;
|
|
46
|
+
overflow: hidden;
|
|
47
|
+
width: 30px;
|
|
48
|
+
font-size: 2rem;
|
|
49
|
+
flex-shrink: 0;
|
|
50
|
+
font-weight: 600;
|
|
51
|
+
line-height: 1;
|
|
52
|
+
color: hsla(var(--color-base-white), 100%, 1);
|
|
53
|
+
gap: 0.25em;
|
|
54
|
+
z-index: -1;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.logo a {
|
|
58
|
+
display: flex;
|
|
59
|
+
padding: 0.5em 0.25em;
|
|
60
|
+
margin: -0.5em -0.25em;
|
|
61
|
+
text-decoration: none;
|
|
62
|
+
font-weight: bold;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.logo a {
|
|
66
|
+
transition: color 100ms ease-out;
|
|
67
|
+
color: var(--theme-text);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.logo a:hover,
|
|
71
|
+
.logo a:focus {
|
|
72
|
+
color: var(--theme-text-accent);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.logo h1 {
|
|
76
|
+
display: none;
|
|
77
|
+
font: inherit;
|
|
78
|
+
color: inherit;
|
|
79
|
+
margin: 0;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.nav-wrapper {
|
|
83
|
+
display: flex;
|
|
84
|
+
align-items: center;
|
|
85
|
+
justify-content: flex-end;
|
|
86
|
+
gap: 1em;
|
|
87
|
+
width: 100%;
|
|
88
|
+
max-width: 82em;
|
|
89
|
+
padding: 0 1rem;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
@media (min-width: 50em) {
|
|
93
|
+
header {
|
|
94
|
+
position: static;
|
|
95
|
+
padding: 2rem 0rem;
|
|
96
|
+
}
|
|
97
|
+
.logo {
|
|
98
|
+
width: auto;
|
|
99
|
+
margin: 0;
|
|
100
|
+
z-index: 0;
|
|
101
|
+
}
|
|
102
|
+
.logo h1 {
|
|
103
|
+
display: initial;
|
|
104
|
+
}
|
|
105
|
+
.menu-toggle {
|
|
106
|
+
display: none;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/** Style Algolia */
|
|
111
|
+
:root {
|
|
112
|
+
--docsearch-primary-color: var(--theme-accent);
|
|
113
|
+
--docsearch-logo-color: var(--theme-text);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.search-item {
|
|
117
|
+
display: none;
|
|
118
|
+
position: relative;
|
|
119
|
+
z-index: 10;
|
|
120
|
+
flex-grow: 1;
|
|
121
|
+
padding-right: 0.7rem;
|
|
122
|
+
display: flex;
|
|
123
|
+
max-width: 200px;
|
|
124
|
+
}
|
|
125
|
+
:global(.search-item > *) {
|
|
126
|
+
flex-grow: 1;
|
|
127
|
+
}
|
|
128
|
+
@media (min-width: 50em) {
|
|
129
|
+
.search-item {
|
|
130
|
+
max-width: 400px;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
</style>
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
.language-select {
|
|
2
|
+
flex-grow: 1;
|
|
3
|
+
width: 48px;
|
|
4
|
+
box-sizing: border-box;
|
|
5
|
+
margin: 0;
|
|
6
|
+
padding: 0.33em 0.5em;
|
|
7
|
+
overflow: visible;
|
|
8
|
+
font-weight: 500;
|
|
9
|
+
font-size: 1rem;
|
|
10
|
+
font-family: inherit;
|
|
11
|
+
line-height: inherit;
|
|
12
|
+
background-color: var(--theme-bg);
|
|
13
|
+
border-color: var(--theme-text-lighter);
|
|
14
|
+
color: var(--theme-text-light);
|
|
15
|
+
border-style: solid;
|
|
16
|
+
border-width: 1px;
|
|
17
|
+
border-radius: 0.25rem;
|
|
18
|
+
outline: 0;
|
|
19
|
+
cursor: pointer;
|
|
20
|
+
transition-timing-function: ease-out;
|
|
21
|
+
transition-duration: 0.2s;
|
|
22
|
+
transition-property: border-color, color;
|
|
23
|
+
-webkit-font-smoothing: antialiased;
|
|
24
|
+
padding-left: 30px;
|
|
25
|
+
padding-right: 1rem;
|
|
26
|
+
}
|
|
27
|
+
.language-select-wrapper .language-select:hover,
|
|
28
|
+
.language-select-wrapper .language-select:focus {
|
|
29
|
+
color: var(--theme-text);
|
|
30
|
+
border-color: var(--theme-text-light);
|
|
31
|
+
}
|
|
32
|
+
.language-select-wrapper {
|
|
33
|
+
color: var(--theme-text-light);
|
|
34
|
+
position: relative;
|
|
35
|
+
}
|
|
36
|
+
.language-select-wrapper > svg {
|
|
37
|
+
position: absolute;
|
|
38
|
+
top: 7px;
|
|
39
|
+
left: 10px;
|
|
40
|
+
pointer-events: none;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
@media (min-width: 50em) {
|
|
44
|
+
.language-select {
|
|
45
|
+
width: 100%;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { FunctionalComponent } from 'preact';
|
|
2
|
+
import { h } from 'preact';
|
|
3
|
+
import './LanguageSelect.css';
|
|
4
|
+
import { KNOWN_LANGUAGES, langPathRegex } from '../../languages';
|
|
5
|
+
|
|
6
|
+
const LanguageSelect: FunctionalComponent<{ lang: string }> = ({ lang }) => {
|
|
7
|
+
return (
|
|
8
|
+
<div class="language-select-wrapper">
|
|
9
|
+
<svg
|
|
10
|
+
aria-hidden="true"
|
|
11
|
+
focusable="false"
|
|
12
|
+
role="img"
|
|
13
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
14
|
+
viewBox="0 0 88.6 77.3"
|
|
15
|
+
height="1.2em"
|
|
16
|
+
width="1.2em"
|
|
17
|
+
>
|
|
18
|
+
<path
|
|
19
|
+
fill="currentColor"
|
|
20
|
+
d="M61,24.6h7.9l18.7,51.6h-7.7l-5.4-15.5H54.3l-5.6,15.5h-7.2L61,24.6z M72.6,55l-8-22.8L56.3,55H72.6z"
|
|
21
|
+
/>
|
|
22
|
+
<path
|
|
23
|
+
fill="currentColor"
|
|
24
|
+
d="M53.6,60.6c-10-4-16-9-22-14c0,0,1.3,1.3,0,0c-6,5-20,13-20,13l-4-6c8-5,10-6,19-13c-2.1-1.9-12-13-13-19h8 c4,9,10,14,10,14c10-8,10-19,10-19h8c0,0-1,13-12,24l0,0c5,5,10,9,19,13L53.6,60.6z M1.6,16.6h56v-8h-23v-7h-9v7h-24V16.6z"
|
|
25
|
+
/>
|
|
26
|
+
</svg>
|
|
27
|
+
<select
|
|
28
|
+
class="language-select"
|
|
29
|
+
value={lang}
|
|
30
|
+
onChange={(e) => {
|
|
31
|
+
const newLang = e.target.value;
|
|
32
|
+
let actualDest = window.location.pathname.replace(langPathRegex, '/');
|
|
33
|
+
if (actualDest == '/') actualDest = `/introduction`;
|
|
34
|
+
window.location.pathname = '/' + newLang + actualDest;
|
|
35
|
+
}}
|
|
36
|
+
>
|
|
37
|
+
{Object.keys(KNOWN_LANGUAGES).map((key) => {
|
|
38
|
+
return (
|
|
39
|
+
<option value={KNOWN_LANGUAGES[key]}>
|
|
40
|
+
<span>{key}</span>
|
|
41
|
+
</option>
|
|
42
|
+
);
|
|
43
|
+
})}
|
|
44
|
+
</select>
|
|
45
|
+
</div>
|
|
46
|
+
);
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export default LanguageSelect;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
.flex-column {
|
|
2
|
+
flex-direction: column;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
.SearchContainer {
|
|
6
|
+
position: relative;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.SearchContainer-input {
|
|
10
|
+
border: 1px solid #333333;
|
|
11
|
+
padding: 0.5rem 1rem;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.SearchContainer-button {
|
|
15
|
+
border-radius: 0px;
|
|
16
|
+
padding: 0.5rem;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.SearchContainer-list {
|
|
20
|
+
background: white;
|
|
21
|
+
top: 2.6rem;
|
|
22
|
+
display: flex;
|
|
23
|
+
flex-direction: column;
|
|
24
|
+
left: 0;
|
|
25
|
+
position: absolute;
|
|
26
|
+
width: 100%;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.SearchContainer-list.has-results {
|
|
30
|
+
border: 1px solid #333333;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.SearchContainer-list_item {
|
|
34
|
+
padding: 0.5rem 1rem;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.SearchContainer-link {
|
|
38
|
+
color: blue;
|
|
39
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { FunctionalComponent } from 'preact'
|
|
2
|
+
import { h, Fragment } from 'preact'
|
|
3
|
+
import { useEffect, useRef, useState } from 'preact/hooks'
|
|
4
|
+
import Fuse from 'fuse.js'
|
|
5
|
+
import './Search.css'
|
|
6
|
+
|
|
7
|
+
const SearchForm: FunctionalComponent = () => {
|
|
8
|
+
const fuse = useRef(null)
|
|
9
|
+
const [results, setResults] = useState([])
|
|
10
|
+
|
|
11
|
+
const searchContent = (event: SubmitEvent) => {
|
|
12
|
+
event.preventDefault()
|
|
13
|
+
const data = Object.fromEntries(
|
|
14
|
+
new FormData(event.currentTarget as HTMLFormElement)
|
|
15
|
+
)
|
|
16
|
+
const result = fuse.current.search(data.search)
|
|
17
|
+
setResults(result.map(({ item }) => item))
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
fetch('/xs-dev/search-index.json')
|
|
22
|
+
.then((res) => res.json())
|
|
23
|
+
.then((content) => {
|
|
24
|
+
const options = { keys: ['title', 'description', 'content'] }
|
|
25
|
+
fuse.current = new Fuse(content, options)
|
|
26
|
+
})
|
|
27
|
+
}, [])
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<div class="flex flex-column SearchContainer">
|
|
31
|
+
<form method="GET" id="search-form" onSubmit={searchContent}>
|
|
32
|
+
<div role="search" class="flex flex-row">
|
|
33
|
+
<input
|
|
34
|
+
type="search"
|
|
35
|
+
id="search"
|
|
36
|
+
name="search"
|
|
37
|
+
aria-label="search documentation content"
|
|
38
|
+
placeholder="search documentation content"
|
|
39
|
+
class="SearchContainer-input"
|
|
40
|
+
/>
|
|
41
|
+
<button type="submit" class="SearchContainer-button">
|
|
42
|
+
Search
|
|
43
|
+
</button>
|
|
44
|
+
</div>
|
|
45
|
+
</form>
|
|
46
|
+
<ul
|
|
47
|
+
class={`SearchContainer-list ${
|
|
48
|
+
results.length > 0 ? 'has-results' : undefined
|
|
49
|
+
}`}
|
|
50
|
+
aria-live="assertive"
|
|
51
|
+
aria-atomic="true"
|
|
52
|
+
>
|
|
53
|
+
{results.map((result) => (
|
|
54
|
+
<li class="SearchContainer-list_item">
|
|
55
|
+
<a href={result.url} class="SearchContainer-link">
|
|
56
|
+
{result.title}
|
|
57
|
+
</a>
|
|
58
|
+
</li>
|
|
59
|
+
))}
|
|
60
|
+
</ul>
|
|
61
|
+
</div>
|
|
62
|
+
)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export default SearchForm
|