pict-docuserve 1.3.0 → 1.3.2

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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pict-docuserve",
3
- "version": "1.3.0",
3
+ "version": "1.3.2",
4
4
  "description": "Pict Documentation Server - A single-page documentation viewer built on Pict",
5
5
  "main": "source/Pict-Application-Docuserve.js",
6
6
  "bin": {
@@ -35,13 +35,14 @@
35
35
  "pict-provider": "^1.0.13",
36
36
  "pict-section-code": "^1.0.11",
37
37
  "pict-section-content": "^1.0.2",
38
+ "pict-section-histogram": "^1.0.1",
38
39
  "pict-section-modal": "^1.1.1",
39
40
  "pict-section-theme": "^1.0.2",
40
41
  "pict-service-commandlineutility": "^1.0.19",
41
42
  "pict-view": "^1.0.68"
42
43
  },
43
44
  "devDependencies": {
44
- "pict-docuserve": "^1.2.0",
45
+ "pict-docuserve": "^1.3.1",
45
46
  "quackage": "^1.2.3"
46
47
  },
47
48
  "copyFilesSettings": {
@@ -117,7 +117,7 @@ class DocuserveApplication extends libPictApplication
117
117
  {
118
118
  this.pict.addProvider('Theme-Section',
119
119
  {
120
- ApplyDefault: 'retold-default',
120
+ ApplyDefault: 'pict-default',
121
121
  DefaultMode: 'system',
122
122
  DefaultScale: 1.0,
123
123
  Brand: pBrand,
@@ -447,6 +447,14 @@ class DocuserveApplication extends libPictApplication
447
447
  this.pict.AppData.Docuserve.Playground = {};
448
448
  }
449
449
  this.pict.AppData.Docuserve.Playground.Config = pConfig || null;
450
+ // Config controls DOM-sandbox pane visibility; let the
451
+ // playground view re-evaluate the moment it lands. No-op
452
+ // if the view hasn't been mounted yet.
453
+ let tmpPlaygroundView = this.pict.views['Docuserve-Fable-Playground'];
454
+ if (tmpPlaygroundView && typeof tmpPlaygroundView._applySandboxMode === 'function')
455
+ {
456
+ tmpPlaygroundView._applySandboxMode();
457
+ }
450
458
  });
451
459
  }
452
460
  else
@@ -455,6 +463,11 @@ class DocuserveApplication extends libPictApplication
455
463
  {
456
464
  this.pict.AppData.Docuserve.Playground.Config = null;
457
465
  }
466
+ let tmpPlaygroundView = this.pict.views['Docuserve-Fable-Playground'];
467
+ if (tmpPlaygroundView && typeof tmpPlaygroundView._applySandboxMode === 'function')
468
+ {
469
+ tmpPlaygroundView._applySandboxMode();
470
+ }
458
471
  }
459
472
  }
460
473
 
@@ -1,6 +1,8 @@
1
1
  const libPictView = require('pict-view');
2
2
  const libPictSectionCode = require('pict-section-code');
3
3
  const libFableServiceProviderBase = require('fable-serviceproviderbase');
4
+ const libPict = require('pict');
5
+ const libPictSectionHistogram = require('pict-section-histogram');
4
6
 
5
7
  // Note: we deliberately do NOT `require('fable')` here. Fable is already
6
8
  // bundled into the host page's pict.min.js (via pict's own dep tree);
@@ -146,6 +148,12 @@ const _ViewConfiguration =
146
148
  }
