ultravisor 1.0.3 → 1.0.8

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 (248) hide show
  1. package/.claude/launch.json +11 -0
  2. package/.claude/ultravisor-dev-config.json +3 -0
  3. package/card-audit.json +1545 -0
  4. package/docs/_sidebar.md +17 -0
  5. package/docs/css/docuserve.css +73 -0
  6. package/docs/features/beacon-authentication.md +209 -0
  7. package/docs/features/beacon-providers.md +1299 -0
  8. package/docs/features/beacons.md +530 -0
  9. package/docs/features/capabilities.md +193 -0
  10. package/docs/features/llm-model-setup.md +505 -0
  11. package/docs/features/llm.md +262 -0
  12. package/docs/features/tasks-content-system.md +110 -0
  13. package/docs/features/tasks-data-transform.md +233 -0
  14. package/docs/features/tasks-extension.md +36 -0
  15. package/docs/features/tasks-file-system.md +203 -0
  16. package/docs/features/tasks-flow-control.md +125 -0
  17. package/docs/features/tasks-http-client.md +119 -0
  18. package/docs/features/tasks-llm.md +118 -0
  19. package/docs/features/tasks-meadow-api.md +163 -0
  20. package/docs/features/tasks-user-interaction.md +49 -0
  21. package/docs/features/tasks.md +14 -0
  22. package/docs/index.html +1 -1
  23. package/docs/retold-catalog.json +1 -1
  24. package/docs/retold-keyword-index.json +17374 -5
  25. package/operation-library/api-data-pipeline.json +143 -0
  26. package/operation-library/beacon-remote-command.json +72 -0
  27. package/operation-library/conditional-file-backup.json +143 -0
  28. package/operation-library/config-processor.json +136 -0
  29. package/operation-library/csv-data-analysis.json +228 -0
  30. package/operation-library/csv-to-json.json +160 -0
  31. package/operation-library/directory-inventory.json +128 -0
  32. package/operation-library/expression-calculator.json +114 -0
  33. package/operation-library/file-search-replace.json +175 -0
  34. package/operation-library/git-status-report.json +368 -0
  35. package/operation-library/health-check-ping.json +329 -0
  36. package/operation-library/json-config-merge.json +313 -0
  37. package/operation-library/llm-embedding-tool-use.json +314 -0
  38. package/operation-library/llm-multi-turn-analysis.json +322 -0
  39. package/operation-library/llm-summarize.json +264 -0
  40. package/operation-library/log-line-counter.json +185 -0
  41. package/operation-library/meadow-crud-lifecycle.json +264 -0
  42. package/operation-library/npm-project-validator.json +193 -0
  43. package/operation-library/rest-api-orchestrator.json +218 -0
  44. package/operation-library/shell-system-info.json +137 -0
  45. package/operation-library/simple-echo.json +95 -0
  46. package/operation-library/template-processor.json +299 -0
  47. package/operation-library/text-sanitizer.json +176 -0
  48. package/package.json +12 -8
  49. package/source/Ultravisor.cjs +30 -3
  50. package/source/beacon/Ultravisor-Beacon-CLI.cjs +143 -0
  51. package/source/beacon/Ultravisor-Beacon-CapabilityProvider.cjs +129 -0
  52. package/source/beacon/Ultravisor-Beacon-Client.cjs +568 -0
  53. package/source/beacon/Ultravisor-Beacon-Executor.cjs +500 -0
  54. package/source/beacon/Ultravisor-Beacon-ProviderRegistry.cjs +330 -0
  55. package/source/beacon/providers/Ultravisor-Beacon-Provider-FileSystem.cjs +331 -0
  56. package/source/beacon/providers/Ultravisor-Beacon-Provider-LLM.cjs +966 -0
  57. package/source/beacon/providers/Ultravisor-Beacon-Provider-Shell.cjs +95 -0
  58. package/source/cli/Ultravisor-CLIProgram.cjs +44 -22
  59. package/source/cli/commands/Ultravisor-Command-SingleOperation.cjs +29 -18
  60. package/source/cli/commands/Ultravisor-Command-SingleTask.cjs +62 -19
  61. package/source/cli/commands/Ultravisor-Command-UpdateTask.cjs +27 -15
  62. package/source/config/Ultravisor-Default-Command-Configuration.cjs +12 -3
  63. package/source/services/Ultravisor-Beacon-Coordinator.cjs +966 -0
  64. package/source/services/Ultravisor-ExecutionEngine.cjs +1093 -0
  65. package/source/services/Ultravisor-ExecutionManifest.cjs +629 -0
  66. package/source/services/Ultravisor-Hypervisor-State.cjs +270 -97
  67. package/source/services/Ultravisor-Hypervisor.cjs +185 -75
  68. package/source/services/Ultravisor-Schedule-Persistence-Base.cjs +45 -0
  69. package/source/services/Ultravisor-StateManager.cjs +253 -0
  70. package/source/services/Ultravisor-TaskTypeRegistry.cjs +213 -0
  71. package/source/services/persistence/Ultravisor-Schedule-Persistence-JSONFile.cjs +140 -0
  72. package/source/services/tasks/Ultravisor-BuiltIn-TaskConfigs.cjs +19 -0
  73. package/source/services/tasks/Ultravisor-TaskHelper-BeaconDispatch.cjs +107 -0
  74. package/source/services/tasks/Ultravisor-TaskType-Base.cjs +125 -0
  75. package/source/services/tasks/content-system/Ultravisor-TaskConfigs-ContentSystem.cjs +90 -0
  76. package/source/services/tasks/content-system/definitions/content-create-folder.json +24 -0
  77. package/source/services/tasks/content-system/definitions/content-list-files.json +27 -0
  78. package/source/services/tasks/content-system/definitions/content-read-file.json +26 -0
  79. package/source/services/tasks/content-system/definitions/content-save-file.json +26 -0
  80. package/source/services/tasks/data-transform/Ultravisor-TaskConfigs-DataTransform.cjs +577 -0
  81. package/source/services/tasks/data-transform/Ultravisor-TaskType-ReplaceString.cjs +80 -0
  82. package/source/services/tasks/data-transform/Ultravisor-TaskType-SetValues.cjs +74 -0
  83. package/source/services/tasks/data-transform/Ultravisor-TaskType-StringAppender.cjs +90 -0
  84. package/source/services/tasks/data-transform/definitions/comprehension-intersect.json +24 -0
  85. package/source/services/tasks/data-transform/definitions/csv-transform.json +24 -0
  86. package/source/services/tasks/data-transform/definitions/expression-solver.json +20 -0
  87. package/source/services/tasks/data-transform/definitions/histogram.json +23 -0
  88. package/source/services/tasks/data-transform/definitions/parse-csv.json +27 -0
  89. package/source/services/tasks/data-transform/definitions/replace-string.json +27 -0
  90. package/source/services/tasks/data-transform/definitions/set-values.json +17 -0
  91. package/source/services/tasks/data-transform/definitions/string-appender.json +22 -0
  92. package/source/services/tasks/data-transform/definitions/template-string.json +20 -0
  93. package/source/services/tasks/extension/Ultravisor-TaskConfigs-Extension.cjs +87 -0
  94. package/source/services/tasks/extension/definitions/beacon-dispatch.json +32 -0
  95. package/source/services/tasks/file-system/Ultravisor-TaskConfigs-FileSystem.cjs +509 -0
  96. package/source/services/tasks/file-system/Ultravisor-TaskType-ReadFile.cjs +96 -0
  97. package/source/services/tasks/file-system/Ultravisor-TaskType-ReadFileBuffered.cjs +123 -0
  98. package/source/services/tasks/file-system/Ultravisor-TaskType-WriteFile.cjs +106 -0
  99. package/source/services/tasks/file-system/definitions/copy-file.json +27 -0
  100. package/source/services/tasks/file-system/definitions/list-files.json +27 -0
  101. package/source/services/tasks/file-system/definitions/read-file-buffered.json +31 -0
  102. package/source/services/tasks/file-system/definitions/read-file.json +26 -0
  103. package/source/services/tasks/file-system/definitions/read-json.json +23 -0
  104. package/source/services/tasks/file-system/definitions/write-file.json +29 -0
  105. package/source/services/tasks/file-system/definitions/write-json.json +30 -0
  106. package/source/services/tasks/flow-control/Ultravisor-TaskConfigs-FlowControl.cjs +353 -0
  107. package/source/services/tasks/flow-control/Ultravisor-TaskType-IfConditional.cjs +125 -0
  108. package/source/services/tasks/flow-control/Ultravisor-TaskType-LaunchOperation.cjs +186 -0
  109. package/source/services/tasks/flow-control/Ultravisor-TaskType-SplitExecute.cjs +164 -0
  110. package/source/services/tasks/flow-control/definitions/if-conditional.json +25 -0
  111. package/source/services/tasks/flow-control/definitions/launch-operation.json +27 -0
  112. package/source/services/tasks/flow-control/definitions/split-execute.json +32 -0
  113. package/source/services/tasks/http-client/Ultravisor-TaskConfigs-HttpClient.cjs +281 -0
  114. package/source/services/tasks/http-client/definitions/get-json.json +26 -0
  115. package/source/services/tasks/http-client/definitions/get-text.json +26 -0
  116. package/source/services/tasks/http-client/definitions/rest-request.json +32 -0
  117. package/source/services/tasks/http-client/definitions/send-json.json +28 -0
  118. package/source/services/tasks/llm/Ultravisor-TaskConfigs-LLM.cjs +605 -0
  119. package/source/services/tasks/llm/definitions/llm-chat-completion.json +46 -0
  120. package/source/services/tasks/llm/definitions/llm-embedding.json +31 -0
  121. package/source/services/tasks/llm/definitions/llm-tool-use.json +42 -0
  122. package/source/services/tasks/meadow-api/Ultravisor-TaskConfigs-MeadowApi.cjs +341 -0
  123. package/source/services/tasks/meadow-api/definitions/meadow-count.json +26 -0
  124. package/source/services/tasks/meadow-api/definitions/meadow-create.json +26 -0
  125. package/source/services/tasks/meadow-api/definitions/meadow-delete.json +23 -0
  126. package/source/services/tasks/meadow-api/definitions/meadow-read.json +26 -0
  127. package/source/services/tasks/meadow-api/definitions/meadow-reads.json +29 -0
  128. package/source/services/tasks/meadow-api/definitions/meadow-update.json +26 -0
  129. package/source/services/tasks/shell/Ultravisor-TaskConfigs-Shell.cjs +63 -0
  130. package/source/services/tasks/shell/definitions/command.json +29 -0
  131. package/source/services/tasks/user-interaction/Ultravisor-TaskConfigs-UserInteraction.cjs +64 -0
  132. package/source/services/tasks/user-interaction/Ultravisor-TaskType-ErrorMessage.cjs +55 -0
  133. package/source/services/tasks/user-interaction/Ultravisor-TaskType-ValueInput.cjs +47 -0
  134. package/source/services/tasks/user-interaction/definitions/error-message.json +18 -0
  135. package/source/services/tasks/user-interaction/definitions/value-input.json +23 -0
  136. package/source/web_server/Ultravisor-API-Server.cjs +849 -124
  137. package/test/Ultravisor_browser_tests.js +2226 -0
  138. package/test/Ultravisor_operation_library_tests.js +894 -0
  139. package/test/Ultravisor_tests.js +4946 -5044
  140. package/test/workflows/test-content-concatenate-all.json +339 -0
  141. package/test/workflows/test-content-full-pipeline.json +159 -0
  142. package/test/workflows/test-content-list-files.json +76 -0
  143. package/test/workflows/test-content-save-and-read.json +106 -0
  144. package/webinterface/css/ultravisor-themes.css +668 -0
  145. package/webinterface/css/ultravisor.css +37 -14
  146. package/webinterface/docs/card-help/beacon-dispatch.md +30 -0
  147. package/webinterface/docs/card-help/command.md +27 -0
  148. package/webinterface/docs/card-help/comprehension-intersect.md +24 -0
  149. package/webinterface/docs/card-help/content-create-folder.md +22 -0
  150. package/webinterface/docs/card-help/content-list-files.md +25 -0
  151. package/webinterface/docs/card-help/content-read-file.md +24 -0
  152. package/webinterface/docs/card-help/content-save-file.md +24 -0
  153. package/webinterface/docs/card-help/copy-file.md +25 -0
  154. package/webinterface/docs/card-help/csv-transform.md +24 -0
  155. package/webinterface/docs/card-help/end.md +11 -0
  156. package/webinterface/docs/card-help/error-message.md +16 -0
  157. package/webinterface/docs/card-help/expression-solver.md +21 -0
  158. package/webinterface/docs/card-help/get-json.md +24 -0
  159. package/webinterface/docs/card-help/get-text.md +24 -0
  160. package/webinterface/docs/card-help/histogram.md +23 -0
  161. package/webinterface/docs/card-help/if-conditional.md +23 -0
  162. package/webinterface/docs/card-help/launch-operation.md +25 -0
  163. package/webinterface/docs/card-help/list-files.md +25 -0
  164. package/webinterface/docs/card-help/llm-chat-completion.md +43 -0
  165. package/webinterface/docs/card-help/llm-embedding.md +24 -0
  166. package/webinterface/docs/card-help/llm-tool-use.md +39 -0
  167. package/webinterface/docs/card-help/meadow-count.md +24 -0
  168. package/webinterface/docs/card-help/meadow-create.md +24 -0
  169. package/webinterface/docs/card-help/meadow-delete.md +19 -0
  170. package/webinterface/docs/card-help/meadow-read.md +24 -0
  171. package/webinterface/docs/card-help/meadow-reads.md +27 -0
  172. package/webinterface/docs/card-help/meadow-update.md +24 -0
  173. package/webinterface/docs/card-help/parse-csv.md +27 -0
  174. package/webinterface/docs/card-help/read-file-buffered.md +29 -0
  175. package/webinterface/docs/card-help/read-file.md +24 -0
  176. package/webinterface/docs/card-help/read-json.md +21 -0
  177. package/webinterface/docs/card-help/replace-string.md +25 -0
  178. package/webinterface/docs/card-help/rest-request.md +30 -0
  179. package/webinterface/docs/card-help/send-json.md +26 -0
  180. package/webinterface/docs/card-help/set-values.md +16 -0
  181. package/webinterface/docs/card-help/split-execute.md +35 -0
  182. package/webinterface/docs/card-help/start.md +11 -0
  183. package/webinterface/docs/card-help/string-appender.md +22 -0
  184. package/webinterface/docs/card-help/template-string.md +21 -0
  185. package/webinterface/docs/card-help/value-input.md +24 -0
  186. package/webinterface/docs/card-help/write-file.md +27 -0
  187. package/webinterface/docs/card-help/write-json.md +28 -0
  188. package/webinterface/html/index.html +5 -0
  189. package/webinterface/package.json +13 -4
  190. package/webinterface/source/Pict-Application-Ultravisor.js +564 -70
  191. package/webinterface/source/Ultravisor-TimingUtils.js +99 -0
  192. package/webinterface/source/card-help-content.js +46 -0
  193. package/webinterface/source/cards/Ultravisor-BuiltIn-CardConfigs.js +174 -0
  194. package/webinterface/source/cards/Ultravisor-CardConfigGenerator.js +431 -0
  195. package/webinterface/source/data/ExampleFlow-CSVPipeline.js +231 -0
  196. package/webinterface/source/data/ExampleFlow-FileProcessor.js +315 -0
  197. package/webinterface/source/data/ExampleFlow-MeadowPipeline.js +328 -0
  198. package/webinterface/source/panels/Ultravisor-CardSettingsPanel.js +902 -0
  199. package/webinterface/source/providers/PictRouter-Ultravisor-Configuration.json +20 -8
  200. package/webinterface/source/views/PictView-Ultravisor-BeaconList.js +817 -0
  201. package/webinterface/source/views/PictView-Ultravisor-BottomBar.js +5 -5
  202. package/webinterface/source/views/PictView-Ultravisor-Dashboard.js +25 -25
  203. package/webinterface/source/views/PictView-Ultravisor-Documentation.js +856 -0
  204. package/webinterface/source/views/PictView-Ultravisor-FlowEditor.js +777 -0
  205. package/webinterface/source/views/PictView-Ultravisor-ManifestList.js +321 -58
  206. package/webinterface/source/views/PictView-Ultravisor-OperationEdit.js +36 -91
  207. package/webinterface/source/views/PictView-Ultravisor-OperationList.js +388 -16
  208. package/webinterface/source/views/PictView-Ultravisor-PendingInput.js +314 -0
  209. package/webinterface/source/views/PictView-Ultravisor-Schedule.js +521 -65
  210. package/webinterface/source/views/PictView-Ultravisor-TimingView.js +333 -71
  211. package/webinterface/source/views/PictView-Ultravisor-TopBar.js +257 -21
  212. package/webinterface/theme-sampler.html +645 -0
  213. package/debug/Harness.js +0 -6
  214. package/source/services/Ultravisor-Operation-Manifest.cjs +0 -160
  215. package/source/services/Ultravisor-Operation.cjs +0 -200
  216. package/source/services/Ultravisor-Task.cjs +0 -349
  217. package/source/services/events/Ultravisor-Hypervisor-Event-Solver.cjs +0 -11
  218. package/source/services/tasks/Ultravisor-Task-Base.cjs +0 -264
  219. package/source/services/tasks/Ultravisor-Task-CollectValues.cjs +0 -188
  220. package/source/services/tasks/Ultravisor-Task-Command.cjs +0 -65
  221. package/source/services/tasks/Ultravisor-Task-CommandEach.cjs +0 -190
  222. package/source/services/tasks/Ultravisor-Task-Conditional.cjs +0 -104
  223. package/source/services/tasks/Ultravisor-Task-DateWindow.cjs +0 -72
  224. package/source/services/tasks/Ultravisor-Task-GeneratePagedOperation.cjs +0 -336
  225. package/source/services/tasks/Ultravisor-Task-LaunchOperation.cjs +0 -143
  226. package/source/services/tasks/Ultravisor-Task-LaunchTask.cjs +0 -146
  227. package/source/services/tasks/Ultravisor-Task-LineMatch.cjs +0 -158
  228. package/source/services/tasks/Ultravisor-Task-Request.cjs +0 -56
  229. package/source/services/tasks/Ultravisor-Task-Solver.cjs +0 -89
  230. package/source/services/tasks/Ultravisor-Task-TemplateString.cjs +0 -93
  231. package/source/services/tasks/rest/Ultravisor-Task-GetBinary.cjs +0 -127
  232. package/source/services/tasks/rest/Ultravisor-Task-GetJSON.cjs +0 -119
  233. package/source/services/tasks/rest/Ultravisor-Task-GetText.cjs +0 -109
  234. package/source/services/tasks/rest/Ultravisor-Task-GetXML.cjs +0 -112
  235. package/source/services/tasks/rest/Ultravisor-Task-RestRequest.cjs +0 -499
  236. package/source/services/tasks/rest/Ultravisor-Task-SendJSON.cjs +0 -150
  237. package/source/services/tasks/stagingfiles/Ultravisor-Task-CopyFile.cjs +0 -110
  238. package/source/services/tasks/stagingfiles/Ultravisor-Task-ListFiles.cjs +0 -89
  239. package/source/services/tasks/stagingfiles/Ultravisor-Task-ReadBinary.cjs +0 -87
  240. package/source/services/tasks/stagingfiles/Ultravisor-Task-ReadJSON.cjs +0 -67
  241. package/source/services/tasks/stagingfiles/Ultravisor-Task-ReadText.cjs +0 -66
  242. package/source/services/tasks/stagingfiles/Ultravisor-Task-ReadXML.cjs +0 -69
  243. package/source/services/tasks/stagingfiles/Ultravisor-Task-WriteBinary.cjs +0 -95
  244. package/source/services/tasks/stagingfiles/Ultravisor-Task-WriteJSON.cjs +0 -96
  245. package/source/services/tasks/stagingfiles/Ultravisor-Task-WriteText.cjs +0 -99
  246. package/source/services/tasks/stagingfiles/Ultravisor-Task-WriteXML.cjs +0 -102
  247. package/webinterface/source/views/PictView-Ultravisor-TaskEdit.js +0 -220
  248. package/webinterface/source/views/PictView-Ultravisor-TaskList.js +0 -248
