pict-docuserve 1.3.2 → 1.3.3

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.
@@ -17,6 +17,7 @@ class DocuserveDocumentationProvider extends libPictProvider
17
17
  super(pFable, pOptions, pServiceHash);
18
18
 
19
19
  this._Catalog = null;
20
+ this._KeywordIndexMode = null;
20
21
  this._ContentCache = {};
21
22
  // (group, module) -> playground config | null (negative cache).
22
23
  // Loaded lazily by loadPlaygroundConfig on first navigation into
@@ -43,6 +44,15 @@ class DocuserveDocumentationProvider extends libPictProvider
43
44
  {
44
45
  return (pHref, pLinkText) =>
45
46
  {
47
+ // Built example applications (and other static .html pages) are
48
+ // served as plain files alongside the docs. Link straight to
49
+ // them in a new tab rather than SPA-routing through #/page/.
50
+ // Scoped strictly to the .html extension — .md pages, catalog
51
+ // routes and http(s):// links fall through unaffected.
52
+ if (!pHref.match(/^[a-z][a-z0-9+.-]*:/i) && pHref.match(/\.html($|[?#])/i))
53
+ {
54
+ return { href: pHref, target: '_blank', rel: 'noopener' };
55
+ }
46
56
  // Convert internal doc links to hash routes
47
57
  if (pHref.match(/^\//) || pHref.match(/^[^:]+\.md/))
48
58
  {
@@ -728,6 +738,7 @@ class DocuserveDocumentationProvider extends libPictProvider
728
738
  {
729
739
  this._LunrIndex = libLunr.Index.load(pIndexData.LunrIndex);
730
740
  this._KeywordDocuments = pIndexData.Documents;
741
+ this._KeywordIndexMode = (pIndexData.Mode === 'module' || pIndexData.Mode === 'ecosystem') ? pIndexData.Mode : null;
731
742
  this.pict.AppData.Docuserve.KeywordIndexLoaded = true;
732
743
  this.pict.AppData.Docuserve.KeywordDocumentCount = pIndexData.DocumentCount || 0;
733
744
  this.log.info(`Docuserve: Keyword index loaded (${pIndexData.DocumentCount || 0} documents).`);
@@ -746,6 +757,47 @@ class DocuserveDocumentationProvider extends libPictProvider
746
757
  });
747
758
  }
748
759
 
760
+ /**
761
+ * Resolve the documentation site mode.
762
+ *
763
+ * 'module' — a single module's own docs site; every doc is a local
764
+ * page (#/page/<docpath>).
765
+ * 'ecosystem' — a catalog of <group>/<module> repos (#/doc/...).
766
+ * 'legacy' — built before the Mode stamp existed; callers keep the
767
+ * pre-Mode heuristic so old docs sites are unaffected.
768
+ *
769
+ * @returns {string} 'module' | 'ecosystem' | 'legacy'
770
+ */
771
+ getDocsMode()
772
+ {
773
+ if (this._Catalog && (this._Catalog.Mode === 'module' || this._Catalog.Mode === 'ecosystem'))
774
+ {
775
+ return this._Catalog.Mode;
776
+ }
777
+ if (this._KeywordIndexMode === 'module' || this._KeywordIndexMode === 'ecosystem')
778
+ {
779
+ return this._KeywordIndexMode;
780
+ }
781
+ return 'legacy';
782
+ }
783
+
784
+ /**
785
+ * Module-mode link resolution: every internal documentation reference is
786
+ * a local page. Normalizes an href to a #/page/ hash route.
787
+ *
788
+ * @param {string} pHref - The raw link href
789
+ * @returns {string} A #/page/ hash route (#/Home for an empty path)
790
+ */
791
+ _toModulePageRoute(pHref)
792
+ {
793
+ let tmpPath = String(pHref || '').replace(/^\.\//, '').replace(/^\//, '').replace(/\/+$/, '');
794
+ if (!tmpPath)
795
+ {
796
+ return '#/Home';
797
+ }
798
+ return '#/page/' + tmpPath.replace(/\.md$/i, '');
799
+ }
800
+
749
801
  /**
750
802
  * Check whether a group/module pair exists in the loaded catalog.
751
803
  *
@@ -864,6 +916,7 @@ class DocuserveDocumentationProvider extends libPictProvider
864
916
  try
865
917
  {
866
918
  let tmpLunrResults = this._LunrIndex.search(pQuery);
919
+ let tmpMode = this.getDocsMode();
867
920
 
868
921
  for (let i = 0; i < tmpLunrResults.length; i++)
869
922
  {
@@ -876,24 +929,37 @@ class DocuserveDocumentationProvider extends libPictProvider
876
929
  continue;
877
930
  }
878
931
 
879
- // Build the hash route from the document key (group/module/docpath)
880
- let tmpParts = tmpRef.split('/');
932
+ // Build the hash route for this result based on the site mode.
881
933
  let tmpRoute = '';
882
- if (tmpParts.length >= 2)
934
+ if (tmpMode === 'module')
883
935
  {
884
- // Check whether this group/module exists in the catalog.
885
- // If it does, route to #/doc/ which fetches from GitHub.
886
- // If not, fall back to #/page/ which fetches locally.
887
- let tmpGroup = tmpParts[0];
888
- let tmpModule = tmpParts[1];
889
-
890
- if (this.isModuleInCatalog(tmpGroup, tmpModule))
936
+ // Single-module site: every doc is a local page; the
937
+ // keyword-index key is the docs-relative path.
938
+ tmpRoute = '#/page/' + (tmpDoc.DocPath || tmpRef);
939
+ }
940
+ else if (tmpMode === 'ecosystem')
941
+ {
942
+ // Ecosystem: catalog modules render from their GitHub docs.
943
+ if (tmpDoc.Group && tmpDoc.Module && tmpDoc.DocPath)
944
+ {
945
+ tmpRoute = '#/doc/' + tmpDoc.Group + '/' + tmpDoc.Module + '/' + tmpDoc.DocPath;
946
+ }
947
+ else
948
+ {
949
+ tmpRoute = '#/page/' + tmpRef;
950
+ }
951
+ }
952
+ else
953
+ {
954
+ // Legacy keyword index (no Mode stamp) — the pre-Mode
955
+ // heuristic: split the key and check the catalog.
956
+ let tmpParts = tmpRef.split('/');
957
+ if (tmpParts.length >= 2 && this.isModuleInCatalog(tmpParts[0], tmpParts[1]))
891
958
  {
892
959
  tmpRoute = '#/doc/' + tmpRef;
893
960
  }
894
961
  else
895
962
  {
896
- // Local document — route via #/page/ using the full ref path
897
963
  tmpRoute = '#/page/' + tmpRef;
898
964
  }
899
965
  }
@@ -1076,6 +1142,14 @@ class DocuserveDocumentationProvider extends libPictProvider
1076
1142
  return '';
1077
1143
  }
1078
1144
 
1145
+ // Already a fully-formed hash route (e.g. "#/page/examples/foo/README").
1146
+ // Pass it straight through — the author has named the exact route, so
1147
+ // do not re-derive one (re-deriving would mangle it into "#/page/#/...").
1148
+ if (pHref.match(/^#\//))
1149
+ {
1150
+ return pHref;
1151
+ }
1152
+
1079
1153
  // Root home link
1080
1154
  if (pHref === '/')
1081
1155
  {
@@ -1112,6 +1186,21 @@ class DocuserveDocumentationProvider extends libPictProvider
1112
1186
  return '#/Home';
1113
1187
  }
1114
1188
 
1189
+ // Static .html pages (built example apps, etc.) — link straight to
1190
+ // the file rather than SPA-routing it through #/page/. Scoped
1191
+ // strictly to the .html extension.
1192
+ if (pHref.match(/\.html($|[?#])/i) && !pHref.match(/^[a-z][a-z0-9+.-]*:/i))
1193
+ {
1194
+ return pHref;
1195
+ }
1196
+
1197
+ // Single-module docs site: every internal reference is a local page —
1198
+ // no catalog #/doc/ routing, no group/module guesswork.
1199
+ if (this.getDocsMode() === 'module')
1200
+ {
1201
+ return this._toModulePageRoute(pHref);
1202
+ }
1203
+
1115
1204
  // Strip leading/trailing slashes for parsing
1116
1205
  let tmpPath = pHref.replace(/^\//, '').replace(/\/$/, '');
1117
1206
 
@@ -1572,6 +1661,12 @@ class DocuserveDocumentationProvider extends libPictProvider
1572
1661
  */
1573
1662
  convertDocLink(pHref, pCurrentGroup, pCurrentModule, pCurrentDocPath)
1574
1663
  {
1664
+ // Single-module docs site: every internal reference is a local page.
1665
+ if (this.getDocsMode() === 'module')
1666
+ {
1667
+ return this._toModulePageRoute(pHref);
1668
+ }
1669
+
1575
1670
  // Strip leading ./ prefix for relative paths
1576
1671
  let tmpPath = pHref.replace(/^\.\//, '');
1577
1672
  // Remove leading slash
@@ -1,327 +0,0 @@
1
- /* ============================================================================
2
- Pict Docuserve - Base Styles & Theme Variables
3
- ============================================================================ */
4
-
5
- /* ----------------------------------------------------------------------------
6
- Theme variables — light defaults on :root.
7
- Dark mode applies when either:
8
- (a) the user explicitly selected dark via <html data-theme="dark">
9
- (b) the user hasn't chosen anything AND the system prefers dark
10
- An explicit <html data-theme="light"> pins the light palette regardless.
11
- ---------------------------------------------------------------------------- */
12
-
13
- :root
14
- {
15
- /* Surfaces */
16
- --docuserve-bg: #FDFBF7;
17
- --docuserve-bg-elevated: #FFFFFF;
18
- --docuserve-border: #DDD6CA;
19
- --docuserve-border-soft: #EAE3D8;
20
-
21
- /* Text */
22
- --docuserve-text: #2A241E;
23
- --docuserve-text-strong: #3D3229;
24
- --docuserve-text-muted: #5E5549;
25
- --docuserve-text-dim: #8A7F72;
26
-
27
- /* Accent / links */
28
- --docuserve-accent: #2E7D74;
29
- --docuserve-accent-hover: #236660;
30
-
31
- /* Top bar */
32
- --docuserve-topbar-bg: #3D3229;
33
- --docuserve-topbar-text: #E8E0D4;
34
- --docuserve-topbar-text-muted: #B5AA9A;
35
- --docuserve-topbar-text-dim: #8A7F72;
36
- --docuserve-topbar-hover-bg: #524438;
37
- --docuserve-topbar-version-bg: rgba(255, 255, 255, 0.06);
38
- --docuserve-topbar-version-border: rgba(255, 255, 255, 0.08);
39
- --docuserve-topbar-version-text: #B5AA9A;
40
-
41
- /* Sidebar */
42
- --docuserve-sidebar-bg: #FAF7F1;
43
- --docuserve-sidebar-border: #DDD6CA;
44
- --docuserve-sidebar-border-soft: #E5DED1;
45
- --docuserve-sidebar-text: #423D37;
46
- --docuserve-sidebar-group-title: #3D3229;
47
- --docuserve-sidebar-module-text: #5E5549;
48
- --docuserve-sidebar-hover-bg: #EAE3D8;
49
- --docuserve-sidebar-hover-text: #2E7D74;
50
- --docuserve-sidebar-active-bg: #E5DED1;
51
- --docuserve-sidebar-active-text: #2E7D74;
52
- --docuserve-sidebar-search-bg: #FFFFFF;
53
- --docuserve-sidebar-search-border: #DDD6CA;
54
-
55
- /* Inline code */
56
- --docuserve-inline-code-bg: #F0ECE4;
57
- --docuserve-inline-code-text: #9E3A50;
58
-
59
- /* Code block panel */
60
- --docuserve-code-bg: #F6F3EE;
61
- --docuserve-code-border: #E5DED1;
62
- --docuserve-code-gutter-bg: #EFEAE0;
63
- --docuserve-code-gutter-border: #DDD6CA;
64
- --docuserve-code-gutter-text: #A59986;
65
- --docuserve-code-text: #2A241E;
66
-
67
- /* Syntax tokens — low-chroma dark-on-light palette */
68
- --docuserve-tok-keyword: #A03472;
69
- --docuserve-tok-string: #1A6640;
70
- --docuserve-tok-number: #B25A00;
71
- --docuserve-tok-comment: #8A7F72;
72
- --docuserve-tok-operator: #2E7D74;
73
- --docuserve-tok-punctuation: #2A241E;
74
- --docuserve-tok-function: #2A5DB0;
75
- --docuserve-tok-property: #9E3A50;
76
- --docuserve-tok-tag: #9E3A50;
77
- --docuserve-tok-attr-name: #B25A00;
78
- --docuserve-tok-attr-value: #1A6640;
79
-
80
- /* Tables, blockquotes, mermaid */
81
- --docuserve-table-header-bg: #F5F0E8;
82
- --docuserve-table-row-alt-bg: #F9F6F0;
83
- --docuserve-blockquote-bg: #F7F5F0;
84
- --docuserve-blockquote-border: #2E7D74;
85
- --docuserve-blockquote-text: #5E5549;
86
- --docuserve-mermaid-bg: #FFFFFF;
87
-
88
- /* Scrollbars */
89
- --docuserve-scrollbar-track: #F5F0E8;
90
- --docuserve-scrollbar-thumb: #D4CCBE;
91
- --docuserve-scrollbar-thumb-hover: #B5AA9A;
92
- }
93
-
94
- @media (prefers-color-scheme: dark)
95
- {
96
- :root:not([data-theme="light"])
97
- {
98
- --docuserve-bg: #15120F;
99
- --docuserve-bg-elevated: #1B1814;
100
- --docuserve-border: #2F2823;
101
- --docuserve-border-soft: #26211C;
102
-
103
- --docuserve-text: #E8E0D4;
104
- --docuserve-text-strong: #F2ECE0;
105
- --docuserve-text-muted: #B5AA9A;
106
- --docuserve-text-dim: #7A6F62;
107
-
108
- --docuserve-accent: #5DB8A8;
109
- --docuserve-accent-hover: #7FCCB8;
110
-
111
- --docuserve-topbar-bg: #1A1612;
112
- --docuserve-topbar-text: #E8E0D4;
113
- --docuserve-topbar-text-muted: #B5AA9A;
114
- --docuserve-topbar-text-dim: #7A6F62;
115
- --docuserve-topbar-hover-bg: #2A241E;
116
- --docuserve-topbar-version-bg: rgba(255, 255, 255, 0.05);
117
- --docuserve-topbar-version-border: rgba(255, 255, 255, 0.09);
118
- --docuserve-topbar-version-text: #B5AA9A;
119
-
120
- --docuserve-sidebar-bg: #1B1814;
121
- --docuserve-sidebar-border: #2F2823;
122
- --docuserve-sidebar-border-soft: #26211C;
123
- --docuserve-sidebar-text: #C9C0B3;
124
- --docuserve-sidebar-group-title: #F2ECE0;
125
- --docuserve-sidebar-module-text: #B5AA9A;
126
- --docuserve-sidebar-hover-bg: #2A241E;
127
- --docuserve-sidebar-hover-text: #7FCCB8;
128
- --docuserve-sidebar-active-bg: #2F2823;
129
- --docuserve-sidebar-active-text: #7FCCB8;
130
- --docuserve-sidebar-search-bg: #26211C;
131
- --docuserve-sidebar-search-border: #2F2823;
132
-
133
- --docuserve-inline-code-bg: #2A241E;
134
- --docuserve-inline-code-text: #E8B07A;
135
-
136
- --docuserve-code-bg: #1E1A17;
137
- --docuserve-code-border: #2F2823;
138
- --docuserve-code-gutter-bg: #17130F;
139
- --docuserve-code-gutter-border: #2F2823;
140
- --docuserve-code-gutter-text: #6A6052;
141
- --docuserve-code-text: #E8E0D4;
142
-
143
- --docuserve-tok-keyword: #C678DD;
144
- --docuserve-tok-string: #98C379;
145
- --docuserve-tok-number: #D19A66;
146
- --docuserve-tok-comment: #7F848E;
147
- --docuserve-tok-operator: #56B6C2;
148
- --docuserve-tok-punctuation: #E8E0D4;
149
- --docuserve-tok-function: #61AFEF;
150
- --docuserve-tok-property: #E06C75;
151
- --docuserve-tok-tag: #E06C75;
152
- --docuserve-tok-attr-name: #D19A66;
153
- --docuserve-tok-attr-value: #98C379;
154
-
155
- --docuserve-table-header-bg: #26211C;
156
- --docuserve-table-row-alt-bg: #1F1B17;
157
- --docuserve-blockquote-bg: #1F1B17;
158
- --docuserve-blockquote-border: #5DB8A8;
159
- --docuserve-blockquote-text: #C9C0B3;
160
- --docuserve-mermaid-bg: #E8E0D4;
161
-
162
- --docuserve-scrollbar-track: #1B1814;
163
- --docuserve-scrollbar-thumb: #3A322B;
164
- --docuserve-scrollbar-thumb-hover: #524438;
165
- }
166
- }
167
-
168
- :root[data-theme="dark"]
169
- {
170
- --docuserve-bg: #15120F;
171
- --docuserve-bg-elevated: #1B1814;
172
- --docuserve-border: #2F2823;
173
- --docuserve-border-soft: #26211C;
174
-
175
- --docuserve-text: #E8E0D4;
176
- --docuserve-text-strong: #F2ECE0;
177
- --docuserve-text-muted: #B5AA9A;
178
- --docuserve-text-dim: #7A6F62;
179
-
180
- --docuserve-accent: #5DB8A8;
181
- --docuserve-accent-hover: #7FCCB8;
182
-
183
- --docuserve-topbar-bg: #1A1612;
184
- --docuserve-topbar-text: #E8E0D4;
185
- --docuserve-topbar-text-muted: #B5AA9A;
186
- --docuserve-topbar-text-dim: #7A6F62;
187
- --docuserve-topbar-hover-bg: #2A241E;
188
- --docuserve-topbar-version-bg: rgba(255, 255, 255, 0.05);
189
- --docuserve-topbar-version-border: rgba(255, 255, 255, 0.09);
190
- --docuserve-topbar-version-text: #B5AA9A;
191
-
192
- --docuserve-sidebar-bg: #1B1814;
193
- --docuserve-sidebar-border: #2F2823;
194
- --docuserve-sidebar-border-soft: #26211C;
195
- --docuserve-sidebar-text: #C9C0B3;
196
- --docuserve-sidebar-group-title: #F2ECE0;
197
- --docuserve-sidebar-module-text: #B5AA9A;
198
- --docuserve-sidebar-hover-bg: #2A241E;
199
- --docuserve-sidebar-hover-text: #7FCCB8;
200
- --docuserve-sidebar-active-bg: #2F2823;
201
- --docuserve-sidebar-active-text: #7FCCB8;
202
- --docuserve-sidebar-search-bg: #26211C;
203
- --docuserve-sidebar-search-border: #2F2823;
204
-
205
- --docuserve-inline-code-bg: #2A241E;
206
- --docuserve-inline-code-text: #E8B07A;
207
-
208
- --docuserve-code-bg: #1E1A17;
209
- --docuserve-code-border: #2F2823;
210
- --docuserve-code-gutter-bg: #17130F;
211
- --docuserve-code-gutter-border: #2F2823;
212
- --docuserve-code-gutter-text: #6A6052;
213
- --docuserve-code-text: #E8E0D4;
214
-
215
- --docuserve-tok-keyword: #C678DD;
216
- --docuserve-tok-string: #98C379;
217
- --docuserve-tok-number: #D19A66;
218
- --docuserve-tok-comment: #7F848E;
219
- --docuserve-tok-operator: #56B6C2;
220
- --docuserve-tok-punctuation: #E8E0D4;
221
- --docuserve-tok-function: #61AFEF;
222
- --docuserve-tok-property: #E06C75;
223
- --docuserve-tok-tag: #E06C75;
224
- --docuserve-tok-attr-name: #D19A66;
225
- --docuserve-tok-attr-value: #98C379;
226
-
227
- --docuserve-table-header-bg: #26211C;
228
- --docuserve-table-row-alt-bg: #1F1B17;
229
- --docuserve-blockquote-bg: #1F1B17;
230
- --docuserve-blockquote-border: #5DB8A8;
231
- --docuserve-blockquote-text: #C9C0B3;
232
- --docuserve-mermaid-bg: #E8E0D4;
233
-
234
- --docuserve-scrollbar-track: #1B1814;
235
- --docuserve-scrollbar-thumb: #3A322B;
236
- --docuserve-scrollbar-thumb-hover: #524438;
237
- }
238
-
239
- /* ----------------------------------------------------------------------------
240
- Reset and base
241
- ---------------------------------------------------------------------------- */
242
-
243
- *, *::before, *::after
244
- {
245
- box-sizing: border-box;
246
- }
247
-
248
- html, body
249
- {
250
- margin: 0;
251
- padding: 0;
252
- font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
253
- font-size: 16px;
254
- line-height: 1.5;
255
- color: var(--docuserve-text);
256
- background-color: var(--docuserve-bg);
257
- -webkit-font-smoothing: antialiased;
258
- -moz-osx-font-smoothing: grayscale;
259
- transition: background-color 0.15s ease, color 0.15s ease;
260
- }
261
-
262
- /* Typography */
263
- h1, h2, h3, h4, h5, h6
264
- {
265
- margin-top: 0;
266
- line-height: 1.3;
267
- color: var(--docuserve-text-strong);
268
- }
269
-
270
- a
271
- {
272
- color: var(--docuserve-accent);
273
- text-decoration: none;
274
- }
275
-
276
- a:hover
277
- {
278
- color: var(--docuserve-accent-hover);
279
- }
280
-
281
- /* Application container */
282
- #Docuserve-Application-Container
283
- {
284
- min-height: 100vh;
285
- }
286
-
287
- /* Utility: scrollbar styling */
288
- ::-webkit-scrollbar
289
- {
290
- width: 8px;
291
- height: 8px;
292
- }
293
-
294
- ::-webkit-scrollbar-track
295
- {
296
- background: var(--docuserve-scrollbar-track);
297
- }
298
-
299
- ::-webkit-scrollbar-thumb
300
- {
301
- background: var(--docuserve-scrollbar-thumb);
302
- border-radius: 4px;
303
- }
304
-
305
- ::-webkit-scrollbar-thumb:hover
306
- {
307
- background: var(--docuserve-scrollbar-thumb-hover);
308
- }
309
-
310
- /* Responsive adjustments */
311
- @media (max-width: 768px)
312
- {
313
- html
314
- {
315
- font-size: 14px;
316
- }
317
-
318
- #Docuserve-Sidebar-Container
319
- {
320
- display: none;
321
- }
322
-
323
- .docuserve-body
324
- {
325
- flex-direction: column;
326
- }
327
- }