pict-section-inlinedocumentation 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.
- package/README.md +107 -0
- package/docs/.nojekyll +0 -0
- package/docs/README.md +83 -0
- package/docs/_cover.md +15 -0
- package/docs/_sidebar.md +24 -0
- package/docs/_topbar.md +8 -0
- package/docs/_version.json +7 -0
- package/docs/api-reference.md +185 -0
- package/docs/architecture.md +103 -0
- package/docs/css/docuserve.css +327 -0
- package/docs/embedding-level1-sidebar.md +92 -0
- package/docs/embedding-level2-routes.md +86 -0
- package/docs/embedding-level3-tooltips.md +97 -0
- package/docs/embedding-level4-autogen.md +126 -0
- package/docs/index.html +39 -0
- package/docs/overview.md +42 -0
- package/docs/quickstart.md +95 -0
- package/docs/reference.md +73 -0
- package/docs/retold-catalog.json +181 -0
- package/docs/retold-keyword-index.json +4374 -0
- package/example_applications/basic/docs/README.md +40 -0
- package/example_applications/basic/docs/_sidebar.md +4 -0
- package/example_applications/basic/docs/_topics.json +10 -0
- package/example_applications/basic/docs/advanced-topics.md +47 -0
- package/example_applications/basic/docs/getting-started.md +70 -0
- package/example_applications/basic/index.html +100 -0
- package/example_applications/bookshop/.quackage.json +10 -0
- package/example_applications/bookshop/Pict-Application-Bookshop-Configuration.json +15 -0
- package/example_applications/bookshop/Pict-Application-Bookshop.js +218 -0
- package/example_applications/bookshop/data/BookshopData.json +65 -0
- package/example_applications/bookshop/data/pict_documentation_topics.json +46 -0
- package/example_applications/bookshop/docs/_sidebar.md +6 -0
- package/example_applications/bookshop/docs/book-detail.md +21 -0
- package/example_applications/bookshop/docs/book-list.md +21 -0
- package/example_applications/bookshop/docs/search-filter.md +18 -0
- package/example_applications/bookshop/docs/store.md +29 -0
- package/example_applications/bookshop/docs/welcome.md +23 -0
- package/example_applications/bookshop/html/index.html +236 -0
- package/example_applications/bookshop/package.json +34 -0
- package/example_applications/bookshop/views/PictView-Bookshop-BookList.js +324 -0
- package/example_applications/bookshop/views/PictView-Bookshop-HelpToggle.js +44 -0
- package/example_applications/bookshop/views/PictView-Bookshop-Store.js +271 -0
- package/package.json +55 -0
- package/source/Pict-Section-InlineDocumentation.js +10 -0
- package/source/providers/Pict-Provider-InlineDocumentation.js +1995 -0
- package/source/views/Pict-View-InlineDocumentation-Content.js +542 -0
- package/source/views/Pict-View-InlineDocumentation-Layout.js +206 -0
- package/source/views/Pict-View-InlineDocumentation-Nav.js +475 -0
- package/source/views/Pict-View-InlineDocumentation-TopicManager.js +1623 -0
- package/test/Browser_Integration_tests.js +1449 -0
- package/test/Pict-Section-InlineDocumentation_test.js +1285 -0
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
const libPictView = require('pict-view');
|
|
2
|
+
|
|
3
|
+
const _ViewConfiguration =
|
|
4
|
+
{
|
|
5
|
+
ViewIdentifier: "InlineDoc-Layout",
|
|
6
|
+
|
|
7
|
+
DefaultRenderable: "InlineDoc-Layout-Container",
|
|
8
|
+
DefaultDestinationAddress: "#InlineDoc-Container",
|
|
9
|
+
|
|
10
|
+
AutoRender: false,
|
|
11
|
+
|
|
12
|
+
CSS: /*css*/`
|
|
13
|
+
.pict-inline-doc {
|
|
14
|
+
display: flex;
|
|
15
|
+
flex-direction: row;
|
|
16
|
+
width: 100%;
|
|
17
|
+
height: 100%;
|
|
18
|
+
min-height: 300px;
|
|
19
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
|
20
|
+
font-size: 15px;
|
|
21
|
+
color: #423D37;
|
|
22
|
+
background: #FDFCFA;
|
|
23
|
+
border: 1px solid #E5DED4;
|
|
24
|
+
border-radius: 6px;
|
|
25
|
+
overflow: hidden;
|
|
26
|
+
}
|
|
27
|
+
.pict-inline-doc-nav-container {
|
|
28
|
+
width: 240px;
|
|
29
|
+
min-width: 200px;
|
|
30
|
+
max-width: 300px;
|
|
31
|
+
border-right: 1px solid #E5DED4;
|
|
32
|
+
background: #F7F5F0;
|
|
33
|
+
overflow-y: auto;
|
|
34
|
+
flex-shrink: 0;
|
|
35
|
+
}
|
|
36
|
+
.pict-inline-doc-content-container {
|
|
37
|
+
flex: 1;
|
|
38
|
+
overflow-y: auto;
|
|
39
|
+
overflow-x: hidden;
|
|
40
|
+
min-width: 0;
|
|
41
|
+
}
|
|
42
|
+
.pict-inline-doc-nav-container.pict-inline-doc-nav-hidden {
|
|
43
|
+
display: none;
|
|
44
|
+
}
|
|
45
|
+
/* Compact mode: nav moves to a horizontal top bar when container is narrow */
|
|
46
|
+
.pict-inline-doc.pict-inline-doc-compact {
|
|
47
|
+
flex-direction: column;
|
|
48
|
+
}
|
|
49
|
+
.pict-inline-doc.pict-inline-doc-compact .pict-inline-doc-nav-container {
|
|
50
|
+
width: 100%;
|
|
51
|
+
min-width: 0;
|
|
52
|
+
max-width: none;
|
|
53
|
+
border-right: none;
|
|
54
|
+
border-bottom: 1px solid #E5DED4;
|
|
55
|
+
overflow-y: visible;
|
|
56
|
+
overflow-x: auto;
|
|
57
|
+
flex-shrink: 0;
|
|
58
|
+
max-height: none;
|
|
59
|
+
}
|
|
60
|
+
/* Compact mode: nav items flow horizontally */
|
|
61
|
+
.pict-inline-doc.pict-inline-doc-compact .pict-inline-doc-nav {
|
|
62
|
+
padding: 0.4em 0.5em;
|
|
63
|
+
display: flex;
|
|
64
|
+
flex-wrap: wrap;
|
|
65
|
+
align-items: center;
|
|
66
|
+
gap: 0.15em 0.3em;
|
|
67
|
+
}
|
|
68
|
+
.pict-inline-doc.pict-inline-doc-compact .pict-inline-doc-nav-group {
|
|
69
|
+
display: flex;
|
|
70
|
+
flex-wrap: wrap;
|
|
71
|
+
align-items: center;
|
|
72
|
+
margin-bottom: 0;
|
|
73
|
+
gap: 0.1em 0.2em;
|
|
74
|
+
}
|
|
75
|
+
.pict-inline-doc.pict-inline-doc-compact .pict-inline-doc-nav-group-header {
|
|
76
|
+
padding: 0.2em 0.5em;
|
|
77
|
+
font-size: 0.75em;
|
|
78
|
+
white-space: nowrap;
|
|
79
|
+
}
|
|
80
|
+
.pict-inline-doc.pict-inline-doc-compact .pict-inline-doc-nav-group-toggle {
|
|
81
|
+
display: none;
|
|
82
|
+
}
|
|
83
|
+
.pict-inline-doc.pict-inline-doc-compact .pict-inline-doc-nav-group-items {
|
|
84
|
+
display: flex !important;
|
|
85
|
+
flex-wrap: wrap;
|
|
86
|
+
gap: 0.1em;
|
|
87
|
+
}
|
|
88
|
+
.pict-inline-doc.pict-inline-doc-compact .pict-inline-doc-nav-item {
|
|
89
|
+
padding: 0.2em 0.5em;
|
|
90
|
+
font-size: 0.8em;
|
|
91
|
+
border-left: none;
|
|
92
|
+
border-radius: 3px;
|
|
93
|
+
white-space: nowrap;
|
|
94
|
+
}
|
|
95
|
+
.pict-inline-doc.pict-inline-doc-compact .pict-inline-doc-nav-item.active {
|
|
96
|
+
border-left: none;
|
|
97
|
+
background: #2E7D74;
|
|
98
|
+
color: #fff;
|
|
99
|
+
}
|
|
100
|
+
.pict-inline-doc.pict-inline-doc-compact .pict-inline-doc-nav-topic-badge {
|
|
101
|
+
margin: 0 0.3em;
|
|
102
|
+
padding: 0.15em 0.5em;
|
|
103
|
+
font-size: 0.75em;
|
|
104
|
+
}
|
|
105
|
+
`,
|
|
106
|
+
|
|
107
|
+
Templates:
|
|
108
|
+
[
|
|
109
|
+
{
|
|
110
|
+
Hash: "InlineDoc-Layout-Template",
|
|
111
|
+
Template: /*html*/`
|
|
112
|
+
<div class="pict-inline-doc">
|
|
113
|
+
<div class="pict-inline-doc-nav-container" id="InlineDoc-Nav-Container"></div>
|
|
114
|
+
<div class="pict-inline-doc-content-container" id="InlineDoc-Content-Container"></div>
|
|
115
|
+
</div>
|
|
116
|
+
`
|
|
117
|
+
}
|
|
118
|
+
],
|
|
119
|
+
|
|
120
|
+
Renderables:
|
|
121
|
+
[
|
|
122
|
+
{
|
|
123
|
+
RenderableHash: "InlineDoc-Layout-Container",
|
|
124
|
+
TemplateHash: "InlineDoc-Layout-Template",
|
|
125
|
+
DestinationAddress: "#InlineDoc-Container",
|
|
126
|
+
RenderMethod: "replace"
|
|
127
|
+
}
|
|
128
|
+
]
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
class InlineDocumentationLayoutView extends libPictView
|
|
132
|
+
{
|
|
133
|
+
constructor(pFable, pOptions, pServiceHash)
|
|
134
|
+
{
|
|
135
|
+
super(pFable, pOptions, pServiceHash);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
onAfterRender()
|
|
139
|
+
{
|
|
140
|
+
// Inject all view CSS into the PICT-CSS style element
|
|
141
|
+
this.pict.CSSMap.injectCSS();
|
|
142
|
+
|
|
143
|
+
// Watch for size changes and toggle compact mode
|
|
144
|
+
this._setupCompactModeObserver();
|
|
145
|
+
|
|
146
|
+
return super.onAfterRender();
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Set up a ResizeObserver to toggle compact mode when the container
|
|
151
|
+
* is too narrow for a side-by-side nav + content layout.
|
|
152
|
+
*
|
|
153
|
+
* Below the threshold, the nav switches to a horizontal top bar.
|
|
154
|
+
*/
|
|
155
|
+
_setupCompactModeObserver()
|
|
156
|
+
{
|
|
157
|
+
if (typeof document === 'undefined' || typeof ResizeObserver === 'undefined')
|
|
158
|
+
{
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
let tmpContainer = document.querySelector('.pict-inline-doc');
|
|
163
|
+
if (!tmpContainer)
|
|
164
|
+
{
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Clean up any previous observer
|
|
169
|
+
if (this._resizeObserver)
|
|
170
|
+
{
|
|
171
|
+
this._resizeObserver.disconnect();
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
let tmpCompactThreshold = 550;
|
|
175
|
+
|
|
176
|
+
this._resizeObserver = new ResizeObserver((pEntries) =>
|
|
177
|
+
{
|
|
178
|
+
for (let i = 0; i < pEntries.length; i++)
|
|
179
|
+
{
|
|
180
|
+
let tmpWidth = pEntries[i].contentRect.width;
|
|
181
|
+
|
|
182
|
+
if (tmpWidth < tmpCompactThreshold)
|
|
183
|
+
{
|
|
184
|
+
tmpContainer.classList.add('pict-inline-doc-compact');
|
|
185
|
+
}
|
|
186
|
+
else
|
|
187
|
+
{
|
|
188
|
+
tmpContainer.classList.remove('pict-inline-doc-compact');
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
this._resizeObserver.observe(tmpContainer);
|
|
194
|
+
|
|
195
|
+
// Also do an immediate check
|
|
196
|
+
let tmpWidth = tmpContainer.offsetWidth;
|
|
197
|
+
if (tmpWidth > 0 && tmpWidth < tmpCompactThreshold)
|
|
198
|
+
{
|
|
199
|
+
tmpContainer.classList.add('pict-inline-doc-compact');
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
module.exports = InlineDocumentationLayoutView;
|
|
205
|
+
|
|
206
|
+
module.exports.default_configuration = _ViewConfiguration;
|
|
@@ -0,0 +1,475 @@
|
|
|
1
|
+
const libPictView = require('pict-view');
|
|
2
|
+
|
|
3
|
+
const _ViewConfiguration =
|
|
4
|
+
{
|
|
5
|
+
ViewIdentifier: "InlineDoc-Nav",
|
|
6
|
+
|
|
7
|
+
DefaultRenderable: "InlineDoc-Nav-Display",
|
|
8
|
+
DefaultDestinationAddress: "#InlineDoc-Nav-Container",
|
|
9
|
+
|
|
10
|
+
AutoRender: false,
|
|
11
|
+
|
|
12
|
+
CSS: /*css*/`
|
|
13
|
+
.pict-inline-doc-nav {
|
|
14
|
+
padding: 1em 0;
|
|
15
|
+
}
|
|
16
|
+
.pict-inline-doc-nav-group {
|
|
17
|
+
margin-bottom: 0.5em;
|
|
18
|
+
}
|
|
19
|
+
.pict-inline-doc-nav-group-header {
|
|
20
|
+
display: flex;
|
|
21
|
+
align-items: center;
|
|
22
|
+
padding: 0.4em 1em;
|
|
23
|
+
font-weight: 600;
|
|
24
|
+
font-size: 0.85em;
|
|
25
|
+
color: #5E5549;
|
|
26
|
+
text-transform: uppercase;
|
|
27
|
+
letter-spacing: 0.03em;
|
|
28
|
+
cursor: pointer;
|
|
29
|
+
user-select: none;
|
|
30
|
+
}
|
|
31
|
+
.pict-inline-doc-nav-group-header:hover {
|
|
32
|
+
color: #3D3229;
|
|
33
|
+
}
|
|
34
|
+
.pict-inline-doc-nav-group-toggle {
|
|
35
|
+
margin-right: 0.4em;
|
|
36
|
+
font-size: 0.7em;
|
|
37
|
+
transition: transform 0.15s ease;
|
|
38
|
+
}
|
|
39
|
+
.pict-inline-doc-nav-group.collapsed .pict-inline-doc-nav-group-toggle {
|
|
40
|
+
transform: rotate(-90deg);
|
|
41
|
+
}
|
|
42
|
+
.pict-inline-doc-nav-group.collapsed .pict-inline-doc-nav-group-items {
|
|
43
|
+
display: none;
|
|
44
|
+
}
|
|
45
|
+
.pict-inline-doc-nav-item {
|
|
46
|
+
display: block;
|
|
47
|
+
padding: 0.3em 1em 0.3em 1.8em;
|
|
48
|
+
color: #5E5549;
|
|
49
|
+
text-decoration: none;
|
|
50
|
+
font-size: 0.9em;
|
|
51
|
+
cursor: pointer;
|
|
52
|
+
border-left: 3px solid transparent;
|
|
53
|
+
transition: background 0.1s ease, border-color 0.1s ease;
|
|
54
|
+
}
|
|
55
|
+
.pict-inline-doc-nav-item:hover {
|
|
56
|
+
background: #EDE8DF;
|
|
57
|
+
color: #3D3229;
|
|
58
|
+
}
|
|
59
|
+
.pict-inline-doc-nav-item.active {
|
|
60
|
+
background: #E8E3D8;
|
|
61
|
+
color: #2E7D74;
|
|
62
|
+
border-left-color: #2E7D74;
|
|
63
|
+
font-weight: 500;
|
|
64
|
+
}
|
|
65
|
+
.pict-inline-doc-nav-topic-badge {
|
|
66
|
+
display: inline-block;
|
|
67
|
+
margin: 0.5em 1em;
|
|
68
|
+
padding: 0.3em 0.7em;
|
|
69
|
+
background: #2E7D74;
|
|
70
|
+
color: #fff;
|
|
71
|
+
border-radius: 4px;
|
|
72
|
+
font-size: 0.8em;
|
|
73
|
+
font-weight: 500;
|
|
74
|
+
}
|
|
75
|
+
.pict-inline-doc-nav-topic-clear {
|
|
76
|
+
margin-left: 0.5em;
|
|
77
|
+
cursor: pointer;
|
|
78
|
+
opacity: 0.8;
|
|
79
|
+
}
|
|
80
|
+
.pict-inline-doc-nav-topic-clear:hover {
|
|
81
|
+
opacity: 1;
|
|
82
|
+
}
|
|
83
|
+
.pict-inline-doc-nav-toolbar {
|
|
84
|
+
display: flex;
|
|
85
|
+
align-items: center;
|
|
86
|
+
gap: 0.3em;
|
|
87
|
+
padding: 0.3em 1em;
|
|
88
|
+
border-bottom: 1px solid #EAE3D8;
|
|
89
|
+
}
|
|
90
|
+
.pict-inline-doc-nav-toolbar-btn {
|
|
91
|
+
display: inline-flex;
|
|
92
|
+
align-items: center;
|
|
93
|
+
justify-content: center;
|
|
94
|
+
width: 28px;
|
|
95
|
+
height: 28px;
|
|
96
|
+
border: 1px solid #DDD6CA;
|
|
97
|
+
border-radius: 3px;
|
|
98
|
+
background: #fff;
|
|
99
|
+
color: #5E5549;
|
|
100
|
+
font-size: 0.9em;
|
|
101
|
+
cursor: pointer;
|
|
102
|
+
transition: background 0.1s, border-color 0.1s;
|
|
103
|
+
}
|
|
104
|
+
.pict-inline-doc-nav-toolbar-btn:hover {
|
|
105
|
+
background: #F0ECE4;
|
|
106
|
+
border-color: #C4BDB3;
|
|
107
|
+
}
|
|
108
|
+
.pict-inline-doc-nav-toolbar-btn.accent {
|
|
109
|
+
border-color: #2E7D74;
|
|
110
|
+
color: #2E7D74;
|
|
111
|
+
}
|
|
112
|
+
.pict-inline-doc-nav-toolbar-btn.accent:hover {
|
|
113
|
+
background: #F0F9F7;
|
|
114
|
+
}
|
|
115
|
+
.pict-inline-doc-nav-toolbar-btn.active {
|
|
116
|
+
background: #2E7D74;
|
|
117
|
+
color: #fff;
|
|
118
|
+
border-color: #2E7D74;
|
|
119
|
+
}
|
|
120
|
+
.pict-inline-doc-nav-toolbar-btn.active:hover {
|
|
121
|
+
background: #266D65;
|
|
122
|
+
}
|
|
123
|
+
.pict-inline-doc-nav-toolbar-spacer {
|
|
124
|
+
flex: 1;
|
|
125
|
+
}
|
|
126
|
+
/* Compact (horizontal) nav mode */
|
|
127
|
+
.pict-inline-doc-compact .pict-inline-doc-nav {
|
|
128
|
+
display: flex;
|
|
129
|
+
flex-wrap: wrap;
|
|
130
|
+
align-items: center;
|
|
131
|
+
padding: 0.4em 0.5em;
|
|
132
|
+
gap: 0.2em 0;
|
|
133
|
+
}
|
|
134
|
+
.pict-inline-doc-compact .pict-inline-doc-nav-group {
|
|
135
|
+
margin-bottom: 0;
|
|
136
|
+
display: flex;
|
|
137
|
+
align-items: center;
|
|
138
|
+
}
|
|
139
|
+
.pict-inline-doc-compact .pict-inline-doc-nav-group-header {
|
|
140
|
+
padding: 0.25em 0.5em;
|
|
141
|
+
font-size: 0.75em;
|
|
142
|
+
}
|
|
143
|
+
.pict-inline-doc-compact .pict-inline-doc-nav-group-toggle {
|
|
144
|
+
display: none;
|
|
145
|
+
}
|
|
146
|
+
.pict-inline-doc-compact .pict-inline-doc-nav-group-items {
|
|
147
|
+
display: flex !important;
|
|
148
|
+
flex-wrap: wrap;
|
|
149
|
+
gap: 0;
|
|
150
|
+
}
|
|
151
|
+
.pict-inline-doc-compact .pict-inline-doc-nav-item {
|
|
152
|
+
padding: 0.25em 0.6em;
|
|
153
|
+
font-size: 0.8em;
|
|
154
|
+
border-left: none;
|
|
155
|
+
border-bottom: 2px solid transparent;
|
|
156
|
+
white-space: nowrap;
|
|
157
|
+
}
|
|
158
|
+
.pict-inline-doc-compact .pict-inline-doc-nav-item.active {
|
|
159
|
+
border-left: none;
|
|
160
|
+
border-bottom-color: #2E7D74;
|
|
161
|
+
}
|
|
162
|
+
.pict-inline-doc-compact .pict-inline-doc-nav-topic-badge {
|
|
163
|
+
margin: 0 0.5em;
|
|
164
|
+
padding: 0.2em 0.5em;
|
|
165
|
+
font-size: 0.75em;
|
|
166
|
+
}
|
|
167
|
+
.pict-inline-doc-compact .pict-inline-doc-nav-toolbar {
|
|
168
|
+
padding: 0.2em 0.5em;
|
|
169
|
+
border-bottom: none;
|
|
170
|
+
border-right: 1px solid #EAE3D8;
|
|
171
|
+
}
|
|
172
|
+
.pict-inline-doc-compact .pict-inline-doc-nav-toolbar-btn {
|
|
173
|
+
width: 24px;
|
|
174
|
+
height: 24px;
|
|
175
|
+
font-size: 0.8em;
|
|
176
|
+
}
|
|
177
|
+
`,
|
|
178
|
+
|
|
179
|
+
Templates:
|
|
180
|
+
[
|
|
181
|
+
{
|
|
182
|
+
Hash: "InlineDoc-Nav-Template",
|
|
183
|
+
Template: /*html*/`<div class="pict-inline-doc-nav" id="InlineDoc-Nav-Body"></div>`
|
|
184
|
+
}
|
|
185
|
+
],
|
|
186
|
+
|
|
187
|
+
Renderables:
|
|
188
|
+
[
|
|
189
|
+
{
|
|
190
|
+
RenderableHash: "InlineDoc-Nav-Display",
|
|
191
|
+
TemplateHash: "InlineDoc-Nav-Template",
|
|
192
|
+
DestinationAddress: "#InlineDoc-Nav-Container",
|
|
193
|
+
RenderMethod: "replace"
|
|
194
|
+
}
|
|
195
|
+
]
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
class InlineDocumentationNavView extends libPictView
|
|
199
|
+
{
|
|
200
|
+
constructor(pFable, pOptions, pServiceHash)
|
|
201
|
+
{
|
|
202
|
+
super(pFable, pOptions, pServiceHash);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
onAfterRender()
|
|
206
|
+
{
|
|
207
|
+
this._renderNavigation();
|
|
208
|
+
return super.onAfterRender();
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Build and inject the navigation HTML into the nav body.
|
|
213
|
+
*/
|
|
214
|
+
_renderNavigation()
|
|
215
|
+
{
|
|
216
|
+
if (typeof document === 'undefined')
|
|
217
|
+
{
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
let tmpContainer = document.getElementById('InlineDoc-Nav-Body');
|
|
222
|
+
if (!tmpContainer)
|
|
223
|
+
{
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
let tmpState = this.pict.AppData.InlineDocumentation;
|
|
228
|
+
if (!tmpState)
|
|
229
|
+
{
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
let tmpHTML = '';
|
|
234
|
+
let tmpCurrentPath = tmpState.CurrentPath || '';
|
|
235
|
+
let tmpActiveTopic = tmpState.Topic;
|
|
236
|
+
let tmpTopicDef = null;
|
|
237
|
+
let tmpTopicDocuments = null;
|
|
238
|
+
|
|
239
|
+
// If a topic is active, show a badge and filter documents.
|
|
240
|
+
// Supports both formats:
|
|
241
|
+
// pict_documentation_topics.json: { TopicCode, TopicTitle, TopicHelpFilePath }
|
|
242
|
+
// legacy: { Name, Documents: [] }
|
|
243
|
+
if (tmpActiveTopic && tmpState.Topics && tmpState.Topics[tmpActiveTopic])
|
|
244
|
+
{
|
|
245
|
+
tmpTopicDef = tmpState.Topics[tmpActiveTopic];
|
|
246
|
+
|
|
247
|
+
// Determine the display name (TopicTitle or Name)
|
|
248
|
+
let tmpTopicName = tmpTopicDef.TopicTitle || tmpTopicDef.Name || tmpActiveTopic;
|
|
249
|
+
|
|
250
|
+
// Determine matching documents
|
|
251
|
+
if (tmpTopicDef.TopicHelpFilePath)
|
|
252
|
+
{
|
|
253
|
+
// pict_documentation_topics.json format — single file per topic
|
|
254
|
+
tmpTopicDocuments = [tmpTopicDef.TopicHelpFilePath];
|
|
255
|
+
}
|
|
256
|
+
else if (tmpTopicDef.Documents)
|
|
257
|
+
{
|
|
258
|
+
// Legacy format — array of document paths
|
|
259
|
+
tmpTopicDocuments = tmpTopicDef.Documents;
|
|
260
|
+
}
|
|
261
|
+
else
|
|
262
|
+
{
|
|
263
|
+
tmpTopicDocuments = [];
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
tmpHTML += '<div class="pict-inline-doc-nav-topic-badge">'
|
|
267
|
+
+ this._escapeHTML(tmpTopicName)
|
|
268
|
+
+ '<span class="pict-inline-doc-nav-topic-clear" id="InlineDoc-Nav-ClearTopic">✕</span>'
|
|
269
|
+
+ '</div>';
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// Topic management toolbar
|
|
273
|
+
if (tmpState.TopicManagerEnabled)
|
|
274
|
+
{
|
|
275
|
+
tmpHTML += '<div class="pict-inline-doc-nav-toolbar">';
|
|
276
|
+
tmpHTML += '<button class="pict-inline-doc-nav-toolbar-btn" id="InlineDoc-Nav-ManageTopics" title="Manage Topics">⚙</button>';
|
|
277
|
+
if (tmpState.CurrentRoute)
|
|
278
|
+
{
|
|
279
|
+
tmpHTML += '<button class="pict-inline-doc-nav-toolbar-btn accent" id="InlineDoc-Nav-BindTopic" title="Bind topic to current route">🔗</button>';
|
|
280
|
+
}
|
|
281
|
+
let tmpTooltipEditActive = tmpState.TooltipEditMode ? ' active' : '';
|
|
282
|
+
tmpHTML += '<button class="pict-inline-doc-nav-toolbar-btn' + tmpTooltipEditActive + '" id="InlineDoc-Nav-TooltipEditMode" title="Toggle tooltip edit mode">💬</button>';
|
|
283
|
+
tmpHTML += '<span class="pict-inline-doc-nav-toolbar-spacer"></span>';
|
|
284
|
+
tmpHTML += '</div>';
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
let tmpGroups = tmpState.SidebarGroups || [];
|
|
288
|
+
|
|
289
|
+
for (let i = 0; i < tmpGroups.length; i++)
|
|
290
|
+
{
|
|
291
|
+
let tmpGroup = tmpGroups[i];
|
|
292
|
+
let tmpGroupItems = tmpGroup.Items || [];
|
|
293
|
+
|
|
294
|
+
// If topic filter is active, only include items that match
|
|
295
|
+
if (tmpTopicDocuments)
|
|
296
|
+
{
|
|
297
|
+
tmpGroupItems = tmpGroupItems.filter((pItem) =>
|
|
298
|
+
{
|
|
299
|
+
return tmpTopicDocuments.indexOf(pItem.Path) >= 0;
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
// Also check if the group-level path matches
|
|
303
|
+
let tmpGroupMatches = tmpTopicDocuments.indexOf(tmpGroup.Path) >= 0;
|
|
304
|
+
|
|
305
|
+
if (tmpGroupItems.length < 1 && !tmpGroupMatches)
|
|
306
|
+
{
|
|
307
|
+
continue;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
tmpHTML += '<div class="pict-inline-doc-nav-group" data-group="' + this._escapeHTML(tmpGroup.Key) + '">';
|
|
312
|
+
tmpHTML += '<div class="pict-inline-doc-nav-group-header">';
|
|
313
|
+
tmpHTML += '<span class="pict-inline-doc-nav-group-toggle">▼</span>';
|
|
314
|
+
tmpHTML += this._escapeHTML(tmpGroup.Name);
|
|
315
|
+
tmpHTML += '</div>';
|
|
316
|
+
|
|
317
|
+
tmpHTML += '<div class="pict-inline-doc-nav-group-items">';
|
|
318
|
+
|
|
319
|
+
// If the group itself has a path (it's a link), show it as the first item
|
|
320
|
+
if (tmpGroup.Path)
|
|
321
|
+
{
|
|
322
|
+
let tmpActive = (tmpCurrentPath === tmpGroup.Path) ? ' active' : '';
|
|
323
|
+
tmpHTML += '<a class="pict-inline-doc-nav-item' + tmpActive
|
|
324
|
+
+ '" data-doc-path="' + this._escapeHTML(tmpGroup.Path) + '">'
|
|
325
|
+
+ this._escapeHTML(tmpGroup.Name)
|
|
326
|
+
+ '</a>';
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
for (let j = 0; j < tmpGroupItems.length; j++)
|
|
330
|
+
{
|
|
331
|
+
let tmpItem = tmpGroupItems[j];
|
|
332
|
+
if (!tmpItem.Path)
|
|
333
|
+
{
|
|
334
|
+
tmpHTML += '<span class="pict-inline-doc-nav-item">' + this._escapeHTML(tmpItem.Name) + '</span>';
|
|
335
|
+
continue;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
let tmpActive = (tmpCurrentPath === tmpItem.Path) ? ' active' : '';
|
|
339
|
+
tmpHTML += '<a class="pict-inline-doc-nav-item' + tmpActive
|
|
340
|
+
+ '" data-doc-path="' + this._escapeHTML(tmpItem.Path) + '">'
|
|
341
|
+
+ this._escapeHTML(tmpItem.Name)
|
|
342
|
+
+ '</a>';
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
tmpHTML += '</div>';
|
|
346
|
+
tmpHTML += '</div>';
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
tmpContainer.innerHTML = tmpHTML;
|
|
350
|
+
|
|
351
|
+
// Wire up click handlers
|
|
352
|
+
this._wireClickHandlers(tmpContainer);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* Wire click handlers on navigation items and group headers.
|
|
357
|
+
*
|
|
358
|
+
* @param {HTMLElement} pContainer - The nav container element
|
|
359
|
+
*/
|
|
360
|
+
_wireClickHandlers(pContainer)
|
|
361
|
+
{
|
|
362
|
+
let tmpProvider = this.pict.providers['Pict-InlineDocumentation'];
|
|
363
|
+
|
|
364
|
+
// Document links
|
|
365
|
+
let tmpLinks = pContainer.querySelectorAll('.pict-inline-doc-nav-item[data-doc-path]');
|
|
366
|
+
for (let i = 0; i < tmpLinks.length; i++)
|
|
367
|
+
{
|
|
368
|
+
let tmpLink = tmpLinks[i];
|
|
369
|
+
tmpLink.addEventListener('click', (pEvent) =>
|
|
370
|
+
{
|
|
371
|
+
pEvent.preventDefault();
|
|
372
|
+
let tmpPath = tmpLink.getAttribute('data-doc-path');
|
|
373
|
+
if (tmpProvider && tmpPath)
|
|
374
|
+
{
|
|
375
|
+
tmpProvider.loadDocument(tmpPath);
|
|
376
|
+
}
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
// Group collapse toggle
|
|
381
|
+
let tmpHeaders = pContainer.querySelectorAll('.pict-inline-doc-nav-group-header');
|
|
382
|
+
for (let i = 0; i < tmpHeaders.length; i++)
|
|
383
|
+
{
|
|
384
|
+
let tmpHeader = tmpHeaders[i];
|
|
385
|
+
tmpHeader.addEventListener('click', () =>
|
|
386
|
+
{
|
|
387
|
+
let tmpGroup = tmpHeader.parentElement;
|
|
388
|
+
if (tmpGroup)
|
|
389
|
+
{
|
|
390
|
+
tmpGroup.classList.toggle('collapsed');
|
|
391
|
+
}
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
// Topic clear button
|
|
396
|
+
let tmpClearBtn = pContainer.querySelector('#InlineDoc-Nav-ClearTopic');
|
|
397
|
+
if (tmpClearBtn && tmpProvider)
|
|
398
|
+
{
|
|
399
|
+
tmpClearBtn.addEventListener('click', (pEvent) =>
|
|
400
|
+
{
|
|
401
|
+
pEvent.stopPropagation();
|
|
402
|
+
tmpProvider.clearTopic();
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// Topic manager button
|
|
407
|
+
let tmpManageBtn = pContainer.querySelector('#InlineDoc-Nav-ManageTopics');
|
|
408
|
+
if (tmpManageBtn)
|
|
409
|
+
{
|
|
410
|
+
tmpManageBtn.addEventListener('click', (pEvent) =>
|
|
411
|
+
{
|
|
412
|
+
pEvent.stopPropagation();
|
|
413
|
+
let tmpTopicManagerView = this.pict.views['InlineDoc-TopicManager'];
|
|
414
|
+
if (tmpTopicManagerView)
|
|
415
|
+
{
|
|
416
|
+
tmpTopicManagerView.showTopicManager();
|
|
417
|
+
}
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
// Tooltip edit mode toggle
|
|
422
|
+
let tmpTooltipEditBtn = pContainer.querySelector('#InlineDoc-Nav-TooltipEditMode');
|
|
423
|
+
if (tmpTooltipEditBtn)
|
|
424
|
+
{
|
|
425
|
+
tmpTooltipEditBtn.addEventListener('click', (pEvent) =>
|
|
426
|
+
{
|
|
427
|
+
pEvent.stopPropagation();
|
|
428
|
+
let tmpDocProvider = this.pict.providers['Pict-InlineDocumentation'];
|
|
429
|
+
if (tmpDocProvider)
|
|
430
|
+
{
|
|
431
|
+
let tmpCurrentState = this.pict.AppData.InlineDocumentation;
|
|
432
|
+
tmpDocProvider.setTooltipEditMode(!tmpCurrentState.TooltipEditMode);
|
|
433
|
+
}
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
// Bind topic to route button
|
|
438
|
+
let tmpBindBtn = pContainer.querySelector('#InlineDoc-Nav-BindTopic');
|
|
439
|
+
if (tmpBindBtn)
|
|
440
|
+
{
|
|
441
|
+
tmpBindBtn.addEventListener('click', (pEvent) =>
|
|
442
|
+
{
|
|
443
|
+
pEvent.stopPropagation();
|
|
444
|
+
let tmpTopicManagerView = this.pict.views['InlineDoc-TopicManager'];
|
|
445
|
+
if (tmpTopicManagerView)
|
|
446
|
+
{
|
|
447
|
+
tmpTopicManagerView.showBindTopicToRoute();
|
|
448
|
+
}
|
|
449
|
+
});
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
/**
|
|
454
|
+
* Escape HTML special characters.
|
|
455
|
+
*
|
|
456
|
+
* @param {string} pText - Text to escape
|
|
457
|
+
* @returns {string} Escaped text
|
|
458
|
+
*/
|
|
459
|
+
_escapeHTML(pText)
|
|
460
|
+
{
|
|
461
|
+
if (!pText)
|
|
462
|
+
{
|
|
463
|
+
return '';
|
|
464
|
+
}
|
|
465
|
+
return pText
|
|
466
|
+
.replace(/&/g, '&')
|
|
467
|
+
.replace(/</g, '<')
|
|
468
|
+
.replace(/>/g, '>')
|
|
469
|
+
.replace(/"/g, '"');
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
module.exports = InlineDocumentationNavView;
|
|
474
|
+
|
|
475
|
+
module.exports.default_configuration = _ViewConfiguration;
|