pict-docuserve 0.0.1

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.
Files changed (36) hide show
  1. package/LICENSE +21 -0
  2. package/build-site.js +172 -0
  3. package/css/docuserve.css +73 -0
  4. package/dist/css/docuserve.css +73 -0
  5. package/dist/index.html +32 -0
  6. package/dist/js/pict.compatible.js +7793 -0
  7. package/dist/js/pict.compatible.js.map +1 -0
  8. package/dist/js/pict.compatible.min.js +12 -0
  9. package/dist/js/pict.compatible.min.js.map +1 -0
  10. package/dist/js/pict.js +7792 -0
  11. package/dist/js/pict.js.map +1 -0
  12. package/dist/js/pict.min.js +12 -0
  13. package/dist/js/pict.min.js.map +1 -0
  14. package/dist/pict-docuserve.compatible.js +5148 -0
  15. package/dist/pict-docuserve.compatible.js.map +1 -0
  16. package/dist/pict-docuserve.compatible.min.js +2 -0
  17. package/dist/pict-docuserve.compatible.min.js.map +1 -0
  18. package/dist/pict-docuserve.js +4670 -0
  19. package/dist/pict-docuserve.js.map +1 -0
  20. package/dist/pict-docuserve.min.js +2 -0
  21. package/dist/pict-docuserve.min.js.map +1 -0
  22. package/html/index.html +32 -0
  23. package/package.json +52 -0
  24. package/source/Pict-Application-Docuserve-Configuration.json +15 -0
  25. package/source/Pict-Application-Docuserve.js +246 -0
  26. package/source/cli/Docuserve-CLI-Program.js +16 -0
  27. package/source/cli/Docuserve-CLI-Run.js +3 -0
  28. package/source/cli/commands/Docuserve-Command-Inject.js +127 -0
  29. package/source/cli/commands/Docuserve-Command-Serve.js +135 -0
  30. package/source/providers/Pict-Provider-Docuserve-Documentation.js +1156 -0
  31. package/source/providers/PictRouter-Docuserve-Configuration.json +26 -0
  32. package/source/views/PictView-Docuserve-Content.js +208 -0
  33. package/source/views/PictView-Docuserve-Layout.js +105 -0
  34. package/source/views/PictView-Docuserve-Sidebar.js +362 -0
  35. package/source/views/PictView-Docuserve-Splash.js +264 -0
  36. package/source/views/PictView-Docuserve-TopBar.js +213 -0
