c0ckp1t 1.0.12 → 1.0.14
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/Config.mjs +1 -0
- package/c0ckp1t-demo/{C0ckp1tConfig.mjs → Config.mjs} +6 -3
- package/c0ckp1t-demo/components/sidebar.vue +1 -2
- package/c0ckp1t-demo/docs/Introduction.md +1 -0
- package/c0ckp1t-demo/docs/Issues.md +3 -0
- package/c0ckp1t-demo/pages/documentation.vue +64 -0
- package/c0ckp1t-demo/store.mjs +2 -2
- package/components/xcode-slot.vue +112 -0
- package/components/xcode.vue +103 -43
- package/components/xmap.vue +2 -2
- package/components/xsound.vue +1 -2
- package/core/CoreUtils.mjs +3 -0
- package/core/DocUtils.mjs +1 -1
- package/core/GlobalStore.mjs +8 -7
- package/core/Island.mjs +5 -1
- package/core/IslandDefault.mjs +16 -10
- package/core/PageMain.vue +34 -12
- package/core/Theme.mjs +8 -1
- package/core/VueUtils.mjs +23 -13
- package/core/WsUtils.mjs +8 -8
- package/core/main-offcanvas.vue +12 -11
- package/core/pages/Cache.vue +1 -1
- package/core/pages/Connection.vue +1 -5
- package/core/pages/Connections.vue +2 -2
- package/core/pages/Documentation.vue +9 -5
- package/core/pages/Notifies.vue +10 -9
- package/core/pages/Traffic.vue +4 -3
- package/core/pages/frontend/Bootstrap.vue +15 -16
- package/core/pages/frontend/ComponentsAdv.vue +127 -7
- package/core/pages/frontend/ComponentsBasic.vue +30 -24
- package/core/pages/frontend/Theme.vue +2 -7
- package/core/pages/frontend/component-view-html.vue +100 -0
- package/core/pages/frontend/component-view.vue +19 -5
- package/index-cdn.html +19 -9
- package/index.html +2 -2
- package/package.json +4 -7
- package/c0ckp1t-demo/CdnConfig.mjs +0 -68
- package/docs/Introduction.md +0 -3
- package/docs/Issues.md +0 -13
package/Config.mjs
CHANGED
|
@@ -189,6 +189,7 @@ export function defaultVueComponents(prefix = "") {
|
|
|
189
189
|
XTextarea: { path: `${prefix}/components/xtextarea.vue`, hash: `f8bb08419082aa5443630ab07172674b50c7a248` },
|
|
190
190
|
XHidden: { path: `${prefix}/components/xhidden.vue`, hash: `ecb396e12dd894040e715c0854275e4d5016fcb9` },
|
|
191
191
|
XCode: { path: `${prefix}/components/xcode.vue`, hash: `4d9d9165fea0539c9a983fcdffae8dedcfd537ae` },
|
|
192
|
+
XCodeSlot: { path: `${prefix}/components/xcode-slot.vue`, hash: `` },
|
|
192
193
|
XButton: { path: `${prefix}/components/xbutton.vue`, hash: `2e956caa47e46377ea5a809f7438d0fc38be73b9` },
|
|
193
194
|
XTabs: { path: `${prefix}/components/xtabs.vue`, hash: `83dc219106bdc86ae86dcd16cf95ebd7f11bc952` },
|
|
194
195
|
XKv: { path: `${prefix}/components/xkv.vue`, hash: `8951d3a5e3786cfc9c705b13c1f71e3f90dd2552` },
|
|
@@ -10,6 +10,8 @@ const instanceId = "demo";
|
|
|
10
10
|
// Used for requestion app components and files
|
|
11
11
|
const appEndpoint = "";
|
|
12
12
|
|
|
13
|
+
const islandDir = "c0ckp1t-demo"
|
|
14
|
+
|
|
13
15
|
// ________________________________________________________________________________
|
|
14
16
|
// GLOBAL CONSTANTS
|
|
15
17
|
// ________________________________________________________________________________
|
|
@@ -21,6 +23,7 @@ export default {
|
|
|
21
23
|
type: "LOCAL",
|
|
22
24
|
appName: "C0ckp1t Demo",
|
|
23
25
|
appEndpoint: appEndpoint,
|
|
26
|
+
islandDir: islandDir,
|
|
24
27
|
|
|
25
28
|
// This creates the navigation tree
|
|
26
29
|
root: {
|
|
@@ -55,11 +58,11 @@ export default {
|
|
|
55
58
|
|
|
56
59
|
// This is used to create routes for the vue router
|
|
57
60
|
routes: [
|
|
58
|
-
{path: instanceId, location: `${appEndpoint}/
|
|
61
|
+
{path: instanceId, location: `${appEndpoint}/${islandDir}/main.vue`, children: [
|
|
59
62
|
{path: '', redirect: `/${instanceId}/homepage`},
|
|
60
|
-
{path: 'homepage', location: `${appEndpoint}/
|
|
63
|
+
{path: 'homepage', location: `${appEndpoint}/${islandDir}/pages/homepage.vue`},
|
|
61
64
|
{path: 'docs', redirect: `/${instanceId}/docs/Introduction.md`},
|
|
62
|
-
{path: 'docs/:pathMatch(.*)*', location: `${appEndpoint}/
|
|
65
|
+
{path: 'docs/:pathMatch(.*)*', location: `${appEndpoint}/${islandDir}/pages/documentation.vue`},
|
|
63
66
|
] },
|
|
64
67
|
]
|
|
65
68
|
|
|
@@ -39,8 +39,7 @@ logger.debug("[INIT]")
|
|
|
39
39
|
|
|
40
40
|
<ul class="nav flex-column mb-auto">
|
|
41
41
|
<RouterLink class="nav-link d-flex align-items-center gap-2" :to="`${routerEndpoint}/homepage`">Homepage</RouterLink>
|
|
42
|
-
<RouterLink class="nav-link d-flex align-items-center gap-2" :class="{ 'router-link-active': isDocsActive }" :to="`${routerEndpoint}/docs`"
|
|
43
|
-
<RouterLink class="nav-link d-flex align-items-center gap-2" :to="`${routerEndpoint}/admin`" v-if="registry?.store?.context?.accessLevel <= 500">Admin</RouterLink>
|
|
42
|
+
<RouterLink class="nav-link d-flex align-items-center gap-2" :class="{ 'router-link-active': isDocsActive }" :to="`${routerEndpoint}/docs`" >Documentation</RouterLink>
|
|
44
43
|
</ul>
|
|
45
44
|
|
|
46
45
|
<hr class="my-2">
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
/*
|
|
3
|
+
[VARS] - init, imports, template, script, style, name
|
|
4
|
+
|
|
5
|
+
Usage:
|
|
6
|
+
const documentation = defineAsyncComponent(() => import("/v3/actions/auth/www/pages/documentation.vue"))
|
|
7
|
+
<documentation/>
|
|
8
|
+
*/
|
|
9
|
+
// ________________________________________________________________________________
|
|
10
|
+
// IMPORTS
|
|
11
|
+
// ________________________________________________________________________________
|
|
12
|
+
import {reactive, computed, ref, onMounted, onUnmounted, defineAsyncComponent, watch} from 'vue'
|
|
13
|
+
import {getLogger} from "Logging";
|
|
14
|
+
import {store as storeLocal, api as apiLocal, registry, instanceId} from '../store.mjs'
|
|
15
|
+
import Documentation from "/core/pages/Documentation.vue"
|
|
16
|
+
|
|
17
|
+
// !# C0CKP1T_START imports
|
|
18
|
+
|
|
19
|
+
// !# C0CKP1T_END imports
|
|
20
|
+
|
|
21
|
+
// ________________________________________________________________________________
|
|
22
|
+
// LOGGING
|
|
23
|
+
// ________________________________________________________________________________
|
|
24
|
+
const LOG_HEADER = "pages/homepage.vue"
|
|
25
|
+
const logger = getLogger(LOG_HEADER)
|
|
26
|
+
logger.debug("[INIT]")
|
|
27
|
+
|
|
28
|
+
// !# C0CKP1T_START script
|
|
29
|
+
const local = reactive({
|
|
30
|
+
id: LOG_HEADER,
|
|
31
|
+
instanceId: instanceId
|
|
32
|
+
})
|
|
33
|
+
// !# C0CKP1T_END script
|
|
34
|
+
|
|
35
|
+
// ________________________________________________________________________________
|
|
36
|
+
// INIT
|
|
37
|
+
// ________________________________________________________________________________
|
|
38
|
+
async function init() {
|
|
39
|
+
if (registry.state.isReady) {
|
|
40
|
+
// !# C0CKP1T_START init
|
|
41
|
+
|
|
42
|
+
// !# C0CKP1T_END init
|
|
43
|
+
} else {
|
|
44
|
+
setTimeout(async () => { await init() }, 1000)
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
onMounted(async () => { init() })
|
|
48
|
+
</script>
|
|
49
|
+
|
|
50
|
+
<template>
|
|
51
|
+
<!-- !# C0CKP1T_START template -->
|
|
52
|
+
<x-section extra="fs-3" k="Documentation" :visible="true">
|
|
53
|
+
<Documentation :remotePathMapping="`/${storeLocal.islandDir}/docs`"></Documentation>
|
|
54
|
+
</x-section>
|
|
55
|
+
<!-- !# C0CKP1T_END template -->
|
|
56
|
+
</template>
|
|
57
|
+
|
|
58
|
+
<style scoped>
|
|
59
|
+
/* !# C0CKP1T_START style */
|
|
60
|
+
|
|
61
|
+
/* !# C0CKP1T_END style */
|
|
62
|
+
</style>
|
|
63
|
+
|
|
64
|
+
|
package/c0ckp1t-demo/store.mjs
CHANGED
|
@@ -12,7 +12,7 @@ import {getLogger} from "Logging";
|
|
|
12
12
|
import {store as storeMain, api as apiMain} from 'GlobalStore'
|
|
13
13
|
|
|
14
14
|
// !# C0CKP1T_START import
|
|
15
|
-
import C0ckp1tConfig from "./
|
|
15
|
+
import C0ckp1tConfig from "./Config.mjs";
|
|
16
16
|
// !# C0CKP1T_END import
|
|
17
17
|
|
|
18
18
|
export const instanceId = C0ckp1tConfig.instanceId
|
|
@@ -38,7 +38,7 @@ export const store = reactive({
|
|
|
38
38
|
endpoint: routerEndpoint,
|
|
39
39
|
|
|
40
40
|
// !# C0CKP1T_START store
|
|
41
|
-
|
|
41
|
+
islandDir: C0ckp1tConfig.islandDir,
|
|
42
42
|
// !# C0CKP1T_END store
|
|
43
43
|
})
|
|
44
44
|
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import {computed, defineProps, reactive} from 'vue'
|
|
3
|
+
import {getLogger} from "Logging";
|
|
4
|
+
|
|
5
|
+
const props = defineProps({
|
|
6
|
+
title: {type: String, required: true, default: "Code"},
|
|
7
|
+
lang: {type: String, default: 'text'},
|
|
8
|
+
code: {type: String, required: true},
|
|
9
|
+
})
|
|
10
|
+
// ________________________________________________________________________________
|
|
11
|
+
// LOGGING
|
|
12
|
+
// ________________________________________________________________________________
|
|
13
|
+
const LOG_HEADER = 'xcode-slot.vue'
|
|
14
|
+
const logger = getLogger(LOG_HEADER)
|
|
15
|
+
logger.debug("[INIT]")
|
|
16
|
+
|
|
17
|
+
// ________________________________________________________________________________
|
|
18
|
+
// STATE
|
|
19
|
+
// ________________________________________________________________________________
|
|
20
|
+
const local = reactive({
|
|
21
|
+
id: LOG_HEADER,
|
|
22
|
+
lang: props.lang,
|
|
23
|
+
copied: false,
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
const HTML_ESCAPE_TEST_RE = /[&<>"]/
|
|
27
|
+
const HTML_ESCAPE_REPLACE_RE = /[&<>"]/g
|
|
28
|
+
const HTML_REPLACEMENTS = {
|
|
29
|
+
'&': '&',
|
|
30
|
+
'<': '<',
|
|
31
|
+
'>': '>',
|
|
32
|
+
'"': '"'
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function replaceUnsafeChar(ch) {
|
|
36
|
+
return HTML_REPLACEMENTS[ch]
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function escapeHtml(str) {
|
|
40
|
+
if (HTML_ESCAPE_TEST_RE.test(str)) {
|
|
41
|
+
return str.replace(HTML_ESCAPE_REPLACE_RE, replaceUnsafeChar)
|
|
42
|
+
}
|
|
43
|
+
return str
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// ________________________________________________________________________________
|
|
47
|
+
// COPY TO CLIPBOARD
|
|
48
|
+
// ________________________________________________________________________________
|
|
49
|
+
async function copyCode() {
|
|
50
|
+
try {
|
|
51
|
+
await navigator.clipboard.writeText(props.code)
|
|
52
|
+
local.copied = true
|
|
53
|
+
logger.debug("[copyCode] - copied to clipboard")
|
|
54
|
+
setTimeout(() => { local.copied = false }, 2000)
|
|
55
|
+
} catch (err) {
|
|
56
|
+
logger.error("[copyCode] - failed to copy", err)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// ________________________________________________________________________________
|
|
61
|
+
// HIGHLIGHTED HTML
|
|
62
|
+
// ________________________________________________________________________________
|
|
63
|
+
const html = computed(() => {
|
|
64
|
+
const code = props.code || ''
|
|
65
|
+
|
|
66
|
+
if (local.lang && hljs.getLanguage(local.lang)) {
|
|
67
|
+
try {
|
|
68
|
+
return '<pre class="hljs"><code>' +
|
|
69
|
+
hljs.highlight(code, {language: local.lang, ignoreIllegals: true}).value +
|
|
70
|
+
'</code></pre>';
|
|
71
|
+
} catch (__) {
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return '<pre class="hljs"><code>' + escapeHtml(code) + '</code></pre>';
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
</script>
|
|
79
|
+
|
|
80
|
+
<template>
|
|
81
|
+
<div>
|
|
82
|
+
<div class="code-item container">
|
|
83
|
+
|
|
84
|
+
<div class="row mb-0 mt-0 pt-0 pb-0 align-items-center">
|
|
85
|
+
<div class="col-auto">
|
|
86
|
+
<span class="code-title">{{ props.title }}</span>
|
|
87
|
+
</div>
|
|
88
|
+
<div class="col"></div>
|
|
89
|
+
<div class="col-auto">
|
|
90
|
+
<button class="btn btn-sm btn-dark copy-btn" @click="copyCode" :title="local.copied ? 'Copied!' : 'Copy to clipboard'">
|
|
91
|
+
<i :class="local.copied ? 'fa fa-check' : 'fa fa-copy'"></i>
|
|
92
|
+
<span v-if="local.copied" class="copy-feedback">Copied!</span>
|
|
93
|
+
</button>
|
|
94
|
+
</div>
|
|
95
|
+
</div>
|
|
96
|
+
|
|
97
|
+
<div v-html="html"></div>
|
|
98
|
+
|
|
99
|
+
</div> <!-- code-item -->
|
|
100
|
+
</div>
|
|
101
|
+
</template>
|
|
102
|
+
|
|
103
|
+
<style scoped>
|
|
104
|
+
.code-item {
|
|
105
|
+
border: 1px solid black;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.code-title {
|
|
109
|
+
font-weight: bold;
|
|
110
|
+
font-size: 0.9em;
|
|
111
|
+
}
|
|
112
|
+
</style>
|
package/components/xcode.vue
CHANGED
|
@@ -1,38 +1,43 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
-
import {computed,
|
|
2
|
+
import {computed, defineProps, reactive, onMounted} from 'vue'
|
|
3
3
|
|
|
4
|
-
import {store as storeMain, api as apiMain} from '
|
|
5
|
-
import {getLogger} from "
|
|
4
|
+
import {store as storeMain, api as apiMain } from 'GlobalStore'
|
|
5
|
+
import {getLogger} from "Logging";
|
|
6
|
+
import {Http} from "WsUtils"
|
|
6
7
|
|
|
7
8
|
const props = defineProps({
|
|
8
9
|
url: {type: String, required: true},
|
|
9
10
|
lang: {type: String, default: 'text'},
|
|
10
|
-
startLine: {type: Number, default: null}, // note: start line is 0 indexed, most editors are 1 indexed
|
|
11
|
-
endLine: {type: Number, default: null},
|
|
11
|
+
startLine: {type: [Number, String], default: null}, // note: start line is 0 indexed, most editors are 1 indexed
|
|
12
|
+
endLine: {type: [Number, String], default: null},
|
|
13
|
+
registryName: {
|
|
14
|
+
type: String,
|
|
15
|
+
default: storeMain.defaultInstanceId
|
|
16
|
+
}
|
|
12
17
|
})
|
|
13
|
-
|
|
14
18
|
// ________________________________________________________________________________
|
|
15
19
|
// LOGGING
|
|
16
20
|
// ________________________________________________________________________________
|
|
17
|
-
const LOG_HEADER = '
|
|
21
|
+
const LOG_HEADER = 'code-item.vue'
|
|
18
22
|
const logger = getLogger(LOG_HEADER)
|
|
19
|
-
logger.debug("INIT")
|
|
23
|
+
logger.debug("[INIT]")
|
|
20
24
|
|
|
21
25
|
// ________________________________________________________________________________
|
|
22
26
|
// STATE
|
|
23
27
|
// ________________________________________________________________________________
|
|
24
28
|
const local = reactive({
|
|
25
|
-
id:
|
|
29
|
+
id: LOG_HEADER,
|
|
26
30
|
isLoading: false,
|
|
27
31
|
// !# C0CKP1T_START local
|
|
28
32
|
code: "Not Available",
|
|
29
33
|
lang: props.lang,
|
|
30
34
|
fullCode: "N/A",
|
|
31
|
-
fullView: false
|
|
35
|
+
fullView: false,
|
|
36
|
+
hasError: false,
|
|
37
|
+
copied: false,
|
|
32
38
|
// !# C0CKP1T_END local
|
|
33
39
|
})
|
|
34
40
|
|
|
35
|
-
|
|
36
41
|
const HTML_ESCAPE_TEST_RE = /[&<>"]/
|
|
37
42
|
const HTML_ESCAPE_REPLACE_RE = /[&<>"]/g
|
|
38
43
|
const HTML_REPLACEMENTS = {
|
|
@@ -52,35 +57,38 @@ function escapeHtml(str) {
|
|
|
52
57
|
}
|
|
53
58
|
return str
|
|
54
59
|
}
|
|
55
|
-
|
|
60
|
+
const registry = storeMain.r[props.registryName]
|
|
56
61
|
async function findCode() {
|
|
57
62
|
if (typeof props.url !== 'string' || props.url.length < 3) {
|
|
58
63
|
local.fullCode = `[INVALID_URL] - problem with props.url\n\n`
|
|
64
|
+
local.hasError = true
|
|
65
|
+
return
|
|
59
66
|
}
|
|
60
|
-
|
|
61
|
-
const resp = await
|
|
67
|
+
logger.debug(`[findCode] - ${props.url}`)
|
|
68
|
+
const resp = await registry.getText( props.url)
|
|
62
69
|
logger.debug(resp)
|
|
63
70
|
if (!resp.isOk) {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
return
|
|
68
|
-
}
|
|
71
|
+
local.fullCode = `[API_ERROR]\n${resp.result}\n\n`
|
|
72
|
+
local.hasError = true
|
|
73
|
+
return
|
|
69
74
|
}
|
|
75
|
+
// Get the full code
|
|
70
76
|
local.fullCode = resp.result
|
|
77
|
+
local.hasError = false
|
|
71
78
|
}
|
|
72
79
|
|
|
73
80
|
// // Highlighter function. Should return escaped HTML
|
|
74
81
|
const html = computed(() => {
|
|
75
|
-
console.log("Recomputing HTML")
|
|
76
|
-
console.log(props)
|
|
82
|
+
// console.log("Recomputing HTML")
|
|
83
|
+
// console.log(props)
|
|
77
84
|
// Handle line range if specified
|
|
78
85
|
let code = local.fullCode
|
|
79
86
|
if (local.fullCode && local.fullView === false) {
|
|
80
87
|
const lines = local.fullCode.split('\n')
|
|
81
|
-
const start = props.startLine != null ? props.startLine : 0
|
|
82
|
-
const end = props.endLine != null ? props.endLine + 1 : lines.length // +1 because slice excludes end
|
|
88
|
+
const start = props.startLine != null ? parseInt(props.startLine) : 0
|
|
89
|
+
const end = props.endLine != null ? parseInt(props.endLine) + 1 : lines.length // +1 because slice excludes end
|
|
83
90
|
|
|
91
|
+
// console.log(`slice - start=${start} - end=${end}`)
|
|
84
92
|
// Extract only the lines we want
|
|
85
93
|
code = lines.slice(start, end).join('\n')
|
|
86
94
|
}
|
|
@@ -96,6 +104,20 @@ const html = computed(() => {
|
|
|
96
104
|
|
|
97
105
|
return '<pre class="hljs"><code>' + escapeHtml(local.code) + '</code></pre>';
|
|
98
106
|
})
|
|
107
|
+
|
|
108
|
+
// ________________________________________________________________________________
|
|
109
|
+
// COPY TO CLIPBOARD
|
|
110
|
+
// ________________________________________________________________________________
|
|
111
|
+
async function copyCode() {
|
|
112
|
+
try {
|
|
113
|
+
await navigator.clipboard.writeText(props.code)
|
|
114
|
+
local.copied = true
|
|
115
|
+
logger.debug("[copyCode] - copied to clipboard")
|
|
116
|
+
setTimeout(() => { local.copied = false }, 2000)
|
|
117
|
+
} catch (err) {
|
|
118
|
+
logger.error("[copyCode] - failed to copy", err)
|
|
119
|
+
}
|
|
120
|
+
}
|
|
99
121
|
// ________________________________________________________________________________
|
|
100
122
|
// INIT
|
|
101
123
|
// ________________________________________________________________________________
|
|
@@ -106,34 +128,72 @@ onMounted(() => {
|
|
|
106
128
|
</script>
|
|
107
129
|
|
|
108
130
|
<template>
|
|
109
|
-
<div
|
|
110
|
-
<div class="
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
<
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
<
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
<
|
|
131
|
+
<div>
|
|
132
|
+
<div class="code-item container" >
|
|
133
|
+
|
|
134
|
+
<div class="row mb-0 mt-0 pt-0 pb-0 align-items-center" v-if="!local.fullView">
|
|
135
|
+
<div class="col-auto">
|
|
136
|
+
<span class="filename">{{ props.url?.split('/').pop() ?? 'INVALID' }}</span>
|
|
137
|
+
</div>
|
|
138
|
+
<div class="col"></div>
|
|
139
|
+
<div class="col-auto">
|
|
140
|
+
<ExecButton class="btn-sm btn btn-dark" icon="fa-rotate-right" :callback="() => findCode()"></ExecButton>
|
|
141
|
+
</div>
|
|
142
|
+
<div class="col-auto">
|
|
143
|
+
<x-toggle k="Full" v-model="local.fullView"></x-toggle>
|
|
144
|
+
</div>
|
|
145
|
+
<div class="col-auto">
|
|
146
|
+
<button class="btn btn-sm btn-dark copy-btn" @click="copyCode" :title="local.copied ? 'Copied!' : 'Copy to clipboard'">
|
|
147
|
+
<i :class="local.copied ? 'fa fa-check' : 'fa fa-copy'"></i>
|
|
148
|
+
<span v-if="local.copied" class="copy-feedback">Copied!</span>
|
|
149
|
+
</button>
|
|
150
|
+
</div>
|
|
124
151
|
</div>
|
|
125
|
-
|
|
126
|
-
|
|
152
|
+
|
|
153
|
+
<div class="full-view mb-0 pb-0 mt-0 pt-0" v-else>
|
|
154
|
+
|
|
155
|
+
<div class="row align-items-center">
|
|
156
|
+
<div class="col-auto">
|
|
157
|
+
<span class="filename">{{ props.url ?? 'INVALID' }}</span>
|
|
158
|
+
</div>
|
|
159
|
+
<div class="col"></div>
|
|
160
|
+
<div class="col-auto">
|
|
161
|
+
<ExecButton icon="fa-rotate-right" :callback="() => findCode()"></ExecButton>
|
|
162
|
+
</div>
|
|
163
|
+
<div class="col-auto">
|
|
164
|
+
<x-toggle k="Full" v-model="local.fullView"></x-toggle>
|
|
165
|
+
</div>
|
|
166
|
+
<div class="col-auto">
|
|
167
|
+
<button class="btn btn-sm btn-dark copy-btn" @click="copyCode" :title="local.copied ? 'Copied!' : 'Copy to clipboard'">
|
|
168
|
+
<i :class="local.copied ? 'fa fa-check' : 'fa fa-copy'"></i>
|
|
169
|
+
<span v-if="local.copied" class="copy-feedback">Copied!</span>
|
|
170
|
+
</button>
|
|
171
|
+
</div>
|
|
172
|
+
</div>
|
|
173
|
+
|
|
174
|
+
<div class="row align-items-center">
|
|
175
|
+
<div class="col-auto">
|
|
176
|
+
<x-label :isCompact="true" k="Lang:">{{ local.lang }}</x-label>
|
|
177
|
+
</div>
|
|
178
|
+
<div class="col-auto" v-if="props.startLine && props.endLine">
|
|
179
|
+
<x-label :isCompact="true" k="Lines:">{{ props.startLine }}-{{ props.endLine }}</x-label>
|
|
180
|
+
</div>
|
|
181
|
+
</div>
|
|
182
|
+
|
|
127
183
|
</div>
|
|
128
|
-
|
|
129
|
-
|
|
184
|
+
|
|
185
|
+
<div v-html="html"></div>
|
|
186
|
+
|
|
187
|
+
</div> <!-- code-item -->
|
|
188
|
+
|
|
130
189
|
</div>
|
|
131
190
|
</template>
|
|
132
191
|
|
|
133
192
|
<style scoped>
|
|
134
193
|
.code-item {
|
|
194
|
+
color: white;
|
|
135
195
|
border: 1px solid black;
|
|
136
|
-
|
|
196
|
+
background-color: #434e5a;
|
|
137
197
|
}
|
|
138
198
|
|
|
139
199
|
</style>
|
package/components/xmap.vue
CHANGED
|
@@ -72,7 +72,7 @@ onMounted(async () => {
|
|
|
72
72
|
|
|
73
73
|
<div class="row menu align-items-center">
|
|
74
74
|
<div class="col-auto">
|
|
75
|
-
<span class="fw-bold
|
|
75
|
+
<span class="fw-bold text-secondary">{{ props.k }}</span>
|
|
76
76
|
</div>
|
|
77
77
|
<div class="col-auto">
|
|
78
78
|
<x-input k="Add Item" v-model="local.textAddKey"></x-input>
|
|
@@ -97,7 +97,7 @@ onMounted(async () => {
|
|
|
97
97
|
</div>
|
|
98
98
|
|
|
99
99
|
<div class="col-auto">
|
|
100
|
-
<ExecButton icon="fa-trash"
|
|
100
|
+
<ExecButton icon="fa-trash" :callback=" () => removeKey(k)"
|
|
101
101
|
></ExecButton>
|
|
102
102
|
</div>
|
|
103
103
|
</div>
|
package/components/xsound.vue
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import { reactive, computed, markRaw, onMounted, onBeforeUnmount } from 'vue'
|
|
3
|
-
import XDropdown2 from '/components/xdropdown2.vue'
|
|
4
3
|
|
|
5
4
|
// https://wavesurfer-js.org/docs/
|
|
6
5
|
// NOTE: streaming not supported?
|
|
@@ -197,7 +196,7 @@ onBeforeUnmount(() => {
|
|
|
197
196
|
</div>
|
|
198
197
|
|
|
199
198
|
<!-- Playback Rate -->
|
|
200
|
-
<
|
|
199
|
+
<x-dropdown2
|
|
201
200
|
v-model="local.playbackRate"
|
|
202
201
|
:items="playbackRateOptions"
|
|
203
202
|
:on-change="onPlaybackRateChange"
|
package/core/CoreUtils.mjs
CHANGED
package/core/DocUtils.mjs
CHANGED
|
@@ -110,7 +110,7 @@ ${message}
|
|
|
110
110
|
}
|
|
111
111
|
|
|
112
112
|
retrieveText = async (registry, remotePath) => {
|
|
113
|
-
logger.info(`[retrieveText] - remotePath=${remotePath}`)
|
|
113
|
+
logger.info(`[retrieveText] - instanceId=${registry?.instanceId} remotePath=${remotePath}`)
|
|
114
114
|
/**
|
|
115
115
|
const key = remotePathURL.substring(remotePathURL.lastIndexOf('/') + 1)
|
|
116
116
|
const cachedText = await cacheGet(key)
|
package/core/GlobalStore.mjs
CHANGED
|
@@ -64,9 +64,15 @@ export const store = reactive({
|
|
|
64
64
|
username: null,
|
|
65
65
|
|
|
66
66
|
// ________________________________________________________________________________
|
|
67
|
-
//
|
|
67
|
+
// TOP NAVBAR
|
|
68
68
|
// ________________________________________________________________________________
|
|
69
|
-
|
|
69
|
+
showTopNavBar: true,
|
|
70
|
+
|
|
71
|
+
// ________________________________________________________________________________
|
|
72
|
+
// documentation
|
|
73
|
+
// ________________________________________________________________________________
|
|
74
|
+
showDocReload: true,
|
|
75
|
+
showDocPath: true,
|
|
70
76
|
|
|
71
77
|
// ________________________________________________________________________________
|
|
72
78
|
// Vue App Instance - gets created in App.vue
|
|
@@ -85,11 +91,6 @@ export const store = reactive({
|
|
|
85
91
|
mainOffCanvasOpen: false,
|
|
86
92
|
mainOffCanvasWidth: 0,
|
|
87
93
|
|
|
88
|
-
// ________________________________________________________________________________
|
|
89
|
-
// Documentation
|
|
90
|
-
// ________________________________________________________________________________
|
|
91
|
-
documentation: "/v3/text-markdown/c0ckp1t/Introduction.md",
|
|
92
|
-
|
|
93
94
|
// ________________________________________________________________________________
|
|
94
95
|
// P1t Modal
|
|
95
96
|
// ________________________________________________________________________________
|
package/core/Island.mjs
CHANGED
|
@@ -40,13 +40,14 @@ export default class Island {
|
|
|
40
40
|
|
|
41
41
|
this.instanceId = config.instanceId
|
|
42
42
|
this.SERVER_API_URL = config.SERVER_API_URL
|
|
43
|
+
this.type = "Island"
|
|
44
|
+
this.apiMain = apiMain;
|
|
43
45
|
|
|
44
46
|
this.LOG_HEADER = `${this.instanceId}`;
|
|
45
47
|
this.logger = getLogger(this.LOG_HEADER);
|
|
46
48
|
this.logger.debug('[INIT]');
|
|
47
49
|
|
|
48
50
|
this.connection = new Connection(config)
|
|
49
|
-
|
|
50
51
|
// ________________________________________________________________________________
|
|
51
52
|
// STATE - NOT saved in browser storage
|
|
52
53
|
// ________________________________________________________________________________
|
|
@@ -335,6 +336,9 @@ export default class Island {
|
|
|
335
336
|
|
|
336
337
|
getText = async (endpoint) => {
|
|
337
338
|
this.logger.info(`[getText] - endpoint=${endpoint}`)
|
|
339
|
+
if (endpoint.startsWith("http") || endpoint.startsWith("HTTP")) {
|
|
340
|
+
return await Http.getText(endpoint, "omit")
|
|
341
|
+
}
|
|
338
342
|
if (endpoint.startsWith('/c0ckp1t/')) {
|
|
339
343
|
const path = `${this.config.SERVER_API_URL}${endpoint}`;
|
|
340
344
|
return await Http.getText(path)
|
package/core/IslandDefault.mjs
CHANGED
|
@@ -20,8 +20,10 @@ import {getLogger} from 'Logging';
|
|
|
20
20
|
export default class IslandDefault {
|
|
21
21
|
constructor(apiMain, config) {
|
|
22
22
|
|
|
23
|
-
this.instanceId = config.instanceId
|
|
24
|
-
this.
|
|
23
|
+
this.instanceId = config.instanceId;
|
|
24
|
+
this.type = "IslandDefault";
|
|
25
|
+
this.config = config;
|
|
26
|
+
this.apiMain = apiMain;
|
|
25
27
|
|
|
26
28
|
this.LOG_HEADER = `${this.instanceId}`;
|
|
27
29
|
this.logger = getLogger(this.LOG_HEADER);
|
|
@@ -69,7 +71,7 @@ export default class IslandDefault {
|
|
|
69
71
|
// ________________________________________________________________________________
|
|
70
72
|
routeByEndpoint = async (endpoint) => {
|
|
71
73
|
this.logger.debug(`routeByEndpoint - endpoint=${endpoint}`);
|
|
72
|
-
await this.apiMain.routeByEndpoint(
|
|
74
|
+
await this.apiMain.routeByEndpoint(`/${this.instanceId}${endpoint}`);
|
|
73
75
|
}
|
|
74
76
|
|
|
75
77
|
/**
|
|
@@ -92,7 +94,7 @@ export default class IslandDefault {
|
|
|
92
94
|
this.logger.info(`selectNode - node.endpoint=${node.endpoint}`);
|
|
93
95
|
this.store.selectedNode = null;
|
|
94
96
|
this.store.selectedNode = node;
|
|
95
|
-
await this.apiMain.routeByEndpoint(
|
|
97
|
+
await this.apiMain.routeByEndpoint(node.endpoint);
|
|
96
98
|
}
|
|
97
99
|
|
|
98
100
|
// ________________________________________________________________________________
|
|
@@ -154,14 +156,14 @@ export default class IslandDefault {
|
|
|
154
156
|
* @param type
|
|
155
157
|
* @returns {Promise<Response>}
|
|
156
158
|
*/
|
|
157
|
-
resolver =
|
|
159
|
+
resolver = async (path, type) => {
|
|
158
160
|
/**
|
|
159
161
|
* Path.normalize() in vue3-sfc-loader's defaultPathResolve
|
|
160
162
|
* collapses // in https:// down to https:/
|
|
161
163
|
* It uses Path.normalize(Path.join(Path.dirname(getPathname(refPath.toString()))
|
|
162
164
|
* but Node's posix.dirname doesn't understand URL protocols
|
|
163
165
|
*/
|
|
164
|
-
if(path.startsWith("https:/c")) {
|
|
166
|
+
if (path.startsWith("https:/c")) {
|
|
165
167
|
path = path.replace("https:/c", "https://c");
|
|
166
168
|
}
|
|
167
169
|
this.logger.debug(`[resolver] - fetching - ${path} - ${type}`)
|
|
@@ -172,9 +174,13 @@ export default class IslandDefault {
|
|
|
172
174
|
|
|
173
175
|
|
|
174
176
|
getText = async (endpoint) => {
|
|
177
|
+
this.logger.debug(`[getText] - ${endpoint}`);
|
|
178
|
+
if (endpoint.startsWith("http") || endpoint.startsWith("HTTP")) {
|
|
179
|
+
return await Http.getText(endpoint, "omit")
|
|
180
|
+
} else {
|
|
175
181
|
const path = `${this.config.SERVER_API_URL}${endpoint}`;
|
|
176
|
-
this.logger.debug(`[getText] - ${path}`);
|
|
177
182
|
return await Http.getText(path)
|
|
183
|
+
}
|
|
178
184
|
}
|
|
179
185
|
|
|
180
186
|
async getBinary(endpoint) {
|
|
@@ -198,9 +204,9 @@ export default class IslandDefault {
|
|
|
198
204
|
// ________________________________________________________________________________
|
|
199
205
|
// init
|
|
200
206
|
// ________________________________________________________________________________
|
|
201
|
-
init = async ()
|
|
202
|
-
|
|
203
|
-
|
|
207
|
+
init = async () => {
|
|
208
|
+
await this.rootNode()
|
|
209
|
+
this.state.isReady = true
|
|
204
210
|
}
|
|
205
211
|
|
|
206
212
|
} // end of IslandDefault class
|