sdocs 0.0.59 → 0.0.61

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.
@@ -0,0 +1,159 @@
1
+ <script lang="ts">
2
+ import type { SectionTree } from '../tree-builder.js';
3
+ import { routeHref } from '../router.svelte.js';
4
+ import { Icon } from '../../ui/Icon/index.js';
5
+
6
+ type ThemeMode = 'light' | 'dark';
7
+
8
+ interface Props {
9
+ title: string;
10
+ logo: string | false;
11
+ sections: SectionTree[];
12
+ activeSlug?: string;
13
+ cssNames?: string[];
14
+ activeStylesheet?: string;
15
+ theme?: ThemeMode;
16
+ onToggleFullscreen?: () => void;
17
+ onStylesheetChange?: (name: string) => void;
18
+ onThemeChange?: (theme: ThemeMode) => void;
19
+ }
20
+
21
+ let {
22
+ title,
23
+ logo,
24
+ sections,
25
+ activeSlug,
26
+ cssNames = [],
27
+ activeStylesheet,
28
+ theme = 'light',
29
+ onToggleFullscreen,
30
+ onStylesheetChange,
31
+ onThemeChange,
32
+ }: Props = $props();
33
+
34
+ const themeIcons: Record<ThemeMode, string> = { light: '☀', dark: '☽' };
35
+ const themeLabels: Record<ThemeMode, string> = { light: 'Light', dark: 'Dark' };
36
+ </script>
37
+
38
+ <header class="sdocs-topbar">
39
+ <a href={routeHref([])} class="sdocs-topbar-brand">
40
+ {#if logo === 'sdocs'}
41
+ <Icon name="sdocs" --w="22px" --h="22px" --fill="#FC1D29" />
42
+ {:else if logo}
43
+ <img class="sdocs-topbar-logo" src={logo} alt="" />
44
+ {/if}
45
+ {title}
46
+ </a>
47
+ <nav class="sdocs-topbar-sections">
48
+ {#each sections as section (section.slug)}
49
+ <a
50
+ class="sdocs-topbar-tab"
51
+ class:is-active={section.slug === activeSlug}
52
+ aria-current={section.slug === activeSlug ? 'page' : undefined}
53
+ href={routeHref(section.firstRoute ?? [section.slug])}
54
+ >
55
+ {section.name}
56
+ </a>
57
+ {/each}
58
+ </nav>
59
+ <div class="sdocs-topbar-actions">
60
+ {#if cssNames.length > 1}
61
+ <select
62
+ class="sdocs-css-picker"
63
+ value={activeStylesheet}
64
+ onchange={(e) => onStylesheetChange?.(e.currentTarget.value)}
65
+ >
66
+ {#each cssNames as name (name)}
67
+ <option value={name}>{name}</option>
68
+ {/each}
69
+ </select>
70
+ {/if}
71
+ <button class="sdocs-topbar-btn" onclick={() => onThemeChange?.(theme === 'light' ? 'dark' : 'light')} title="{themeLabels[theme]} theme">
72
+ {themeIcons[theme]}
73
+ </button>
74
+ <button class="sdocs-topbar-btn" onclick={() => onToggleFullscreen?.()} title="Fullscreen">
75
+ &#x26F6;
76
+ </button>
77
+ </div>
78
+ </header>
79
+
80
+ <style>
81
+ .sdocs-topbar {
82
+ display: flex;
83
+ align-items: center;
84
+ gap: 24px;
85
+ padding: 0 16px;
86
+ height: 48px;
87
+ flex-shrink: 0;
88
+ border-bottom: 1px solid var(--color-base-200);
89
+ background: var(--color-base-0);
90
+ font-family: var(--sans);
91
+ }
92
+ .sdocs-topbar-brand {
93
+ display: flex;
94
+ align-items: center;
95
+ gap: 6px;
96
+ font-weight: 700;
97
+ font-size: 18px;
98
+ color: var(--color-base-900);
99
+ text-decoration: none;
100
+ }
101
+ .sdocs-topbar-logo {
102
+ width: 22px;
103
+ height: 22px;
104
+ object-fit: contain;
105
+ }
106
+ .sdocs-topbar-sections {
107
+ display: flex;
108
+ align-items: stretch;
109
+ gap: 4px;
110
+ height: 100%;
111
+ flex: 1;
112
+ min-width: 0;
113
+ overflow-x: auto;
114
+ }
115
+ .sdocs-topbar-tab {
116
+ display: flex;
117
+ align-items: center;
118
+ padding: 0 12px;
119
+ font-size: 13px;
120
+ font-weight: 500;
121
+ color: var(--color-base-500);
122
+ text-decoration: none;
123
+ border-bottom: 2px solid transparent;
124
+ white-space: nowrap;
125
+ }
126
+ .sdocs-topbar-tab:hover {
127
+ color: var(--color-base-900);
128
+ }
129
+ .sdocs-topbar-tab.is-active {
130
+ color: var(--color-action-500);
131
+ border-bottom-color: var(--color-action-500);
132
+ }
133
+ .sdocs-topbar-actions {
134
+ display: flex;
135
+ align-items: center;
136
+ gap: 6px;
137
+ }
138
+ .sdocs-css-picker {
139
+ font-size: 12px;
140
+ padding: 2px 4px;
141
+ border: 1px solid var(--color-base-200);
142
+ border-radius: 4px;
143
+ background: var(--color-base-0);
144
+ color: var(--color-base-600);
145
+ }
146
+ .sdocs-topbar-btn {
147
+ padding: 2px 6px;
148
+ border: 1px solid var(--color-base-200);
149
+ border-radius: 4px;
150
+ background: var(--color-base-0);
151
+ color: var(--color-base-600);
152
+ cursor: pointer;
153
+ font-size: 14px;
154
+ line-height: 1;
155
+ }
156
+ .sdocs-topbar-btn:hover {
157
+ background: var(--color-base-100);
158
+ }
159
+ </style>
@@ -0,0 +1,14 @@
1
+ import { SvelteComponentTyped } from "svelte";
2
+ declare const __propDef: {
3
+ props: Record<string, never>;
4
+ events: {
5
+ [evt: string]: CustomEvent<any>;
6
+ };
7
+ slots: {};
8
+ };
9
+ export type TopBarProps = typeof __propDef.props;
10
+ export type TopBarEvents = typeof __propDef.events;
11
+ export type TopBarSlots = typeof __propDef.slots;
12
+ export default class TopBar extends SvelteComponentTyped<TopBarProps, TopBarEvents, TopBarSlots> {
13
+ }
14
+ export {};
@@ -70,18 +70,35 @@ export const configSchema = {
70
70
  doc: 'Folder of static assets served at the site root — images for pages, files for previews. Standalone CLI flows; embedded apps use the host\'s public directory.',
71
71
  insert: ": './${0:static}'",
72
72
  },
73
- logo: {
73
+ title: {
74
74
  detail: 'string',
75
- doc: 'Sidebar logo text. Default: `sdocs`.',
75
+ doc: 'Header title text. Default: `sdocs`.',
76
76
  insert: ": '${0:sdocs}'",
77
77
  },
78
- icon: {
78
+ logo: {
79
79
  detail: 'string | false',
80
- doc: "Sidebar logo icon: `'sdocs'` for the built-in mascot, an image URL, or `false` to hide it. Default: `'sdocs'`.",
80
+ doc: "Header logo: `'sdocs'` for the built-in mascot, an image URL, or `false` to hide it. Default: `'sdocs'`.",
81
81
  insert: ": '${0:sdocs}'",
82
82
  values: ['sdocs'],
83
83
  quoted: true,
84
84
  },
85
+ sections: {
86
+ detail: 'string[]',
87
+ doc: 'Top-bar section order. Sections come from `@Section/…` title prefixes; unlisted sections follow alphabetically.',
88
+ insert: ': [$0]',
89
+ },
90
+ defaultSection: {
91
+ detail: 'string',
92
+ doc: 'Section for docs without an `@Section/` title prefix. Default: `Docs`.',
93
+ insert: ": '${0:Docs}'",
94
+ },
95
+ routing: {
96
+ detail: "'history' | 'hash'",
97
+ doc: "URL style: `'history'` for real paths (standalone CLI default), `'hash'` for `#/` URLs (embedded default).",
98
+ insert: ": '${0:history}'",
99
+ values: ['history', 'hash'],
100
+ quoted: true,
101
+ },
85
102
  sidebar: {
86
103
  detail: 'object',
87
104
  doc: 'Sidebar ordering and default-expanded folders.',
@@ -116,8 +116,11 @@ mount(Explorer, {
116
116
  docs,
117
117
  cssNames,
118
118
  pageModules,
119
+ title: ${JSON.stringify(config.title)},
119
120
  logo: ${JSON.stringify(config.logo)},
120
- icon: ${JSON.stringify(config.icon)},
121
+ sections: ${JSON.stringify(config.sections)},
122
+ defaultSection: ${JSON.stringify(config.defaultSection)},
123
+ routing: ${JSON.stringify(config.routing ?? 'history')},
121
124
  sidebarConfig: ${JSON.stringify(config.sidebar)},
122
125
  }
123
126
  });`;
@@ -192,7 +195,7 @@ export async function generateDevFiles(config, cwd) {
192
195
  // Copy Explorer components into the staging dir so they're compiled outside node_modules
193
196
  await copyExplorerApp(sdocsDir);
194
197
  await linkStagedDeps(sdocsDir, cwd);
195
- await writeFile(resolve(sdocsDir, 'index.html'), generateIndexHtml(config.logo));
198
+ await writeFile(resolve(sdocsDir, 'index.html'), generateIndexHtml(config.title));
196
199
  await writeFile(resolve(sdocsDir, 'entry.js'), generateEntryJs(config));
197
200
  return sdocsDir;
198
201
  }
@@ -205,7 +208,7 @@ export async function generateBuildFiles(config, cwd) {
205
208
  // Copy Explorer components into the staging dir
206
209
  await copyExplorerApp(sdocsDir);
207
210
  await linkStagedDeps(sdocsDir, cwd);
208
- await writeFile(resolve(sdocsDir, 'index.html'), generateIndexHtml(config.logo));
211
+ await writeFile(resolve(sdocsDir, 'index.html'), generateIndexHtml(config.title));
209
212
  await writeFile(resolve(sdocsDir, 'entry.js'), generateEntryJs(config));
210
213
  const inputs = {
211
214
  main: resolve(sdocsDir, 'index.html'),
@@ -8,8 +8,11 @@ const DEFAULTS = {
8
8
  open: false,
9
9
  css: null,
10
10
  static: null,
11
+ title: 'sdocs',
11
12
  logo: 'sdocs',
12
- icon: 'sdocs',
13
+ sections: [],
14
+ defaultSection: 'Docs',
15
+ routing: null,
13
16
  sidebar: {
14
17
  order: {},
15
18
  open: [],
@@ -87,14 +90,26 @@ export function resolveConfig(userConfig) {
87
90
  ? userConfig.include
88
91
  : [userConfig.include]
89
92
  : DEFAULTS.include;
93
+ // Pre-0.0.61 configs: `logo` was the header text and `icon` the image.
94
+ // An `icon` key marks the old shape — map it onto the new keys and warn.
95
+ const legacy = userConfig;
96
+ const isLegacy = 'icon' in legacy;
97
+ if (isLegacy) {
98
+ console.warn("[sdocs] config `icon` was renamed: use `logo` for the image and `title` for the header text.");
99
+ }
100
+ const title = userConfig.title ?? (isLegacy && typeof legacy.logo === 'string' ? legacy.logo : undefined);
101
+ const logo = isLegacy ? legacy.icon : userConfig.logo;
90
102
  return {
91
103
  include,
92
104
  port: userConfig.port ?? DEFAULTS.port,
93
105
  open: userConfig.open ?? DEFAULTS.open,
94
106
  css: userConfig.css ?? DEFAULTS.css,
95
107
  static: userConfig.static ?? DEFAULTS.static,
96
- logo: userConfig.logo ?? DEFAULTS.logo,
97
- icon: userConfig.icon ?? DEFAULTS.icon,
108
+ title: title ?? DEFAULTS.title,
109
+ logo: logo ?? DEFAULTS.logo,
110
+ sections: userConfig.sections ?? DEFAULTS.sections,
111
+ defaultSection: userConfig.defaultSection ?? DEFAULTS.defaultSection,
112
+ routing: userConfig.routing ?? DEFAULTS.routing,
98
113
  sidebar: {
99
114
  order: userConfig.sidebar?.order ?? DEFAULTS.sidebar.order,
100
115
  open: userConfig.sidebar?.open ?? DEFAULTS.sidebar.open,
package/dist/types.d.ts CHANGED
@@ -12,10 +12,21 @@ export interface SdocsConfig {
12
12
  * files for previews. Standalone CLI flows (`sdocs dev`/`build`); when
13
13
  * embedding the Vite plugin, use the host app's own public directory. */
14
14
  static?: string;
15
- /** Sidebar logo text. Default: 'sdocs' */
16
- logo?: string;
17
- /** Sidebar logo icon: 'sdocs' for the built-in mascot, an image URL, or false to hide. Default: 'sdocs' */
18
- icon?: string | false;
15
+ /** Header title text. Default: 'sdocs' */
16
+ title?: string;
17
+ /** Header logo: 'sdocs' for the built-in mascot, an image URL, or false to hide. Default: 'sdocs' */
18
+ logo?: string | false;
19
+ /** Top-bar section order. Sections come from `@Section/...` title prefixes;
20
+ * unlisted sections follow alphabetically. Default: default section first,
21
+ * rest alphabetical. */
22
+ sections?: string[];
23
+ /** Name of the section that docs without an `@Section/` prefix belong to.
24
+ * Default: 'Docs' */
25
+ defaultSection?: string;
26
+ /** URL style: 'history' for real paths (default in the standalone CLI,
27
+ * needs the server to fall back to the shell), 'hash' for #/ URLs
28
+ * (default when embedding — works under any host routing). */
29
+ routing?: 'history' | 'hash';
19
30
  /** Sidebar configuration */
20
31
  sidebar?: {
21
32
  /** Per-folder sort overrides. Keys are folder paths, 'root' for top level. '*' = unlisted items. */
@@ -74,8 +85,12 @@ export interface ResolvedSdocsConfig {
74
85
  open: boolean;
75
86
  css: string | Record<string, string> | null;
76
87
  static: string | null;
77
- logo: string;
78
- icon: string | false;
88
+ title: string;
89
+ logo: string | false;
90
+ sections: string[];
91
+ defaultSection: string;
92
+ /** null = per-mode default (standalone: history, embedded: hash) */
93
+ routing: 'history' | 'hash' | null;
79
94
  sidebar: {
80
95
  order: Record<string, string[]>;
81
96
  open: string[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sdocs",
3
- "version": "0.0.59",
3
+ "version": "0.0.61",
4
4
  "description": "A lightweight documentation tool for Svelte 5 components",
5
5
  "type": "module",
6
6
  "license": "MIT",