@entropicwarrior/sdoc 0.2.17 → 0.2.18

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/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@entropicwarrior/sdoc",
3
3
  "displayName": "SDOC - Docs for Human/Agent Teams",
4
4
  "description": "A plain-text documentation format with explicit brace scoping — deterministic parsing, AI-agent efficiency, and 10-50x token savings vs Markdown.",
5
- "version": "0.2.17",
5
+ "version": "0.2.18",
6
6
  "publisher": "entropicwarrior-msenfin",
7
7
  "license": "MIT",
8
8
  "repository": {
package/src/sdoc.js CHANGED
@@ -3287,7 +3287,10 @@ function renderHtmlDocumentFromParsed(parsed, title, options = {}) {
3287
3287
  const footerHtml = meta.footerNodes ? renderFragment(meta.footerNodes, 2)
3288
3288
  : meta.footerText ? renderTextParagraphs(meta.footerText)
3289
3289
  : renderTextParagraphs(config.footer);
3290
- const footerContent = [footerHtml, companyHtml].filter(Boolean).join("\n");
3290
+ // A specific footer (footer: meta, or config.footer) overrides the company
3291
+ // auto-footer so the two do not stack into a doubled footer. The company name
3292
+ // is used only as the fallback footer when no footer text is provided.
3293
+ const footerContent = footerHtml || companyHtml;
3291
3294
 
3292
3295
  const cssBase = options.cssOverride ?? DEFAULT_STYLE;
3293
3296
  const cssAppend = options.cssAppend ? `\n${options.cssAppend}\n${PRINT_STYLE}` : `\n${PRINT_STYLE}`;
@@ -322,8 +322,15 @@ function renderSlides(nodes, options = {}) {
322
322
  slideScopes = nodes;
323
323
  }
324
324
 
325
- // Filter to scope nodes only (skip stray paragraphs and :comment scopes)
326
- const slides = slideScopes.filter((n) => n.type === "scope" && n.scopeType !== "comment");
325
+ // Filter to scope nodes only (skip stray paragraphs, :comment scopes, and the
326
+ // reserved @meta / @about metadata scopes — these are document metadata, not slides).
327
+ const RESERVED_SCOPE_IDS = new Set(["meta", "about"]);
328
+ const slides = slideScopes.filter(
329
+ (n) =>
330
+ n.type === "scope" &&
331
+ n.scopeType !== "comment" &&
332
+ !(n.id && RESERVED_SCOPE_IDS.has(n.id.toLowerCase()))
333
+ );
327
334
 
328
335
  // Build per-slide footer:
329
336
  // < CONFIDENTIAL ---gap--- Company N/Total >
@@ -387,7 +394,37 @@ function renderSlides(nodes, options = {}) {
387
394
 
388
395
  // Structural styles — always injected regardless of theme.
389
396
  const structuralCss = `
390
- .slide { position: relative; }
397
+ /* --- Fixed design box + fit-to-window scaling ---------------------------
398
+ Slides are laid out at a fixed design size (1280x720 CSS px, which is
399
+ exactly the 13.333in x 7.5in print page at 96dpi) and then scaled as a
400
+ whole to fill the window. This is the standard deck technique: the
401
+ author's layout is preserved verbatim at every window size, and screen
402
+ and PDF are the same geometry by construction.
403
+
404
+ --sdoc-slide-scale is written by the theme runtime (fitSlidesToWindow in
405
+ themes/default/theme.js) on load and on resize. If JS never runs the
406
+ scale stays 1 and the deck renders at its natural design size, which is
407
+ the pre-scaling behaviour rather than a broken one.
408
+
409
+ Themes must NOT set width/height/max-width/margin on .slide — those come
410
+ from the design-box variables below. A theme that wants a different
411
+ aspect ratio should override --sdoc-slide-w / --sdoc-slide-h on :root
412
+ (and the @page size in the print block, if PDF output matters). */
413
+ :root {
414
+ --sdoc-slide-w: 1280px;
415
+ --sdoc-slide-h: 720px;
416
+ --sdoc-slide-scale: 1;
417
+ }
418
+ .slide {
419
+ position: absolute;
420
+ top: 50%;
421
+ left: 50%;
422
+ width: var(--sdoc-slide-w);
423
+ height: var(--sdoc-slide-h);
424
+ transform: translate(-50%, -50%) scale(var(--sdoc-slide-scale));
425
+ transform-origin: center center;
426
+ overflow: hidden;
427
+ }
391
428
  .slide-footer {
392
429
  position: absolute; bottom: 20px; left: 32px; right: 32px;
393
430
  display: flex; align-items: baseline;
@@ -433,7 +470,14 @@ function renderSlides(nodes, options = {}) {
433
470
  opacity: 1 !important;
434
471
  pointer-events: auto !important;
435
472
  page-break-after: always; break-after: page;
436
- width: 100vw; height: 100vh; max-width: none;
473
+ /* The design box IS the page (1280x720px == 13.333in x 7.5in @96dpi),
474
+ so no fit-to-window scaling applies here — each slide flows as one
475
+ page at its natural size. Overflowing content is still shrunk by
476
+ the inner .slide-content-scale wrapper (see fitSlidesForPrint). */
477
+ top: auto !important; left: auto !important;
478
+ transform: none !important;
479
+ margin: 0 !important;
480
+ width: var(--sdoc-slide-w); height: var(--sdoc-slide-h); max-width: none;
437
481
  overflow: hidden;
438
482
  page-break-inside: avoid; break-inside: avoid;
439
483
  }