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/CHANGELOG.md +58 -0
- package/dist/commands/build.js +2 -0
- package/dist/commands/dev.js +2 -0
- package/dist/explorer/Explorer.svelte +4 -1
- package/dist/explorer/views/PageView.svelte +285 -41
- package/dist/grammar/sdoc.tmLanguage.json +45 -0
- package/dist/language/config-schema.js +13 -1
- package/dist/language/page-islands.d.ts +3 -1
- package/dist/language/page-islands.js +15 -1
- package/dist/language/parser.d.ts +4 -0
- package/dist/language/parser.js +69 -20
- package/dist/language/projection.js +53 -0
- package/dist/language/scanner.d.ts +5 -3
- package/dist/language/scanner.js +90 -2
- package/dist/server/app-gen.js +5 -3
- package/dist/server/config.js +5 -1
- package/dist/server/doc-model.d.ts +8 -2
- package/dist/server/doc-model.js +22 -9
- package/dist/server/page-markdown.d.ts +3 -0
- package/dist/server/page-markdown.js +60 -3
- package/dist/server/snippet-compiler.d.ts +14 -0
- package/dist/server/snippet-compiler.js +30 -0
- package/dist/types.d.ts +19 -1
- package/dist/vite.js +62 -7
- package/package.json +1 -1
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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' });
|