@farming-labs/astro-theme 0.0.29 → 0.0.30
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@farming-labs/astro-theme",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.30",
|
|
4
4
|
"description": "Astro UI components for @farming-labs/docs — layout, sidebar, TOC, search, and theme toggle",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"astro",
|
|
@@ -79,8 +79,8 @@
|
|
|
79
79
|
},
|
|
80
80
|
"dependencies": {
|
|
81
81
|
"sugar-high": "^0.9.5",
|
|
82
|
-
"@farming-labs/docs": "0.0.
|
|
83
|
-
"@farming-labs/astro": "0.0.
|
|
82
|
+
"@farming-labs/docs": "0.0.30",
|
|
83
|
+
"@farming-labs/astro": "0.0.30"
|
|
84
84
|
},
|
|
85
85
|
"peerDependencies": {
|
|
86
86
|
"astro": ">=4.0.0"
|
|
@@ -107,7 +107,8 @@ const htmlWithoutFirstH1 = (data.html || "").replace(/<h1[^>]*>[\s\S]*?<\/h1>\s*
|
|
|
107
107
|
</head>
|
|
108
108
|
|
|
109
109
|
<DocsPage
|
|
110
|
-
entry={config?.entry ?? "docs"}
|
|
110
|
+
entry={data.entry ?? config?.entry ?? "docs"}
|
|
111
|
+
locale={data.locale}
|
|
111
112
|
tocEnabled={tocEnabled}
|
|
112
113
|
tocStyle={tocStyle}
|
|
113
114
|
breadcrumbEnabled={breadcrumbEnabled}
|
|
@@ -7,8 +7,25 @@ const { tree, config = null, title, titleUrl, flatPages = null } = Astro.props;
|
|
|
7
7
|
const sidebarFlat = !!(config?.sidebar && typeof config.sidebar === "object" && (config.sidebar as { flat?: boolean }).flat);
|
|
8
8
|
const useFlatSidebar = sidebarFlat && Array.isArray(flatPages) && flatPages.length > 0;
|
|
9
9
|
|
|
10
|
+
const i18n = config?.i18n as { locales?: string[]; defaultLocale?: string } | undefined;
|
|
11
|
+
const locales = Array.isArray(i18n?.locales) ? i18n.locales.filter(Boolean) : [];
|
|
12
|
+
const defaultLocale = (i18n?.defaultLocale && locales.includes(i18n.defaultLocale))
|
|
13
|
+
? i18n.defaultLocale
|
|
14
|
+
: locales[0];
|
|
15
|
+
const activeLocale =
|
|
16
|
+
Astro.url.searchParams.get("lang") ??
|
|
17
|
+
Astro.url.searchParams.get("locale") ??
|
|
18
|
+
defaultLocale;
|
|
19
|
+
const withLang = (url?: string | null) => {
|
|
20
|
+
if (!url || url.startsWith("#")) return url ?? "";
|
|
21
|
+
const parsed = new URL(url, Astro.url);
|
|
22
|
+
if (activeLocale) parsed.searchParams.set("lang", activeLocale);
|
|
23
|
+
else parsed.searchParams.delete("lang");
|
|
24
|
+
return `${parsed.pathname}${parsed.search}${parsed.hash}`;
|
|
25
|
+
};
|
|
26
|
+
|
|
10
27
|
const resolvedTitle = title ?? config?.nav?.title ?? "Docs";
|
|
11
|
-
const resolvedTitleUrl = titleUrl ?? config?.nav?.url ?? "/docs";
|
|
28
|
+
const resolvedTitleUrl = withLang(titleUrl ?? config?.nav?.url ?? "/docs");
|
|
12
29
|
|
|
13
30
|
const showThemeToggle = (() => {
|
|
14
31
|
const toggle = config?.themeToggle;
|
|
@@ -207,7 +224,7 @@ const showSearch = !staticExport;
|
|
|
207
224
|
const icon = getIcon(page.icon);
|
|
208
225
|
return (
|
|
209
226
|
<a
|
|
210
|
-
href={page.url}
|
|
227
|
+
href={withLang(page.url)}
|
|
211
228
|
class={`fd-sidebar-link fd-sidebar-top-link ${isActive(page.url) ? 'fd-sidebar-link-active' : ''} ${i === 0 ? 'fd-sidebar-first-item' : ''}`}
|
|
212
229
|
data-active={isActive(page.url) || undefined}
|
|
213
230
|
>
|
|
@@ -224,7 +241,7 @@ const showSearch = !staticExport;
|
|
|
224
241
|
const icon = getIcon(node.icon);
|
|
225
242
|
return (
|
|
226
243
|
<a
|
|
227
|
-
href={node.url}
|
|
244
|
+
href={withLang(node.url)}
|
|
228
245
|
class={`fd-sidebar-link fd-sidebar-top-link ${isActive(node.url) ? 'fd-sidebar-link-active' : ''} ${i === 0 ? 'fd-sidebar-first-item' : ''}`}
|
|
229
246
|
data-active={isActive(node.url) || undefined}
|
|
230
247
|
>
|
|
@@ -248,7 +265,7 @@ const showSearch = !staticExport;
|
|
|
248
265
|
<div class="fd-sidebar-folder-content">
|
|
249
266
|
{node.index && (
|
|
250
267
|
<a
|
|
251
|
-
href={node.index.url}
|
|
268
|
+
href={withLang(node.index.url)}
|
|
252
269
|
class={`fd-sidebar-link fd-sidebar-child-link ${isActive(node.index.url) ? 'fd-sidebar-link-active' : ''}`}
|
|
253
270
|
data-active={isActive(node.index.url) || undefined}
|
|
254
271
|
>
|
|
@@ -259,7 +276,7 @@ const showSearch = !staticExport;
|
|
|
259
276
|
if (child.type === "page") {
|
|
260
277
|
return (
|
|
261
278
|
<a
|
|
262
|
-
href={child.url}
|
|
279
|
+
href={withLang(child.url)}
|
|
263
280
|
class={`fd-sidebar-link fd-sidebar-child-link ${isActive(child.url) ? 'fd-sidebar-link-active' : ''}`}
|
|
264
281
|
data-active={isActive(child.url) || undefined}
|
|
265
282
|
>
|
|
@@ -278,7 +295,7 @@ const showSearch = !staticExport;
|
|
|
278
295
|
<div class="fd-sidebar-folder-content">
|
|
279
296
|
{child.index && (
|
|
280
297
|
<a
|
|
281
|
-
href={child.index.url}
|
|
298
|
+
href={withLang(child.index.url)}
|
|
282
299
|
class={`fd-sidebar-link fd-sidebar-child-link ${isActive(child.index.url) ? 'fd-sidebar-link-active' : ''}`}
|
|
283
300
|
data-active={isActive(child.index.url) || undefined}
|
|
284
301
|
>
|
|
@@ -289,7 +306,7 @@ const showSearch = !staticExport;
|
|
|
289
306
|
if (grandchild.type === "page") {
|
|
290
307
|
return (
|
|
291
308
|
<a
|
|
292
|
-
|
|
309
|
+
href={withLang(grandchild.url)}
|
|
293
310
|
class={`fd-sidebar-link fd-sidebar-child-link ${isActive(grandchild.url) ? 'fd-sidebar-link-active' : ''}`}
|
|
294
311
|
data-active={isActive(grandchild.url) || undefined}
|
|
295
312
|
>
|
|
@@ -317,9 +334,33 @@ const showSearch = !staticExport;
|
|
|
317
334
|
</div>
|
|
318
335
|
)}
|
|
319
336
|
|
|
320
|
-
{showThemeToggle && (
|
|
337
|
+
{(locales.length > 0 || showThemeToggle) && (
|
|
321
338
|
<div class="fd-sidebar-footer">
|
|
322
|
-
<
|
|
339
|
+
<div style="display:flex;align-items:center;justify-content:space-between;gap:12px;width:100%">
|
|
340
|
+
{locales.length > 0 && (
|
|
341
|
+
<div style="position:relative;display:inline-flex;align-items:center;flex-shrink:0">
|
|
342
|
+
<select
|
|
343
|
+
id="fd-locale-select"
|
|
344
|
+
aria-label="Select language"
|
|
345
|
+
data-default-locale={defaultLocale}
|
|
346
|
+
style="appearance:none;-webkit-appearance:none;-moz-appearance:none;min-width:84px;height:36px;border-radius:9999px;border:1px solid var(--color-fd-border);background:var(--color-fd-card, var(--color-fd-background));color:var(--color-fd-foreground);padding:0 36px 0 14px;font-size:12px;font-weight:600;letter-spacing:.04em;line-height:1;cursor:pointer;box-shadow:0 1px 2px rgba(15,23,42,.08)"
|
|
347
|
+
>
|
|
348
|
+
{locales.map((item) => (
|
|
349
|
+
<option value={item} selected={item === activeLocale}>{item.toUpperCase()}</option>
|
|
350
|
+
))}
|
|
351
|
+
</select>
|
|
352
|
+
<span
|
|
353
|
+
aria-hidden="true"
|
|
354
|
+
style="position:absolute;right:12px;display:inline-flex;align-items:center;justify-content:center;color:var(--color-fd-muted-foreground);pointer-events:none"
|
|
355
|
+
>
|
|
356
|
+
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
357
|
+
<polyline points="6 9 12 15 18 9" />
|
|
358
|
+
</svg>
|
|
359
|
+
</span>
|
|
360
|
+
</div>
|
|
361
|
+
)}
|
|
362
|
+
{showThemeToggle && <ThemeToggle />}
|
|
363
|
+
</div>
|
|
323
364
|
</div>
|
|
324
365
|
)}
|
|
325
366
|
</aside>
|
|
@@ -331,7 +372,7 @@ const showSearch = !staticExport;
|
|
|
331
372
|
|
|
332
373
|
{showFloatingAI && (
|
|
333
374
|
<FloatingAIChat
|
|
334
|
-
api="/api/docs"
|
|
375
|
+
api={withLang("/api/docs")}
|
|
335
376
|
suggestedQuestions={aiConfig?.suggestedQuestions ?? []}
|
|
336
377
|
aiLabel={aiConfig?.aiLabel ?? "AI"}
|
|
337
378
|
position={aiConfig?.position ?? "bottom-right"}
|
|
@@ -393,4 +434,12 @@ const showSearch = !staticExport;
|
|
|
393
434
|
overlay!.style.display = 'none';
|
|
394
435
|
});
|
|
395
436
|
});
|
|
437
|
+
|
|
438
|
+
document.getElementById('fd-locale-select')?.addEventListener('change', (event) => {
|
|
439
|
+
const target = event.target as HTMLSelectElement;
|
|
440
|
+
const url = new URL(window.location.href);
|
|
441
|
+
if (target.value) url.searchParams.set('lang', target.value);
|
|
442
|
+
else url.searchParams.delete('lang');
|
|
443
|
+
window.location.assign(`${url.pathname}${url.search}${url.hash}`);
|
|
444
|
+
});
|
|
396
445
|
</script>
|
|
@@ -4,6 +4,7 @@ const {
|
|
|
4
4
|
tocStyle = "default",
|
|
5
5
|
breadcrumbEnabled = true,
|
|
6
6
|
entry = "docs",
|
|
7
|
+
locale = null,
|
|
7
8
|
previousPage = null,
|
|
8
9
|
nextPage = null,
|
|
9
10
|
editOnGithub = null,
|
|
@@ -13,19 +14,34 @@ const {
|
|
|
13
14
|
|
|
14
15
|
const pathname = Astro.url.pathname;
|
|
15
16
|
const segments = pathname.split("/").filter(Boolean);
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
?
|
|
17
|
+
const entryParts = entry.split("/").filter(Boolean);
|
|
18
|
+
const contentSegments = segments.slice(entryParts.length);
|
|
19
|
+
const parentLabel = contentSegments.length >= 2
|
|
20
|
+
? contentSegments[contentSegments.length - 2].replace(/-/g, " ").replace(/\b\w/g, c => c.toUpperCase())
|
|
20
21
|
: "";
|
|
22
|
+
const currentLabel = contentSegments.length >= 2
|
|
23
|
+
? contentSegments[contentSegments.length - 1].replace(/-/g, " ").replace(/\b\w/g, c => c.toUpperCase())
|
|
24
|
+
: "";
|
|
25
|
+
const parentUrl = contentSegments.length >= 2
|
|
26
|
+
? "/" + [...segments.slice(0, entryParts.length), ...contentSegments.slice(0, contentSegments.length - 1)].join("/")
|
|
27
|
+
: "";
|
|
28
|
+
const llmsLangParam = locale ? `&lang=${encodeURIComponent(locale)}` : "";
|
|
29
|
+
const withLang = (url: string) => {
|
|
30
|
+
if (!url || url.startsWith("#")) return url;
|
|
31
|
+
const parsed = new URL(url, Astro.url);
|
|
32
|
+
if (locale) parsed.searchParams.set("lang", locale);
|
|
33
|
+
else parsed.searchParams.delete("lang");
|
|
34
|
+
return `${parsed.pathname}${parsed.search}${parsed.hash}`;
|
|
35
|
+
};
|
|
36
|
+
const localizedParentUrl = withLang(parentUrl);
|
|
21
37
|
---
|
|
22
38
|
|
|
23
39
|
<div class="fd-page">
|
|
24
40
|
<article class="fd-page-article" id="nd-page">
|
|
25
|
-
{breadcrumbEnabled &&
|
|
41
|
+
{breadcrumbEnabled && contentSegments.length >= 2 && (
|
|
26
42
|
<nav class="fd-breadcrumb" aria-label="Breadcrumb">
|
|
27
43
|
<span class="fd-breadcrumb-item">
|
|
28
|
-
<a href={
|
|
44
|
+
<a href={localizedParentUrl} class="fd-breadcrumb-parent fd-breadcrumb-link">{parentLabel}</a>
|
|
29
45
|
</span>
|
|
30
46
|
<span class="fd-breadcrumb-item">
|
|
31
47
|
<span class="fd-breadcrumb-sep">/</span>
|
|
@@ -54,8 +70,8 @@ const parentUrl = segments.length >= 2
|
|
|
54
70
|
)}
|
|
55
71
|
{llmsTxtEnabled && (
|
|
56
72
|
<span class="fd-llms-txt-links">
|
|
57
|
-
<a href=
|
|
58
|
-
<a href=
|
|
73
|
+
<a href={`/api/docs?format=llms${llmsLangParam}`} target="_blank" rel="noopener noreferrer" class="fd-llms-txt-link">llms.txt</a>
|
|
74
|
+
<a href={`/api/docs?format=llms-full${llmsLangParam}`} target="_blank" rel="noopener noreferrer" class="fd-llms-txt-link">llms-full.txt</a>
|
|
59
75
|
</span>
|
|
60
76
|
)}
|
|
61
77
|
{lastModified && (
|
|
@@ -67,7 +83,7 @@ const parentUrl = segments.length >= 2
|
|
|
67
83
|
{(previousPage || nextPage) && (
|
|
68
84
|
<nav class="fd-page-nav" aria-label="Page navigation">
|
|
69
85
|
{previousPage ? (
|
|
70
|
-
<a href={previousPage.url} class="fd-page-nav-card fd-page-nav-prev">
|
|
86
|
+
<a href={withLang(previousPage.url)} class="fd-page-nav-card fd-page-nav-prev">
|
|
71
87
|
<span class="fd-page-nav-label">
|
|
72
88
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
73
89
|
<polyline points="15 18 9 12 15 6" />
|
|
@@ -78,7 +94,7 @@ const parentUrl = segments.length >= 2
|
|
|
78
94
|
</a>
|
|
79
95
|
) : <div />}
|
|
80
96
|
{nextPage ? (
|
|
81
|
-
<a href={nextPage.url} class="fd-page-nav-card fd-page-nav-next">
|
|
97
|
+
<a href={withLang(nextPage.url)} class="fd-page-nav-card fd-page-nav-next">
|
|
82
98
|
<span class="fd-page-nav-label">
|
|
83
99
|
Next
|
|
84
100
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
@@ -127,6 +143,20 @@ const parentUrl = segments.length >= 2
|
|
|
127
143
|
const tocAside = document.getElementById('fd-toc');
|
|
128
144
|
if (container && tocList) {
|
|
129
145
|
const headings = container.querySelectorAll('h2[id], h3[id], h4[id]');
|
|
146
|
+
const activeLocale =
|
|
147
|
+
new URL(window.location.href).searchParams.get('lang') ||
|
|
148
|
+
new URL(window.location.href).searchParams.get('locale');
|
|
149
|
+
container.querySelectorAll('a[href]').forEach((link) => {
|
|
150
|
+
const href = link.getAttribute('href');
|
|
151
|
+
if (!href || href.startsWith('#') || /^(mailto:|tel:|javascript:)/i.test(href)) return;
|
|
152
|
+
try {
|
|
153
|
+
const url = new URL(href, window.location.origin);
|
|
154
|
+
if (url.origin !== window.location.origin) return;
|
|
155
|
+
if (activeLocale) url.searchParams.set('lang', activeLocale);
|
|
156
|
+
else url.searchParams.delete('lang');
|
|
157
|
+
link.setAttribute('href', `${url.pathname}${url.search}${url.hash}`);
|
|
158
|
+
} catch {}
|
|
159
|
+
});
|
|
130
160
|
const isClerk = tocList.closest('[data-toc-style]')?.getAttribute('data-toc-style') === 'directional';
|
|
131
161
|
|
|
132
162
|
const tocItems = [];
|
|
@@ -125,6 +125,29 @@ const { config = null } = Astro.props;
|
|
|
125
125
|
} catch (e) {}
|
|
126
126
|
}
|
|
127
127
|
|
|
128
|
+
function getActiveLocale() {
|
|
129
|
+
try {
|
|
130
|
+
var current = new URL(window.location.href);
|
|
131
|
+
return current.searchParams.get("lang") || current.searchParams.get("locale") || "";
|
|
132
|
+
} catch (e) {
|
|
133
|
+
return "";
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function withLang(url) {
|
|
138
|
+
if (!url || url.charAt(0) === "#") return url;
|
|
139
|
+
try {
|
|
140
|
+
var parsed = new URL(url, window.location.origin);
|
|
141
|
+
if (parsed.origin !== window.location.origin) return url;
|
|
142
|
+
var locale = getActiveLocale();
|
|
143
|
+
if (locale) parsed.searchParams.set("lang", locale);
|
|
144
|
+
else parsed.searchParams.delete("lang");
|
|
145
|
+
return parsed.pathname + parsed.search + parsed.hash;
|
|
146
|
+
} catch (e) {
|
|
147
|
+
return url;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
128
151
|
function openDialog() {
|
|
129
152
|
var dialog = getDialog();
|
|
130
153
|
if (dialog) {
|
|
@@ -241,14 +264,15 @@ const { config = null } = Astro.props;
|
|
|
241
264
|
|
|
242
265
|
function navigateToUrl(url, newTab) {
|
|
243
266
|
if (!url) return;
|
|
267
|
+
var localizedUrl = withLang(url);
|
|
244
268
|
if (newTab || url.startsWith("http")) {
|
|
245
269
|
try {
|
|
246
|
-
window.open(
|
|
270
|
+
window.open(localizedUrl, "_blank", "noopener,noreferrer");
|
|
247
271
|
} catch (err) {
|
|
248
|
-
window.location.assign(
|
|
272
|
+
window.location.assign(localizedUrl);
|
|
249
273
|
}
|
|
250
274
|
} else {
|
|
251
|
-
window.location.assign(
|
|
275
|
+
window.location.assign(localizedUrl);
|
|
252
276
|
}
|
|
253
277
|
}
|
|
254
278
|
|
|
@@ -352,9 +376,8 @@ const { config = null } = Astro.props;
|
|
|
352
376
|
if (items[activeIndex]) {
|
|
353
377
|
var it = items[activeIndex];
|
|
354
378
|
saveRecent({ id: it.url, label: it.content || it.label, url: it.url });
|
|
355
|
-
if (it.url.startsWith("http")) window.open(it.url, "_blank", "noopener");
|
|
356
|
-
else window.location.href = it.url;
|
|
357
379
|
closeDialog();
|
|
380
|
+
navigateToUrl(it.url, it.url.startsWith("http"));
|
|
358
381
|
}
|
|
359
382
|
}
|
|
360
383
|
|
|
@@ -375,7 +398,7 @@ const { config = null } = Astro.props;
|
|
|
375
398
|
if (!q) return;
|
|
376
399
|
debounceTimer = setTimeout(function () {
|
|
377
400
|
if (getLoading()) getLoading().style.display = "flex";
|
|
378
|
-
fetch("/api/docs?query=" + encodeURIComponent(q))
|
|
401
|
+
fetch(withLang("/api/docs?query=" + encodeURIComponent(q)))
|
|
379
402
|
.then(function (res) { return res.ok ? res.json() : []; })
|
|
380
403
|
.then(function (data) {
|
|
381
404
|
currentResults = Array.isArray(data) ? data : [];
|