c0ckp1t 1.0.18 → 1.0.20
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/components/MarkdownUtils.mjs +24 -18
- package/components/vue3-ace-editor.vue +12 -7
- package/components/xinput.vue +11 -3
- package/components/xjson.vue +28 -3
- package/components/xmarkdown.vue +11 -75
- package/components/xmd.vue +75 -0
- package/components/xsection.vue +6 -3
- package/components/xterminal.vue +293 -94
- package/config.default.mjs +327 -0
- package/config.mjs +312 -0
- package/core/ConfigUtils.mjs +197 -328
- package/core/Content.mjs +1 -0
- package/core/GlobalStore.mjs +69 -30
- package/core/Island.mjs +97 -39
- package/core/IslandDefault.mjs +10 -27
- package/core/JsUtils.mjs +28 -0
- package/core/PageMain.vue +2 -0
- package/core/PageNavigation.vue +31 -5
- package/core/Stash.mjs +92 -0
- package/core/VueUtils.mjs +2 -0
- package/core/WsLogUtils.mjs +19 -22
- package/core/alert-offcanvas.vue +137 -0
- package/core/img/200by200.png +0 -0
- package/core/main-offcanvas.vue +3 -11
- package/core/notify/NotifyUtils.mjs +59 -27
- package/core/pages/Connection.vue +22 -14
- package/core/pages/Connections.vue +85 -35
- package/core/pages/Documentation.vue +82 -63
- package/core/pages/Notifies.vue +3 -14
- package/core/pages/Traffic.vue +102 -51
- package/core/pages/connections/ConfigIsland.vue +41 -37
- package/core/pages/connections/connection-header.vue +1 -1
- package/core/pages/frontend/Bootstrap.vue +0 -1
- package/core/pages/frontend/ComponentsAdv.vue +7 -0
- package/core/pages/traffic/log-ws-event.vue +81 -0
- package/core/sfc/code-item2.vue +171 -0
- package/core/sfc/p1t-event-.vue +98 -0
- package/core/ws-client/AuthNState.mjs +109 -55
- package/core/ws-client/Connection.mjs +374 -395
- package/core/ws-client/WsClient.mjs +14 -1
- package/index-cdn.html +74 -7
- package/index.html +8 -11
- package/js_ext/Makefile +17 -0
- package/js_ext/README.md +16 -0
- package/js_ext/chart.umd.min.js +14 -0
- package/js_ext/chartjs-plugin-zoom.min.js +7 -0
- package/js_ext/hammer.min.js +7 -0
- package/js_ext/moment-timezone.min.js +1 -0
- package/js_ext/xstate-5.29.0.esm.mjs +8 -0
- package/package.json +3 -2
- package/style.css +9 -0
- package/Config.mjs +0 -58
- package/components/FsTree.vue +0 -550
- package/components/Tree.mjs +0 -175
- package/core/pages/connections/ws-connection.vue +0 -145
- package/core/ws-client/Session.mjs +0 -72
- package/core/ws-client/ws-connection.vue +0 -140
|
@@ -10,8 +10,6 @@ const LOG_HEADER = 'MarkdownUtils.mjs'
|
|
|
10
10
|
const logger = getLogger(LOG_HEADER)
|
|
11
11
|
logger.debug("[INIT]")
|
|
12
12
|
|
|
13
|
-
const remotePathPrefix = '/docs/';
|
|
14
|
-
|
|
15
13
|
// ________________________________________________________________________________
|
|
16
14
|
// EXPORTED UTILITY FUNCTIONS
|
|
17
15
|
// ________________________________________________________________________________
|
|
@@ -100,26 +98,34 @@ export function extractSizeFromAlt(alt) {
|
|
|
100
98
|
* Converts relative paths to absolute paths for documentation
|
|
101
99
|
*
|
|
102
100
|
* @param {string} inputString - HTML string with img tags
|
|
101
|
+
* @param {Object} images
|
|
103
102
|
* @returns {string} Modified HTML string
|
|
104
103
|
*/
|
|
105
|
-
export function replaceImgLinks(inputString) {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
104
|
+
export function replaceImgLinks(inputString, images = {}) {
|
|
105
|
+
return inputString.replace(
|
|
106
|
+
/img src="([^"]*)" alt="([^"]*)"/g,
|
|
107
|
+
(match, src, alt) => {
|
|
108
|
+
logger.debug(`[REGEX_IMG] match=${match} src=${src} alt=${alt}`)
|
|
109
|
+
const size = extractSizeFromAlt(alt);
|
|
110
|
+
let sizeAttrs = '';
|
|
111
|
+
if (size) {
|
|
112
|
+
sizeAttrs = `width="${size.width}" `;
|
|
113
|
+
// sizeAttrs = `width="${size.width}" height="${size.height}"`;
|
|
114
|
+
alt = alt.replace(/=(\d+)x(\d+)$/, ''); // Remove size from alt
|
|
115
|
+
}
|
|
116
|
+
if (match.toLowerCase().includes("http") || match.toLowerCase().includes("class")) {
|
|
117
|
+
// do nothing
|
|
118
|
+
return `${match} class="mk-img"`
|
|
119
|
+
} else {
|
|
120
|
+
images[src] = null
|
|
121
|
+
// return `${match} class="mk-img"`
|
|
122
|
+
return `img :src="images['${src}']" alt="${alt.trim()}" class="mk-img" ${sizeAttrs}`
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
);
|
|
121
126
|
}
|
|
122
127
|
|
|
128
|
+
|
|
123
129
|
/**
|
|
124
130
|
* Replace Vue template syntax to prevent interpretation
|
|
125
131
|
* Escapes {{ }} so they display literally in markdown
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
import {ref, reactive, markRaw, onMounted, onBeforeUnmount, watch} from 'vue';
|
|
8
8
|
import {loadAce} from './AceLoader.mjs';
|
|
9
|
+
import {store as storeMain, api as apiMain} from 'GlobalStore'
|
|
9
10
|
|
|
10
11
|
const root = ref("");
|
|
11
12
|
|
|
@@ -101,7 +102,8 @@ let _editor = undefined
|
|
|
101
102
|
let _ro = undefined
|
|
102
103
|
let _contentBackup = undefined;
|
|
103
104
|
let _isSettingContent = false;
|
|
104
|
-
|
|
105
|
+
const currentHeight = ref(props.height);
|
|
106
|
+
const container = ref(null)
|
|
105
107
|
|
|
106
108
|
watch(() => props.modelValue, (first, second) => {
|
|
107
109
|
value(first)
|
|
@@ -139,7 +141,7 @@ onMounted(async () => {
|
|
|
139
141
|
console.error('Ace editor failed to load:', err)
|
|
140
142
|
return
|
|
141
143
|
}
|
|
142
|
-
ace.config.set('basePath',
|
|
144
|
+
ace.config.set('basePath', `${storeMain.appEndpoint}/js_ext/ace-editor`);
|
|
143
145
|
_editor = markRaw(ace.edit(root.value, {
|
|
144
146
|
mode: 'ace/mode/' + props.lang,
|
|
145
147
|
theme: 'ace/theme/' + props.theme,
|
|
@@ -171,8 +173,12 @@ onMounted(async () => {
|
|
|
171
173
|
local.currentRelativeLineNumbers = false;
|
|
172
174
|
|
|
173
175
|
value(props.modelValue)
|
|
174
|
-
_ro = new ResizeObserver(() =>
|
|
175
|
-
|
|
176
|
+
_ro = new ResizeObserver(() => {
|
|
177
|
+
if (container.value) {
|
|
178
|
+
currentHeight.value = container.value.style.height || container.value.offsetHeight + 'px';
|
|
179
|
+
}
|
|
180
|
+
_editor.resize();
|
|
181
|
+
});
|
|
176
182
|
emit('init', _editor);
|
|
177
183
|
})
|
|
178
184
|
|
|
@@ -246,7 +252,7 @@ function maxLines(val) {
|
|
|
246
252
|
</script>
|
|
247
253
|
|
|
248
254
|
<template>
|
|
249
|
-
<div class="ace-editor" style="display: flex; flex-direction: column;" :style="{ height:
|
|
255
|
+
<div ref="container" class="ace-editor" style="display: flex; flex-direction: column;" :style="{ height: currentHeight }">
|
|
250
256
|
<div class="debug-toolbar" v-if="props.debug">
|
|
251
257
|
<label>
|
|
252
258
|
Theme:
|
|
@@ -286,8 +292,7 @@ function maxLines(val) {
|
|
|
286
292
|
|
|
287
293
|
.ace-editor {
|
|
288
294
|
resize: vertical;
|
|
289
|
-
overflow
|
|
290
|
-
overflow-x: hidden;
|
|
295
|
+
overflow: hidden;
|
|
291
296
|
}
|
|
292
297
|
|
|
293
298
|
.debug-toolbar {
|
package/components/xinput.vue
CHANGED
|
@@ -21,6 +21,10 @@ const props = defineProps({
|
|
|
21
21
|
type: String,
|
|
22
22
|
default: 'text'
|
|
23
23
|
},
|
|
24
|
+
step: {
|
|
25
|
+
type: Number,
|
|
26
|
+
default: 1
|
|
27
|
+
},
|
|
24
28
|
showLabel: {
|
|
25
29
|
type: Boolean,
|
|
26
30
|
default: true
|
|
@@ -34,6 +38,10 @@ const props = defineProps({
|
|
|
34
38
|
inputStyle: {
|
|
35
39
|
type: String,
|
|
36
40
|
default: ""
|
|
41
|
+
},
|
|
42
|
+
readonly: {
|
|
43
|
+
type: Boolean,
|
|
44
|
+
default: false
|
|
37
45
|
}
|
|
38
46
|
})
|
|
39
47
|
|
|
@@ -61,13 +69,13 @@ const typeCheck = computed (() => {
|
|
|
61
69
|
<span v-if="showLabel" :style="props.styleObject" class=" input-group-text label fw-bold" > {{ k }} </span>
|
|
62
70
|
|
|
63
71
|
<input :type="type" aria-label="message" class="form-control"
|
|
64
|
-
:style="props.inputStyle" v-model.number="message" v-if="type.toUpperCase() === 'NUMBER'">
|
|
72
|
+
:style="props.inputStyle" v-model.number="message" :step="step" :readonly="props.readonly" v-if="type.toUpperCase() === 'NUMBER'">
|
|
65
73
|
|
|
66
74
|
<input :type="isPasswordVisible ? 'text' : 'password'" aria-label="message" class="form-control"
|
|
67
|
-
:style="props.inputStyle" v-model="message" v-else-if="type.toUpperCase() === 'PASSWORD'">
|
|
75
|
+
:style="props.inputStyle" v-model="message" :readonly="props.readonly" v-else-if="type.toUpperCase() === 'PASSWORD'">
|
|
68
76
|
|
|
69
77
|
<input :type="type" aria-label="message" class="form-control"
|
|
70
|
-
:style="props.inputStyle" v-model="message" v-else>
|
|
78
|
+
:style="props.inputStyle" v-model="message" :readonly="props.readonly" v-else>
|
|
71
79
|
|
|
72
80
|
<div class="input-group-text text-primary icon-container" @click="isPasswordVisible = !isPasswordVisible" v-if="type.toUpperCase() === 'PASSWORD'">
|
|
73
81
|
<i class="fa-solid fa-eye" v-if="isPasswordVisible"></i>
|
package/components/xjson.vue
CHANGED
|
@@ -14,6 +14,10 @@ const props = defineProps({
|
|
|
14
14
|
expanded: {
|
|
15
15
|
type: Boolean,
|
|
16
16
|
default: false
|
|
17
|
+
},
|
|
18
|
+
copyButton: {
|
|
19
|
+
type: Boolean,
|
|
20
|
+
default: true
|
|
17
21
|
}
|
|
18
22
|
})
|
|
19
23
|
const emit = defineEmits(['select'])
|
|
@@ -30,7 +34,9 @@ function sanitize(obj, seen = new WeakSet()) {
|
|
|
30
34
|
if (typeof obj === 'function') return `[Function: ${obj.name || 'anonymous'}]`
|
|
31
35
|
if (typeof obj === 'symbol') return obj.toString()
|
|
32
36
|
if (typeof obj !== 'object') return obj
|
|
33
|
-
|
|
37
|
+
if (obj instanceof Set) {
|
|
38
|
+
return Array.from(obj).map(item => sanitize(item, seen))
|
|
39
|
+
}
|
|
34
40
|
// Handle circular references
|
|
35
41
|
if (seen.has(obj)) return '[Circular]'
|
|
36
42
|
seen.add(obj)
|
|
@@ -53,6 +59,7 @@ const local = reactive({
|
|
|
53
59
|
id: id,
|
|
54
60
|
el: null,
|
|
55
61
|
isExpanded: props.expanded,
|
|
62
|
+
copied: false,
|
|
56
63
|
})
|
|
57
64
|
|
|
58
65
|
watch(
|
|
@@ -75,6 +82,14 @@ function collapseAll() {
|
|
|
75
82
|
local.el.collapse('**');
|
|
76
83
|
}
|
|
77
84
|
|
|
85
|
+
function copyToClipboard() {
|
|
86
|
+
const text = JSON.stringify(sanitize(props.obj), null, 2)
|
|
87
|
+
navigator.clipboard.writeText(text).then(() => {
|
|
88
|
+
local.copied = true
|
|
89
|
+
setTimeout(() => { local.copied = false }, 1500)
|
|
90
|
+
})
|
|
91
|
+
}
|
|
92
|
+
|
|
78
93
|
function toggleExpand() {
|
|
79
94
|
if(local.isExpanded) {
|
|
80
95
|
local.isExpanded = false
|
|
@@ -110,11 +125,21 @@ onMounted(async () => { init() })
|
|
|
110
125
|
|
|
111
126
|
<template>
|
|
112
127
|
<div class="x-json">
|
|
113
|
-
|
|
128
|
+
<button v-if="props.copyButton" class="btn btn-sm btn-outline-secondary copy-btn" @click="copyToClipboard">
|
|
129
|
+
<i class="fa-solid" :class="local.copied ? 'fa-check' : 'fa-copy'"></i>
|
|
130
|
+
</button>
|
|
114
131
|
<json-viewer class="p-1" :id="local.id"> </json-viewer>
|
|
115
132
|
</div>
|
|
116
133
|
</template>
|
|
117
134
|
|
|
118
135
|
<style scoped>
|
|
119
|
-
|
|
136
|
+
.x-json {
|
|
137
|
+
position: relative;
|
|
138
|
+
}
|
|
139
|
+
.copy-btn {
|
|
140
|
+
position: absolute;
|
|
141
|
+
top: 4px;
|
|
142
|
+
right: 4px;
|
|
143
|
+
z-index: 1;
|
|
144
|
+
}
|
|
120
145
|
</style>
|
package/components/xmarkdown.vue
CHANGED
|
@@ -18,6 +18,7 @@ import {getLogger} from "Logging"
|
|
|
18
18
|
import {md} from "./Markdown.mjs"
|
|
19
19
|
|
|
20
20
|
import CodeItem from "../core/sfc/code-item.vue"
|
|
21
|
+
import CodeItem2 from "../core/sfc/code-item2.vue"
|
|
21
22
|
|
|
22
23
|
import {
|
|
23
24
|
replaceHrefLinks,
|
|
@@ -25,7 +26,7 @@ import {
|
|
|
25
26
|
replaceVueSpecial,
|
|
26
27
|
removeMarkdownHeader,
|
|
27
28
|
slugify,
|
|
28
|
-
|
|
29
|
+
decorateTableHTML
|
|
29
30
|
} from "./MarkdownUtils.mjs";
|
|
30
31
|
|
|
31
32
|
const props = defineProps({
|
|
@@ -48,91 +49,25 @@ const emit = defineEmits(['href'])
|
|
|
48
49
|
// ________________________________________________________________________________
|
|
49
50
|
const LOG_HEADER = 'xmarkdown.vue'
|
|
50
51
|
const logger = getLogger(LOG_HEADER)
|
|
51
|
-
logger.debug("
|
|
52
|
+
logger.debug("INIT")
|
|
52
53
|
|
|
53
54
|
// ________________________________________________________________________________
|
|
54
55
|
// LOCAL STATE
|
|
55
56
|
// ________________________________________________________________________________
|
|
56
57
|
const local = reactive({
|
|
58
|
+
id: LOG_HEADER,
|
|
57
59
|
isLoading: false,
|
|
58
|
-
|
|
59
60
|
markdownComponent: null,
|
|
60
|
-
|
|
61
61
|
images: null,
|
|
62
|
-
text: null,
|
|
63
62
|
})
|
|
64
63
|
|
|
65
64
|
// ______________________________________________________________________________________
|
|
66
65
|
// RENDING VUE COMPONENT
|
|
67
66
|
// ______________________________________________________________________________________
|
|
68
|
-
// Note: Helper functions have been extracted to MarkdownUtils.mjs for testability
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
// We do not support recursive injection
|
|
72
|
-
async function injectText(text) {
|
|
73
|
-
logger.debug(`Scanning for markdown injection`)
|
|
74
|
-
|
|
75
|
-
// Fetch all
|
|
76
|
-
const promises = [];
|
|
77
|
-
text.replace(/{%\s*include\s+(.*?)\s*%}/g, (match, param) => {
|
|
78
|
-
logger.debug(`[REGEX_INJECT] match=${match} param=${param}`)
|
|
79
|
-
const promise = props.fetchText(param)
|
|
80
|
-
promises.push(promise);
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
// Replace all
|
|
84
|
-
const results = await Promise.all(promises)
|
|
85
|
-
|
|
86
|
-
let currentIndex = 0;
|
|
87
|
-
return text.replace(/{%\s*include\s+(.*?)\s*%}/g, () => results[currentIndex++]);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
async function injectTextV2(text) {
|
|
91
|
-
logger.debug(`[INJECT_TEXT] - Version 2`)
|
|
92
|
-
|
|
93
|
-
// Fetch all
|
|
94
|
-
const promises = [];
|
|
95
|
-
text.replace(/<div data-ref="([^"]+)".*?><\/div>/g, (match, param) => {
|
|
96
|
-
logger.debug(`match=${match} param=${param}`)
|
|
97
|
-
|
|
98
|
-
const refRegex = /data-(id|lines)="([^"]+)"/g;
|
|
99
|
-
const refMatch = refRegex.exec(match)
|
|
100
|
-
if(refMatch !== null) {
|
|
101
|
-
logger.debug(`type=${refMatch[1]} refId=${refMatch[2]}`)
|
|
102
|
-
const promise = props.fetchText(param, refMatch[2])
|
|
103
|
-
promises.push(promise);
|
|
104
|
-
} else {
|
|
105
|
-
const promise = props.fetchText(param)
|
|
106
|
-
promises.push(promise);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
// Replace all
|
|
112
|
-
const results = await Promise.all(promises);
|
|
113
|
-
logger.trace("received injection text:")
|
|
114
|
-
logger.trace(results)
|
|
115
|
-
let currentIndex = 0;
|
|
116
|
-
return text.replace(/<div data-ref="([^"]+)".*?><\/div>/g, () => results[currentIndex++]);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
async function fetchAllText() {
|
|
121
|
-
const fetchPromises = Object.keys(local.text).map(relativeURL => {
|
|
122
|
-
logger.debug(`fetchText - ${relativeURL}`)
|
|
123
|
-
return props.fetchText(relativeURL).then(text => {
|
|
124
|
-
logger.debug(text)
|
|
125
|
-
local.text[relativeURL] = text
|
|
126
|
-
});
|
|
127
|
-
});
|
|
128
|
-
await Promise.all(fetchPromises);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
67
|
async function fetchAllImages() {
|
|
132
68
|
const fetchPromises = Object.keys(local.images).map(relativeURL => {
|
|
133
69
|
logger.debug(`fetchImage - ${relativeURL}`)
|
|
134
70
|
return props.fetchImage(relativeURL).then(blobUrl => {
|
|
135
|
-
console.log(blobUrl)
|
|
136
71
|
local.images[relativeURL] = blobUrl
|
|
137
72
|
});
|
|
138
73
|
});
|
|
@@ -150,11 +85,16 @@ function renderMarkdown(html) {
|
|
|
150
85
|
template: html,
|
|
151
86
|
components: {
|
|
152
87
|
CodeItem,
|
|
88
|
+
CodeItem2,
|
|
89
|
+
},
|
|
90
|
+
provide() {
|
|
91
|
+
return {
|
|
92
|
+
fetchText: props.fetchText,
|
|
93
|
+
}
|
|
153
94
|
},
|
|
154
95
|
data: () => {
|
|
155
96
|
return {
|
|
156
97
|
images: local.images,
|
|
157
|
-
text: local.text
|
|
158
98
|
}
|
|
159
99
|
},
|
|
160
100
|
methods: {
|
|
@@ -217,8 +157,6 @@ async function buildComponent(markdownText) {
|
|
|
217
157
|
logger.trace(markdownText)
|
|
218
158
|
|
|
219
159
|
let markdown = removeMarkdownHeader(markdownText)
|
|
220
|
-
// markdown = await injectText(markdown)
|
|
221
|
-
markdown = await injectTextV2(markdown)
|
|
222
160
|
logger.trace("markdown after injection")
|
|
223
161
|
logger.trace(markdown)
|
|
224
162
|
|
|
@@ -227,10 +165,8 @@ async function buildComponent(markdownText) {
|
|
|
227
165
|
html = replaceVueSpecial(html)
|
|
228
166
|
html = replaceHrefLinks(html, props.adjustHrefPath)
|
|
229
167
|
html = decorateTableHTML(html)
|
|
230
|
-
|
|
231
|
-
// Initialize images object before replacing img links
|
|
232
168
|
local.images = {}
|
|
233
|
-
html = replaceImgLinks(html)
|
|
169
|
+
html = replaceImgLinks(html, local.images)
|
|
234
170
|
|
|
235
171
|
local.markdownComponent = markRaw(renderMarkdown(html))
|
|
236
172
|
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
/*
|
|
3
|
+
<XMd url="/docs/Introduction.md" />
|
|
4
|
+
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import {computed, defineProps, reactive, onMounted} from 'vue'
|
|
8
|
+
|
|
9
|
+
import {store as storeMain, api as apiMain } from 'GlobalStore'
|
|
10
|
+
import {getLogger} from "Logging";
|
|
11
|
+
|
|
12
|
+
const props = defineProps({
|
|
13
|
+
url: {type: String, required: true},
|
|
14
|
+
instanceId: {type: String, required: false, default: "default"}
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
// ________________________________________________________________________________
|
|
18
|
+
// LOGGING
|
|
19
|
+
// ________________________________________________________________________________
|
|
20
|
+
const LOG_HEADER = 'xmd.vue'
|
|
21
|
+
const logger = getLogger(LOG_HEADER)
|
|
22
|
+
logger.debug("[INIT]")
|
|
23
|
+
|
|
24
|
+
// ________________________________________________________________________________
|
|
25
|
+
// STATE
|
|
26
|
+
// ________________________________________________________________________________
|
|
27
|
+
const local = reactive({
|
|
28
|
+
id: LOG_HEADER,
|
|
29
|
+
isLoading: false,
|
|
30
|
+
// !# C0CKP1T_START local
|
|
31
|
+
hasError: false,
|
|
32
|
+
fullCode: "N/A",
|
|
33
|
+
// !# C0CKP1T_END local
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
async function findCode() {
|
|
38
|
+
const registry = storeMain.r[props.instanceId]
|
|
39
|
+
|
|
40
|
+
if (typeof props.url !== 'string' || props.url.length < 3) {
|
|
41
|
+
local.fullCode = `[INVALID_URL] - problem with props.url\n\n`
|
|
42
|
+
local.hasError = true
|
|
43
|
+
return
|
|
44
|
+
}
|
|
45
|
+
logger.debug(`[findCode] - ${props.url}`)
|
|
46
|
+
const resp = await registry.getText( props.url)
|
|
47
|
+
logger.debug(resp)
|
|
48
|
+
if (!resp.isOk) {
|
|
49
|
+
local.fullCode = `[API_ERROR]\n${resp.result}\n\n`
|
|
50
|
+
local.hasError = true
|
|
51
|
+
return
|
|
52
|
+
}
|
|
53
|
+
// Get the full code
|
|
54
|
+
local.fullCode = resp.result
|
|
55
|
+
local.hasError = false
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// ________________________________________________________________________________
|
|
59
|
+
// INIT
|
|
60
|
+
// ________________________________________________________________________________
|
|
61
|
+
onMounted(() => {
|
|
62
|
+
findCode()
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
</script>
|
|
66
|
+
|
|
67
|
+
<template>
|
|
68
|
+
<div>
|
|
69
|
+
<XMarkdown :v="local.fullCode" />
|
|
70
|
+
</div>
|
|
71
|
+
</template>
|
|
72
|
+
|
|
73
|
+
<style scoped>
|
|
74
|
+
|
|
75
|
+
</style>
|
package/components/xsection.vue
CHANGED
|
@@ -124,19 +124,22 @@ function titleClick() {
|
|
|
124
124
|
<template>
|
|
125
125
|
<div class="x-section">
|
|
126
126
|
|
|
127
|
-
<div class="
|
|
128
|
-
|
|
127
|
+
<div class="d-flex justify-content-between align-items-center no-select py-1" :class="bgClass">
|
|
128
|
+
|
|
129
|
+
<div class="ms-2 col" @click="titleClick">
|
|
129
130
|
<span :class="[fontSizeClass, textClass]" class="title"> {{ props.k }} </span>
|
|
130
131
|
</div>
|
|
132
|
+
|
|
131
133
|
<div class="col-auto d-flex align-items-center">
|
|
132
134
|
<slot name="header"></slot>
|
|
133
|
-
<button class="btn
|
|
135
|
+
<button class="btn btn-sm ms-2 me-2" :class="btnClass" @click="titleClick">
|
|
134
136
|
<span class="icon is-small">
|
|
135
137
|
<i class="fa-solid fa-eye" v-if="local.visible"></i>
|
|
136
138
|
<i class="fa-solid fa-eye-slash" v-else></i>
|
|
137
139
|
</span>
|
|
138
140
|
</button>
|
|
139
141
|
</div>
|
|
142
|
+
|
|
140
143
|
</div>
|
|
141
144
|
|
|
142
145
|
<div class="mt-2" v-if="local.visible">
|