@umami/shiso 1.4.0 → 1.5.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/CHANGELOG.md +17 -0
- package/bin/shiso.mjs +9 -1
- package/config.js +8 -0
- package/dist/chunks/App.js +240 -62
- package/dist/entry-client.js +1 -1
- package/dist/entry-server.js +16 -5
- package/docs.schema.json +29 -26
- package/package.json +7 -1
- package/scripts/build-runtime.mjs +1 -0
- package/scripts/generate-search-index.mjs +4 -3
- package/scripts/load-shiso-config.mjs +167 -0
- package/scripts/prerender.mjs +4 -2
- package/scripts/validate-config.mjs +23 -10
- package/scripts/vite-docs-config.mjs +52 -13
- package/src/App.tsx +12 -3
- package/src/components/Header.tsx +61 -24
- package/src/components/TopNav.tsx +9 -7
- package/src/components/docs/Button.tsx +67 -0
- package/src/components/docs/index.ts +1 -0
- package/src/declarations.d.ts +7 -0
- package/src/entry-server.tsx +20 -3
- package/src/lib/content.ts +10 -2
- package/src/lib/head.ts +15 -7
- package/src/lib/locale.ts +1 -1
- package/src/lib/paths.ts +11 -7
- package/src/lib/site-config.ts +21 -3
- package/src/lib/site-model.ts +7 -2
- package/src/lib/standalone-pages.ts +129 -0
- package/src/lib/types.ts +33 -3
- package/src/pages/StandalonePage.tsx +42 -0
- package/types/config.d.ts +19 -0
- package/vite.config.ts +58 -18
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,23 @@
|
|
|
3
3
|
All notable changes to `@umami/shiso` are documented here. This project follows
|
|
4
4
|
[Semantic Versioning](https://semver.org/).
|
|
5
5
|
|
|
6
|
+
## 2.0.0 - 2026-08-21
|
|
7
|
+
|
|
8
|
+
### Breaking
|
|
9
|
+
|
|
10
|
+
- Move project settings (`docsPrefix`, `contentDir`, `siteUrl`, `locale`) from
|
|
11
|
+
the `$shiso` key in docs.json to a new optional `shiso.config.ts` file at the
|
|
12
|
+
project root. `shiso check` now rejects docs.json files that still contain
|
|
13
|
+
`$shiso` with a migration message.
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- New `@umami/shiso/config` export providing `defineConfig` and the
|
|
18
|
+
`ShisoConfig` type for shiso.config.ts.
|
|
19
|
+
- `shiso.config.ts`, `shiso.config.mjs`, and `shiso.config.js` are supported;
|
|
20
|
+
the file is optional and defaults apply when absent. Config edits (and
|
|
21
|
+
creating the file) hot-reload during development.
|
|
22
|
+
|
|
6
23
|
## 1.1.11 - 2026-08-19
|
|
7
24
|
|
|
8
25
|
### Changed
|
package/bin/shiso.mjs
CHANGED
|
@@ -5,6 +5,7 @@ import fs from 'node:fs/promises';
|
|
|
5
5
|
import path from 'node:path';
|
|
6
6
|
import process from 'node:process';
|
|
7
7
|
import { fileURLToPath } from 'node:url';
|
|
8
|
+
import { loadShisoConfig } from '../scripts/load-shiso-config.mjs';
|
|
8
9
|
import { validateProject } from '../scripts/validate-config.mjs';
|
|
9
10
|
|
|
10
11
|
const PACKAGE_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
@@ -22,7 +23,7 @@ Commands:
|
|
|
22
23
|
dev Start the development server
|
|
23
24
|
build Validate and build the static site
|
|
24
25
|
preview Preview the production build
|
|
25
|
-
check Validate docs.json
|
|
26
|
+
check Validate docs.json and shiso.config
|
|
26
27
|
|
|
27
28
|
Options after dev, build, or preview are passed to Vite.
|
|
28
29
|
`;
|
|
@@ -55,6 +56,13 @@ async function check(projectRoot) {
|
|
|
55
56
|
}
|
|
56
57
|
|
|
57
58
|
console.log('docs.json is valid.');
|
|
59
|
+
|
|
60
|
+
// Fails fast on a broken shiso.config.* before any Vite build starts.
|
|
61
|
+
const shiso = await loadShisoConfig({ root: projectRoot });
|
|
62
|
+
|
|
63
|
+
if (shiso.sourcePath) {
|
|
64
|
+
console.log(`${path.basename(shiso.sourcePath)} loaded.`);
|
|
65
|
+
}
|
|
58
66
|
}
|
|
59
67
|
|
|
60
68
|
async function main() {
|
package/config.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Identity helper that gives shiso.config.ts typing today and room for future
|
|
3
|
+
* config forms (functions, plugins) without another migration. Ships as plain
|
|
4
|
+
* JS so it resolves under Node and jiti with no build step or dependencies.
|
|
5
|
+
*/
|
|
6
|
+
export function defineConfig(config) {
|
|
7
|
+
return config;
|
|
8
|
+
}
|
package/dist/chunks/App.js
CHANGED
|
@@ -11,6 +11,7 @@ import { MDXProvider } from "@mdx-js/react";
|
|
|
11
11
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
12
12
|
import * as ReactDOM from "react-dom";
|
|
13
13
|
import { ICON_REGISTRY } from "@/lib/icon-registry.generated";
|
|
14
|
+
import shiso from "virtual:shiso-config";
|
|
14
15
|
import rawConfig from "virtual:shiso-docs-config";
|
|
15
16
|
import { LAST_MODIFIED } from "@/generated/last-modified";
|
|
16
17
|
|
|
@@ -4561,7 +4562,7 @@ function renderTag(Tag, props) {
|
|
|
4561
4562
|
*
|
|
4562
4563
|
* Documentation: [Base UI Button](https://base-ui.com/react/components/button)
|
|
4563
4564
|
*/
|
|
4564
|
-
const Button$
|
|
4565
|
+
const Button$2 = /*#__PURE__*/ React$1.forwardRef(function Button(componentProps, forwardedRef) {
|
|
4565
4566
|
const { render, className, disabled = false, focusableWhenDisabled = false, nativeButton = true, style, ...elementProps } = componentProps;
|
|
4566
4567
|
const { getButtonProps, buttonRef } = useButton({
|
|
4567
4568
|
disabled,
|
|
@@ -4574,7 +4575,7 @@ const Button$1 = /*#__PURE__*/ React$1.forwardRef(function Button(componentProps
|
|
|
4574
4575
|
props: [elementProps, getButtonProps]
|
|
4575
4576
|
});
|
|
4576
4577
|
});
|
|
4577
|
-
Button$
|
|
4578
|
+
Button$2.displayName = "Button";
|
|
4578
4579
|
|
|
4579
4580
|
//#endregion
|
|
4580
4581
|
//#region ../../node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.mjs
|
|
@@ -8063,8 +8064,8 @@ const buttonVariants = cva("group/button inline-flex shrink-0 items-center justi
|
|
|
8063
8064
|
size: "default"
|
|
8064
8065
|
}
|
|
8065
8066
|
});
|
|
8066
|
-
function Button({ className, variant = "default", size = "default", ...props }) {
|
|
8067
|
-
return /* @__PURE__ */ jsx(Button$
|
|
8067
|
+
function Button$1({ className, variant = "default", size = "default", ...props }) {
|
|
8068
|
+
return /* @__PURE__ */ jsx(Button$2, {
|
|
8068
8069
|
"data-slot": "button",
|
|
8069
8070
|
className: cn(buttonVariants({
|
|
8070
8071
|
variant,
|
|
@@ -9582,7 +9583,7 @@ function CodeBlock({ children, className }) {
|
|
|
9582
9583
|
className: `code-block p-3 pr-12 text-sm text-foreground leading-[1.6] font-mono ${className || ""}`,
|
|
9583
9584
|
children
|
|
9584
9585
|
})
|
|
9585
|
-
}), /* @__PURE__ */ jsx(Button, {
|
|
9586
|
+
}), /* @__PURE__ */ jsx(Button$1, {
|
|
9586
9587
|
type: "button",
|
|
9587
9588
|
variant: "ghost",
|
|
9588
9589
|
size: "icon-sm",
|
|
@@ -11332,6 +11333,40 @@ function Badge({ color, size = "md", shape = "rounded", icon, stroke = false, di
|
|
|
11332
11333
|
});
|
|
11333
11334
|
}
|
|
11334
11335
|
|
|
11336
|
+
//#endregion
|
|
11337
|
+
//#region src/components/docs/Button.tsx
|
|
11338
|
+
/**
|
|
11339
|
+
* MDX-facing button. Renders a link when `href` is set (internal routes go
|
|
11340
|
+
* through react-router), otherwise a plain button element.
|
|
11341
|
+
*/
|
|
11342
|
+
function Button({ href, variant = "default", size = "default", icon, className, children }) {
|
|
11343
|
+
const resolvedIcon = resolveIcon(icon, 16);
|
|
11344
|
+
const content = /* @__PURE__ */ jsxs(Fragment, { children: [resolvedIcon, children] });
|
|
11345
|
+
const baseClassName = cn(resolvedIcon ? "gap-2" : "", "[&_p]:m-0", className);
|
|
11346
|
+
if (!href) return /* @__PURE__ */ jsx(Button$1, {
|
|
11347
|
+
variant,
|
|
11348
|
+
size,
|
|
11349
|
+
className: baseClassName,
|
|
11350
|
+
children: content
|
|
11351
|
+
});
|
|
11352
|
+
const linkClassName = cn(buttonVariants({
|
|
11353
|
+
variant,
|
|
11354
|
+
size
|
|
11355
|
+
}), "no-underline hover:no-underline active:no-underline", baseClassName);
|
|
11356
|
+
if (/^https?:\/\//i.test(href)) return /* @__PURE__ */ jsx("a", {
|
|
11357
|
+
href,
|
|
11358
|
+
className: linkClassName,
|
|
11359
|
+
target: "_blank",
|
|
11360
|
+
rel: "noreferrer",
|
|
11361
|
+
children: content
|
|
11362
|
+
});
|
|
11363
|
+
return /* @__PURE__ */ jsx(Link, {
|
|
11364
|
+
to: href,
|
|
11365
|
+
className: linkClassName,
|
|
11366
|
+
children: content
|
|
11367
|
+
});
|
|
11368
|
+
}
|
|
11369
|
+
|
|
11335
11370
|
//#endregion
|
|
11336
11371
|
//#region src/components/ui/alert.tsx
|
|
11337
11372
|
const alertVariants = cva("group/alert relative grid w-full gap-0.5 rounded-lg border px-2.5 py-2 text-left text-sm has-data-[slot=alert-action]:relative has-data-[slot=alert-action]:pr-18 has-[>svg]:grid-cols-[auto_1fr] has-[>svg]:gap-x-2 *:[svg]:row-span-2 *:[svg]:translate-y-0.5 *:[svg]:text-current *:[svg:not([class*='size-'])]:size-4", {
|
|
@@ -20509,7 +20544,7 @@ function DialogContent$1({ className, children, showCloseButton = true, overlayC
|
|
|
20509
20544
|
...props,
|
|
20510
20545
|
children: [children, showCloseButton && /* @__PURE__ */ jsxs(DialogClose, {
|
|
20511
20546
|
"data-slot": "dialog-close",
|
|
20512
|
-
render: /* @__PURE__ */ jsx(Button, {
|
|
20547
|
+
render: /* @__PURE__ */ jsx(Button$1, {
|
|
20513
20548
|
variant: "ghost",
|
|
20514
20549
|
className: "absolute top-2 right-2",
|
|
20515
20550
|
size: "icon-sm"
|
|
@@ -20571,6 +20606,7 @@ var docs_exports = /* @__PURE__ */ __exportAll({
|
|
|
20571
20606
|
Accordion: () => Accordion,
|
|
20572
20607
|
AccordionGroup: () => AccordionGroup,
|
|
20573
20608
|
Badge: () => Badge,
|
|
20609
|
+
Button: () => Button,
|
|
20574
20610
|
Callout: () => Callout,
|
|
20575
20611
|
Card: () => Card,
|
|
20576
20612
|
CardGroup: () => CardGroup,
|
|
@@ -20628,7 +20664,7 @@ function Banner({ banner, dismissLabel }) {
|
|
|
20628
20664
|
children: [/* @__PURE__ */ jsx("div", {
|
|
20629
20665
|
className: "[&_a:hover]:opacity-[0.85] [&_a]:text-inherit [&_a]:underline [&_a]:underline-offset-2 [&_code]:rounded-sm [&_code]:bg-black/20 [&_code]:px-1 [&_code]:py-[0.0625rem] [&_code]:text-[0.8125rem] [&_code]:font-mono",
|
|
20630
20666
|
children: renderInlineMarkdown(banner.content)
|
|
20631
|
-
}), banner.dismissible && /* @__PURE__ */ jsx(Button, {
|
|
20667
|
+
}), banner.dismissible && /* @__PURE__ */ jsx(Button$1, {
|
|
20632
20668
|
type: "button",
|
|
20633
20669
|
variant: "ghost",
|
|
20634
20670
|
size: "icon-xs",
|
|
@@ -22216,8 +22252,10 @@ function DropdownMenuItem({ className, inset, variant = "default", ...props }) {
|
|
|
22216
22252
|
* DOCS_PREFIX but not BASE_URL. React Router's `basename` adds BASE_URL, so
|
|
22217
22253
|
* only code that bypasses the router (prerender output paths, canonical URLs,
|
|
22218
22254
|
* raw <a href>) needs `toHref`.
|
|
22255
|
+
*
|
|
22256
|
+
* Values from `virtual:shiso-config` arrive with defaults applied and already
|
|
22257
|
+
* normalized by scripts/load-shiso-config.mjs.
|
|
22219
22258
|
*/
|
|
22220
|
-
const shiso = rawConfig.$shiso || {};
|
|
22221
22259
|
/** Strips trailing slashes; "/" and "" both normalize to "". */
|
|
22222
22260
|
function normalizePrefix(value) {
|
|
22223
22261
|
const trimmed = value.trim().replace(/\/+$/, "");
|
|
@@ -22225,11 +22263,14 @@ function normalizePrefix(value) {
|
|
|
22225
22263
|
return trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
|
|
22226
22264
|
}
|
|
22227
22265
|
const BASE_URL = normalizePrefix(import.meta.env?.BASE_URL || "/");
|
|
22228
|
-
const DOCS_PREFIX =
|
|
22266
|
+
const DOCS_PREFIX = shiso.docsPrefix;
|
|
22229
22267
|
/** Content directory, relative to the project root, without leading/trailing slashes. */
|
|
22230
|
-
const CONTENT_DIR =
|
|
22268
|
+
const CONTENT_DIR = shiso.contentDir;
|
|
22269
|
+
/** Fixed root for standalone (non-docs) page files. Not configurable, so page
|
|
22270
|
+
* slugs can never collide with the docs content tree. */
|
|
22271
|
+
const PAGES_DIR = "content/pages";
|
|
22231
22272
|
/** Absolute origin used for canonical and og:url tags. Undefined when unconfigured. */
|
|
22232
|
-
const SITE_URL = shiso.siteUrl
|
|
22273
|
+
const SITE_URL = shiso.siteUrl;
|
|
22233
22274
|
/** Joins path segments with exactly one slash between them. */
|
|
22234
22275
|
function joinPath(...parts) {
|
|
22235
22276
|
const joined = parts.filter((part) => !!part).join("/").replace(/\/{2,}/g, "/");
|
|
@@ -22813,7 +22854,7 @@ function isNodeHidden(node) {
|
|
|
22813
22854
|
* without Suspense, at the cost of bundling all pages together.
|
|
22814
22855
|
*
|
|
22815
22856
|
* The glob pattern must be a literal for Vite to statically analyze it, so it
|
|
22816
|
-
* covers all of `content/` and the configured
|
|
22857
|
+
* covers all of `content/` and the configured shiso.config `contentDir` is applied at
|
|
22817
22858
|
* lookup time instead. That also lets later versioned/localized content roots
|
|
22818
22859
|
* (`content/v2`, `content/es`) work without touching this glob.
|
|
22819
22860
|
*/
|
|
@@ -22826,6 +22867,13 @@ const docModules = import.meta.glob("/content/**/*.{md,mdx}", { eager: true });
|
|
|
22826
22867
|
function resolveDocFile(fileSlug, contentDir = CONTENT_DIR) {
|
|
22827
22868
|
return [`/${contentDir}/${fileSlug}.mdx`, `/${contentDir}/${fileSlug}.md`].find((candidate) => candidate in docModules);
|
|
22828
22869
|
}
|
|
22870
|
+
/**
|
|
22871
|
+
* Resolves a standalone page slug (docs.json `pages[].page`) to a module key
|
|
22872
|
+
* under the fixed content/pages root.
|
|
22873
|
+
*/
|
|
22874
|
+
function resolvePageFile(fileSlug) {
|
|
22875
|
+
return resolveDocFile(fileSlug, PAGES_DIR);
|
|
22876
|
+
}
|
|
22829
22877
|
function getDocModule(filePath) {
|
|
22830
22878
|
return docModules[filePath];
|
|
22831
22879
|
}
|
|
@@ -22866,7 +22914,7 @@ function isValidLocale(value) {
|
|
|
22866
22914
|
}
|
|
22867
22915
|
/**
|
|
22868
22916
|
* Locale for a page: its scope's language code when valid, then the
|
|
22869
|
-
* site-wide
|
|
22917
|
+
* site-wide shiso.config `locale`, then en-US.
|
|
22870
22918
|
*/
|
|
22871
22919
|
function resolveLocale(language, fallback) {
|
|
22872
22920
|
if (isValidLocale(language)) return Intl.getCanonicalLocales(language)[0];
|
|
@@ -22975,7 +23023,7 @@ function normalizeFooter(config) {
|
|
|
22975
23023
|
attribution
|
|
22976
23024
|
} : null;
|
|
22977
23025
|
}
|
|
22978
|
-
function resolveSiteModel(config, docs) {
|
|
23026
|
+
function resolveSiteModel(config, docs, shiso) {
|
|
22979
23027
|
const appearance = config.appearance || {};
|
|
22980
23028
|
const logo = config.logo ? typeof config.logo === "string" ? {
|
|
22981
23029
|
light: config.logo,
|
|
@@ -23008,7 +23056,7 @@ function resolveSiteModel(config, docs) {
|
|
|
23008
23056
|
},
|
|
23009
23057
|
showTimestamp: config.metadata?.timestamp === true,
|
|
23010
23058
|
drilldown: config.interaction?.drilldown,
|
|
23011
|
-
locale:
|
|
23059
|
+
locale: shiso?.locale || "en-US",
|
|
23012
23060
|
labels: SHISO_THEME_LABELS,
|
|
23013
23061
|
docs
|
|
23014
23062
|
};
|
|
@@ -23085,6 +23133,58 @@ function resolveContextualOptions(options, page, labels = SHISO_THEME_LABELS) {
|
|
|
23085
23133
|
return resolved;
|
|
23086
23134
|
}
|
|
23087
23135
|
|
|
23136
|
+
//#endregion
|
|
23137
|
+
//#region src/lib/standalone-pages.ts
|
|
23138
|
+
function invalid(message) {
|
|
23139
|
+
return /* @__PURE__ */ new Error(`Invalid docs config: ${message}`);
|
|
23140
|
+
}
|
|
23141
|
+
/** Trims and canonicalizes a standalone route path; throws when malformed. */
|
|
23142
|
+
function normalizePath(rawPath) {
|
|
23143
|
+
const value = typeof rawPath === "string" ? rawPath.trim() : "";
|
|
23144
|
+
if (!value.startsWith("/")) throw invalid(`standalone page path "${String(rawPath)}" must start with "/".`);
|
|
23145
|
+
if (/[:*]/.test(value)) throw invalid(`standalone page path "${value}" must not use wildcard patterns.`);
|
|
23146
|
+
if (/\.mdx?$/i.test(value)) throw invalid(`standalone page path "${value}" must be a route, not a file — drop the extension.`);
|
|
23147
|
+
return value.replace(/\/{2,}/g, "/").replace(/\/+$/, "") || "/";
|
|
23148
|
+
}
|
|
23149
|
+
/** Mirrors normalizePageReference in docs-config.ts for the `page` slug. */
|
|
23150
|
+
function normalizePageSlug(rawSlug) {
|
|
23151
|
+
return (typeof rawSlug === "string" ? rawSlug : "").trim().replace(/\\/g, "/").replace(/^\/+/, "").replace(/^pages\//, "").replace(/\.mdx?$/, "").replace(/\/+$/, "") || "index";
|
|
23152
|
+
}
|
|
23153
|
+
function normalizeStandalonePages(config, resolvePageFile, site, options = {}) {
|
|
23154
|
+
const items = config.pages || [];
|
|
23155
|
+
if (!items.length) return [];
|
|
23156
|
+
const docsPrefix = options.docsPrefix || "";
|
|
23157
|
+
const pages = [];
|
|
23158
|
+
const seen = /* @__PURE__ */ new Set();
|
|
23159
|
+
for (const item of items) {
|
|
23160
|
+
const path = normalizePath(item?.path);
|
|
23161
|
+
if (seen.has(path)) throw invalid(`duplicate standalone page path "${path}".`);
|
|
23162
|
+
seen.add(path);
|
|
23163
|
+
if (path === "/404") throw invalid("standalone page path \"/404\" is reserved for the error page.");
|
|
23164
|
+
const docsPage = site.pageByUrl[path];
|
|
23165
|
+
if (docsPage) throw invalid(`standalone page path "${path}" collides with the docs page "${docsPage.fileSlug}". Standalone pages must live outside the docs navigation.`);
|
|
23166
|
+
if (docsPrefix && (path === docsPrefix || path.startsWith(`${docsPrefix}/`))) throw invalid(`standalone page path "${path}" is inside the docs prefix "${docsPrefix}". Standalone pages must live outside the docs tree.`);
|
|
23167
|
+
const fileSlug = normalizePageSlug(item?.page);
|
|
23168
|
+
const filePath = resolvePageFile(fileSlug);
|
|
23169
|
+
if (!filePath) throw new Error(`Missing standalone page file for "${fileSlug}": expected "content/pages/${fileSlug}.mdx" or ".md".`);
|
|
23170
|
+
pages.push({
|
|
23171
|
+
path,
|
|
23172
|
+
filePath,
|
|
23173
|
+
title: item?.title?.trim() || void 0
|
|
23174
|
+
});
|
|
23175
|
+
}
|
|
23176
|
+
return pages;
|
|
23177
|
+
}
|
|
23178
|
+
/**
|
|
23179
|
+
* Exact standalone page lookup by base-relative pathname. Tolerates trailing
|
|
23180
|
+
* slashes and an explicit `/index` suffix, like getPageByPathname.
|
|
23181
|
+
*/
|
|
23182
|
+
function getStandalonePageByPathname(pages, pathname) {
|
|
23183
|
+
const trimmed = pathname.replace(/\/+$/, "") || "/";
|
|
23184
|
+
const collapsed = trimmed === "/index" ? "/" : trimmed.replace(/\/index$/, "") || "/";
|
|
23185
|
+
return pages.find((page) => page.path === trimmed || page.path === collapsed) || null;
|
|
23186
|
+
}
|
|
23187
|
+
|
|
23088
23188
|
//#endregion
|
|
23089
23189
|
//#region src/lib/site-config.ts
|
|
23090
23190
|
assertDocsConfig(rawConfig, "docs.json");
|
|
@@ -23095,7 +23195,14 @@ const docsSite = normalizeDocsSite(siteConfig, resolveDocFile);
|
|
|
23095
23195
|
const docsConfig = getDefaultScope(docsSite).docs;
|
|
23096
23196
|
/** Landing page of the default scope: the site-wide "docs home" URL. */
|
|
23097
23197
|
const docsHomeUrl = getDefaultScope(docsSite).firstPageUrl;
|
|
23098
|
-
const siteModel = resolveSiteModel(siteConfig, docsConfig);
|
|
23198
|
+
const siteModel = resolveSiteModel(siteConfig, docsConfig, shiso);
|
|
23199
|
+
/** Standalone pages declared with the top-level `pages` key, e.g. a home page. */
|
|
23200
|
+
const standalonePages = normalizeStandalonePages(siteConfig, resolvePageFile, docsSite, { docsPrefix: DOCS_PREFIX });
|
|
23201
|
+
/** True when a standalone page owns "/", replacing the root docs redirect. */
|
|
23202
|
+
const hasRootStandalonePage = standalonePages.some((page) => page.path === "/");
|
|
23203
|
+
function getStandalonePage(pathname) {
|
|
23204
|
+
return getStandalonePageByPathname(standalonePages, stripBase(pathname));
|
|
23205
|
+
}
|
|
23099
23206
|
/** Scope that owns the current pathname; the default scope for unknown paths. */
|
|
23100
23207
|
function getScopeByPathname(pathname) {
|
|
23101
23208
|
const page = getPageByPathname(pathname);
|
|
@@ -23168,7 +23275,7 @@ function LanguageSwitcher() {
|
|
|
23168
23275
|
const options = getLanguageScopes(docsSite);
|
|
23169
23276
|
if (!current.language || options.length < 2 && !current.hidden) return null;
|
|
23170
23277
|
return /* @__PURE__ */ jsxs(DropdownMenu, { children: [/* @__PURE__ */ jsxs(DropdownMenuTrigger, {
|
|
23171
|
-
render: /* @__PURE__ */ jsx(Button, {
|
|
23278
|
+
render: /* @__PURE__ */ jsx(Button$1, {
|
|
23172
23279
|
variant: "outline",
|
|
23173
23280
|
className: "h-auto gap-1.5 rounded-md bg-card px-2.5 py-1.5 text-sm font-medium text-foreground"
|
|
23174
23281
|
}),
|
|
@@ -26081,7 +26188,7 @@ function Search({ config, labels }) {
|
|
|
26081
26188
|
open,
|
|
26082
26189
|
onOpenChange: (nextOpen) => nextOpen ? openDialog() : closeDialog(),
|
|
26083
26190
|
children: [/* @__PURE__ */ jsxs(DialogTrigger, {
|
|
26084
|
-
render: /* @__PURE__ */ jsx(Button, {
|
|
26191
|
+
render: /* @__PURE__ */ jsx(Button$1, {
|
|
26085
26192
|
variant: "outline",
|
|
26086
26193
|
className: "h-auto gap-2 rounded-md bg-card px-2.5 py-1.5 text-muted-foreground hover:border-input hover:bg-card hover:text-foreground"
|
|
26087
26194
|
}),
|
|
@@ -26152,7 +26259,7 @@ function ThemeToggle({ label }) {
|
|
|
26152
26259
|
localStorage.setItem("shiso-theme", next);
|
|
26153
26260
|
} catch {}
|
|
26154
26261
|
};
|
|
26155
|
-
return /* @__PURE__ */ jsxs(Button, {
|
|
26262
|
+
return /* @__PURE__ */ jsxs(Button$1, {
|
|
26156
26263
|
type: "button",
|
|
26157
26264
|
variant: "ghost",
|
|
26158
26265
|
size: "icon",
|
|
@@ -26197,7 +26304,10 @@ function TopNav({ docs, label }) {
|
|
|
26197
26304
|
const navigate = useNavigate();
|
|
26198
26305
|
const tabs = docs.tabs.filter((tab) => !tab.hidden);
|
|
26199
26306
|
if (!tabs.length) return null;
|
|
26200
|
-
const
|
|
26307
|
+
const page = docs.pages.find((item) => item.url === pathname);
|
|
26308
|
+
const matchedTabId = [...tabs].sort((a, b) => b.url.length - a.url.length).find((tab) => pathname === tab.url || pathname.startsWith(`${tab.url}/`))?.id;
|
|
26309
|
+
const fallbackTabId = getStandalonePage(pathname) ? void 0 : tabs[0]?.id;
|
|
26310
|
+
const selected = page?.tabId || matchedTabId || fallbackTabId;
|
|
26201
26311
|
const tabClass = (tab) => cn("flex h-full items-center gap-1 whitespace-nowrap border-transparent border-b-2 font-medium", {
|
|
26202
26312
|
"border-b-primary text-foreground": tab.id === selected,
|
|
26203
26313
|
"text-muted-foreground hover:text-foreground": tab.id !== selected
|
|
@@ -26255,7 +26365,7 @@ function VersionSwitcher() {
|
|
|
26255
26365
|
const options = docsSite.scopes.filter((scope) => scope.version && !scope.hidden && scope.language === current.language);
|
|
26256
26366
|
if (!current.version || options.length < 2 && !current.hidden) return null;
|
|
26257
26367
|
return /* @__PURE__ */ jsxs(DropdownMenu, { children: [/* @__PURE__ */ jsxs(DropdownMenuTrigger, {
|
|
26258
|
-
render: /* @__PURE__ */ jsx(Button, {
|
|
26368
|
+
render: /* @__PURE__ */ jsx(Button$1, {
|
|
26259
26369
|
variant: "outline",
|
|
26260
26370
|
className: "h-auto gap-1.5 rounded-md bg-card px-2.5 py-1.5 text-sm font-medium text-foreground"
|
|
26261
26371
|
}),
|
|
@@ -26277,24 +26387,54 @@ function VersionSwitcher() {
|
|
|
26277
26387
|
|
|
26278
26388
|
//#endregion
|
|
26279
26389
|
//#region src/components/Header.tsx
|
|
26390
|
+
/**
|
|
26391
|
+
* Header hrefs come from config, so they may point inside the site or off it.
|
|
26392
|
+
* In-app routes go through react-router; anything external (or explicitly
|
|
26393
|
+
* opened in a new tab) stays a plain anchor and triggers a document load.
|
|
26394
|
+
*/
|
|
26395
|
+
function isRoutedHref(href, target) {
|
|
26396
|
+
return href.startsWith("/") && !isExternalHref(href) && target !== "_blank";
|
|
26397
|
+
}
|
|
26280
26398
|
function NavbarLinkItem({ link, primary = false }) {
|
|
26281
26399
|
const iconOnly = !link.label;
|
|
26282
26400
|
const accessibleLabel = link.ariaLabel || link.icon || link.href;
|
|
26283
|
-
|
|
26401
|
+
const className = primary ? `ml-1 inline-flex items-center justify-center rounded-full bg-primary text-sm font-semibold text-primary-foreground hover:opacity-90 ${iconOnly ? "size-8" : "gap-1.5 px-3.5 py-1.5"}` : `inline-flex items-center rounded-md text-sm font-medium text-foreground hover:bg-accent hover:text-foreground ${iconOnly ? "size-8 justify-center" : "gap-1.5 px-2.5 py-1.5"}`;
|
|
26402
|
+
const content = /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(ConfiguredIcon, { icon: link.icon }), link.label] });
|
|
26403
|
+
if (isRoutedHref(link.href, link.target)) return /* @__PURE__ */ jsx(Link, {
|
|
26404
|
+
to: link.href,
|
|
26405
|
+
className,
|
|
26406
|
+
"aria-label": iconOnly ? accessibleLabel : void 0,
|
|
26407
|
+
children: content
|
|
26408
|
+
});
|
|
26409
|
+
return /* @__PURE__ */ jsx("a", {
|
|
26284
26410
|
href: link.href,
|
|
26285
|
-
className
|
|
26411
|
+
className,
|
|
26286
26412
|
target: link.target,
|
|
26287
26413
|
rel: link.target === "_blank" ? "noreferrer" : void 0,
|
|
26288
26414
|
"aria-label": iconOnly ? accessibleLabel : void 0,
|
|
26289
|
-
children:
|
|
26415
|
+
children: content
|
|
26290
26416
|
});
|
|
26291
26417
|
}
|
|
26292
26418
|
function Header({ site }) {
|
|
26293
26419
|
const { logo, navbar, name, appearance, labels, search } = site;
|
|
26294
26420
|
const { pathname } = useLocation();
|
|
26295
26421
|
const docs = getScopeByPathname(pathname).docs;
|
|
26296
|
-
const brandHref = logo?.href || docsHomeUrl;
|
|
26422
|
+
const brandHref = logo?.href || (hasRootStandalonePage ? "/" : docsHomeUrl);
|
|
26297
26423
|
const hasBrand = !!name || !!logo?.light || !!logo?.dark;
|
|
26424
|
+
const brandClassName = "inline-flex items-center gap-2 text-xl font-bold text-foreground tracking-[-0.03em]";
|
|
26425
|
+
const brandContent = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
26426
|
+
logo?.light ? /* @__PURE__ */ jsx("img", {
|
|
26427
|
+
src: logo.light,
|
|
26428
|
+
alt: "",
|
|
26429
|
+
className: "h-6 w-auto dark:hidden"
|
|
26430
|
+
}) : null,
|
|
26431
|
+
logo?.dark ? /* @__PURE__ */ jsx("img", {
|
|
26432
|
+
src: logo.dark,
|
|
26433
|
+
alt: "",
|
|
26434
|
+
className: "hidden h-6 w-auto dark:block"
|
|
26435
|
+
}) : null,
|
|
26436
|
+
name ? /* @__PURE__ */ jsx("span", { children: name }) : null
|
|
26437
|
+
] });
|
|
26298
26438
|
return /* @__PURE__ */ jsx("header", {
|
|
26299
26439
|
className: "sticky top-0 z-50 h-[var(--header-height)] shrink-0 border-border border-b bg-[color-mix(in_srgb,var(--background)_92%,transparent)] backdrop-blur-md",
|
|
26300
26440
|
children: /* @__PURE__ */ jsxs("div", {
|
|
@@ -26302,24 +26442,16 @@ function Header({ site }) {
|
|
|
26302
26442
|
children: [
|
|
26303
26443
|
/* @__PURE__ */ jsxs("div", {
|
|
26304
26444
|
className: "flex min-w-0 items-center gap-5 justify-self-start",
|
|
26305
|
-
children: [hasBrand ? /* @__PURE__ */
|
|
26445
|
+
children: [hasBrand ? isRoutedHref(brandHref, logo?.target) ? /* @__PURE__ */ jsx(Link, {
|
|
26446
|
+
to: brandHref,
|
|
26447
|
+
className: brandClassName,
|
|
26448
|
+
children: brandContent
|
|
26449
|
+
}) : /* @__PURE__ */ jsx("a", {
|
|
26306
26450
|
href: brandHref,
|
|
26307
26451
|
target: logo?.target,
|
|
26308
26452
|
rel: logo?.target === "_blank" ? "noreferrer" : void 0,
|
|
26309
|
-
className:
|
|
26310
|
-
children:
|
|
26311
|
-
logo?.light ? /* @__PURE__ */ jsx("img", {
|
|
26312
|
-
src: logo.light,
|
|
26313
|
-
alt: "",
|
|
26314
|
-
className: "h-6 w-auto dark:hidden"
|
|
26315
|
-
}) : null,
|
|
26316
|
-
logo?.dark ? /* @__PURE__ */ jsx("img", {
|
|
26317
|
-
src: logo.dark,
|
|
26318
|
-
alt: "",
|
|
26319
|
-
className: "hidden h-6 w-auto dark:block"
|
|
26320
|
-
}) : null,
|
|
26321
|
-
name ? /* @__PURE__ */ jsx("span", { children: name }) : null
|
|
26322
|
-
]
|
|
26453
|
+
className: brandClassName,
|
|
26454
|
+
children: brandContent
|
|
26323
26455
|
}) : null, /* @__PURE__ */ jsxs("div", {
|
|
26324
26456
|
className: "hidden items-center gap-2 lg:flex",
|
|
26325
26457
|
children: [/* @__PURE__ */ jsx(VersionSwitcher, {}), /* @__PURE__ */ jsx(LanguageSwitcher, {})]
|
|
@@ -26365,14 +26497,16 @@ function escapeJsonLd(value) {
|
|
|
26365
26497
|
}
|
|
26366
26498
|
function buildHead(pathname) {
|
|
26367
26499
|
const page = getPageByPathname(pathname);
|
|
26368
|
-
const
|
|
26500
|
+
const standalone = page ? null : getStandalonePage(pathname);
|
|
26501
|
+
const filePath = page?.filePath || standalone?.filePath;
|
|
26502
|
+
const frontmatter = (filePath ? getDocModule(filePath) : void 0)?.frontmatter;
|
|
26369
26503
|
const seo = getSeo();
|
|
26370
|
-
const pageTitle = frontmatter?.title || page?.label;
|
|
26504
|
+
const pageTitle = frontmatter?.title || standalone?.title || page?.label;
|
|
26371
26505
|
const title = getPageTitle(pageTitle);
|
|
26372
26506
|
const description = frontmatter?.description || siteConfig.description;
|
|
26373
|
-
const canonical = page ? toAbsoluteUrl(page.url) : void 0;
|
|
26507
|
+
const canonical = page ? toAbsoluteUrl(page.url) : standalone ? toAbsoluteUrl(standalone.path) : void 0;
|
|
26374
26508
|
const hidden = !!page && (!!page.hidden || !!getScopeByPathname(pathname).hidden);
|
|
26375
|
-
const noindex = !page || frontmatter?.noindex === true || hidden && seo.indexing !== "all";
|
|
26509
|
+
const noindex = !page && !standalone || frontmatter?.noindex === true || hidden && seo.indexing !== "all";
|
|
26376
26510
|
const tags = [{
|
|
26377
26511
|
tag: "title",
|
|
26378
26512
|
children: title
|
|
@@ -26402,7 +26536,7 @@ function buildHead(pathname) {
|
|
|
26402
26536
|
tag: "meta",
|
|
26403
26537
|
attrs: {
|
|
26404
26538
|
property: "og:type",
|
|
26405
|
-
content: "article"
|
|
26539
|
+
content: standalone ? "website" : "article"
|
|
26406
26540
|
}
|
|
26407
26541
|
}, {
|
|
26408
26542
|
tag: "meta",
|
|
@@ -26452,7 +26586,7 @@ function buildHead(pathname) {
|
|
|
26452
26586
|
content: description
|
|
26453
26587
|
}
|
|
26454
26588
|
});
|
|
26455
|
-
const lastModified =
|
|
26589
|
+
const lastModified = filePath && showTimestamp(frontmatter?.timestamp) ? getLastModified(filePath) : void 0;
|
|
26456
26590
|
if (lastModified) tags.push({
|
|
26457
26591
|
tag: "meta",
|
|
26458
26592
|
attrs: {
|
|
@@ -26600,14 +26734,14 @@ function ContextualMenu({ options, labels }) {
|
|
|
26600
26734
|
const optionIcon = (option, showCopied = false) => showCopied && copied ? /* @__PURE__ */ jsx(Check$1, { className: "size-3.5" }) : /* @__PURE__ */ jsx(ConfiguredIcon, { icon: option.icon });
|
|
26601
26735
|
return /* @__PURE__ */ jsxs("div", {
|
|
26602
26736
|
className: "inline-flex shrink-0 items-stretch",
|
|
26603
|
-
children: [/* @__PURE__ */ jsxs(Button, {
|
|
26737
|
+
children: [/* @__PURE__ */ jsxs(Button$1, {
|
|
26604
26738
|
variant: "outline",
|
|
26605
26739
|
size: "sm",
|
|
26606
26740
|
className: "rounded-r-none bg-card text-foreground only:rounded-md",
|
|
26607
26741
|
onClick: () => runOption(primary),
|
|
26608
26742
|
children: [optionIcon(primary, primary.action === "copy"), primary.action === "copy" && copied ? labels.copied : primary.title]
|
|
26609
26743
|
}), options.length > 1 && /* @__PURE__ */ jsxs(DropdownMenu, { children: [/* @__PURE__ */ jsx(DropdownMenuTrigger, {
|
|
26610
|
-
render: /* @__PURE__ */ jsx(Button, {
|
|
26744
|
+
render: /* @__PURE__ */ jsx(Button$1, {
|
|
26611
26745
|
variant: "outline",
|
|
26612
26746
|
size: "icon-sm",
|
|
26613
26747
|
className: "rounded-l-none border-l-0 bg-card",
|
|
@@ -26948,7 +27082,7 @@ function CollapsibleGroup({ node, pathname, depth, drilldown, expandLabel, colla
|
|
|
26948
27082
|
className: isTopLevel ? sectionLabelClass : groupLabelClass,
|
|
26949
27083
|
children: [resolveIcon(node.icon), node.label]
|
|
26950
27084
|
}), /* @__PURE__ */ jsx(CollapsibleTrigger, {
|
|
26951
|
-
render: /* @__PURE__ */ jsx(Button, {
|
|
27085
|
+
render: /* @__PURE__ */ jsx(Button$1, {
|
|
26952
27086
|
type: "button",
|
|
26953
27087
|
variant: "ghost",
|
|
26954
27088
|
size: "icon-xs",
|
|
@@ -26958,7 +27092,7 @@ function CollapsibleGroup({ node, pathname, depth, drilldown, expandLabel, colla
|
|
|
26958
27092
|
children: chevron
|
|
26959
27093
|
})]
|
|
26960
27094
|
}) : /* @__PURE__ */ jsxs(CollapsibleTrigger, {
|
|
26961
|
-
render: /* @__PURE__ */ jsx(Button, {
|
|
27095
|
+
render: /* @__PURE__ */ jsx(Button$1, {
|
|
26962
27096
|
type: "button",
|
|
26963
27097
|
variant: "ghost",
|
|
26964
27098
|
className: cn(headerClass, "group/section group/collapsible-trigger flex h-auto w-full items-center justify-start gap-[0.4rem] whitespace-normal rounded-none px-0 py-0 text-left hover:bg-transparent aria-expanded:bg-transparent dark:hover:bg-transparent", {
|
|
@@ -27119,7 +27253,7 @@ function SheetContent({ className, children, side = "right", showCloseButton = t
|
|
|
27119
27253
|
...props,
|
|
27120
27254
|
children: [children, showCloseButton && /* @__PURE__ */ jsxs(DialogClose, {
|
|
27121
27255
|
"data-slot": "sheet-close",
|
|
27122
|
-
render: /* @__PURE__ */ jsx(Button, {
|
|
27256
|
+
render: /* @__PURE__ */ jsx(Button$1, {
|
|
27123
27257
|
variant: "ghost",
|
|
27124
27258
|
className: "absolute top-3 right-3",
|
|
27125
27259
|
size: "icon-sm"
|
|
@@ -27185,7 +27319,7 @@ function Docs({ page, doc, site }) {
|
|
|
27185
27319
|
children: [/* @__PURE__ */ jsx("div", {
|
|
27186
27320
|
className: "flex justify-end lg:hidden",
|
|
27187
27321
|
children: /* @__PURE__ */ jsxs(SheetTrigger, {
|
|
27188
|
-
render: /* @__PURE__ */ jsx(Button, {
|
|
27322
|
+
render: /* @__PURE__ */ jsx(Button$1, {
|
|
27189
27323
|
variant: "outline",
|
|
27190
27324
|
className: "bg-card"
|
|
27191
27325
|
}),
|
|
@@ -27277,6 +27411,40 @@ function DocPage({ site }) {
|
|
|
27277
27411
|
});
|
|
27278
27412
|
}
|
|
27279
27413
|
|
|
27414
|
+
//#endregion
|
|
27415
|
+
//#region src/pages/StandalonePage.tsx
|
|
27416
|
+
/**
|
|
27417
|
+
* A standalone (non-docs) page: site chrome from Layout (banner, header),
|
|
27418
|
+
* the MDX content at full container width — no sidebar, TOC, or pager — and
|
|
27419
|
+
* the footer. MDX components come from the app-level MDXProvider.
|
|
27420
|
+
*/
|
|
27421
|
+
function StandalonePageView({ page, site }) {
|
|
27422
|
+
const { pathname } = useLocation();
|
|
27423
|
+
const doc = getDocModule(page.filePath);
|
|
27424
|
+
useEffect(() => {
|
|
27425
|
+
if (!window.location.hash) window.scrollTo({
|
|
27426
|
+
top: 0,
|
|
27427
|
+
left: 0
|
|
27428
|
+
});
|
|
27429
|
+
}, [pathname]);
|
|
27430
|
+
if (!doc) return /* @__PURE__ */ jsx(Docs, {
|
|
27431
|
+
page: null,
|
|
27432
|
+
doc: null,
|
|
27433
|
+
site
|
|
27434
|
+
});
|
|
27435
|
+
const Content = doc.default;
|
|
27436
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
27437
|
+
className: "flex min-h-full flex-col",
|
|
27438
|
+
children: [/* @__PURE__ */ jsx("article", {
|
|
27439
|
+
className: "grow py-8",
|
|
27440
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
27441
|
+
className: "docs-markdown",
|
|
27442
|
+
children: /* @__PURE__ */ jsx(Content, {})
|
|
27443
|
+
})
|
|
27444
|
+
}), /* @__PURE__ */ jsx(Footer, { footer: site.footer })]
|
|
27445
|
+
});
|
|
27446
|
+
}
|
|
27447
|
+
|
|
27280
27448
|
//#endregion
|
|
27281
27449
|
//#region src/App.tsx
|
|
27282
27450
|
const mdxComponents = {
|
|
@@ -27289,19 +27457,29 @@ function App() {
|
|
|
27289
27457
|
components: mdxComponents,
|
|
27290
27458
|
children: /* @__PURE__ */ jsx(Layout, {
|
|
27291
27459
|
site: siteModel,
|
|
27292
|
-
children: /* @__PURE__ */ jsxs(Routes, { children: [
|
|
27293
|
-
|
|
27294
|
-
|
|
27295
|
-
|
|
27296
|
-
|
|
27460
|
+
children: /* @__PURE__ */ jsxs(Routes, { children: [
|
|
27461
|
+
standalonePages.map((page) => /* @__PURE__ */ jsx(Route, {
|
|
27462
|
+
path: page.path,
|
|
27463
|
+
element: /* @__PURE__ */ jsx(StandalonePageView, {
|
|
27464
|
+
page,
|
|
27465
|
+
site: siteModel
|
|
27466
|
+
})
|
|
27467
|
+
}, page.path)),
|
|
27468
|
+
docsHomeUrl !== "/" && !hasRootStandalonePage ? /* @__PURE__ */ jsx(Route, {
|
|
27469
|
+
path: "/",
|
|
27470
|
+
element: /* @__PURE__ */ jsx(Navigate, {
|
|
27471
|
+
to: docsHomeUrl,
|
|
27472
|
+
replace: true
|
|
27473
|
+
})
|
|
27474
|
+
}) : null,
|
|
27475
|
+
/* @__PURE__ */ jsx(Route, {
|
|
27476
|
+
path: "*",
|
|
27477
|
+
element: /* @__PURE__ */ jsx(DocPage, { site: siteModel })
|
|
27297
27478
|
})
|
|
27298
|
-
})
|
|
27299
|
-
path: "*",
|
|
27300
|
-
element: /* @__PURE__ */ jsx(DocPage, { site: siteModel })
|
|
27301
|
-
})] })
|
|
27479
|
+
] })
|
|
27302
27480
|
})
|
|
27303
27481
|
}) });
|
|
27304
27482
|
}
|
|
27305
27483
|
|
|
27306
27484
|
//#endregion
|
|
27307
|
-
export {
|
|
27485
|
+
export { Router as _, docsSite as a, ABSOLUTE_URL_REGEX as b, getSeo as c, getDocModule as d, getLastModified as f, BrowserRouter as g, toAbsoluteUrl as h, docsHomeUrl as i, siteName as l, BASE_URL as m, buildHead as n, getLocaleByPathname as o, getScopeForPage as p, renderHeadToString as r, getRedirects as s, App as t, standalonePages as u, createPath as v, parsePath as y };
|
package/dist/entry-client.js
CHANGED