sdocs 0.0.56 → 0.0.58

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/types.d.ts CHANGED
@@ -8,6 +8,10 @@ export interface SdocsConfig {
8
8
  open?: boolean;
9
9
  /** CSS loaded in preview iframes. Single path or named stylesheets. */
10
10
  css?: string | Record<string, string>;
11
+ /** Folder of static assets served at the site root — images for pages,
12
+ * files for previews. Standalone CLI flows (`sdocs dev`/`build`); when
13
+ * embedding the Vite plugin, use the host app's own public directory. */
14
+ static?: string;
11
15
  /** Sidebar logo text. Default: 'sdocs' */
12
16
  logo?: string;
13
17
  /** Sidebar logo icon: 'sdocs' for the built-in mascot, an image URL, or false to hide. Default: 'sdocs' */
@@ -25,6 +29,9 @@ export interface SdocsConfig {
25
29
  page?: ContentSizing & {
26
30
  /** Show the table of contents. Default: true */
27
31
  toc?: boolean;
32
+ /** Horizontal alignment of the content column (with its toc) inside
33
+ * the view: 'left'|'center'|'right'. Default: 'left' */
34
+ contentX?: string;
28
35
  };
29
36
  /** [DOCS] pages: maxWidth is the content column (default '1200px');
30
37
  * padding/direction/gap are the default preview/example stage layout
@@ -66,6 +73,7 @@ export interface ResolvedSdocsConfig {
66
73
  port: number;
67
74
  open: boolean;
68
75
  css: string | Record<string, string> | null;
76
+ static: string | null;
69
77
  logo: string;
70
78
  icon: string | false;
71
79
  sidebar: {
@@ -75,6 +83,7 @@ export interface ResolvedSdocsConfig {
75
83
  content: {
76
84
  page: Required<ContentSizing> & {
77
85
  toc: boolean;
86
+ contentX: string;
78
87
  };
79
88
  docs: Required<ContentSizing> & {
80
89
  direction: string;
@@ -176,7 +185,7 @@ export interface DocEntry {
176
185
  meta: SdocMeta;
177
186
  /** Live previews (component kind; empty otherwise) */
178
187
  previews: PreviewEntry[];
179
- /** Frozen examples (component kind; empty otherwise) */
188
+ /** Frozen examples (component and page kinds; empty otherwise) */
180
189
  examples: ExtractedSnippet[];
181
190
  /** The rendered body (page/layout kind; null otherwise) */
182
191
  content: ExtractedSnippet | null;
@@ -184,6 +193,15 @@ export interface DocEntry {
184
193
  toc?: TocHeading[];
185
194
  /** Resolved content-column max width (component and page kinds) */
186
195
  maxWidth?: string;
196
+ /** Resolved page padding (pages only) */
197
+ padding?: string;
198
+ /** Resolved horizontal alignment of the content column (pages only) */
199
+ contentX?: string;
187
200
  /** Resolved table-of-contents visibility (pages only) */
188
201
  showToc?: boolean;
202
+ /** The body's `#` heading, shown as the page title instead of the entity
203
+ * title (pages only) */
204
+ bodyTitle?: string;
205
+ /** Key into the virtual module's pageModules map (pages only) */
206
+ contentKey?: string;
189
207
  }
package/dist/vite.js CHANGED
@@ -6,18 +6,20 @@ import { parseSdoc, offsetToPosition } from './language/index.js';
6
6
  import { planEntitySnippets, extractImports, resolveComponentImport, } from './server/doc-model.js';
7
7
  import { renderPageMarkdown } from './server/page-markdown.js';
8
8
  import { highlight, disposeHighlighter } from './server/highlighter.js';
9
- import { parseIframeId, parseMountId, parsePreviewUrl, resolveScriptImports, generateIframeComponent, generateMountScript, generatePreviewHtml, generateStaticPreviewHtml, iframeVirtualId, mountVirtualId, previewUrl, buildPreviewUrl, encodeEntityId, entityKey, setDocPathRoot, } from './server/snippet-compiler.js';
9
+ import { parseIframeId, parseMountId, parsePageId, parsePreviewUrl, resolveScriptImports, generateIframeComponent, generateMountScript, generatePageComponent, generatePreviewHtml, generateStaticPreviewHtml, iframeVirtualId, mountVirtualId, pageVirtualId, previewUrl, buildPreviewUrl, encodeEntityId, entityKey, setDocPathRoot, } from './server/snippet-compiler.js';
10
10
  const VIRTUAL_MODULE_ID = 'virtual:sdocs';
11
11
  const RESOLVED_VIRTUAL_ID = '\0virtual:sdocs';
12
12
  const IFRAME_PREFIX = '/@sdocs/iframe/';
13
13
  const PREVIEW_PREFIX = '/@sdocs/preview/';
14
14
  const MOUNT_PREFIX = '/@sdocs/mount/';
15
- /** Every renderable snippet of an entry, in order. */
15
+ const PAGE_PREFIX = '/@sdocs/page/';
16
+ /** Every iframe-served snippet of an entry, in order. A PAGE's content
17
+ * renders natively in the Explorer (via pageModules), never as an iframe. */
16
18
  function allSnippets(entry) {
17
19
  return [
18
20
  ...entry.previews.map((p) => p.snippet),
19
21
  ...entry.examples,
20
- ...(entry.content ? [entry.content] : []),
22
+ ...(entry.content && entry.kind !== 'page' ? [entry.content] : []),
21
23
  ];
22
24
  }
23
25
  export function sdocsPlugin(userConfig) {
@@ -206,6 +208,8 @@ export function sdocsPlugin(userConfig) {
206
208
  return '\0' + id;
207
209
  if (id.startsWith(MOUNT_PREFIX))
208
210
  return '\0' + id;
211
+ if (id.startsWith(PAGE_PREFIX))
212
+ return '\0' + id;
209
213
  },
210
214
  load(id) {
211
215
  if (id === RESOLVED_VIRTUAL_ID) {
@@ -230,6 +234,17 @@ export function sdocsPlugin(userConfig) {
230
234
  const stateNames = (preview?.componentData?.state ?? []).map((s) => s.name);
231
235
  return generateIframeComponent(scriptPrelude, snippet.body, stateNames, preview?.componentName ?? undefined, snippet.stage);
232
236
  }
237
+ // Virtual native content component for a PAGE entity
238
+ if (id.startsWith('\0' + PAGE_PREFIX)) {
239
+ const parsed = parsePageId(id.slice(1));
240
+ if (!parsed)
241
+ return null;
242
+ const entry = docEntries.get(entityKey(parsed.docFilePath, parsed.entitySlug));
243
+ if (!entry?.content)
244
+ return null;
245
+ const scriptPrelude = docScriptCache.get(parsed.docFilePath) ?? '';
246
+ return generatePageComponent(scriptPrelude, entry.content.body);
247
+ }
233
248
  // Virtual mount script for an emitted preview page
234
249
  if (id.startsWith('\0' + MOUNT_PREFIX)) {
235
250
  const parsed = parseMountId(id.slice(1));
@@ -363,11 +378,33 @@ export function sdocsPlugin(userConfig) {
363
378
  }
364
379
  }
365
380
  else if (entity.kind === 'PAGE') {
381
+ // The page body renders natively in the Explorer; only its
382
+ // [example] blocks are staged in iframes (with the project css),
383
+ // cascading block attributes over the content.docs stage defaults.
366
384
  const rendered = await renderPageMarkdown(entity.body);
367
385
  snippets[0].body = rendered.html;
368
- snippets[0].stage = stageOf();
369
386
  entry.content = snippets[0];
370
387
  entry.toc = rendered.toc;
388
+ entry.padding = entity.sizing.padding ?? config.content.page.padding;
389
+ entry.contentX = entity.sizing.contentX ?? config.content.page.contentX;
390
+ entry.bodyTitle = rendered.bodyTitle;
391
+ entry.contentKey = encodeEntityId(filePath, entity.slug);
392
+ entry.examples = snippets.filter((s) => s.role === 'example');
393
+ entity.examples.forEach((example, i) => {
394
+ if (entry.examples[i]) {
395
+ entry.examples[i].stage = {
396
+ maxWidth: example.sizing.maxWidth ?? '100%',
397
+ padding: example.sizing.padding ?? config.content.docs.padding,
398
+ direction: example.sizing.direction ?? config.content.docs.direction,
399
+ gap: example.sizing.gap ?? config.content.docs.gap,
400
+ contentX: example.sizing.contentX ?? config.content.docs.contentX,
401
+ contentY: example.sizing.contentY ?? config.content.docs.contentY,
402
+ };
403
+ }
404
+ });
405
+ for (const example of entry.examples) {
406
+ example.highlightedHtml = await highlight(example.body);
407
+ }
371
408
  }
372
409
  else {
373
410
  snippets[0].stage = stageOf();
@@ -396,16 +433,28 @@ export function sdocsPlugin(userConfig) {
396
433
  meta: e.meta,
397
434
  previews: e.previews.map((p) => ({ ...p, snippet: withUrl(e, p.snippet) })),
398
435
  examples: e.examples.map((s) => withUrl(e, s)),
399
- content: e.content ? withUrl(e, e.content) : null,
436
+ // Page content renders natively (no iframe URL); see pageModules below.
437
+ content: e.content ? (e.kind === 'page' ? e.content : withUrl(e, e.content)) : null,
400
438
  toc: e.toc,
401
439
  maxWidth: e.maxWidth,
440
+ padding: e.padding,
441
+ contentX: e.contentX,
402
442
  showToc: e.showToc,
443
+ bodyTitle: e.bodyTitle,
444
+ contentKey: e.contentKey,
403
445
  }));
404
446
  // Extract named CSS stylesheet names (empty array if single string or null)
405
447
  const cssNames = config.css && typeof config.css === 'object'
406
448
  ? Object.keys(config.css)
407
449
  : [];
408
- return `export const docs = ${JSON.stringify(data)};\nexport const cssNames = ${JSON.stringify(cssNames)};\nexport default docs;`;
450
+ // Native page components, as static dynamic imports so every mode (dev,
451
+ // embedded build, CLI build) code-splits them through the module graph —
452
+ // shared Svelte runtime, component CSS handled by Vite's import helper.
453
+ const pageImports = Array.from(docEntries.values())
454
+ .filter((e) => e.kind === 'page')
455
+ .map((e) => `\t${JSON.stringify(encodeEntityId(e.filePath, e.entitySlug))}: () => import(${JSON.stringify(pageVirtualId(e.filePath, e.entitySlug))}),`)
456
+ .join('\n');
457
+ return `export const docs = ${JSON.stringify(data)};\nexport const cssNames = ${JSON.stringify(cssNames)};\nexport const pageModules = {\n${pageImports}\n};\nexport default docs;`;
409
458
  }
410
459
  // ─── HMR helpers ───
411
460
  function invalidateVirtualModule(docFilePath) {
@@ -415,7 +464,7 @@ export function sdocsPlugin(userConfig) {
415
464
  if (mod) {
416
465
  server.moduleGraph.invalidateModule(mod);
417
466
  }
418
- // Also invalidate iframe virtual modules for the changed doc file
467
+ // Also invalidate iframe and page virtual modules for the changed doc file
419
468
  if (docFilePath) {
420
469
  for (const entry of entriesOf(docFilePath)) {
421
470
  for (const snippet of allSnippets(entry)) {
@@ -425,6 +474,12 @@ export function sdocsPlugin(userConfig) {
425
474
  server.moduleGraph.invalidateModule(iframeMod);
426
475
  }
427
476
  }
477
+ if (entry.kind === 'page') {
478
+ const pageMod = server.moduleGraph.getModuleById('\0' + pageVirtualId(docFilePath, entry.entitySlug));
479
+ if (pageMod) {
480
+ server.moduleGraph.invalidateModule(pageMod);
481
+ }
482
+ }
428
483
  }
429
484
  }
430
485
  server.ws.send({ type: 'full-reload' });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sdocs",
3
- "version": "0.0.56",
3
+ "version": "0.0.58",
4
4
  "description": "A lightweight documentation tool for Svelte 5 components",
5
5
  "type": "module",
6
6
  "license": "MIT",