147
149
  .docuserve-playground-pane-code { border-right: 1px solid var(--theme-color-border-default, #DDD6CA); }
148
150
  .docuserve-playground-pane-log { background: var(--theme-color-background-secondary, #F6F3EE); }
151
+ /* DOM sandbox pane — third column, opt-in via _playground.json's
152
+ "Sandbox": "dom" field. Hidden by default so fable-family docs
153
+ keep their familiar two-pane layout. */
154
+ .docuserve-playground-pane-dom { display: none; border-left: 1px solid var(--theme-color-border-default, #DDD6CA); background: var(--theme-color-background-panel, #FFFFFF); }
155
+ .docuserve-playground-mode-dom .docuserve-playground-pane-dom { display: flex; }
156
+ .docuserve-playground-sandbox { flex: 1 1 0; min-height: 0; overflow: auto; padding: 12px; }
149
157
 
150
158
  /* Per-pane header — small uppercase label on the left, controls
151
159
  on the right. Same row height as the doc page section
@@ -407,6 +415,17 @@ const _ViewConfiguration =
407
415
  </div>
408
416
  <pre class="docuserve-playground-log" id="Docuserve-Fable-Playground-Log">{~T:Docuserve-Fable-Playground-Log-Body-Template:AppData~}</pre>
409
417
  </div>
418
+ <div class="docuserve-playground-pane docuserve-playground-pane-dom">
419
+ <div class="docuserve-playground-pane-header">
420
+ <span class="docuserve-playground-pane-title">DOM sandbox</span>
421
+ <div class="docuserve-playground-pane-controls">
422
+ <button type="button" class="docuserve-playground-iconbtn" title="Clear sandbox" aria-label="Clear sandbox" onclick="{~P~}.views['Docuserve-Fable-Playground'].clearSandbox()">
423
+ <svg viewBox="0 0 24 24" aria-hidden="true"><path d="M3 6h18"/><path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/><path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/><path d="M10 11v6M14 11v6"/></svg>
424
+ </button>
425
+ </div>
426
+ </div>
427
+ <div class="docuserve-playground-sandbox" id="Docuserve-Fable-Playground-Sandbox"></div>
428
+ </div>
410
429
  </div>
411
430
  </div>
412
431
  `
@@ -505,6 +524,42 @@ class DocuserveFablePlaygroundView extends libPictView
505
524
  }
506
525
  this._wireHelpTooltip();
507
526
  this._mountCodeEditor();
527
+ // Toggle the DOM-sandbox pane visibility based on the loaded
528
+ // _playground.json config. Safe to call repeatedly — it just
529
+ // adds/removes the mode class on the playground root.
530
+ this._applySandboxMode();
531
+ }
532
+
533
+ /**
534
+ * Read the current `_playground.json` (already cached into AppData
535
+ * by the application's route handler) and toggle the
536
+ * `docuserve-playground-mode-dom` class on the playground root
537
+ * accordingly. Idempotent. Called from `mountInto()` and on
538
+ * every `run()` so a config that loads asynchronously still gets
539
+ * picked up the moment the user interacts with the playground.
540
+ */
541
+ _applySandboxMode()
542
+ {
543
+ let tmpRoot = document.querySelector('.docuserve-playground');
544
+ if (!tmpRoot) { return; }
545
+ let tmpConfig = this.pict.AppData.Docuserve
546
+ && this.pict.AppData.Docuserve.Playground
547
+ && this.pict.AppData.Docuserve.Playground.Config;
548
+ let tmpSandboxMode = (tmpConfig && tmpConfig.Sandbox === 'dom');
549
+ tmpRoot.classList.toggle('docuserve-playground-mode-dom', tmpSandboxMode);
550
+ }
551
+
552
+ /**
553
+ * Empty the DOM sandbox. Wired to the trash-icon button in the
554
+ * sandbox pane header. Doesn't touch the log pane.
555
+ */
556
+ clearSandbox()
557
+ {
558
+ let tmpSandbox = document.getElementById('Docuserve-Fable-Playground-Sandbox');
559
+ if (tmpSandbox)
560
+ {
561
+ tmpSandbox.innerHTML = '';
562
+ }
508
563
  }
509
564
 
510
565
  /**
@@ -716,6 +771,17 @@ class DocuserveFablePlaygroundView extends libPictView
716
771
  this._cancelAsyncRender();
717
772
  this._cancelFinishBanner();
718
773
 
774
+ // Re-evaluate sandbox-pane visibility every run — covers the
775
+ // case where _playground.json finishes loading after the
776
+ // playground has already been mounted.
777
+ this._applySandboxMode();
778
+
779
+ // Reset the DOM sandbox so each Run starts on a clean canvas.
780
+ // Doing this BEFORE the user code runs (not after) means async
781
+ // renders that arrive on a later tick aren't wiped out. Snippets
782
+ // in console-mode docs leave the sandbox empty and pay nothing.
783
+ this.clearSandbox();
784
+
719
785
  let tmpCode = this._getCurrentCode();
720
786
  this.pict.AppData.Docuserve.Playground.Code = tmpCode;
721
787
 
@@ -742,7 +808,17 @@ class DocuserveFablePlaygroundView extends libPictView
742
808
  // (firing template-render traces) keep using the global
743
809
  // console untouched — avoids the obvious feedback loop.
744
810
 
811
+ // Sandbox-mode flag determines whether we hand the user a fresh
812
+ // Pict (DOM-mode docs need view registrations isolated per run)
813
+ // or the docuserve app's pict (console-mode docs preserve today's
814
+ // behaviour exactly).
815
+ let tmpConfig = this.pict.AppData.Docuserve
816
+ && this.pict.AppData.Docuserve.Playground
817
+ && this.pict.AppData.Docuserve.Playground.Config;
818
+ let tmpSandboxMode = (tmpConfig && tmpConfig.Sandbox === 'dom');
819
+
745
820
  let tmpFable;
821
+ let tmpUserPict = this.pict;
746
822
  try
747
823
  {
748
824
  let tmpFableClass = this.fable && this.fable.constructor;
@@ -750,8 +826,25 @@ class DocuserveFablePlaygroundView extends libPictView
750
826
  {
751
827
  throw new Error('Fable constructor unavailable on this.fable');
752
828
  }
753
- tmpFable = new tmpFableClass({ Product: 'FablePlayground', LogStreams: [] });
754
- tmpFable.log.addLogger(this._buildCaptureLogger(tmpRecords, tmpStart), 'trace');
829
+ if (tmpSandboxMode)
830
+ {
831
+ // DOM mode: fresh Pict (extends Fable) so user code's
832
+ // `pict.addView`, `pict.TemplateProvider`, etc. don't
833
+ // pollute the docuserve UI. The Pict instance IS a
834
+ // Fable, so `fable === pict` here — same capture
835
+ // logger, single object.
836
+ tmpUserPict = new libPict({ Product: 'FablePlayground', LogStreams: [] });
837
+ tmpUserPict.log.addLogger(this._buildCaptureLogger(tmpRecords, tmpStart), 'trace');
838
+ tmpFable = tmpUserPict;
839
+ }
840
+ else
841
+ {
842
+ tmpFable = new tmpFableClass({ Product: 'FablePlayground', LogStreams: [] });
843
+ tmpFable.log.addLogger(this._buildCaptureLogger(tmpRecords, tmpStart), 'trace');
844
+ // Console-mode: `pict` param stays docuserve's pict
845
+ // for backwards compat with the fable-family docs.
846
+ tmpUserPict = this.pict;
847
+ }
755
848
  }
756
849
  catch (pError)
757
850
  {
@@ -790,9 +883,10 @@ class DocuserveFablePlaygroundView extends libPictView
790
883
  // into error-level records in the log pane.
791
884
  let tmpRequire = this._buildRequireShim(tmpFable, tmpRecords, tmpStart);
792
885
  let tmpConsole = this._buildCapturingConsole(tmpRecords, tmpStart);
793
- let tmpFn = new Function('fable', 'pict', 'require', 'console',
886
+ let tmpSandboxEl = document.getElementById('Docuserve-Fable-Playground-Sandbox');
887
+ let tmpFn = new Function('fable', 'pict', 'require', 'console', 'sandbox',
794
888
  'return (async () => { ' + tmpCode + '\n})();');
795
- let tmpPromise = tmpFn(tmpFable, this.pict, tmpRequire, tmpConsole);
889
+ let tmpPromise = tmpFn(tmpFable, tmpUserPict, tmpRequire, tmpConsole, tmpSandboxEl);
796
890
  if (tmpPromise && typeof tmpPromise.then === 'function')
797
891
  {
798
892
  let tmpSelf = this;
@@ -1180,7 +1274,8 @@ class DocuserveFablePlaygroundView extends libPictView
1180
1274
  let tmpResolvers =
1181
1275
  {
1182
1276
  'fable': () => tmpAutoCapture ? PlaygroundFableWrapper : tmpFableClass,
1183
- 'pict': () => tmpPict.constructor,
1277
+ 'pict': () => libPict,
1278
+ 'pict-section-histogram': () => libPictSectionHistogram,
1184
1279
  'fable-uuid': () => pFableInstance.UUID && pFableInstance.UUID.constructor,
1185
1280
  'fable-settings': () => pFableInstance.SettingsManager && pFableInstance.SettingsManager.constructor,
1186
1281
  'fable-log': () => tmpFableLogClass ? PlaygroundFableLogWrapper : null,
@@ -95,7 +95,9 @@ const _ViewConfiguration =
95
95
  }
96
96
  .docuserve-splash-actions .primary {
97
97
  background-color: var(--theme-color-brand-primary, #2E7D74);
98
- color: var(--theme-color-background-panel, #fff);
98
+ /* text-on-brand falls to a fixed light hex — never to background-panel,
99
+ which inverts contrast in dark themes (dark text on brand bg). */
100
+ color: var(--theme-color-text-on-brand, #fff);
99
101
  }
100
102
  .docuserve-splash-actions .primary:hover {
101
103
  background-color: var(--theme-color-brand-primary-hover, #236660);
@@ -36,7 +36,7 @@ const _ViewConfiguration =
36
36
  }
37
37
  .docuserve-nav-links a
38
38
  {
39
- color: var(--theme-color-text-on-brand, var(--theme-color-text-secondary, #B5AA9A));
39
+ color: var(--theme-color-text-on-brand, var(--theme-color-text-primary, #E8E0D4));
40
40
  text-decoration: none;
41
41
  padding: 0.45em 0.7em;
42
42
  border-radius: 4px;
@@ -47,7 +47,10 @@ const _ViewConfiguration =
47
47
  .docuserve-nav-links a:hover
48
48
  {
49
49
  background-color: var(--theme-color-background-hover, rgba(255, 255, 255, 0.06));
50
- color: var(--theme-color-text-on-brand, var(--theme-color-background-panel, #fff));
50
+ /* Keep the text token chain on hover — falling to background-panel
51
+ here inverts contrast (dark text on dark hover) in themes that
52
+ don't define text-on-brand (e.g. night, twilight). */
53
+ color: var(--theme-color-text-on-brand, var(--theme-color-text-primary, #ffffff));
51
54
  }
52
55
  .docuserve-nav-version
53
56
  {