@@ -0,0 +1,264 @@
1
+ const libPictView = require('pict-view');
2
+
3
+ const _ViewConfiguration =
4
+ {
5
+ ViewIdentifier: "Docuserve-Splash",
6
+
7
+ DefaultRenderable: "Docuserve-Splash-Content",
8
+ DefaultDestinationAddress: "#Docuserve-Content-Container",
9
+
10
+ AutoRender: false,
11
+
12
+ CSS: /*css*/`
13
+ .docuserve-splash {
14
+ display: flex;
15
+ flex-direction: column;
16
+ align-items: center;
17
+ justify-content: center;
18
+ min-height: calc(100vh - 56px);
19
+ padding: 3em 2em;
20
+ text-align: center;
21
+ background: linear-gradient(135deg, #f5f7fa 0%, #e8f5e9 100%);
22
+ }
23
+ .docuserve-splash h1 {
24
+ font-size: 3em;
25
+ font-weight: 700;
26
+ color: #2c3e50;
27
+ margin: 0 0 0.25em 0;
28
+ }
29
+ .docuserve-splash-tagline {
30
+ font-size: 1.25em;
31
+ color: #666;
32
+ margin-bottom: 1.5em;
33
+ font-style: italic;
34
+ }
35
+ .docuserve-splash-description {
36
+ font-size: 1em;
37
+ color: #555;
38
+ max-width: 600px;
39
+ line-height: 1.7;
40
+ margin-bottom: 2em;
41
+ }
42
+ .docuserve-splash-highlights {
43
+ display: grid;
44
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
45
+ gap: 1.25em;
46
+ max-width: 900px;
47
+ width: 100%;
48
+ margin-bottom: 2.5em;
49
+ }
50
+ .docuserve-splash-highlight-card {
51
+ background: #fff;
52
+ border: 1px solid #e0e0e0;
53
+ border-radius: 8px;
54
+ padding: 1.25em;
55
+ text-align: left;
56
+ transition: box-shadow 0.2s, border-color 0.2s;
57
+ }
58
+ .docuserve-splash-highlight-card:hover {
59
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
60
+ border-color: #42b983;
61
+ }
62
+ .docuserve-splash-highlight-card h3 {
63
+ margin: 0 0 0.5em 0;
64
+ color: #2c3e50;
65
+ font-size: 1em;
66
+ }
67
+ .docuserve-splash-highlight-card p {
68
+ margin: 0;
69
+ color: #777;
70
+ font-size: 0.85em;
71
+ line-height: 1.5;
72
+ }
73
+ .docuserve-splash-actions {
74
+ display: flex;
75
+ gap: 1em;
76
+ flex-wrap: wrap;
77
+ justify-content: center;
78
+ }
79
+ .docuserve-splash-actions a {
80
+ display: inline-block;
81
+ padding: 0.7em 1.5em;
82
+ border-radius: 6px;
83
+ font-size: 0.95em;
84
+ font-weight: 600;
85
+ text-decoration: none;
86
+ transition: background-color 0.15s, color 0.15s;
87
+ cursor: pointer;
88
+ }
89
+ .docuserve-splash-actions .primary {
90
+ background-color: #42b983;
91
+ color: #fff;
92
+ }
93
+ .docuserve-splash-actions .primary:hover {
94
+ background-color: #38a373;
95
+ }
96
+ .docuserve-splash-actions .secondary {
97
+ background-color: #fff;
98
+ color: #2c3e50;
99
+ border: 1px solid #ddd;
100
+ }
101
+ .docuserve-splash-actions .secondary:hover {
102
+ border-color: #42b983;
103
+ color: #42b983;
104
+ }
105
+ `,
106
+
107
+ Templates:
108
+ [
109
+ {
110
+ Hash: "Docuserve-Splash-Template",
111
+ Template: /*html*/`
112
+ <div class="docuserve-splash">
113
+ <h1 id="Docuserve-Splash-Title"></h1>
114
+ <div class="docuserve-splash-tagline" id="Docuserve-Splash-Tagline"></div>
115
+ <div class="docuserve-splash-description" id="Docuserve-Splash-Description"></div>
116
+ <div class="docuserve-splash-highlights" id="Docuserve-Splash-Highlights"></div>
117
+ <div class="docuserve-splash-actions" id="Docuserve-Splash-Actions"></div>
118
+ </div>
119
+ `
120
+ }
121
+ ],
122
+
123
+ Renderables:
124
+ [
125
+ {
126
+ RenderableHash: "Docuserve-Splash-Content",
127
+ TemplateHash: "Docuserve-Splash-Template",
128
+ DestinationAddress: "#Docuserve-Content-Container",
129
+ RenderMethod: "replace"
130
+ }
131
+ ]
132
+ };
133
+
134
+ class DocusserveSplashView extends libPictView
135
+ {
136
+ constructor(pFable, pOptions, pServiceHash)
137
+ {
138
+ super(pFable, pOptions, pServiceHash);
139
+ }
140
+
141
+ onAfterRender(pRenderable, pRenderDestinationAddress, pRecord, pContent)
142
+ {
143
+ let tmpDocuserve = this.pict.AppData.Docuserve;
144
+
145
+ if (tmpDocuserve.CoverLoaded && tmpDocuserve.Cover)
146
+ {
147
+ this.renderFromCover(tmpDocuserve.Cover);
148
+ }
149
+ else
150
+ {
151
+ this.renderFromCatalog(tmpDocuserve);
152
+ }
153
+
154
+ return super.onAfterRender(pRenderable, pRenderDestinationAddress, pRecord, pContent);
155
+ }
156
+
157
+ /**
158
+ * Render the splash screen from parsed cover.md data.
159
+ *
160
+ * @param {Object} pCover - The parsed cover data { Title, Tagline, Description, Highlights, Actions }
161
+ */
162
+ renderFromCover(pCover)
163
+ {
164
+ this.pict.ContentAssignment.assignContent('#Docuserve-Splash-Title', this.escapeHTML(pCover.Title));
165
+ this.pict.ContentAssignment.assignContent('#Docuserve-Splash-Tagline', this.escapeHTML(pCover.Tagline));
166
+ this.pict.ContentAssignment.assignContent('#Docuserve-Splash-Description', this.escapeHTML(pCover.Description));
167
+
168
+ // Render highlight cards
169
+ let tmpHighlightsHTML = '';
170
+ for (let i = 0; i < pCover.Highlights.length; i++)
171
+ {
172
+ let tmpHighlight = pCover.Highlights[i];
173
+ tmpHighlightsHTML += '<div class="docuserve-splash-highlight-card">';
174
+ if (tmpHighlight.Label)
175
+ {
176
+ tmpHighlightsHTML += '<h3>' + this.escapeHTML(tmpHighlight.Label) + '</h3>';
177
+ }
178
+ tmpHighlightsHTML += '<p>' + this.escapeHTML(tmpHighlight.Text) + '</p>';
179
+ tmpHighlightsHTML += '</div>';
180
+ }
181
+ this.pict.ContentAssignment.assignContent('#Docuserve-Splash-Highlights', tmpHighlightsHTML);
182
+
183
+ // Render action buttons
184
+ let tmpActionsHTML = '';
185
+ let tmpDocProvider = this.pict.providers['Docuserve-Documentation'];
186
+ for (let i = 0; i < pCover.Actions.length; i++)
187
+ {
188
+ let tmpAction = pCover.Actions[i];
189
+ let tmpClass = (i === 0) ? 'primary' : 'secondary';
190
+ let tmpHref = tmpAction.Href;
191
+
192
+ // External links open in new tab
193
+ if (tmpHref.match(/^https?:\/\//))
194
+ {
195
+ tmpActionsHTML += '<a class="' + tmpClass + '" href="' + this.escapeHTML(tmpHref) + '" target="_blank" rel="noopener">' + this.escapeHTML(tmpAction.Text) + '</a>';
196
+ }
197
+ else
198
+ {
199
+ // Internal links go through the app router
200
+ let tmpRoute = tmpDocProvider.convertSidebarLink(tmpHref);
201
+ tmpActionsHTML += '<a class="' + tmpClass + '" href="' + this.escapeHTML(tmpRoute) + '">' + this.escapeHTML(tmpAction.Text) + '</a>';
202
+ }
203
+ }
204
+ this.pict.ContentAssignment.assignContent('#Docuserve-Splash-Actions', tmpActionsHTML);
205
+ }
206
+
207
+ /**
208
+ * Render the splash screen from catalog data as a fallback when cover.md
209
+ * is not available.
210
+ *
211
+ * @param {Object} pDocuserve - The AppData.Docuserve state
212
+ */
213
+ renderFromCatalog(pDocuserve)
214
+ {
215
+ this.pict.ContentAssignment.assignContent('#Docuserve-Splash-Title', 'Retold');
216
+ this.pict.ContentAssignment.assignContent('#Docuserve-Splash-Tagline', 'Documentation');
217
+ this.pict.ContentAssignment.assignContent('#Docuserve-Splash-Description', '');
218
+
219
+ // Build highlight cards from catalog groups
220
+ let tmpHighlightsHTML = '';
221
+ let tmpGroups = pDocuserve.SidebarGroups || [];
222
+ for (let i = 0; i < tmpGroups.length; i++)
223
+ {
224
+ let tmpGroup = tmpGroups[i];
225
+ // Skip groups with no modules (like "Home" or "Getting Started")
226
+ if (!tmpGroup.Modules || tmpGroup.Modules.length < 1)
227
+ {
228
+ continue;
229
+ }
230
+ let tmpDescription = tmpGroup.Description || (tmpGroup.Modules.length + ' modules');
231
+ tmpHighlightsHTML += '<div class="docuserve-splash-highlight-card">';
232
+ tmpHighlightsHTML += '<h3>' + this.escapeHTML(tmpGroup.Name) + '</h3>';
233
+ tmpHighlightsHTML += '<p>' + this.escapeHTML(tmpDescription) + '</p>';
234
+ tmpHighlightsHTML += '</div>';
235
+ }
236
+ this.pict.ContentAssignment.assignContent('#Docuserve-Splash-Highlights', tmpHighlightsHTML);
237
+
238
+ // Default action buttons
239
+ this.pict.ContentAssignment.assignContent('#Docuserve-Splash-Actions', '');
240
+ }
241
+
242
+ /**
243
+ * Escape HTML special characters.
244
+ *
245
+ * @param {string} pText - The text to escape
246
+ * @returns {string} The escaped text
247
+ */
248
+ escapeHTML(pText)
249
+ {
250
+ if (!pText)
251
+ {
252
+ return '';
253
+ }
254
+ return pText
255
+ .replace(/&/g, '&amp;')
256
+ .replace(/</g, '&lt;')
257
+ .replace(/>/g, '&gt;')
258
+ .replace(/"/g, '&quot;');
259
+ }
260
+ }
261
+
262
+ module.exports = DocusserveSplashView;
263
+
264
+ module.exports.default_configuration = _ViewConfiguration;
@@ -0,0 +1,213 @@
1
+ const libPictView = require('pict-view');
2
+
3
+ const _ViewConfiguration =
4
+ {
5
+ ViewIdentifier: "Docuserve-TopBar",
6
+
7
+ DefaultRenderable: "Docuserve-TopBar-Content",
8
+ DefaultDestinationAddress: "#Docuserve-TopBar-Container",
9
+
10
+ AutoRender: false,
11
+
12
+ CSS: /*css*/`
13
+ .docuserve-topbar {
14
+ display: flex;
15
+ align-items: center;
16
+ justify-content: space-between;
17
+ background-color: #2c3e50;
18
+ color: #ecf0f1;
19
+ padding: 0 1.5em;
20
+ height: 56px;
21
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15);
22
+ position: sticky;
23
+ top: 0;
24
+ z-index: 100;
25
+ }
26
+ .docuserve-topbar-brand {
27
+ font-size: 1.25em;
28
+ font-weight: 600;
29
+ letter-spacing: 0.02em;
30
+ color: #ecf0f1;
31
+ text-decoration: none;
32
+ cursor: pointer;
33
+ }
34
+ .docuserve-topbar-brand:hover {
35
+ color: #fff;
36
+ }
37
+ .docuserve-topbar-nav {
38
+ display: flex;
39
+ align-items: center;
40
+ gap: 0.25em;
41
+ }
42
+ .docuserve-topbar-nav a {
43
+ color: #bdc3c7;
44
+ text-decoration: none;
45
+ padding: 0.5em 0.75em;
46
+ border-radius: 4px;
47
+ font-size: 0.9em;
48
+ transition: background-color 0.15s, color 0.15s;
49
+ cursor: pointer;
50
+ }
51
+ .docuserve-topbar-nav a:hover {
52
+ background-color: #34495e;
53
+ color: #fff;
54
+ }
55
+ .docuserve-topbar-links {
56
+ display: flex;
57
+ align-items: center;
58
+ gap: 0.5em;
59
+ }
60
+ .docuserve-topbar-links a {
61
+ color: #95a5a6;
62
+ text-decoration: none;
63
+ font-size: 0.85em;
64
+ padding: 0.4em 0.6em;
65
+ border-radius: 4px;
66
+ transition: background-color 0.15s, color 0.15s;
67
+ }
68
+ .docuserve-topbar-links a:hover {
69
+ background-color: #34495e;
70
+ color: #ecf0f1;
71
+ }
72
+ .docuserve-topbar-toggle {
73
+ display: none;
74
+ background: none;
75
+ border: none;
76
+ color: #bdc3c7;
77
+ font-size: 1.3em;
78
+ cursor: pointer;
79
+ padding: 0.3em 0.5em;
80
+ margin-left: 0.5em;
81
+ line-height: 1;
82
+ }
83
+ .docuserve-topbar-toggle:hover {
84
+ color: #fff;
85
+ }
86
+ .docuserve-topbar-right {
87
+ display: flex;
88
+ align-items: center;
89
+ }
90
+ `,
91
+
92
+ Templates:
93
+ [
94
+ {
95
+ Hash: "Docuserve-TopBar-Template",
96
+ Template: /*html*/`
97
+ <div class="docuserve-topbar">
98
+ <a id="Docuserve-TopBar-Brand" class="docuserve-topbar-brand" href="#/Home"></a>
99
+ <div id="Docuserve-TopBar-Nav" class="docuserve-topbar-nav"></div>
100
+ <div class="docuserve-topbar-right">
101
+ <div id="Docuserve-TopBar-Links" class="docuserve-topbar-links"></div>
102
+ <button id="Docuserve-TopBar-Toggle" class="docuserve-topbar-toggle" onclick="{~P~}.views['Docuserve-Sidebar'].toggleSidebar()">&#9776;</button>
103
+ </div>
104
+ </div>
105
+ `
106
+ }
107
+ ],
108
+
109
+ Renderables:
110
+ [
111
+ {
112
+ RenderableHash: "Docuserve-TopBar-Content",
113
+ TemplateHash: "Docuserve-TopBar-Template",
114
+ DestinationAddress: "#Docuserve-TopBar-Container",
115
+ RenderMethod: "replace"
116
+ }
117
+ ]
118
+ };
119
+
120
+ class DocuserveTopBarView extends libPictView
121
+ {
122
+ constructor(pFable, pOptions, pServiceHash)
123
+ {
124
+ super(pFable, pOptions, pServiceHash);
125
+ }
126
+
127
+ onAfterRender(pRenderable, pRenderDestinationAddress, pRecord, pContent)
128
+ {
129
+ this.renderTopBarContent();
130
+ return super.onAfterRender(pRenderable, pRenderDestinationAddress, pRecord, pContent);
131
+ }
132
+
133
+ /**
134
+ * Populate the top bar from _topbar.md data or fall back to defaults.
135
+ */
136
+ renderTopBarContent()
137
+ {
138
+ let tmpDocuserve = this.pict.AppData.Docuserve;
139
+ let tmpBrandEl = document.getElementById('Docuserve-TopBar-Brand');
140
+ let tmpNavEl = document.getElementById('Docuserve-TopBar-Nav');
141
+ let tmpLinksEl = document.getElementById('Docuserve-TopBar-Links');
142
+
143
+ if (!tmpBrandEl || !tmpNavEl || !tmpLinksEl)
144
+ {
145
+ return;
146
+ }
147
+
148
+ if (tmpDocuserve.TopBarLoaded && tmpDocuserve.TopBar)
149
+ {
150
+ // Data-driven from _topbar.md
151
+ let tmpTopBar = tmpDocuserve.TopBar;
152
+
153
+ // Brand
154
+ tmpBrandEl.textContent = tmpTopBar.Brand || 'Documentation';
155
+
156
+ // Navigation links (centre)
157
+ let tmpNavHTML = '<a href="#/Home">Home</a>';
158
+ for (let i = 0; i < tmpTopBar.NavLinks.length; i++)
159
+ {
160
+ let tmpLink = tmpTopBar.NavLinks[i];
161
+ tmpNavHTML += '<a href="' + tmpLink.Href + '">' + this.escapeHTML(tmpLink.Text) + '</a>';
162
+ }
163
+ tmpNavEl.innerHTML = tmpNavHTML;
164
+
165
+ // External links (right side)
166
+ let tmpLinksHTML = '';
167
+ for (let i = 0; i < tmpTopBar.ExternalLinks.length; i++)
168
+ {
169
+ let tmpLink = tmpTopBar.ExternalLinks[i];
170
+ tmpLinksHTML += '<a href="' + this.escapeHTML(tmpLink.Href) + '" target="_blank" rel="noopener">' + this.escapeHTML(tmpLink.Text) + '</a>';
171
+ }
172
+ tmpLinksEl.innerHTML = tmpLinksHTML;
173
+ }
174
+ else
175
+ {
176
+ // Fallback: use brand from cover or a default, and just show Home
177
+ let tmpBrand = 'Documentation';
178
+ if (tmpDocuserve.CoverLoaded && tmpDocuserve.Cover && tmpDocuserve.Cover.Title)
179
+ {
180
+ tmpBrand = tmpDocuserve.Cover.Title;
181
+ }
182
+ else if (tmpDocuserve.CatalogLoaded && tmpDocuserve.Catalog && tmpDocuserve.Catalog.Name)
183
+ {
184
+ tmpBrand = tmpDocuserve.Catalog.Name;
185
+ }
186
+
187
+ tmpBrandEl.textContent = tmpBrand;
188
+ tmpNavEl.innerHTML = '<a href="#/Home">Home</a>';
189
+ tmpLinksEl.innerHTML = '';
190
+ }
191
+ }
192
+
193
+ /**
194
+ * Escape HTML special characters.
195
+ */
196
+ escapeHTML(pText)
197
+ {
198
+ if (!pText)
199
+ {
200
+ return '';
201
+ }
202
+ return pText
203
+ .replace(/&/g, '&amp;')
204
+ .replace(/</g, '&lt;')
205
+ .replace(/>/g, '&gt;')
206
+ .replace(/"/g, '&quot;')
207
+ .replace(/'/g, '&#39;');
208
+ }
209
+ }
210
+
211
+ module.exports = DocuserveTopBarView;
212
+
213
+ module.exports.default_configuration = _ViewConfiguration;