@bndynet/vue-site 1.0.4 → 1.2.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/dist/router.d.ts CHANGED
@@ -1,10 +1,16 @@
1
1
  import { RouterHistory } from 'vue-router';
2
- import { NavItem, ResolvedNavItem, StandalonePage } from './types';
2
+ import { LocaleCode, NavItem, ResolvedNavItem, StandalonePage } from './types';
3
+ import { MessageCatalog } from './i18n-utils';
3
4
  /**
4
5
  * Recursively drop nav items whose `visible()` predicate resolves to `false`. Sibling
5
6
  * predicates are evaluated in parallel. A hidden parent removes its subtree; a group left
6
7
  * with no children and no own `page`/`link` is pruned. Awaited once at startup.
7
8
  */
8
9
  export declare function filterNavItems(items: NavItem[]): Promise<NavItem[]>;
9
- export declare function resolveNavItems(items: NavItem[], parentIndex?: number): ResolvedNavItem[];
10
- export declare function createSiteRouter(resolvedNav: ResolvedNavItem[], pages?: StandalonePage[], history?: RouterHistory, defaultPath?: string): Promise<import('vue-router').Router>;
10
+ /**
11
+ * Resolve nav items into `ResolvedNavItem`s. Route paths are derived from a **canonical** label
12
+ * string (the `defaultLocale` entry, else the first entry) so that switching language never changes
13
+ * URLs. The original `label` (possibly a `LocalizedString`) is preserved for reactive rendering.
14
+ */
15
+ export declare function resolveNavItems(items: NavItem[], defaultLocale?: LocaleCode, catalog?: MessageCatalog, parentIndex?: number): ResolvedNavItem[];
16
+ export declare function createSiteRouter(resolvedNav: ResolvedNavItem[], pages?: StandalonePage[], history?: RouterHistory, defaultPath?: string, defaultLocale?: LocaleCode, catalog?: MessageCatalog): Promise<import('vue-router').Router>;
package/dist/style.css CHANGED
@@ -1 +1 @@
1
- .page-view[data-v-98336c56]{min-height:200px}.page-loading[data-v-98336c56]{display:flex;justify-content:center;padding:60px 0}.page-loading-dot[data-v-98336c56]{width:8px;height:8px;border-radius:50%;background:var(--color-link);animation:pulse-98336c56 1s ease-in-out infinite}@keyframes pulse-98336c56{0%,to{opacity:.3;transform:scale(.8)}50%{opacity:1;transform:scale(1)}}.nav-item[data-v-a35b68cd]{display:flex;align-items:center;gap:10px;padding:9px 14px;margin-bottom:2px;border-radius:8px;color:var(--color-sidebar-text);font-size:.9rem;font-weight:500;text-decoration:none;transition:background-color .15s ease,color .15s ease}.nav-item--indent[data-v-a35b68cd]{padding-left:22px;font-size:.85rem}.nav-item[data-v-a35b68cd]:hover{background:var(--color-sidebar-item-hover);text-decoration:none}.nav-item--active[data-v-a35b68cd]{background:var(--color-sidebar-item-active);color:var(--color-sidebar-item-active-text)}.nav-item-label[data-v-a35b68cd]{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.nav-group-header[data-v-0faf5c71]{display:flex;align-items:center;gap:10px;width:100%;padding:9px 14px;margin-bottom:2px;border:none;border-radius:8px;background:none;color:var(--color-sidebar-text);font-size:.9rem;font-weight:500;cursor:pointer;text-align:left;transition:background-color .15s ease}.nav-group-header[data-v-0faf5c71]:hover{background:var(--color-sidebar-item-hover)}.nav-group-label[data-v-0faf5c71]{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.nav-group-chevron[data-v-0faf5c71]{flex-shrink:0;transition:transform .2s ease;opacity:.5}.nav-group--expanded .nav-group-chevron[data-v-0faf5c71]{transform:rotate(90deg)}.nav-group-children[data-v-0faf5c71]{padding-left:8px}.tooltip-overlay[data-v-d0b5d0eb]{max-width:min(280px,calc(100vw - 16px));padding:6px 10px;font-size:.75rem;line-height:1.35;font-weight:500;color:var(--color-sidebar-text, #606770);background:var(--color-sidebar-bg, #f5f6f7);border:1px solid var(--color-sidebar-border, #ebedf0);border-radius:8px;box-shadow:0 4px 12px #0000001f,0 2px 4px #0000000f;pointer-events:none}.ui-tooltip[data-v-c96e8e51]{display:inline-flex;align-items:center;max-width:100%}.site-external-links[data-v-89ad5b4d]{display:flex;align-items:center;gap:6px}.site-external-link[data-v-89ad5b4d]{display:flex;align-items:center;justify-content:center;width:34px;height:34px;padding:0;border-radius:999px;text-decoration:none;cursor:pointer;background:transparent;color:var(--color-theme-switch-text);border:1px solid transparent;box-shadow:none;transition:background-color .2s ease,border-color .2s ease,box-shadow .2s ease,color .2s ease}.site-external-link[data-v-89ad5b4d]:hover{background:var(--color-theme-switch-hover);border-color:color-mix(in srgb,var(--color-theme-switch-text) 16%,transparent);box-shadow:0 1px 2px #0000001a,0 6px 14px #00000014;text-decoration:none}.site-external-link[data-v-89ad5b4d]:focus-visible{outline:none;box-shadow:0 0 0 2px var(--color-sidebar-bg),0 0 0 4px color-mix(in srgb,var(--color-link) 85%,transparent)}.site-external-links--compact .site-external-link[data-v-89ad5b4d]{width:28px;height:28px}.theme-switch[data-v-66173833]{position:relative;display:inline-flex;flex-direction:column;align-items:center;width:fit-content;max-width:100%;color:var(--color-theme-switch-text)}.theme-switch summary[data-v-66173833]{list-style:none}.theme-switch summary[data-v-66173833]::-webkit-details-marker{display:none}.theme-switch-trigger[data-v-66173833]{display:inline-flex;align-items:center;justify-content:center;width:34px;height:34px;padding:0;border-radius:999px;cursor:pointer;background:transparent;color:var(--color-theme-switch-text);border:1px solid transparent;box-shadow:none;transition:background-color .2s ease,border-color .2s ease,box-shadow .2s ease}.theme-switch-trigger[data-v-66173833]:hover{background:var(--color-theme-switch-hover);border-color:color-mix(in srgb,var(--color-theme-switch-text) 16%,transparent);box-shadow:0 1px 2px #0000001a,0 6px 14px #00000014}.theme-switch-trigger[data-v-66173833]:focus-visible{outline:none;box-shadow:0 0 0 2px var(--color-sidebar-bg),0 0 0 4px color-mix(in srgb,var(--color-link) 85%,transparent)}.theme-switch-trigger-icon[data-v-66173833]{display:flex;align-items:center;justify-content:center}.theme-switch-menu[data-v-66173833]{position:absolute;left:50%;right:auto;top:calc(100% + 6px);transform:translate(-50%);z-index:40;display:flex;flex-direction:column;align-items:center;gap:4px;min-width:40px;padding:6px;border-radius:12px;background:var(--color-sidebar-bg);border:1px solid var(--color-sidebar-border);box-shadow:0 4px 12px #0000001f,0 12px 28px #0000001a}.theme-switch-option[data-v-66173833]{display:flex;align-items:center;justify-content:center;width:36px;height:36px;padding:0;margin:0;border:none;border-radius:999px;cursor:pointer;color:var(--color-sidebar-text);background:transparent;transition:background-color .15s ease}.theme-switch-option[data-v-66173833]:hover{background:var(--color-sidebar-item-hover)}.theme-switch-option--active[data-v-66173833]{background:var(--color-sidebar-item-active);color:var(--color-sidebar-item-active-text)}.theme-switch-option[data-v-66173833]:focus-visible{outline:none;box-shadow:0 0 0 2px var(--color-content-bg),0 0 0 4px color-mix(in srgb,var(--color-link) 85%,transparent)}.theme-switch--compact .theme-switch-trigger[data-v-66173833]{width:28px;height:28px}.theme-switch--compact .theme-switch-menu[data-v-66173833]{top:auto;bottom:calc(100% + 6px);transform:translate(-50%);padding:4px;gap:2px;border-radius:10px;box-shadow:0 -4px 12px #0000001a,0 -8px 24px #00000014}.theme-switch--compact .theme-switch-option[data-v-66173833]{width:30px;height:30px}@media(prefers-reduced-motion:reduce){.theme-switch-trigger[data-v-66173833]{transition:none}}.site-primary-nav-links[data-v-320c51ce]{display:flex;align-items:stretch;gap:0;min-width:0;flex:1;overflow-x:auto;padding:0;-webkit-overflow-scrolling:touch;scrollbar-width:thin}.site-primary-nav-link[data-v-320c51ce]{display:inline-flex;align-items:center;gap:8px;flex-shrink:0;padding:0 14px;border-radius:0;font-size:.9rem;font-weight:600;color:var(--color-sidebar-text);text-decoration:none;background:transparent;transition:background-color .15s ease,color .15s ease}.site-primary-nav-link[data-v-320c51ce]:hover{background:var(--color-sidebar-item-hover);text-decoration:none}.site-primary-nav-link--active[data-v-320c51ce]{background:var(--color-sidebar-item-active);color:var(--color-sidebar-item-active-text)}.site-primary-nav-link-label[data-v-320c51ce]{white-space:nowrap}*,*:before,*:after{box-sizing:border-box;margin:0;padding:0}html{font-size:16px;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;line-height:1.6;color:var(--color-text);background-color:var(--color-bg);transition:color .2s ease,background-color .2s ease}a{color:var(--color-link);text-decoration:none}a:hover{text-decoration:underline}img{max-width:100%;height:auto}::-webkit-scrollbar{width:6px;height:6px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:var(--color-scrollbar);border-radius:3px}:root{--site-top-nav-height: 48px;--site-sidebar-width: 200px}.site-layout{min-height:100vh}.site-layout--tiered-nav .site-sidebar{top:var(--site-top-nav-height);height:calc(100vh - var(--site-top-nav-height))}.site-layout--tiered-nav .site-content{margin-top:var(--site-top-nav-height)}.site-layout--tiered-no-sidebar .site-content{margin-left:0}.site-layout--blank .site-content{margin-left:0;margin-top:0}.site-layout--blank .site-content-inner{max-width:none;margin:0;padding:0}.site-footer-standalone{margin-left:0;padding:1rem;text-align:center;border-top:1px solid var(--color-border);background:var(--color-content-bg);transition:background-color .2s ease}.site-primary-nav{position:fixed;top:0;left:0;right:0;z-index:21;display:flex;align-items:stretch;height:var(--site-top-nav-height);padding:0 12px 0 0;box-sizing:border-box;background:var(--color-sidebar-bg);border-bottom:1px solid var(--color-sidebar-border);transition:background-color .2s ease,border-color .2s ease}.site-primary-nav-end{display:flex;align-items:center;gap:6px;flex-shrink:0}.site-primary-nav-theme{flex-shrink:0}.site-primary-nav-brand{display:flex;flex-direction:row;align-items:center;justify-content:center;gap:10px;flex:0 0 var(--site-sidebar-width);width:var(--site-sidebar-width);min-width:0;max-width:var(--site-sidebar-width);box-sizing:border-box;padding:0 12px;text-decoration:none;color:inherit}.site-primary-nav-brand:hover{text-decoration:none;opacity:.9}.site-primary-nav-logo{display:block;height:auto;max-height:32px;width:auto;max-width:100%;object-fit:contain}.site-primary-nav-title{min-width:0;font-size:1.05rem;font-weight:700;color:var(--color-sidebar-title);letter-spacing:-.01em;line-height:1.2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.site-layout--tiered-nav .site-sidebar-nav{padding-top:12px}.site-sidebar-toolbar{display:flex;align-items:center;justify-content:center;flex-wrap:wrap;gap:6px;width:100%}.site-sidebar{position:fixed;top:0;left:0;width:var(--site-sidebar-width);height:100vh;background:var(--color-sidebar-bg);border-right:1px solid var(--color-sidebar-border);display:flex;flex-direction:column;overflow:hidden;z-index:10;transition:background-color .2s ease,border-color .2s ease}.site-sidebar-header{flex-shrink:0;padding:1rem 1rem .75rem;display:flex;justify-content:center}.site-sidebar-brand{display:flex;flex-direction:row;align-items:center;justify-content:center;gap:10px;min-width:0;max-width:100%}.site-sidebar-logo{display:block;max-width:100%;height:auto;max-height:40px;width:auto;object-fit:contain}.site-sidebar-title{min-width:0;font-size:1.15rem;font-weight:700;color:var(--color-sidebar-title);letter-spacing:-.01em;line-height:1.25;text-align:center}.site-sidebar-nav{flex:1 1 auto;min-height:0;overflow-x:hidden;overflow-y:auto;padding:0 8px}.site-sidebar-footer{flex-shrink:0;padding:10px 12px 12px;border-top:1px solid var(--color-sidebar-border);display:flex;flex-direction:column;align-items:center;gap:10px}.site-footer-text{margin:0;font-size:.75rem;line-height:1.45;color:var(--color-text-secondary);white-space:pre-wrap;word-break:break-word;text-align:center}.site-content{margin-left:var(--site-sidebar-width);min-height:100vh;background:var(--color-content-bg);transition:background-color .2s ease}.site-content-inner{max-width:860px;margin:0 auto;padding:40px 48px}.markdown-body h1{font-size:2rem;font-weight:700;margin-bottom:.5rem;padding-bottom:.3rem;border-bottom:1px solid var(--color-border);color:var(--color-text)}.markdown-body h2{font-size:1.5rem;font-weight:600;margin-top:2rem;margin-bottom:.75rem;padding-bottom:.25rem;border-bottom:1px solid var(--color-border);color:var(--color-text)}.markdown-body h3{font-size:1.25rem;font-weight:600;margin-top:1.5rem;margin-bottom:.5rem;color:var(--color-text)}.markdown-body h4,.markdown-body h5,.markdown-body h6{font-size:1rem;font-weight:600;margin-top:1.25rem;margin-bottom:.5rem;color:var(--color-text)}.markdown-body p{margin-bottom:1rem;color:var(--color-text-secondary);line-height:1.75}.markdown-body ul,.markdown-body ol{margin-bottom:1rem;padding-left:2em;color:var(--color-text-secondary)}.markdown-body li{margin-bottom:.25rem}.markdown-body li>ul,.markdown-body li>ol{margin-bottom:0}.markdown-body code{font-family:SF Mono,Fira Code,Fira Mono,Menlo,Consolas,monospace;font-size:.875em;padding:.2em .4em;background:var(--color-code-bg);border-radius:4px;color:var(--color-code-text)}.markdown-body pre{margin-bottom:1.25rem;border-radius:8px;overflow-x:auto;border:1px solid var(--color-code-border)}.markdown-body pre code{display:block;padding:16px 20px;background:var(--color-code-block-bg);font-size:.85rem;line-height:1.6;border-radius:0}.markdown-body blockquote{margin-bottom:1rem;padding:12px 20px;border-left:4px solid var(--color-blockquote-border);background:var(--color-blockquote-bg);border-radius:0 6px 6px 0;color:var(--color-blockquote-text)}.markdown-body blockquote p:last-child{margin-bottom:0}.markdown-body table{width:100%;margin-bottom:1rem;border-collapse:collapse;border:1px solid var(--color-table-border)}.markdown-body th{background:var(--color-table-header-bg);padding:10px 14px;text-align:left;font-weight:600;border:1px solid var(--color-table-border);color:var(--color-text)}.markdown-body td{padding:10px 14px;border:1px solid var(--color-table-border);color:var(--color-text-secondary)}.markdown-body tr:hover td{background:var(--color-table-row-hover)}.markdown-body hr{margin:2rem 0;border:none;border-top:1px solid var(--color-border)}.markdown-body a{color:var(--color-link)}.markdown-body a:hover{color:var(--color-link-hover)}.markdown-body img{max-width:100%;border-radius:6px}.markdown-body strong{color:var(--color-text)}[data-theme=light] .hljs{color:#24292f;background:var(--color-code-block-bg)}[data-theme=light] .hljs-comment,[data-theme=light] .hljs-quote{color:#6a737d;font-style:italic}[data-theme=light] .hljs-keyword,[data-theme=light] .hljs-selector-tag,[data-theme=light] .hljs-type{color:#d73a49}[data-theme=light] .hljs-string,[data-theme=light] .hljs-addition{color:#032f62}[data-theme=light] .hljs-number,[data-theme=light] .hljs-literal{color:#005cc5}[data-theme=light] .hljs-built_in,[data-theme=light] .hljs-builtin-name,[data-theme=light] .hljs-title,[data-theme=light] .hljs-title.function_,[data-theme=light] .hljs-section{color:#6f42c1}[data-theme=light] .hljs-attr,[data-theme=light] .hljs-attribute{color:#005cc5}[data-theme=light] .hljs-variable,[data-theme=light] .hljs-template-variable{color:#e36209}[data-theme=light] .hljs-name,[data-theme=light] .hljs-tag{color:#22863a}[data-theme=light] .hljs-selector-class,[data-theme=light] .hljs-selector-id{color:#6f42c1}[data-theme=light] .hljs-deletion{color:#b31d28;background:#ffeef0}[data-theme=light] .hljs-addition{background:#f0fff4}[data-theme=light] .hljs-meta{color:#735c0f}[data-theme=light] .hljs-regexp{color:#032f62}[data-theme=light] .hljs-symbol{color:#005cc5}[data-theme=light] .hljs-params{color:#24292f}[data-theme=dark] .hljs{color:#e2e8f0;background:var(--color-code-block-bg)}[data-theme=dark] .hljs-comment,[data-theme=dark] .hljs-quote{color:#8b949e;font-style:italic}[data-theme=dark] .hljs-keyword,[data-theme=dark] .hljs-selector-tag,[data-theme=dark] .hljs-type{color:#ff7b72}[data-theme=dark] .hljs-string,[data-theme=dark] .hljs-addition{color:#a5d6ff}[data-theme=dark] .hljs-number,[data-theme=dark] .hljs-literal{color:#79c0ff}[data-theme=dark] .hljs-built_in,[data-theme=dark] .hljs-builtin-name,[data-theme=dark] .hljs-title,[data-theme=dark] .hljs-title.function_,[data-theme=dark] .hljs-section{color:#d2a8ff}[data-theme=dark] .hljs-attr,[data-theme=dark] .hljs-attribute{color:#79c0ff}[data-theme=dark] .hljs-variable,[data-theme=dark] .hljs-template-variable{color:#ffa657}[data-theme=dark] .hljs-name,[data-theme=dark] .hljs-tag{color:#7ee787}[data-theme=dark] .hljs-selector-class,[data-theme=dark] .hljs-selector-id{color:#d2a8ff}[data-theme=dark] .hljs-deletion{color:#ffdcd7;background:#67060c}[data-theme=dark] .hljs-addition{background:#0d4429}[data-theme=dark] .hljs-meta{color:#d29922}[data-theme=dark] .hljs-regexp{color:#a5d6ff}[data-theme=dark] .hljs-symbol{color:#79c0ff}[data-theme=dark] .hljs-params{color:#e2e8f0}:root{--el-bg-color-page: var(--color-bg);--el-bg-color: var(--color-content-bg);--el-bg-color-overlay: var(--color-content-bg);--el-text-color-primary: var(--color-text);--el-text-color-regular: var(--color-sidebar-text);--el-text-color-secondary: var(--color-text-secondary);--el-text-color-placeholder: color-mix(in srgb, var(--color-text-secondary) 70%, var(--color-bg));--el-text-color-disabled: color-mix(in srgb, var(--color-text-secondary) 50%, var(--color-bg));--el-border-color: var(--color-border);--el-border-color-light: color-mix(in srgb, var(--color-border) 70%, var(--color-bg));--el-border-color-lighter: color-mix(in srgb, var(--color-border) 50%, var(--color-bg));--el-border-color-extra-light: color-mix(in srgb, var(--color-border) 30%, var(--color-bg));--el-border-color-dark: color-mix(in srgb, var(--color-border) 80%, var(--color-text));--el-border-color-darker: color-mix(in srgb, var(--color-border) 60%, var(--color-text));--el-fill-color: var(--color-table-header-bg);--el-fill-color-light: color-mix(in srgb, var(--color-table-header-bg) 80%, var(--color-bg));--el-fill-color-lighter: color-mix(in srgb, var(--color-table-header-bg) 50%, var(--color-bg));--el-fill-color-extra-light: color-mix(in srgb, var(--color-table-header-bg) 30%, var(--color-bg));--el-fill-color-dark: color-mix(in srgb, var(--color-table-header-bg) 120%, var(--color-border));--el-fill-color-darker: color-mix(in srgb, var(--color-table-header-bg) 80%, var(--color-border));--el-fill-color-blank: var(--color-bg);--el-table-header-bg-color: var(--color-table-header-bg);--el-table-tr-bg-color: var(--color-bg);--el-table-expanded-cell-bg-color: color-mix(in srgb, var(--color-table-header-bg) 50%, var(--color-bg));--el-table-row-hover-bg-color: var(--color-table-row-hover);--el-menu-bg-color: var(--color-sidebar-bg);--el-menu-text-color: var(--color-sidebar-text);--el-menu-active-color: var(--color-link);--el-menu-hover-bg-color: var(--color-sidebar-item-hover);--el-dropdown-menuItem-hover-fill: var(--color-sidebar-item-hover);--el-dropdown-menuItem-hover-color: var(--color-text)}html.dark{--el-bg-color-page: var(--color-bg);--el-bg-color: var(--color-content-bg);--el-bg-color-overlay: var(--color-sidebar-bg);--el-text-color-primary: var(--color-text);--el-text-color-regular: var(--color-sidebar-text);--el-text-color-secondary: var(--color-text-secondary);--el-text-color-placeholder: color-mix(in srgb, var(--color-text-secondary) 70%, var(--color-bg));--el-text-color-disabled: color-mix(in srgb, var(--color-text-secondary) 50%, var(--color-bg));--el-border-color: var(--color-border);--el-border-color-light: color-mix(in srgb, var(--color-border) 70%, var(--color-bg));--el-border-color-lighter: color-mix(in srgb, var(--color-border) 50%, var(--color-bg));--el-border-color-extra-light: color-mix(in srgb, var(--color-border) 30%, var(--color-bg));--el-border-color-dark: color-mix(in srgb, var(--color-border) 80%, var(--color-text));--el-border-color-darker: color-mix(in srgb, var(--color-border) 60%, var(--color-text));--el-fill-color: var(--color-table-header-bg);--el-fill-color-light: color-mix(in srgb, var(--color-table-header-bg) 80%, var(--color-bg));--el-fill-color-lighter: color-mix(in srgb, var(--color-table-header-bg) 50%, var(--color-bg));--el-fill-color-extra-light: color-mix(in srgb, var(--color-table-header-bg) 30%, var(--color-bg));--el-fill-color-dark: color-mix(in srgb, var(--color-table-header-bg) 120%, var(--color-border));--el-fill-color-darker: color-mix(in srgb, var(--color-table-header-bg) 80%, var(--color-border));--el-fill-color-blank: var(--color-bg);--el-table-header-bg-color: var(--color-table-header-bg);--el-table-tr-bg-color: var(--color-bg);--el-table-expanded-cell-bg-color: color-mix(in srgb, var(--color-table-header-bg) 50%, var(--color-bg));--el-table-row-hover-bg-color: var(--color-table-row-hover);--el-menu-bg-color: var(--color-sidebar-bg);--el-menu-text-color: var(--color-sidebar-text);--el-menu-active-color: var(--color-link);--el-menu-hover-bg-color: var(--color-sidebar-item-hover);--el-dropdown-menuItem-hover-fill: var(--color-sidebar-item-hover);--el-dropdown-menuItem-hover-color: var(--color-text);--el-box-shadow: 0 12px 32px 4px rgba(0, 0, 0, .5), 0 8px 20px rgba(0, 0, 0, .6);--el-box-shadow-light: 0 0 12px rgba(0, 0, 0, .6);--el-box-shadow-lighter: 0 0 6px rgba(0, 0, 0, .5);--el-box-shadow-dark: 0 16px 48px 16px rgba(0, 0, 0, .7), 0 12px 32px rgba(0, 0, 0, .6);--el-mask-color: rgba(0, 0, 0, .8);--el-mask-color-extra-light: rgba(0, 0, 0, .3)}
1
+ .page-view[data-v-4990c67a]{min-height:200px}.page-loading[data-v-4990c67a]{display:flex;justify-content:center;padding:60px 0}.page-loading-dot[data-v-4990c67a]{width:8px;height:8px;border-radius:50%;background:var(--color-link);animation:pulse-4990c67a 1s ease-in-out infinite}@keyframes pulse-4990c67a{0%,to{opacity:.3;transform:scale(.8)}50%{opacity:1;transform:scale(1)}}.nav-item[data-v-562dbe5f]{display:flex;align-items:center;gap:10px;padding:9px 14px;margin-bottom:2px;border-radius:8px;color:var(--color-sidebar-text);font-size:.9rem;font-weight:500;text-decoration:none;transition:background-color .15s ease,color .15s ease}.nav-item--indent[data-v-562dbe5f]{padding-left:22px;font-size:.85rem}.nav-item[data-v-562dbe5f]:hover{background:var(--color-sidebar-item-hover);text-decoration:none}.nav-item--active[data-v-562dbe5f]{background:var(--color-sidebar-item-active);color:var(--color-sidebar-item-active-text)}.nav-item-label[data-v-562dbe5f]{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.nav-group-header[data-v-d83c4e05]{display:flex;align-items:center;gap:10px;width:100%;padding:9px 14px;margin-bottom:2px;border:none;border-radius:8px;background:none;color:var(--color-sidebar-text);font-size:.9rem;font-weight:500;cursor:pointer;text-align:left;transition:background-color .15s ease}.nav-group-header[data-v-d83c4e05]:hover{background:var(--color-sidebar-item-hover)}.nav-group-label[data-v-d83c4e05]{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.nav-group-chevron[data-v-d83c4e05]{flex-shrink:0;transition:transform .2s ease;opacity:.5}.nav-group--expanded .nav-group-chevron[data-v-d83c4e05]{transform:rotate(90deg)}.nav-group-children[data-v-d83c4e05]{padding-left:8px}.tooltip-overlay[data-v-d0b5d0eb]{max-width:min(280px,calc(100vw - 16px));padding:6px 10px;font-size:.75rem;line-height:1.35;font-weight:500;color:var(--color-sidebar-text, #606770);background:var(--color-sidebar-bg, #f5f6f7);border:1px solid var(--color-sidebar-border, #ebedf0);border-radius:8px;box-shadow:0 4px 12px #0000001f,0 2px 4px #0000000f;pointer-events:none}.ui-tooltip[data-v-c96e8e51]{display:inline-flex;align-items:center;max-width:100%}.site-external-links[data-v-d90eed72]{display:flex;align-items:center;gap:6px}.site-external-link[data-v-d90eed72]{display:flex;align-items:center;justify-content:center;width:34px;height:34px;padding:0;border-radius:999px;text-decoration:none;cursor:pointer;background:transparent;color:var(--color-theme-switch-text);border:1px solid transparent;box-shadow:none;transition:background-color .2s ease,border-color .2s ease,box-shadow .2s ease,color .2s ease}.site-external-link[data-v-d90eed72]:hover{background:var(--color-theme-switch-hover);border-color:color-mix(in srgb,var(--color-theme-switch-text) 16%,transparent);box-shadow:0 1px 2px #0000001a,0 6px 14px #00000014;text-decoration:none}.site-external-link[data-v-d90eed72]:focus-visible{outline:none;box-shadow:0 0 0 2px var(--color-sidebar-bg),0 0 0 4px color-mix(in srgb,var(--color-link) 85%,transparent)}.site-external-links--compact .site-external-link[data-v-d90eed72]{width:28px;height:28px}.theme-switch[data-v-efe2a351]{position:relative;display:inline-flex;flex-direction:column;align-items:center;width:fit-content;max-width:100%;color:var(--color-theme-switch-text)}.theme-switch summary[data-v-efe2a351]{list-style:none}.theme-switch summary[data-v-efe2a351]::-webkit-details-marker{display:none}.theme-switch-trigger[data-v-efe2a351]{display:inline-flex;align-items:center;justify-content:center;width:34px;height:34px;padding:0;border-radius:999px;cursor:pointer;background:transparent;color:var(--color-theme-switch-text);border:1px solid transparent;box-shadow:none;transition:background-color .2s ease,border-color .2s ease,box-shadow .2s ease}.theme-switch-trigger[data-v-efe2a351]:hover{background:var(--color-theme-switch-hover);border-color:color-mix(in srgb,var(--color-theme-switch-text) 16%,transparent);box-shadow:0 1px 2px #0000001a,0 6px 14px #00000014}.theme-switch-trigger[data-v-efe2a351]:focus-visible{outline:none;box-shadow:0 0 0 2px var(--color-sidebar-bg),0 0 0 4px color-mix(in srgb,var(--color-link) 85%,transparent)}.theme-switch-trigger-icon[data-v-efe2a351]{display:flex;align-items:center;justify-content:center}.theme-switch-menu[data-v-efe2a351]{position:absolute;left:50%;right:auto;top:calc(100% + 6px);transform:translate(-50%);z-index:40;display:flex;flex-direction:column;align-items:center;gap:4px;min-width:40px;padding:6px;border-radius:12px;background:var(--color-sidebar-bg);border:1px solid var(--color-sidebar-border);box-shadow:0 4px 12px #0000001f,0 12px 28px #0000001a}.theme-switch-option[data-v-efe2a351]{display:flex;align-items:center;justify-content:center;width:36px;height:36px;padding:0;margin:0;border:none;border-radius:999px;cursor:pointer;color:var(--color-sidebar-text);background:transparent;transition:background-color .15s ease}.theme-switch-option[data-v-efe2a351]:hover{background:var(--color-sidebar-item-hover)}.theme-switch-option--active[data-v-efe2a351]{background:var(--color-sidebar-item-active);color:var(--color-sidebar-item-active-text)}.theme-switch-option[data-v-efe2a351]:focus-visible{outline:none;box-shadow:0 0 0 2px var(--color-content-bg),0 0 0 4px color-mix(in srgb,var(--color-link) 85%,transparent)}.theme-switch--compact .theme-switch-trigger[data-v-efe2a351]{width:28px;height:28px}.theme-switch--compact .theme-switch-menu[data-v-efe2a351]{top:auto;bottom:calc(100% + 6px);transform:translate(-50%);padding:4px;gap:2px;border-radius:10px;box-shadow:0 -4px 12px #0000001a,0 -8px 24px #00000014}.theme-switch--compact .theme-switch-option[data-v-efe2a351]{width:30px;height:30px}@media(prefers-reduced-motion:reduce){.theme-switch-trigger[data-v-efe2a351]{transition:none}}.locale-switch[data-v-66c5d143]{position:relative;display:inline-flex;flex-direction:column;align-items:center;width:fit-content;max-width:100%;color:var(--color-theme-switch-text)}.locale-switch summary[data-v-66c5d143]{list-style:none}.locale-switch summary[data-v-66c5d143]::-webkit-details-marker{display:none}.locale-switch-trigger[data-v-66c5d143]{display:inline-flex;align-items:center;justify-content:center;width:34px;height:34px;padding:0;border-radius:999px;cursor:pointer;background:transparent;color:var(--color-theme-switch-text);border:1px solid transparent;box-shadow:none;transition:background-color .2s ease,border-color .2s ease,box-shadow .2s ease}.locale-switch-trigger[data-v-66c5d143]:hover{background:var(--color-theme-switch-hover);border-color:color-mix(in srgb,var(--color-theme-switch-text) 16%,transparent);box-shadow:0 1px 2px #0000001a,0 6px 14px #00000014}.locale-switch-trigger[data-v-66c5d143]:focus-visible{outline:none;box-shadow:0 0 0 2px var(--color-sidebar-bg),0 0 0 4px color-mix(in srgb,var(--color-link) 85%,transparent)}.locale-switch-trigger-icon[data-v-66c5d143]{display:flex;align-items:center;justify-content:center}.locale-switch-menu[data-v-66c5d143]{position:absolute;left:50%;right:auto;top:calc(100% + 6px);transform:translate(-50%);z-index:40;display:flex;flex-direction:column;align-items:stretch;gap:2px;min-width:140px;padding:6px;border-radius:12px;background:var(--color-sidebar-bg);border:1px solid var(--color-sidebar-border);box-shadow:0 4px 12px #0000001f,0 12px 28px #0000001a}.locale-switch-option[data-v-66c5d143]{display:flex;align-items:center;gap:10px;width:100%;padding:8px 12px;margin:0;border:none;border-radius:8px;cursor:pointer;font-size:.875rem;font-weight:500;text-align:left;white-space:nowrap;color:var(--color-sidebar-text);background:transparent;transition:background-color .15s ease}.locale-switch-option[data-v-66c5d143]:hover{background:var(--color-sidebar-item-hover)}.locale-switch-option--active[data-v-66c5d143]{background:var(--color-sidebar-item-active);color:var(--color-sidebar-item-active-text)}.locale-switch-option[data-v-66c5d143]:focus-visible{outline:none;box-shadow:0 0 0 2px var(--color-content-bg),0 0 0 4px color-mix(in srgb,var(--color-link) 85%,transparent)}.locale-switch-option-label[data-v-66c5d143]{flex:1}.locale-switch--compact .locale-switch-trigger[data-v-66c5d143]{width:28px;height:28px}.locale-switch--compact .locale-switch-menu[data-v-66c5d143]{top:auto;bottom:calc(100% + 6px);transform:translate(-50%);padding:4px;border-radius:10px;box-shadow:0 -4px 12px #0000001a,0 -8px 24px #00000014}@media(prefers-reduced-motion:reduce){.locale-switch-trigger[data-v-66c5d143]{transition:none}}.site-primary-nav-links[data-v-d6741411]{display:flex;align-items:stretch;gap:0;min-width:0;flex:1;overflow-x:auto;padding:0;-webkit-overflow-scrolling:touch;scrollbar-width:thin}.site-primary-nav-link[data-v-d6741411]{display:inline-flex;align-items:center;gap:8px;flex-shrink:0;padding:0 14px;border-radius:0;font-size:.9rem;font-weight:600;color:var(--color-sidebar-text);text-decoration:none;background:transparent;transition:background-color .15s ease,color .15s ease}.site-primary-nav-link[data-v-d6741411]:hover{background:var(--color-sidebar-item-hover);text-decoration:none}.site-primary-nav-link--active[data-v-d6741411]{background:var(--color-sidebar-item-active);color:var(--color-sidebar-item-active-text)}.site-primary-nav-link-label[data-v-d6741411]{white-space:nowrap}*,*:before,*:after{box-sizing:border-box;margin:0;padding:0}html{font-size:16px;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;line-height:1.6;color:var(--color-text);background-color:var(--color-bg);transition:color .2s ease,background-color .2s ease}a{color:var(--color-link);text-decoration:none}a:hover{text-decoration:underline}img{max-width:100%;height:auto}::-webkit-scrollbar{width:6px;height:6px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:var(--color-scrollbar);border-radius:3px}:root{--site-top-nav-height: 48px;--site-sidebar-width: 200px}.site-layout{min-height:100vh}.site-layout--tiered-nav .site-sidebar{top:var(--site-top-nav-height);height:calc(100vh - var(--site-top-nav-height))}.site-layout--tiered-nav .site-content{margin-top:var(--site-top-nav-height)}.site-layout--tiered-no-sidebar .site-content{margin-left:0}.site-layout--blank .site-content{margin-left:0;margin-top:0}.site-layout--blank .site-content-inner{max-width:none;margin:0;padding:0}.site-footer-standalone{margin-left:0;padding:1rem;text-align:center;border-top:1px solid var(--color-border);background:var(--color-content-bg);transition:background-color .2s ease}.site-primary-nav{position:fixed;top:0;left:0;right:0;z-index:21;display:flex;align-items:stretch;height:var(--site-top-nav-height);padding:0 12px 0 0;box-sizing:border-box;background:var(--color-sidebar-bg);border-bottom:1px solid var(--color-sidebar-border);transition:background-color .2s ease,border-color .2s ease}.site-primary-nav-end{display:flex;align-items:center;gap:6px;flex-shrink:0}.site-primary-nav-theme{flex-shrink:0}.site-primary-nav-brand{display:flex;flex-direction:row;align-items:center;justify-content:center;gap:10px;flex:0 0 var(--site-sidebar-width);width:var(--site-sidebar-width);min-width:0;max-width:var(--site-sidebar-width);box-sizing:border-box;padding:0 12px;text-decoration:none;color:inherit}.site-primary-nav-brand:hover{text-decoration:none;opacity:.9}.site-primary-nav-logo{display:block;height:auto;max-height:32px;width:auto;max-width:100%;object-fit:contain}.site-primary-nav-title{min-width:0;font-size:1.05rem;font-weight:700;color:var(--color-sidebar-title);letter-spacing:-.01em;line-height:1.2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.site-layout--tiered-nav .site-sidebar-nav{padding-top:12px}.site-sidebar-toolbar{display:flex;align-items:center;justify-content:center;flex-wrap:wrap;gap:6px;width:100%}.site-sidebar{position:fixed;top:0;left:0;width:var(--site-sidebar-width);height:100vh;background:var(--color-sidebar-bg);border-right:1px solid var(--color-sidebar-border);display:flex;flex-direction:column;overflow:hidden;z-index:10;transition:background-color .2s ease,border-color .2s ease}.site-sidebar-header{flex-shrink:0;padding:1rem 1rem .75rem;display:flex;justify-content:center}.site-sidebar-brand{display:flex;flex-direction:row;align-items:center;justify-content:center;gap:10px;min-width:0;max-width:100%}.site-sidebar-logo{display:block;max-width:100%;height:auto;max-height:40px;width:auto;object-fit:contain}.site-sidebar-title{min-width:0;font-size:1.15rem;font-weight:700;color:var(--color-sidebar-title);letter-spacing:-.01em;line-height:1.25;text-align:center}.site-sidebar-nav{flex:1 1 auto;min-height:0;overflow-x:hidden;overflow-y:auto;padding:0 8px}.site-sidebar-footer{flex-shrink:0;padding:10px 12px 12px;border-top:1px solid var(--color-sidebar-border);display:flex;flex-direction:column;align-items:center;gap:10px}.site-footer-text{margin:0;font-size:.75rem;line-height:1.45;color:var(--color-text-secondary);white-space:pre-wrap;word-break:break-word;text-align:center}.site-content{margin-left:var(--site-sidebar-width);min-height:100vh;background:var(--color-content-bg);transition:background-color .2s ease}.site-content-inner{max-width:860px;margin:0 auto;padding:40px 48px}.markdown-body h1{font-size:2rem;font-weight:700;margin-bottom:.5rem;padding-bottom:.3rem;border-bottom:1px solid var(--color-border);color:var(--color-text)}.markdown-body h2{font-size:1.5rem;font-weight:600;margin-top:2rem;margin-bottom:.75rem;padding-bottom:.25rem;border-bottom:1px solid var(--color-border);color:var(--color-text)}.markdown-body h3{font-size:1.25rem;font-weight:600;margin-top:1.5rem;margin-bottom:.5rem;color:var(--color-text)}.markdown-body h4,.markdown-body h5,.markdown-body h6{font-size:1rem;font-weight:600;margin-top:1.25rem;margin-bottom:.5rem;color:var(--color-text)}.markdown-body p{margin-bottom:1rem;color:var(--color-text-secondary);line-height:1.75}.markdown-body ul,.markdown-body ol{margin-bottom:1rem;padding-left:2em;color:var(--color-text-secondary)}.markdown-body li{margin-bottom:.25rem}.markdown-body li>ul,.markdown-body li>ol{margin-bottom:0}.markdown-body code{font-family:SF Mono,Fira Code,Fira Mono,Menlo,Consolas,monospace;font-size:.875em;padding:.2em .4em;background:var(--color-code-bg);border-radius:4px;color:var(--color-code-text)}.markdown-body pre{margin-bottom:1.25rem;border-radius:8px;overflow-x:auto;border:1px solid var(--color-code-border)}.markdown-body pre code{display:block;padding:16px 20px;background:var(--color-code-block-bg);font-size:.85rem;line-height:1.6;border-radius:0}.markdown-body blockquote{margin-bottom:1rem;padding:12px 20px;border-left:4px solid var(--color-blockquote-border);background:var(--color-blockquote-bg);border-radius:0 6px 6px 0;color:var(--color-blockquote-text)}.markdown-body blockquote p:last-child{margin-bottom:0}.markdown-body table{width:100%;margin-bottom:1rem;border-collapse:collapse;border:1px solid var(--color-table-border)}.markdown-body th{background:var(--color-table-header-bg);padding:10px 14px;text-align:left;font-weight:600;border:1px solid var(--color-table-border);color:var(--color-text)}.markdown-body td{padding:10px 14px;border:1px solid var(--color-table-border);color:var(--color-text-secondary)}.markdown-body tr:hover td{background:var(--color-table-row-hover)}.markdown-body hr{margin:2rem 0;border:none;border-top:1px solid var(--color-border)}.markdown-body a{color:var(--color-link)}.markdown-body a:hover{color:var(--color-link-hover)}.markdown-body img{max-width:100%;border-radius:6px}.markdown-body strong{color:var(--color-text)}[data-theme=light] .hljs{color:#24292f;background:var(--color-code-block-bg)}[data-theme=light] .hljs-comment,[data-theme=light] .hljs-quote{color:#6a737d;font-style:italic}[data-theme=light] .hljs-keyword,[data-theme=light] .hljs-selector-tag,[data-theme=light] .hljs-type{color:#d73a49}[data-theme=light] .hljs-string,[data-theme=light] .hljs-addition{color:#032f62}[data-theme=light] .hljs-number,[data-theme=light] .hljs-literal{color:#005cc5}[data-theme=light] .hljs-built_in,[data-theme=light] .hljs-builtin-name,[data-theme=light] .hljs-title,[data-theme=light] .hljs-title.function_,[data-theme=light] .hljs-section{color:#6f42c1}[data-theme=light] .hljs-attr,[data-theme=light] .hljs-attribute{color:#005cc5}[data-theme=light] .hljs-variable,[data-theme=light] .hljs-template-variable{color:#e36209}[data-theme=light] .hljs-name,[data-theme=light] .hljs-tag{color:#22863a}[data-theme=light] .hljs-selector-class,[data-theme=light] .hljs-selector-id{color:#6f42c1}[data-theme=light] .hljs-deletion{color:#b31d28;background:#ffeef0}[data-theme=light] .hljs-addition{background:#f0fff4}[data-theme=light] .hljs-meta{color:#735c0f}[data-theme=light] .hljs-regexp{color:#032f62}[data-theme=light] .hljs-symbol{color:#005cc5}[data-theme=light] .hljs-params{color:#24292f}[data-theme=dark] .hljs{color:#e2e8f0;background:var(--color-code-block-bg)}[data-theme=dark] .hljs-comment,[data-theme=dark] .hljs-quote{color:#8b949e;font-style:italic}[data-theme=dark] .hljs-keyword,[data-theme=dark] .hljs-selector-tag,[data-theme=dark] .hljs-type{color:#ff7b72}[data-theme=dark] .hljs-string,[data-theme=dark] .hljs-addition{color:#a5d6ff}[data-theme=dark] .hljs-number,[data-theme=dark] .hljs-literal{color:#79c0ff}[data-theme=dark] .hljs-built_in,[data-theme=dark] .hljs-builtin-name,[data-theme=dark] .hljs-title,[data-theme=dark] .hljs-title.function_,[data-theme=dark] .hljs-section{color:#d2a8ff}[data-theme=dark] .hljs-attr,[data-theme=dark] .hljs-attribute{color:#79c0ff}[data-theme=dark] .hljs-variable,[data-theme=dark] .hljs-template-variable{color:#ffa657}[data-theme=dark] .hljs-name,[data-theme=dark] .hljs-tag{color:#7ee787}[data-theme=dark] .hljs-selector-class,[data-theme=dark] .hljs-selector-id{color:#d2a8ff}[data-theme=dark] .hljs-deletion{color:#ffdcd7;background:#67060c}[data-theme=dark] .hljs-addition{background:#0d4429}[data-theme=dark] .hljs-meta{color:#d29922}[data-theme=dark] .hljs-regexp{color:#a5d6ff}[data-theme=dark] .hljs-symbol{color:#79c0ff}[data-theme=dark] .hljs-params{color:#e2e8f0}:root{--el-bg-color-page: var(--color-bg);--el-bg-color: var(--color-content-bg);--el-bg-color-overlay: var(--color-content-bg);--el-text-color-primary: var(--color-text);--el-text-color-regular: var(--color-sidebar-text);--el-text-color-secondary: var(--color-text-secondary);--el-text-color-placeholder: color-mix(in srgb, var(--color-text-secondary) 70%, var(--color-bg));--el-text-color-disabled: color-mix(in srgb, var(--color-text-secondary) 50%, var(--color-bg));--el-border-color: var(--color-border);--el-border-color-light: color-mix(in srgb, var(--color-border) 70%, var(--color-bg));--el-border-color-lighter: color-mix(in srgb, var(--color-border) 50%, var(--color-bg));--el-border-color-extra-light: color-mix(in srgb, var(--color-border) 30%, var(--color-bg));--el-border-color-dark: color-mix(in srgb, var(--color-border) 80%, var(--color-text));--el-border-color-darker: color-mix(in srgb, var(--color-border) 60%, var(--color-text));--el-fill-color: var(--color-table-header-bg);--el-fill-color-light: color-mix(in srgb, var(--color-table-header-bg) 80%, var(--color-bg));--el-fill-color-lighter: color-mix(in srgb, var(--color-table-header-bg) 50%, var(--color-bg));--el-fill-color-extra-light: color-mix(in srgb, var(--color-table-header-bg) 30%, var(--color-bg));--el-fill-color-dark: color-mix(in srgb, var(--color-table-header-bg) 120%, var(--color-border));--el-fill-color-darker: color-mix(in srgb, var(--color-table-header-bg) 80%, var(--color-border));--el-fill-color-blank: var(--color-bg);--el-table-header-bg-color: var(--color-table-header-bg);--el-table-tr-bg-color: var(--color-bg);--el-table-expanded-cell-bg-color: color-mix(in srgb, var(--color-table-header-bg) 50%, var(--color-bg));--el-table-row-hover-bg-color: var(--color-table-row-hover);--el-menu-bg-color: var(--color-sidebar-bg);--el-menu-text-color: var(--color-sidebar-text);--el-menu-active-color: var(--color-link);--el-menu-hover-bg-color: var(--color-sidebar-item-hover);--el-dropdown-menuItem-hover-fill: var(--color-sidebar-item-hover);--el-dropdown-menuItem-hover-color: var(--color-text)}html.dark{--el-bg-color-page: var(--color-bg);--el-bg-color: var(--color-content-bg);--el-bg-color-overlay: var(--color-sidebar-bg);--el-text-color-primary: var(--color-text);--el-text-color-regular: var(--color-sidebar-text);--el-text-color-secondary: var(--color-text-secondary);--el-text-color-placeholder: color-mix(in srgb, var(--color-text-secondary) 70%, var(--color-bg));--el-text-color-disabled: color-mix(in srgb, var(--color-text-secondary) 50%, var(--color-bg));--el-border-color: var(--color-border);--el-border-color-light: color-mix(in srgb, var(--color-border) 70%, var(--color-bg));--el-border-color-lighter: color-mix(in srgb, var(--color-border) 50%, var(--color-bg));--el-border-color-extra-light: color-mix(in srgb, var(--color-border) 30%, var(--color-bg));--el-border-color-dark: color-mix(in srgb, var(--color-border) 80%, var(--color-text));--el-border-color-darker: color-mix(in srgb, var(--color-border) 60%, var(--color-text));--el-fill-color: var(--color-table-header-bg);--el-fill-color-light: color-mix(in srgb, var(--color-table-header-bg) 80%, var(--color-bg));--el-fill-color-lighter: color-mix(in srgb, var(--color-table-header-bg) 50%, var(--color-bg));--el-fill-color-extra-light: color-mix(in srgb, var(--color-table-header-bg) 30%, var(--color-bg));--el-fill-color-dark: color-mix(in srgb, var(--color-table-header-bg) 120%, var(--color-border));--el-fill-color-darker: color-mix(in srgb, var(--color-table-header-bg) 80%, var(--color-border));--el-fill-color-blank: var(--color-bg);--el-table-header-bg-color: var(--color-table-header-bg);--el-table-tr-bg-color: var(--color-bg);--el-table-expanded-cell-bg-color: color-mix(in srgb, var(--color-table-header-bg) 50%, var(--color-bg));--el-table-row-hover-bg-color: var(--color-table-row-hover);--el-menu-bg-color: var(--color-sidebar-bg);--el-menu-text-color: var(--color-sidebar-text);--el-menu-active-color: var(--color-link);--el-menu-hover-bg-color: var(--color-sidebar-item-hover);--el-dropdown-menuItem-hover-fill: var(--color-sidebar-item-hover);--el-dropdown-menuItem-hover-color: var(--color-text);--el-box-shadow: 0 12px 32px 4px rgba(0, 0, 0, .5), 0 8px 20px rgba(0, 0, 0, .6);--el-box-shadow-light: 0 0 12px rgba(0, 0, 0, .6);--el-box-shadow-lighter: 0 0 6px rgba(0, 0, 0, .5);--el-box-shadow-dark: 0 16px 48px 16px rgba(0, 0, 0, .7), 0 12px 32px rgba(0, 0, 0, .6);--el-mask-color: rgba(0, 0, 0, .8);--el-mask-color-extra-light: rgba(0, 0, 0, .3)}
package/dist/types.d.ts CHANGED
@@ -40,13 +40,24 @@ export interface AuthConfig {
40
40
  loginPath?: string;
41
41
  }
42
42
  export interface NavItem {
43
- label: string;
43
+ /**
44
+ * Display label. Accepts a plain `string`, or a `LocalizedString` map for multi-language sites.
45
+ * Only the menu text is localized — the derived route path stays stable (computed once from the
46
+ * default locale / first entry), so switching language never changes URLs. Set an explicit `path`
47
+ * to control the route directly.
48
+ */
49
+ label: LocalizedString;
44
50
  icon?: string;
45
- page?: (() => Promise<{
46
- default: string;
47
- }>) | (() => Promise<{
48
- default: Component;
49
- }>);
51
+ /**
52
+ * Page content for this item's route. Either:
53
+ * - a **loader function** — `() => import('./Page.vue')` / `() => import('./page.md?raw')`, or a
54
+ * per-locale loader from {@link localizedPage}; or
55
+ * - a **file path string** — e.g. `'./pages/AdminView.vue'` or `'./pages/guide.md'`. The
56
+ * **vue-site CLI** resolves it exactly like `localizedPage('<path>')`: sibling
57
+ * `name.<code>.ext` files are auto-imported per locale and a missing locale falls back to the
58
+ * base file. The string form is CLI-only — in library mode use a loader (or {@link localizedPage}).
59
+ */
60
+ page?: PageLoader | string;
50
61
  children?: NavItem[];
51
62
  path?: string;
52
63
  /**
@@ -82,11 +93,8 @@ export interface NavItem {
82
93
  export interface StandalonePage {
83
94
  /** Route path (used as-is, no label-based derivation), e.g. `/landing`. */
84
95
  path: string;
85
- page: (() => Promise<{
86
- default: string;
87
- }>) | (() => Promise<{
88
- default: Component;
89
- }>);
96
+ /** Page content. Same forms as {@link NavItem.page} (a loader function or a CLI-resolved path string). */
97
+ page: PageLoader | string;
90
98
  /**
91
99
  * Optional visibility predicate, awaited once at app startup. Return `false` (or a
92
100
  * promise resolving to `false`) to skip registering this page's route entirely.
@@ -99,6 +107,86 @@ export interface StandalonePage {
99
107
  */
100
108
  auth?: AuthRule;
101
109
  }
110
+ /** A BCP-47 language tag (e.g. `'en'`, `'zh'`, `'zh-CN'`). */
111
+ export type LocaleCode = string;
112
+ /**
113
+ * Loader for a page's content. Returns either a Markdown string (imported with `?raw`) or a Vue
114
+ * component (its `default` export). The active `locale` is passed in, so a loader can return
115
+ * per-language content (e.g. via {@link localizedPage}); single-language loaders may ignore it,
116
+ * which keeps the plain `() => import(...)` form working.
117
+ */
118
+ export type PageLoader = ((locale: LocaleCode) => Promise<{
119
+ default: string;
120
+ }>) | ((locale: LocaleCode) => Promise<{
121
+ default: Component;
122
+ }>);
123
+ /**
124
+ * A reference to a message id defined centrally in `SiteConfig.i18n.messages` (layered over the
125
+ * framework's built-in strings). Build one with {@link tk} and use it anywhere a `LocalizedString`
126
+ * is accepted (e.g. `title`, `nav[].label`, `footer`) to keep all translations in one message file
127
+ * instead of inlining per-locale text. Resolution uses the active locale with the same fallback as
128
+ * `t()` (exact → primary-subtag → defaultLocale → `en` → the id itself).
129
+ */
130
+ export interface MessageRef {
131
+ /** Message id, e.g. `'nav.home'`. */
132
+ $t: string;
133
+ /** Optional `{name}` interpolation params. */
134
+ params?: Record<string, string | number>;
135
+ }
136
+ /**
137
+ * A string that may be localized. Use a plain `string` for single-language sites, a map of
138
+ * `LocaleCode -> string` for inline per-language values, or a {@link MessageRef} (via {@link tk})
139
+ * to reference a key from a central message file. When the active locale has no matching entry,
140
+ * the framework falls back to the configured default locale, then to the first available entry.
141
+ * A bare `string` is always returned as-is, so existing single-language configs keep working.
142
+ */
143
+ export type LocalizedString = string | Record<LocaleCode, string> | MessageRef;
144
+ /**
145
+ * A dictionary of messages for one locale. Values are either the message string or a nested group,
146
+ * so both flat (`{ 'site.title': '…' }`) and nested (`{ site: { title: '…' } }`) layouts are
147
+ * accepted. Nested groups are flattened to dotted ids (`site.title`) when resolved.
148
+ */
149
+ export interface MessageTree {
150
+ [key: string]: string | MessageTree;
151
+ }
152
+ /** One selectable language in the locale switcher. */
153
+ export interface LocaleOption {
154
+ /** BCP-47 language tag used as the locale id and persisted to localStorage. */
155
+ code: LocaleCode;
156
+ /** Human-readable name shown in the locale switcher (e.g. `English`, `简体中文`). */
157
+ label: string;
158
+ /** Optional Lucide icon name for this language (default: a generic `languages` icon). */
159
+ icon?: string;
160
+ }
161
+ /** Internationalization configuration. Omit to disable multi-language support entirely. */
162
+ export interface I18nConfig {
163
+ /** Supported languages, in display order. The first entry is the implicit fallback. */
164
+ locales: LocaleOption[];
165
+ /**
166
+ * Initial locale used when nothing valid is persisted and browser detection finds no match.
167
+ * Must be one of `locales[].code`. Defaults to `locales[0].code`.
168
+ */
169
+ defaultLocale?: LocaleCode;
170
+ /**
171
+ * Detect the initial locale from `navigator.language(s)` on first visit (before falling back to
172
+ * `defaultLocale`). A previously stored choice always wins over detection.
173
+ * @default true
174
+ */
175
+ detectBrowser?: boolean;
176
+ /**
177
+ * localStorage key for persisting the chosen locale.
178
+ * @default 'vue-site-locale'
179
+ */
180
+ storageKey?: string;
181
+ /**
182
+ * Override or extend the framework's built-in UI strings, keyed by locale then message id.
183
+ * Merged on top of the framework defaults (and any auto-loaded `locales/<code>.json` files) for
184
+ * that locale. Each locale's messages may be **flat** (`{ 'site.title': '…' }`) or **nested**
185
+ * (`{ site: { title: '…' } }`) — nested trees are flattened to dotted ids, so `tk('site.title')`
186
+ * and `t('site.title')` work either way.
187
+ */
188
+ messages?: Record<LocaleCode, MessageTree>;
189
+ }
102
190
  /** CSS custom properties for one theme (`--color-bg`, etc.). */
103
191
  export type ThemePaletteVars = Record<string, string>;
104
192
  /** Extra theme: copies a built-in palette (`basedOn`), then merges `palette`. */
@@ -185,11 +273,15 @@ export interface SiteEnvConfig {
185
273
  export interface SiteExternalLink {
186
274
  icon: string;
187
275
  link: string;
188
- /** Tooltip text on hover; if omitted, the hostname is used when possible */
189
- title?: string;
276
+ /**
277
+ * Tooltip text on hover; if omitted, the hostname is used when possible. Accepts a
278
+ * `LocalizedString` for multi-language sites.
279
+ */
280
+ title?: LocalizedString;
190
281
  }
191
282
  export interface SiteConfig {
192
- title: string;
283
+ /** Site title (browser tab + header). Accepts a `LocalizedString` for multi-language sites. */
284
+ title: LocalizedString;
193
285
  logo?: string;
194
286
  nav: NavItem[];
195
287
  /**
@@ -219,7 +311,14 @@ export interface SiteConfig {
219
311
  * theme is persisted to or read from localStorage.
220
312
  */
221
313
  theme?: ThemeConfig | false;
222
- footer?: string;
314
+ /**
315
+ * Internationalization configuration. When set, the framework enables a locale switcher,
316
+ * resolves `LocalizedString` config fields against the active locale, and exposes the current
317
+ * locale via `useLocale()`. Omit to keep the site single-language.
318
+ */
319
+ i18n?: I18nConfig;
320
+ /** Footer text. Accepts a `LocalizedString` for multi-language sites. */
321
+ footer?: LocalizedString;
223
322
  readme?: string;
224
323
  /** External links shown as icons next to the theme control */
225
324
  links?: SiteExternalLink[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bndynet/vue-site",
3
- "version": "1.0.4",
3
+ "version": "1.2.0",
4
4
  "type": "module",
5
5
  "description": "A configurable Vue 3 site framework with sidebar navigation, markdown rendering, and theme switching.",
6
6
  "repository": {