@@ -0,0 +1,856 @@
1
+ const libPictView = require('pict-view');
2
+ const libDocuserveProvider = require('pict-docuserve/source/providers/Pict-Provider-Docuserve-Documentation.js');
3
+
4
+ const _ViewConfiguration =
5
+ {
6
+ ViewIdentifier: "Ultravisor-Documentation",
7
+
8
+ DefaultRenderable: "Ultravisor-Documentation-Content",
9
+ DefaultDestinationAddress: "#Ultravisor-Content-Container",
10
+
11
+ AutoRender: false,
12
+
13
+ CSS: /*css*/`
14
+ .ultravisor-docs {
15
+ display: flex;
16
+ height: calc(100vh - 56px - 39px);
17
+ min-height: 400px;
18
+ overflow: hidden;
19
+ }
20
+ .ultravisor-docs-sidebar {
21
+ flex-shrink: 0;
22
+ width: 260px;
23
+ background-color: var(--uv-bg-surface);
24
+ border-right: 1px solid var(--uv-border-subtle);
25
+ overflow-y: auto;
26
+ display: flex;
27
+ flex-direction: column;
28
+ }
29
+ .ultravisor-docs-sidebar-search {
30
+ padding: 0.75em;
31
+ border-bottom: 1px solid var(--uv-border-subtle);
32
+ }
33
+ .ultravisor-docs-sidebar-search input {
34
+ width: 100%;
35
+ padding: 0.4em 0.6em;
36
+ border: 1px solid var(--uv-border-subtle);
37
+ border-radius: 4px;
38
+ background: var(--uv-bg-elevated);
39
+ color: var(--uv-text);
40
+ font-size: 0.85em;
41
+ outline: none;
42
+ box-sizing: border-box;
43
+ }
44
+ .ultravisor-docs-sidebar-search input:focus {
45
+ border-color: var(--uv-brand);
46
+ }
47
+ .ultravisor-docs-sidebar-search input::placeholder {
48
+ color: var(--uv-text-tertiary);
49
+ }
50
+ .ultravisor-docs-search-results {
51
+ margin-top: 0.5em;
52
+ }
53
+ .ultravisor-docs-search-results a {
54
+ display: block;
55
+ padding: 0.35em 0.5em;
56
+ color: var(--uv-text-secondary);
57
+ text-decoration: none;
58
+ font-size: 0.8em;
59
+ border-radius: 3px;
60
+ cursor: pointer;
61
+ }
62
+ .ultravisor-docs-search-results a:hover {
63
+ background-color: var(--uv-topbar-hover);
64
+ color: #fff;
65
+ }
66
+ .ultravisor-docs-search-result-title {
67
+ font-weight: 600;
68
+ color: var(--uv-text);
69
+ }
70
+ .ultravisor-docs-search-results a:hover .ultravisor-docs-search-result-title {
71
+ color: #fff;
72
+ }
73
+ .ultravisor-docs-search-result-meta {
74
+ font-size: 0.9em;
75
+ color: var(--uv-text-tertiary);
76
+ }
77
+ .ultravisor-docs-sidebar-nav {
78
+ flex: 1;
79
+ overflow-y: auto;
80
+ padding: 0.5em 0;
81
+ }
82
+ .ultravisor-docs-sidebar-home {
83
+ padding: 0.5em 1em;
84
+ }
85
+ .ultravisor-docs-sidebar-home a {
86
+ color: var(--uv-link);
87
+ text-decoration: none;
88
+ font-weight: 600;
89
+ font-size: 0.85em;
90
+ cursor: pointer;
91
+ }
92
+ .ultravisor-docs-sidebar-home a:hover {
93
+ color: var(--uv-link-hover);
94
+ }
95
+ .ultravisor-docs-sidebar-group {
96
+ margin-top: 0.25em;
97
+ }
98
+ .ultravisor-docs-group-title {
99
+ display: block;
100
+ padding: 0.5em 1em;
101
+ font-weight: 600;
102
+ font-size: 0.8em;
103
+ color: var(--uv-text-secondary);
104
+ text-transform: uppercase;
105
+ letter-spacing: 0.04em;
106
+ cursor: pointer;
107
+ text-decoration: none;
108
+ transition: background-color 0.15s, color 0.15s;
109
+ }
110
+ .ultravisor-docs-group-title:hover {
111
+ color: var(--uv-link);
112
+ background-color: #1a2744;
113
+ }
114
+ .ultravisor-docs-group-title.active {
115
+ color: var(--uv-link);
116
+ background-color: var(--uv-bg-elevated);
117
+ }
118
+ .ultravisor-docs-module-list {
119
+ list-style: none;
120
+ margin: 0;
121
+ padding: 0;
122
+ }
123
+ .ultravisor-docs-module-list a {
124
+ display: block;
125
+ padding: 0.3em 1em 0.3em 1.75em;
126
+ color: var(--uv-text-secondary);
127
+ text-decoration: none;
128
+ font-size: 0.85em;
129
+ cursor: pointer;
130
+ transition: background-color 0.15s, color 0.15s;
131
+ }
132
+ .ultravisor-docs-module-list a:hover {
133
+ background-color: #1a2744;
134
+ color: #fff;
135
+ }
136
+ .ultravisor-docs-module-list a.active {
137
+ color: var(--uv-link);
138
+ font-weight: 600;
139
+ background-color: var(--uv-bg-elevated);
140
+ }
141
+ .ultravisor-docs-module-list .no-docs {
142
+ display: block;
143
+ padding: 0.3em 1em 0.3em 1.75em;
144
+ color: var(--uv-btn-secondary-bg);
145
+ font-size: 0.85em;
146
+ }
147
+ .ultravisor-docs-content {
148
+ flex: 1;
149
+ min-width: 0;
150
+ overflow-y: auto;
151
+ background-color: var(--uv-bg-base);
152
+ }
153
+ .ultravisor-docs-body {
154
+ padding: 2em 3em;
155
+ max-width: 900px;
156
+ margin: 0 auto;
157
+ }
158
+ .ultravisor-docs-loading {
159
+ display: flex;
160
+ align-items: center;
161
+ justify-content: center;
162
+ min-height: 200px;
163
+ color: var(--uv-text-tertiary);
164
+ font-size: 1em;
165
+ }
166
+ /* Markdown content styling for dark theme */
167
+ .ultravisor-docs-body h1 {
168
+ font-size: 2em;
169
+ color: var(--uv-text);
170
+ border-bottom: 1px solid var(--uv-border-subtle);
171
+ padding-bottom: 0.3em;
172
+ margin-top: 0;
173
+ font-weight: 300;
174
+ }
175
+ .ultravisor-docs-body h2 {
176
+ font-size: 1.5em;
177
+ color: var(--uv-text);
178
+ border-bottom: 1px solid #1e3a5f;
179
+ padding-bottom: 0.25em;
180
+ margin-top: 1.5em;
181
+ font-weight: 400;
182
+ }
183
+ .ultravisor-docs-body h3 {
184
+ font-size: 1.25em;
185
+ color: var(--uv-text);
186
+ margin-top: 1.25em;
187
+ }
188
+ .ultravisor-docs-body h4,
189
+ .ultravisor-docs-body h5,
190
+ .ultravisor-docs-body h6 {
191
+ color: var(--uv-text-secondary);
192
+ margin-top: 1em;
193
+ }
194
+ .ultravisor-docs-body p {
195
+ line-height: 1.7;
196
+ color: var(--uv-text-secondary);
197
+ margin: 0.75em 0;
198
+ }
199
+ .ultravisor-docs-body a {
200
+ color: var(--uv-link);
201
+ text-decoration: none;
202
+ }
203
+ .ultravisor-docs-body a:hover {
204
+ text-decoration: underline;
205
+ color: var(--uv-link-hover);
206
+ }
207
+ .ultravisor-docs-body pre {
208
+ background: #0d1b2a;
209
+ color: var(--uv-text);
210
+ padding: 1.25em;
211
+ border-radius: 6px;
212
+ overflow-x: auto;
213
+ line-height: 1.5;
214
+ font-size: 0.9em;
215
+ border: 1px solid var(--uv-border-subtle);
216
+ }
217
+ .ultravisor-docs-body code {
218
+ background: #0d1b2a;
219
+ padding: 0.15em 0.4em;
220
+ border-radius: 3px;
221
+ font-size: 0.9em;
222
+ color: var(--uv-brand);
223
+ }
224
+ .ultravisor-docs-body pre code {
225
+ background: none;
226
+ padding: 0;
227
+ color: inherit;
228
+ font-size: inherit;
229
+ }
230
+ .ultravisor-docs-body .pict-content-code-wrap {
231
+ position: relative;
232
+ font-family: 'SFMono-Regular', 'SF Mono', 'Menlo', 'Consolas', monospace;
233
+ font-size: 14px;
234
+ line-height: 1.5;
235
+ border-radius: 6px;
236
+ overflow: auto;
237
+ margin: 1em 0;
238
+ background: #0d1b2a;
239
+ border: 1px solid var(--uv-border-subtle);
240
+ }
241
+ .ultravisor-docs-body .pict-content-code-wrap .pict-content-code-line-numbers {
242
+ position: absolute;
243
+ top: 0;
244
+ left: 0;
245
+ width: 40px;
246
+ padding: 1.25em 0;
247
+ text-align: right;
248
+ background: #0a1525;
249
+ border-right: 1px solid var(--uv-border-subtle);
250
+ color: var(--uv-btn-secondary-bg);
251
+ font-size: 13px;
252
+ line-height: 1.5;
253
+ user-select: none;
254
+ pointer-events: none;
255
+ box-sizing: border-box;
256
+ }
257
+ .ultravisor-docs-body .pict-content-code-wrap .pict-content-code-line-numbers span {
258
+ display: block;
259
+ padding: 0 8px 0 0;
260
+ }
261
+ .ultravisor-docs-body .pict-content-code-wrap pre {
262
+ margin: 0;
263
+ background: #0d1b2a;
264
+ color: var(--uv-text);
265
+ padding: 1.25em 1.25em 1.25em 52px;
266
+ border-radius: 6px;
267
+ overflow-x: auto;
268
+ line-height: 1.5;
269
+ font-size: inherit;
270
+ border: none;
271
+ }
272
+ .ultravisor-docs-body .pict-content-code-wrap pre code {
273
+ background: none;
274
+ padding: 0;
275
+ color: inherit;
276
+ font-size: inherit;
277
+ font-family: inherit;
278
+ }
279
+ .ultravisor-docs-body .pict-content-code-wrap .keyword { color: #C678DD; }
280
+ .ultravisor-docs-body .pict-content-code-wrap .string { color: #98C379; }
281
+ .ultravisor-docs-body .pict-content-code-wrap .number { color: #D19A66; }
282
+ .ultravisor-docs-body .pict-content-code-wrap .comment { color: #546e7a; font-style: italic; }
283
+ .ultravisor-docs-body .pict-content-code-wrap .operator { color: #56B6C2; }
284
+ .ultravisor-docs-body .pict-content-code-wrap .punctuation { color: var(--uv-text); }
285
+ .ultravisor-docs-body .pict-content-code-wrap .function-name { color: #61AFEF; }
286
+ .ultravisor-docs-body .pict-content-code-wrap .property { color: #E06C75; }
287
+ .ultravisor-docs-body .pict-content-code-wrap .tag { color: #E06C75; }
288
+ .ultravisor-docs-body .pict-content-code-wrap .attr-name { color: #D19A66; }
289
+ .ultravisor-docs-body .pict-content-code-wrap .attr-value { color: #98C379; }
290
+ .ultravisor-docs-body blockquote {
291
+ border-left: 4px solid var(--uv-brand);
292
+ margin: 1em 0;
293
+ padding: 0.5em 1em;
294
+ background: var(--uv-bg-surface);
295
+ color: var(--uv-text-secondary);
296
+ }
297
+ .ultravisor-docs-body blockquote p {
298
+ margin: 0.25em 0;
299
+ }
300
+ .ultravisor-docs-body ul,
301
+ .ultravisor-docs-body ol {
302
+ padding-left: 2em;
303
+ line-height: 1.8;
304
+ }
305
+ .ultravisor-docs-body li {
306
+ margin: 0.25em 0;
307
+ color: var(--uv-text-secondary);
308
+ }
309
+ .ultravisor-docs-body hr {
310
+ border: none;
311
+ border-top: 1px solid var(--uv-border-subtle);
312
+ margin: 2em 0;
313
+ }
314
+ .ultravisor-docs-body table {
315
+ width: 100%;
316
+ border-collapse: collapse;
317
+ margin: 1em 0;
318
+ }
319
+ .ultravisor-docs-body table th {
320
+ background: var(--uv-bg-surface);
321
+ border: 1px solid var(--uv-border-subtle);
322
+ padding: 0.6em 0.8em;
323
+ text-align: left;
324
+ font-weight: 600;
325
+ color: var(--uv-text);
326
+ }
327
+ .ultravisor-docs-body table td {
328
+ border: 1px solid var(--uv-border-subtle);
329
+ padding: 0.5em 0.8em;
330
+ color: var(--uv-text-secondary);
331
+ }
332
+ .ultravisor-docs-body table tr:nth-child(even) {
333
+ background: var(--uv-bg-surface);
334
+ }
335
+ .ultravisor-docs-body img {
336
+ max-width: 100%;
337
+ height: auto;
338
+ }
339
+ .ultravisor-docs-body strong {
340
+ color: var(--uv-text);
341
+ }
342
+ .ultravisor-docs-not-found {
343
+ text-align: center;
344
+ padding: 3em 1em;
345
+ color: var(--uv-text-tertiary);
346
+ }
347
+ .ultravisor-docs-not-found h2 {
348
+ color: var(--uv-text-secondary);
349
+ font-size: 1.5em;
350
+ border-bottom: none;
351
+ }
352
+ `,
353
+
354
+ Templates:
355
+ [
356
+ {
357
+ Hash: "Ultravisor-Documentation-Template",
358
+ Template: /*html*/`
359
+ <div class="ultravisor-docs">
360
+ <div class="ultravisor-docs-sidebar">
361
+ <div class="ultravisor-docs-sidebar-search" id="Ultravisor-Docs-Search-Container" style="display:none;">
362
+ <input type="text" placeholder="Search docs..." id="Ultravisor-Docs-Search-Input">
363
+ <div id="Ultravisor-Docs-Search-Results" class="ultravisor-docs-search-results"></div>
364
+ </div>
365
+ <div class="ultravisor-docs-sidebar-nav" id="Ultravisor-Docs-Sidebar-Nav">
366
+ <div class="ultravisor-docs-loading">Loading...</div>
367
+ </div>
368
+ </div>
369
+ <div class="ultravisor-docs-content">
370
+ <div id="Ultravisor-Docs-Content-Body" class="ultravisor-docs-body">
371
+ <div class="ultravisor-docs-loading">Loading documentation...</div>
372
+ </div>
373
+ </div>
374
+ </div>
375
+ `
376
+ }
377
+ ],
378
+
379
+ Renderables:
380
+ [
381
+ {
382
+ RenderableHash: "Ultravisor-Documentation-Content",
383
+ TemplateHash: "Ultravisor-Documentation-Template",
384
+ DestinationAddress: "#Ultravisor-Content-Container",
385
+ RenderMethod: "replace"
386
+ }
387
+ ]
388
+ };
389
+
390
+ class UltravisorDocumentationView extends libPictView
391
+ {
392
+ constructor(pFable, pOptions, pServiceHash)
393
+ {
394
+ super(pFable, pOptions, pServiceHash);
395
+
396
+ this._Initialized = false;
397
+ this._SearchDebounceTimer = null;
398
+ }
399
+
400
+ /**
401
+ * Initialize the Docuserve provider and AppData state if not already done.
402
+ *
403
+ * @param {Function} fCallback - Called once initialization is complete
404
+ */
405
+ _ensureInitialized(fCallback)
406
+ {
407
+ if (this._Initialized)
408
+ {
409
+ return fCallback();
410
+ }
411
+
412
+ // Initialize docuserve application state
413
+ if (!this.pict.AppData.Docuserve)
414
+ {
415
+ this.pict.AppData.Docuserve =
416
+ {
417
+ CatalogLoaded: false,
418
+ Catalog: null,
419
+ CoverLoaded: false,
420
+ Cover: null,
421
+ SidebarLoaded: false,
422
+ SidebarGroups: [],
423
+ TopBarLoaded: false,
424
+ TopBar: null,
425
+ ErrorPageLoaded: false,
426
+ ErrorPageHTML: null,
427
+ KeywordIndexLoaded: false,
428
+ KeywordDocumentCount: 0,
429
+ CurrentGroup: '',
430
+ CurrentModule: '',
431
+ CurrentPath: '',
432
+ SidebarVisible: true,
433
+ DocsBaseURL: 'docs/',
434
+ CatalogURL: 'docs/retold-catalog.json'
435
+ };
436
+ }
437
+
438
+ // Register the docuserve documentation provider if not already done
439
+ if (!this.pict.providers['Docuserve-Documentation'])
440
+ {
441
+ this.pict.addProvider('Docuserve-Documentation', libDocuserveProvider.default_configuration, libDocuserveProvider);
442
+ }
443
+
444
+ let tmpDocProvider = this.pict.providers['Docuserve-Documentation'];
445
+
446
+ // Load catalog and optional files
447
+ tmpDocProvider.loadCatalog(
448
+ function ()
449
+ {
450
+ this._Initialized = true;
451
+ return fCallback();
452
+ }.bind(this));
453
+ }
454
+
455
+ onAfterRender(pRenderable, pRenderDestinationAddress, pRecord, pContent)
456
+ {
457
+ this._ensureInitialized(
458
+ function ()
459
+ {
460
+ this._renderSidebar();
461
+
462
+ // Set up search input
463
+ let tmpSearchContainer = document.getElementById('Ultravisor-Docs-Search-Container');
464
+ if (tmpSearchContainer && this.pict.AppData.Docuserve.KeywordIndexLoaded)
465
+ {
466
+ tmpSearchContainer.style.display = '';
467
+
468
+ let tmpInput = document.getElementById('Ultravisor-Docs-Search-Input');
469
+ if (tmpInput)
470
+ {
471
+ tmpInput.addEventListener('input',
472
+ function ()
473
+ {
474
+ if (this._SearchDebounceTimer)
475
+ {
476
+ clearTimeout(this._SearchDebounceTimer);
477
+ }
478
+ this._SearchDebounceTimer = setTimeout(
479
+ function ()
480
+ {
481
+ this._performSearch(tmpInput.value);
482
+ }.bind(this), 250);
483
+ }.bind(this));
484
+ }
485
+ }
486
+
487
+ // Load the current page or default to the cover/overview
488
+ let tmpCurrentPath = this.pict.AppData.Docuserve.CurrentPath;
489
+ if (tmpCurrentPath)
490
+ {
491
+ this.navigateToPage(tmpCurrentPath);
492
+ }
493
+ else
494
+ {
495
+ // Show the overview page by default
496
+ this.navigateToPage('overview');
497
+ }
498
+ }.bind(this));
499
+
500
+ return super.onAfterRender(pRenderable, pRenderDestinationAddress, pRecord, pContent);
501
+ }
502
+
503
+ /**
504
+ * Render the sidebar navigation from the parsed SidebarGroups data.
505
+ */
506
+ _renderSidebar()
507
+ {
508
+ let tmpGroups = this.pict.AppData.Docuserve.SidebarGroups;
509
+ let tmpCurrentPath = this.pict.AppData.Docuserve.CurrentPath;
510
+
511
+ let tmpHTML = '';
512
+
513
+ // Home link
514
+ tmpHTML += '<div class="ultravisor-docs-sidebar-home">';
515
+ tmpHTML += '<a onclick="_Pict.views[\'Ultravisor-Documentation\'].navigateToPage(\'overview\')">Documentation</a>';
516
+ tmpHTML += '</div>';
517
+
518
+ if (!tmpGroups || tmpGroups.length < 1)
519
+ {
520
+ this.pict.ContentAssignment.assignContent('#Ultravisor-Docs-Sidebar-Nav', tmpHTML);
521
+ return;
522
+ }
523
+
524
+ for (let i = 0; i < tmpGroups.length; i++)
525
+ {
526
+ let tmpGroup = tmpGroups[i];
527
+ tmpHTML += '<div class="ultravisor-docs-sidebar-group">';
528
+
529
+ // Group title
530
+ let tmpGroupActive = '';
531
+ if (tmpGroup.Modules && tmpGroup.Modules.length > 0)
532
+ {
533
+ // Check if any child module is active
534
+ for (let k = 0; k < tmpGroup.Modules.length; k++)
535
+ {
536
+ if (tmpGroup.Modules[k].Route && this._isRouteActive(tmpGroup.Modules[k].Route))
537
+ {
538
+ tmpGroupActive = ' active';
539
+ break;
540
+ }
541
+ }
542
+ }
543
+
544
+ // Determine group click action
545
+ let tmpGroupClickPath = this._extractPagePath(tmpGroup.Route);
546
+ if (tmpGroupClickPath)
547
+ {
548
+ tmpHTML += '<a class="ultravisor-docs-group-title' + tmpGroupActive + '" onclick="_Pict.views[\'Ultravisor-Documentation\'].navigateToPage(\'' + this._escapeAttr(tmpGroupClickPath) + '\')">' + this._escapeHTML(tmpGroup.Name) + '</a>';
549
+ }
550
+ else
551
+ {
552
+ tmpHTML += '<div class="ultravisor-docs-group-title' + tmpGroupActive + '">' + this._escapeHTML(tmpGroup.Name) + '</div>';
553
+ }
554
+
555
+ // Module list
556
+ if (tmpGroup.Modules && tmpGroup.Modules.length > 0)
557
+ {
558
+ tmpHTML += '<ul class="ultravisor-docs-module-list">';
559
+
560
+ for (let j = 0; j < tmpGroup.Modules.length; j++)
561
+ {
562
+ let tmpModule = tmpGroup.Modules[j];
563
+
564
+ if (tmpModule.HasDocs && tmpModule.Route)
565
+ {
566
+ let tmpModulePath = this._extractPagePath(tmpModule.Route);
567
+ let tmpActiveClass = this._isRouteActive(tmpModule.Route) ? ' class="active"' : '';
568
+
569
+ if (tmpModulePath)
570
+ {
571
+ tmpHTML += '<li><a' + tmpActiveClass + ' onclick="_Pict.views[\'Ultravisor-Documentation\'].navigateToPage(\'' + this._escapeAttr(tmpModulePath) + '\')">' + this._escapeHTML(tmpModule.Name) + '</a></li>';
572
+ }
573
+ else
574
+ {
575
+ tmpHTML += '<li><a' + tmpActiveClass + '>' + this._escapeHTML(tmpModule.Name) + '</a></li>';
576
+ }
577
+ }
578
+ else
579
+ {
580
+ tmpHTML += '<li><span class="no-docs">' + this._escapeHTML(tmpModule.Name) + '</span></li>';
581
+ }
582
+ }
583
+
584
+ tmpHTML += '</ul>';
585
+ }
586
+
587
+ tmpHTML += '</div>';
588
+ }
589
+
590
+ this.pict.ContentAssignment.assignContent('#Ultravisor-Docs-Sidebar-Nav', tmpHTML);
591
+ }
592
+
593
+ /**
594
+ * Navigate to a documentation page by path.
595
+ *
596
+ * @param {string} pPath - The page path (e.g. 'overview', 'features/tasks')
597
+ */
598
+ navigateToPage(pPath)
599
+ {
600
+ if (!pPath)
601
+ {
602
+ return;
603
+ }
604
+
605
+ let tmpDocProvider = this.pict.providers['Docuserve-Documentation'];
606
+ if (!tmpDocProvider)
607
+ {
608
+ return;
609
+ }
610
+
611
+ // Update current path
612
+ this.pict.AppData.Docuserve.CurrentPath = pPath;
613
+
614
+ // Show loading
615
+ this.pict.ContentAssignment.assignContent('#Ultravisor-Docs-Content-Body',
616
+ '<div class="ultravisor-docs-loading">Loading documentation...</div>');
617
+
618
+ // Re-render sidebar to update active states
619
+ this._renderSidebar();
620
+
621
+ // Ensure the path has a .md extension
622
+ let tmpFilePath = pPath;
623
+ if (!tmpFilePath.match(/\.md$/))
624
+ {
625
+ tmpFilePath = tmpFilePath + '.md';
626
+ }
627
+
628
+ // Fetch the local document
629
+ tmpDocProvider.fetchLocalDocument(tmpFilePath,
630
+ function (pError, pHTML)
631
+ {
632
+ if (pError || !pHTML)
633
+ {
634
+ // Check if this is a network error (server down) vs a missing document
635
+ if (pError && typeof(pError) === 'object' && pError.message && pError.message.match(/fetch|network|failed/i))
636
+ {
637
+ this.pict.PictApplication._setConnectionState(false);
638
+ }
639
+ else
640
+ {
641
+ this.pict.ContentAssignment.assignContent('#Ultravisor-Docs-Content-Body',
642
+ '<div class="ultravisor-docs-not-found"><h2>Page Not Found</h2><p>The document <code>' + this._escapeHTML(pPath) + '</code> could not be loaded.</p></div>');
643
+ }
644
+ return;
645
+ }
646
+
647
+ this.pict.ContentAssignment.assignContent('#Ultravisor-Docs-Content-Body', pHTML);
648
+
649
+ // Scroll content to top
650
+ let tmpContentEl = document.querySelector('.ultravisor-docs-content');
651
+ if (tmpContentEl)
652
+ {
653
+ tmpContentEl.scrollTop = 0;
654
+ }
655
+
656
+ // Intercept internal links to route through our navigation
657
+ this._interceptLinks();
658
+ }.bind(this));
659
+ }
660
+
661
+ /**
662
+ * Intercept links within the rendered content that point to local docs.
663
+ */
664
+ _interceptLinks()
665
+ {
666
+ let tmpContentBody = document.getElementById('Ultravisor-Docs-Content-Body');
667
+ if (!tmpContentBody)
668
+ {
669
+ return;
670
+ }
671
+
672
+ let tmpLinks = tmpContentBody.querySelectorAll('a[href]');
673
+ for (let i = 0; i < tmpLinks.length; i++)
674
+ {
675
+ let tmpLink = tmpLinks[i];
676
+ let tmpHref = tmpLink.getAttribute('href');
677
+
678
+ // Skip external links
679
+ if (tmpHref.match(/^https?:\/\//) || tmpHref.match(/^mailto:/))
680
+ {
681
+ tmpLink.setAttribute('target', '_blank');
682
+ tmpLink.setAttribute('rel', 'noopener');
683
+ continue;
684
+ }
685
+
686
+ // Handle hash links from docuserve link resolver
687
+ if (tmpHref.match(/^#\/page\//))
688
+ {
689
+ let tmpPagePath = tmpHref.replace(/^#\/page\//, '');
690
+ tmpLink.setAttribute('href', 'javascript:void(0)');
691
+ tmpLink.setAttribute('onclick', '_Pict.views[\'Ultravisor-Documentation\'].navigateToPage(\'' + this._escapeAttr(tmpPagePath) + '\')');
692
+ continue;
693
+ }
694
+
695
+ // Handle relative .md links
696
+ if (tmpHref.match(/\.md$/))
697
+ {
698
+ let tmpPagePath = tmpHref.replace(/^\.\//, '').replace(/\.md$/, '');
699
+
700
+ // If the current page is in a subdirectory, resolve relative paths
701
+ let tmpCurrentPath = this.pict.AppData.Docuserve.CurrentPath || '';
702
+ let tmpCurrentDir = '';
703
+ let tmpDirParts = tmpCurrentPath.split('/');
704
+ if (tmpDirParts.length > 1)
705
+ {
706
+ tmpDirParts.pop();
707
+ tmpCurrentDir = tmpDirParts.join('/') + '/';
708
+ }
709
+
710
+ if (!tmpPagePath.includes('/') && tmpCurrentDir)
711
+ {
712
+ tmpPagePath = tmpCurrentDir + tmpPagePath;
713
+ }
714
+
715
+ tmpLink.setAttribute('href', 'javascript:void(0)');
716
+ tmpLink.setAttribute('onclick', '_Pict.views[\'Ultravisor-Documentation\'].navigateToPage(\'' + this._escapeAttr(tmpPagePath) + '\')');
717
+ }
718
+ }
719
+ }
720
+
721
+ /**
722
+ * Perform a sidebar search using the docuserve provider.
723
+ *
724
+ * @param {string} pQuery - The search query
725
+ */
726
+ _performSearch(pQuery)
727
+ {
728
+ let tmpResultsEl = document.getElementById('Ultravisor-Docs-Search-Results');
729
+ if (!tmpResultsEl)
730
+ {
731
+ return;
732
+ }
733
+
734
+ if (!pQuery || !pQuery.trim())
735
+ {
736
+ tmpResultsEl.innerHTML = '';
737
+ return;
738
+ }
739
+
740
+ let tmpDocProvider = this.pict.providers['Docuserve-Documentation'];
741
+ let tmpResults = tmpDocProvider.search(pQuery);
742
+
743
+ if (tmpResults.length === 0)
744
+ {
745
+ tmpResultsEl.innerHTML = '<div style="padding: 0.35em 0.5em; font-size: 0.8em; color:var(--uv-text-tertiary);">No results found.</div>';
746
+ return;
747
+ }
748
+
749
+ let tmpMaxResults = 8;
750
+ let tmpHTML = '';
751
+
752
+ for (let i = 0; i < tmpResults.length && i < tmpMaxResults; i++)
753
+ {
754
+ let tmpResult = tmpResults[i];
755
+ let tmpPagePath = tmpResult.Key || '';
756
+ let tmpMeta = '';
757
+
758
+ if (tmpResult.Group && tmpResult.Module)
759
+ {
760
+ tmpMeta = tmpResult.Group + ' / ' + tmpResult.Module;
761
+ }
762
+
763
+ tmpHTML += '<a onclick="_Pict.views[\'Ultravisor-Documentation\'].navigateToPage(\'' + this._escapeAttr(tmpPagePath) + '\')">';
764
+ tmpHTML += '<div class="ultravisor-docs-search-result-title">' + this._escapeHTML(tmpResult.Title) + '</div>';
765
+ if (tmpMeta)
766
+ {
767
+ tmpHTML += '<div class="ultravisor-docs-search-result-meta">' + this._escapeHTML(tmpMeta) + '</div>';
768
+ }
769
+ tmpHTML += '</a>';
770
+ }
771
+
772
+ tmpResultsEl.innerHTML = tmpHTML;
773
+ }
774
+
775
+ /**
776
+ * Extract the page path from a hash route for internal navigation.
777
+ *
778
+ * @param {string} pRoute - A hash route (e.g. '#/page/overview', '#/doc/group/module')
779
+ * @returns {string} The extracted page path or empty string
780
+ */
781
+ _extractPagePath(pRoute)
782
+ {
783
+ if (!pRoute)
784
+ {
785
+ return '';
786
+ }
787
+
788
+ // #/page/something
789
+ let tmpPageMatch = pRoute.match(/^#\/page\/(.+)/);
790
+ if (tmpPageMatch)
791
+ {
792
+ return tmpPageMatch[1];
793
+ }
794
+
795
+ // #/Home
796
+ if (pRoute === '#/Home')
797
+ {
798
+ return 'overview';
799
+ }
800
+
801
+ return '';
802
+ }
803
+
804
+ /**
805
+ * Check whether a route matches the current navigation state.
806
+ *
807
+ * @param {string} pRoute - The hash route to check
808
+ * @returns {boolean} True if the route is active
809
+ */
810
+ _isRouteActive(pRoute)
811
+ {
812
+ let tmpCurrentPath = this.pict.AppData.Docuserve.CurrentPath || '';
813
+ let tmpRoutePath = this._extractPagePath(pRoute);
814
+
815
+ if (!tmpRoutePath || !tmpCurrentPath)
816
+ {
817
+ return false;
818
+ }
819
+
820
+ return tmpCurrentPath === tmpRoutePath;
821
+ }
822
+
823
+ /**
824
+ * Escape HTML special characters.
825
+ *
826
+ * @param {string} pText - The text to escape
827
+ * @returns {string} The escaped text
828
+ */
829
+ _escapeHTML(pText)
830
+ {
831
+ if (!pText)
832
+ {
833
+ return '';
834
+ }
835
+ return String(pText).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
836
+ }
837
+
838
+ /**
839
+ * Escape a string for use in an HTML attribute.
840
+ *
841
+ * @param {string} pText - The text to escape
842
+ * @returns {string} The escaped text
843
+ */
844
+ _escapeAttr(pText)
845
+ {
846
+ if (!pText)
847
+ {
848
+ return '';
849
+ }
850
+ return String(pText).replace(/\\/g, '\\\\').replace(/'/g, "\\'").replace(/"/g, '&quot;');
851
+ }
852
+ }
853
+
854
+ module.exports = UltravisorDocumentationView;
855
+
856
+ module.exports.default_configuration = _ViewConfiguration;