pinokiod 0.1.32 → 0.1.33
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/kernel/api/index.js +5 -0
- package/kernel/api/key/index.js +26 -0
- package/kernel/index.js +5 -1
- package/kernel/key.js +43 -0
- package/package.json +2 -1
- package/server/index.js +84 -39
- package/server/public/modalinput.js +9 -0
- package/server/public/style.css +23 -4
- package/server/views/browser.ejs +205 -53
- package/server/views/editor.ejs +143 -26
- package/server/views/fullscreen_editor.ejs +41 -1
- package/server/views/index.ejs +28 -26
package/kernel/api/index.js
CHANGED
|
@@ -381,6 +381,8 @@ class Api {
|
|
|
381
381
|
}
|
|
382
382
|
async step (request, rawrpc, input, i, total) {
|
|
383
383
|
|
|
384
|
+
console.log("STEP", { request, rawrpc, input, i, total })
|
|
385
|
+
|
|
384
386
|
// clear global regular expression object RegExp.lastMatch (memory leak prevention)
|
|
385
387
|
let r = /\s*/g.exec("");
|
|
386
388
|
|
|
@@ -795,6 +797,7 @@ class Api {
|
|
|
795
797
|
// API Call
|
|
796
798
|
|
|
797
799
|
request.path = this.resolvePath(this.userdir, request.uri)
|
|
800
|
+
console.log("#PROCESS", { request, userdir: this.userdir })
|
|
798
801
|
let { cwd, script } = await this.resolveScript(request.path)
|
|
799
802
|
request.cwd = cwd
|
|
800
803
|
|
|
@@ -880,8 +883,10 @@ class Api {
|
|
|
880
883
|
filename = path.parse(scriptpath).base
|
|
881
884
|
}
|
|
882
885
|
|
|
886
|
+
|
|
883
887
|
// get the core script
|
|
884
888
|
let script = (await this.loader.load(scriptpath)).resolved
|
|
889
|
+
console.log("##### ", { scriptpath, script })
|
|
885
890
|
|
|
886
891
|
// if the sccript is a function, instantiate first
|
|
887
892
|
if (typeof script === "function") {
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/*
|
|
2
|
+
# 1. key.set => pops up key + password input
|
|
3
|
+
{
|
|
4
|
+
"method": "key.set"
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
# 2. key.get => pops up key + password input
|
|
8
|
+
# 2.1. Publick key/val
|
|
9
|
+
{
|
|
10
|
+
"method": "key.get"
|
|
11
|
+
}
|
|
12
|
+
*/
|
|
13
|
+
const fs = require('fs')
|
|
14
|
+
const { createStore } = require('key-store')
|
|
15
|
+
class Key {
|
|
16
|
+
async set(req, ondata, kernel) {
|
|
17
|
+
ondata(req.params, "key.set")
|
|
18
|
+
let { key, password } = await kernel.api.wait(req.parent.path)
|
|
19
|
+
}
|
|
20
|
+
async get(req, ondata, kernel) {
|
|
21
|
+
ondata(req.params, "key.get")
|
|
22
|
+
let { key, password } = await kernel.api.wait(req.parent.path)
|
|
23
|
+
return response
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
module.exports = Key
|
package/kernel/index.js
CHANGED
|
@@ -11,6 +11,7 @@ const Bin = require('./bin')
|
|
|
11
11
|
const Api = require("./api")
|
|
12
12
|
const Template = require('./template')
|
|
13
13
|
const Shells = require("./shells")
|
|
14
|
+
const Key = require("./key")
|
|
14
15
|
const Config = require("./pinokio.json")
|
|
15
16
|
const VARS = {
|
|
16
17
|
pip: {
|
|
@@ -26,7 +27,7 @@ class Kernel {
|
|
|
26
27
|
this.store = store
|
|
27
28
|
this.arch = os.arch()
|
|
28
29
|
this.platform = os.platform()
|
|
29
|
-
|
|
30
|
+
this.key = new Key()
|
|
30
31
|
}
|
|
31
32
|
resumeprocess(uri) {
|
|
32
33
|
let proc = this.procs[uri]
|
|
@@ -174,6 +175,9 @@ class Kernel {
|
|
|
174
175
|
}
|
|
175
176
|
console.log("this.vars", this.vars)
|
|
176
177
|
|
|
178
|
+
// let keyfile = path.resolve(this.homedir, "keys.json")
|
|
179
|
+
// await this.key.init(keyfile)
|
|
180
|
+
|
|
177
181
|
// let home = this.store.get("home")
|
|
178
182
|
// if (home) {
|
|
179
183
|
// this.homedir = home
|
package/kernel/key.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
const { createStore } = require('key-store')
|
|
2
|
+
class Key {
|
|
3
|
+
async init(filePath) {
|
|
4
|
+
const saveKeys = (data) => {
|
|
5
|
+
return fs.promises.writeFile(filePath, JSON.stringify(data, null, 2), 'utf8')
|
|
6
|
+
}
|
|
7
|
+
const readKeys = async () => {
|
|
8
|
+
try {
|
|
9
|
+
let s = await fs.promises.readFile(filePath, "utf8")
|
|
10
|
+
return JSON.parse(s)
|
|
11
|
+
} catch (e) {
|
|
12
|
+
return {}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
let keys = await readKeys()
|
|
16
|
+
|
|
17
|
+
this.store = await createStore(saveKeys, keys)
|
|
18
|
+
}
|
|
19
|
+
keys() {
|
|
20
|
+
return this.store.getKeyIDs()
|
|
21
|
+
}
|
|
22
|
+
get(key, password) {
|
|
23
|
+
if (password) {
|
|
24
|
+
return this.store.getPrivateKeyData(key, password)
|
|
25
|
+
} else {
|
|
26
|
+
return this.store.getPublicKeyData(key)
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
set(key, val, password) {
|
|
30
|
+
if (password) {
|
|
31
|
+
console.log({ key, val, password})
|
|
32
|
+
return this.store.saveKey(key, password, String(val))
|
|
33
|
+
} else {
|
|
34
|
+
console.log({ key, val})
|
|
35
|
+
//return this.store.savePublicKeyData(key, String(val))
|
|
36
|
+
return this.store.saveKey(key, "", "", String(val))
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
del(key) {
|
|
40
|
+
this.store.removeKey(key)
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
module.exports = Key
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pinokiod",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.33",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
"http-terminator": "^3.2.0",
|
|
33
33
|
"isomorphic-git": "^1.23.0",
|
|
34
34
|
"jsonpath-plus": "^7.2.0",
|
|
35
|
+
"key-store": "^1.2.0",
|
|
35
36
|
"localtunnel": "^2.0.2",
|
|
36
37
|
"lodash": "^4.17.21",
|
|
37
38
|
"marked": "^5.0.1",
|
package/server/index.js
CHANGED
|
@@ -23,11 +23,13 @@ const multer = require('multer');
|
|
|
23
23
|
const localtunnel = require('localtunnel');
|
|
24
24
|
|
|
25
25
|
|
|
26
|
+
|
|
26
27
|
const Socket = require('./socket')
|
|
27
28
|
const Kernel = require("../kernel")
|
|
28
29
|
const packagejson = require("../package.json")
|
|
29
30
|
class Server {
|
|
30
31
|
constructor(config) {
|
|
32
|
+
this.tabs = {}
|
|
31
33
|
this.agent = config.agent
|
|
32
34
|
this.port = config.port
|
|
33
35
|
this.kernel = new Kernel(config.store)
|
|
@@ -169,7 +171,8 @@ class Server {
|
|
|
169
171
|
}
|
|
170
172
|
|
|
171
173
|
// check if it's a folder or a file
|
|
172
|
-
let p = "/api"
|
|
174
|
+
let p = "/api" // run mode
|
|
175
|
+
let _p = "/_api" // edit mode
|
|
173
176
|
let paths = [{
|
|
174
177
|
name: '<i class="fa-solid fa-house"></i>',
|
|
175
178
|
path: "/",
|
|
@@ -337,6 +340,7 @@ class Server {
|
|
|
337
340
|
val: this.theme,
|
|
338
341
|
options: ["light", "dark"]
|
|
339
342
|
}]
|
|
343
|
+
console.log("agent", this.agent)
|
|
340
344
|
res.render("settings", {
|
|
341
345
|
version: this.version,
|
|
342
346
|
logo: this.logo,
|
|
@@ -480,6 +484,11 @@ class Server {
|
|
|
480
484
|
let template
|
|
481
485
|
template = "fullscreen_editor"
|
|
482
486
|
|
|
487
|
+
if (req.query && req.query.mode === "source") {
|
|
488
|
+
template = "editor"
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
|
|
483
492
|
// Deprecate source view and form view => Everything is full screen by default
|
|
484
493
|
// if (req.query && req.query.mode === "source") {
|
|
485
494
|
// if (req.query && req.query.fullscreen) {
|
|
@@ -681,6 +690,16 @@ class Server {
|
|
|
681
690
|
// })
|
|
682
691
|
// }
|
|
683
692
|
console.log("mem", mem)
|
|
693
|
+
console.log("originalUrl", req.originalUrl)
|
|
694
|
+
let edu = new URL("http://localhost" + req.originalUrl)
|
|
695
|
+
edu.searchParams.set("mode", "source")
|
|
696
|
+
let editorUrl = edu.pathname + edu.search
|
|
697
|
+
console.log("editorUrl", editorUrl)
|
|
698
|
+
console.log("req.query", req.query)
|
|
699
|
+
|
|
700
|
+
|
|
701
|
+
|
|
702
|
+
|
|
684
703
|
const result = {
|
|
685
704
|
error,
|
|
686
705
|
memory: mem,
|
|
@@ -688,7 +707,8 @@ class Server {
|
|
|
688
707
|
logo: this.logo,
|
|
689
708
|
theme: this.theme,
|
|
690
709
|
//run: (req.query && req.query.run ? true : false),
|
|
691
|
-
run: true, // run mode by default
|
|
710
|
+
//run: true, // run mode by default
|
|
711
|
+
run: (req.query && req.query.mode === "source" ? false : true),
|
|
692
712
|
stop: (req.query && req.query.stop ? true : false),
|
|
693
713
|
pinokioPath,
|
|
694
714
|
runnable,
|
|
@@ -709,6 +729,8 @@ class Server {
|
|
|
709
729
|
install_required,
|
|
710
730
|
//current: encodeURIComponent(req.originalUrl),
|
|
711
731
|
current: req.originalUrl,
|
|
732
|
+
editorUrl,
|
|
733
|
+
execUrl: "~" + req.originalUrl.replace(/^\/_api/, "\/api")
|
|
712
734
|
}
|
|
713
735
|
console.log("RESULT", result)
|
|
714
736
|
|
|
@@ -936,6 +958,12 @@ class Server {
|
|
|
936
958
|
// items
|
|
937
959
|
|
|
938
960
|
|
|
961
|
+
console.log("ITEMS", items)
|
|
962
|
+
|
|
963
|
+
|
|
964
|
+
let U = `${_p}/${pathComponents.join("/")}`
|
|
965
|
+
console.log("*******", { filepath, pathComponents, U })
|
|
966
|
+
|
|
939
967
|
|
|
940
968
|
res.render("index", {
|
|
941
969
|
error: error,
|
|
@@ -956,43 +984,45 @@ class Server {
|
|
|
956
984
|
notRunning,
|
|
957
985
|
readme,
|
|
958
986
|
filepath,
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
//
|
|
993
|
-
//
|
|
994
|
-
|
|
995
|
-
|
|
987
|
+
items: items.map((x) => {
|
|
988
|
+
//let name = (x.name.startsWith("0x") ? Buffer.from(x.name.slice(2), "hex").toString() : x.name)
|
|
989
|
+
let name
|
|
990
|
+
let description
|
|
991
|
+
let icon
|
|
992
|
+
let uri
|
|
993
|
+
if (meta) {
|
|
994
|
+
let m = meta[x.name]
|
|
995
|
+
name = (m && m.title ? m.title : x.name)
|
|
996
|
+
description = (m && m.description ? m.description : "")
|
|
997
|
+
if (m && m.icon) {
|
|
998
|
+
icon = m.icon
|
|
999
|
+
} else {
|
|
1000
|
+
icon = null
|
|
1001
|
+
}
|
|
1002
|
+
uri = x.name
|
|
1003
|
+
} else {
|
|
1004
|
+
if (x.isDirectory()) {
|
|
1005
|
+
icon = "fa-solid fa-folder"
|
|
1006
|
+
} else {
|
|
1007
|
+
icon = "fa-regular fa-file"
|
|
1008
|
+
}
|
|
1009
|
+
name = x.name
|
|
1010
|
+
description = ""
|
|
1011
|
+
}
|
|
1012
|
+
return {
|
|
1013
|
+
icon,
|
|
1014
|
+
menu: x.menu,
|
|
1015
|
+
//icon: (x.isDirectory() ? "fa-solid fa-folder" : "fa-regular fa-file"),
|
|
1016
|
+
name,
|
|
1017
|
+
uri,
|
|
1018
|
+
//description: x.path,
|
|
1019
|
+
description,
|
|
1020
|
+
//url: p + "/" + x.name,
|
|
1021
|
+
// url: _p + "/" + x.name,
|
|
1022
|
+
url: `${U}/${x.name}`,
|
|
1023
|
+
browser_url: "/pinokio/browser/" + x.name
|
|
1024
|
+
}
|
|
1025
|
+
}),
|
|
996
1026
|
})
|
|
997
1027
|
}
|
|
998
1028
|
}
|
|
@@ -1585,6 +1615,15 @@ class Server {
|
|
|
1585
1615
|
res.status(404).send(e.message);
|
|
1586
1616
|
}
|
|
1587
1617
|
})
|
|
1618
|
+
this.app.get("/_api/*", async (req, res) => {
|
|
1619
|
+
let pathComponents = req.params[0].split("/")
|
|
1620
|
+
req.query.mode = "source"
|
|
1621
|
+
try {
|
|
1622
|
+
await this.render(req, res, pathComponents)
|
|
1623
|
+
} catch (e) {
|
|
1624
|
+
res.status(404).send(e.message)
|
|
1625
|
+
}
|
|
1626
|
+
})
|
|
1588
1627
|
this.app.get("/api/*", async (req, res) => {
|
|
1589
1628
|
let pathComponents = req.params[0].split("/")
|
|
1590
1629
|
try {
|
|
@@ -1660,6 +1699,10 @@ class Server {
|
|
|
1660
1699
|
res.json({ error: e.message })
|
|
1661
1700
|
}
|
|
1662
1701
|
})
|
|
1702
|
+
this.app.post("/pinokio/tabs", async (req, res) => {
|
|
1703
|
+
this.tabs[req.body.name] = req.body.tabs
|
|
1704
|
+
res.json({ success: true })
|
|
1705
|
+
})
|
|
1663
1706
|
this.app.get("/pinokio/browser/:name", async (req, res) => {
|
|
1664
1707
|
let name = req.params.name
|
|
1665
1708
|
let app_path = this.kernel.path("api", name, "pinokio.js")
|
|
@@ -1689,12 +1732,14 @@ class Server {
|
|
|
1689
1732
|
memory: this.kernel.memory,
|
|
1690
1733
|
sidebar: "/pinokio/sidebar/" + name,
|
|
1691
1734
|
name,
|
|
1735
|
+
tabs: (this.tabs[name] || []),
|
|
1692
1736
|
config,
|
|
1693
1737
|
// sidebar_url: "/pinokio/sidebar/" + name,
|
|
1694
1738
|
home: req.originalUrl,
|
|
1695
1739
|
// paths,
|
|
1696
1740
|
theme: this.theme,
|
|
1697
1741
|
agent: this.agent,
|
|
1742
|
+
src: "/_api/" + name,
|
|
1698
1743
|
rawpath
|
|
1699
1744
|
})
|
|
1700
1745
|
})
|
|
@@ -4,6 +4,8 @@ const ModalInput = async (params) => {
|
|
|
4
4
|
title,
|
|
5
5
|
type: "modal" (default) |"notify"
|
|
6
6
|
form: [{
|
|
7
|
+
type,
|
|
8
|
+
items,
|
|
7
9
|
key,
|
|
8
10
|
title,
|
|
9
11
|
description,
|
|
@@ -21,6 +23,13 @@ const ModalInput = async (params) => {
|
|
|
21
23
|
let input
|
|
22
24
|
if (type === 'textarea') {
|
|
23
25
|
input = `<textarea oninput="autoExpand(this)" data-id="${field.key}" class="swal2-input" placeholder="${field.placeholder ? field.placeholder : ''}"></textarea>`
|
|
26
|
+
} else if (type === 'select') {
|
|
27
|
+
if (field.items && Array.isArray(field.items)) {
|
|
28
|
+
let items = field.items.map((item) => {
|
|
29
|
+
return `<option value="${item}">${item}</option>`
|
|
30
|
+
}).join("")
|
|
31
|
+
input = `<select>${items}</select>`
|
|
32
|
+
}
|
|
24
33
|
} else {
|
|
25
34
|
input = `<input type='${type}' data-id="${field.key}" class="swal2-input" placeholder="${field.placeholder ? field.placeholder : ''}">`
|
|
26
35
|
}
|
package/server/public/style.css
CHANGED
|
@@ -783,10 +783,10 @@ body.dark .line {
|
|
|
783
783
|
border-bottom: 1px solid var(--dark-thin);
|
|
784
784
|
}
|
|
785
785
|
body.dark .line.selected {
|
|
786
|
-
/*
|
|
787
786
|
background: rgba(0,0,0, 0.2);
|
|
788
|
-
|
|
787
|
+
/*
|
|
789
788
|
border-left: 6px solid white;
|
|
789
|
+
*/
|
|
790
790
|
}
|
|
791
791
|
body.dark .line:hover {
|
|
792
792
|
background: rgba(0,0,0, 0.2);
|
|
@@ -795,9 +795,9 @@ body.dark .line:hover {
|
|
|
795
795
|
background: rgba(200,0,0, 0.04);
|
|
796
796
|
}
|
|
797
797
|
.line.selected {
|
|
798
|
-
border-left: 6px solid black;
|
|
799
|
-
/*
|
|
800
798
|
background: rgba(0,0,100, 0.03);
|
|
799
|
+
/*
|
|
800
|
+
border-left: 6px solid black;
|
|
801
801
|
*/
|
|
802
802
|
}
|
|
803
803
|
.line {
|
|
@@ -966,7 +966,10 @@ button {
|
|
|
966
966
|
cursor: pointer;
|
|
967
967
|
}
|
|
968
968
|
body.dark .btn {
|
|
969
|
+
/*
|
|
969
970
|
color: var(--dark-btn-color);
|
|
971
|
+
*/
|
|
972
|
+
color: white;
|
|
970
973
|
background: var(--dark-btn-bg);
|
|
971
974
|
}
|
|
972
975
|
.btn {
|
|
@@ -1286,7 +1289,10 @@ b {
|
|
|
1286
1289
|
background: royalblue;
|
|
1287
1290
|
}
|
|
1288
1291
|
body.dark #new-window {
|
|
1292
|
+
/*
|
|
1289
1293
|
color: var(--dark-btn-color);
|
|
1294
|
+
*/
|
|
1295
|
+
color: white;
|
|
1290
1296
|
}
|
|
1291
1297
|
#new-window {
|
|
1292
1298
|
padding: 10px;
|
|
@@ -1296,7 +1302,10 @@ body.dark #new-window {
|
|
|
1296
1302
|
color: var(--light-color);
|
|
1297
1303
|
}
|
|
1298
1304
|
body.dark .btn2 {
|
|
1305
|
+
/*
|
|
1299
1306
|
color: var(--dark-btn-color);
|
|
1307
|
+
*/
|
|
1308
|
+
color: white;
|
|
1300
1309
|
}
|
|
1301
1310
|
.btn2:hover {
|
|
1302
1311
|
background: rgba(0,0,0,0.06);
|
|
@@ -1378,10 +1387,17 @@ nav.error-message {
|
|
|
1378
1387
|
}
|
|
1379
1388
|
/*
|
|
1380
1389
|
.running-apps {
|
|
1390
|
+
background: rgba(0,0,100, 0.03);
|
|
1381
1391
|
background: rgba(255,215, 0, 0.2);
|
|
1382
1392
|
}
|
|
1383
1393
|
*/
|
|
1394
|
+
/*
|
|
1395
|
+
body.dark .running-apps {
|
|
1396
|
+
border-left: 6px solid gold;
|
|
1397
|
+
}
|
|
1398
|
+
*/
|
|
1384
1399
|
.running-apps {
|
|
1400
|
+
border-left: 10px solid gold;
|
|
1385
1401
|
/*
|
|
1386
1402
|
background: rgba(255,215,0,0.03);
|
|
1387
1403
|
*/
|
|
@@ -1403,7 +1419,10 @@ nav.error-message {
|
|
|
1403
1419
|
*/
|
|
1404
1420
|
}
|
|
1405
1421
|
body.dark header .home {
|
|
1422
|
+
/*
|
|
1406
1423
|
color: var(--dark-btn-color);
|
|
1424
|
+
*/
|
|
1425
|
+
color: white;
|
|
1407
1426
|
}
|
|
1408
1427
|
header .home {
|
|
1409
1428
|
color: var(--light-color);
|
package/server/views/browser.ejs
CHANGED
|
@@ -75,6 +75,7 @@ main iframe {
|
|
|
75
75
|
text-decoration: none;
|
|
76
76
|
align-items: center;
|
|
77
77
|
border-radius: 0;
|
|
78
|
+
cursor: pointer;
|
|
78
79
|
}
|
|
79
80
|
.header-item.selected {
|
|
80
81
|
}
|
|
@@ -99,7 +100,10 @@ body.dark .header-item .btn2 {
|
|
|
99
100
|
border-radius: 30px;
|
|
100
101
|
}
|
|
101
102
|
body.dark .header-item.btn {
|
|
103
|
+
color: white;
|
|
104
|
+
/*
|
|
102
105
|
color: var(--dark-color);
|
|
106
|
+
*/
|
|
103
107
|
}
|
|
104
108
|
.header-item.btn {
|
|
105
109
|
padding: 10px;
|
|
@@ -114,13 +118,19 @@ body .logo {
|
|
|
114
118
|
color: var(--light-color);
|
|
115
119
|
}
|
|
116
120
|
body.dark .logo {
|
|
121
|
+
/*
|
|
117
122
|
color: var(--dark-btn-color);
|
|
123
|
+
*/
|
|
124
|
+
color: white;
|
|
118
125
|
}
|
|
119
126
|
body #new-window {
|
|
120
127
|
color: var(--light-color);
|
|
121
128
|
}
|
|
122
129
|
body.dark #new-window {
|
|
130
|
+
/*
|
|
123
131
|
color: var(--dark-btn-color);
|
|
132
|
+
*/
|
|
133
|
+
color: white;
|
|
124
134
|
}
|
|
125
135
|
.app-info {
|
|
126
136
|
/*
|
|
@@ -167,17 +177,35 @@ body .footer {
|
|
|
167
177
|
body.dark .footer {
|
|
168
178
|
border-bottom: 1px solid rgba(255,255,255,0.04);
|
|
169
179
|
}
|
|
180
|
+
body.dark .header-item.cursor {
|
|
181
|
+
background: rgba(0,0,0, 0.2) !important;
|
|
182
|
+
}
|
|
170
183
|
.header-item.cursor {
|
|
184
|
+
background: rgba(0,0,100, 0.03) !important;
|
|
185
|
+
/*
|
|
171
186
|
border-left: 5px solid gold;
|
|
187
|
+
*/
|
|
172
188
|
}
|
|
173
189
|
body .frame-link.selected {
|
|
190
|
+
border-left: 10px solid gold;
|
|
191
|
+
/*
|
|
174
192
|
background: rgba(0,0,200,0.1) !important;
|
|
193
|
+
*/
|
|
175
194
|
}
|
|
195
|
+
/*
|
|
176
196
|
body.dark .frame-link.selected {
|
|
177
197
|
background: rgba(0,0,0,0.2) !important;
|
|
178
198
|
}
|
|
199
|
+
*/
|
|
179
200
|
.frame-link .tab {
|
|
180
201
|
flex-grow: 1;
|
|
202
|
+
width: 100%;
|
|
203
|
+
}
|
|
204
|
+
.frame-link .tab .flexible {
|
|
205
|
+
min-width: 5px;
|
|
206
|
+
}
|
|
207
|
+
.frame-link .tab .display {
|
|
208
|
+
word-break: break-word;
|
|
181
209
|
}
|
|
182
210
|
body.dark .grid-btns {
|
|
183
211
|
border-top: 1px solid rgba(255,255,255,0.04);
|
|
@@ -198,7 +226,10 @@ body.dark .grid-btns {
|
|
|
198
226
|
cursor: pointer;
|
|
199
227
|
}
|
|
200
228
|
body.dark .grid-btns .btn2 {
|
|
229
|
+
color: white;
|
|
230
|
+
/*
|
|
201
231
|
color: var(--dark-btn-color);
|
|
232
|
+
*/
|
|
202
233
|
}
|
|
203
234
|
.footer {
|
|
204
235
|
width: 100%;
|
|
@@ -214,6 +245,9 @@ body.dark .grid-btns .btn2 {
|
|
|
214
245
|
.tab i {
|
|
215
246
|
margin-right: 10px;
|
|
216
247
|
}
|
|
248
|
+
.temp-menu .del i {
|
|
249
|
+
margin: 0;
|
|
250
|
+
}
|
|
217
251
|
body .footer {
|
|
218
252
|
}
|
|
219
253
|
/*
|
|
@@ -250,6 +284,16 @@ nav .logo {
|
|
|
250
284
|
.header-item.header-top {
|
|
251
285
|
display: block;
|
|
252
286
|
}
|
|
287
|
+
#new-tab:hover {
|
|
288
|
+
background: rgba(0,0,0,0.07) !important;
|
|
289
|
+
}
|
|
290
|
+
#new-tab {
|
|
291
|
+
justify-content: center;
|
|
292
|
+
border-top: 1px solid rgba(0,0,0,0.04);
|
|
293
|
+
}
|
|
294
|
+
body.dark #new-tab {
|
|
295
|
+
border-top: 1px solid rgba(255,255,255,0.04);
|
|
296
|
+
}
|
|
253
297
|
</style>
|
|
254
298
|
</head>
|
|
255
299
|
<body class='<%=theme%>'>
|
|
@@ -260,10 +304,15 @@ nav .logo {
|
|
|
260
304
|
<div><%=config.title%></div>
|
|
261
305
|
</div>
|
|
262
306
|
</div>
|
|
307
|
+
<div class='system'>
|
|
308
|
+
<a data-index="1" target="<%=src%>" href="<%=src%>" class='btn header-item selectable frame-link'>
|
|
309
|
+
<div class='tab'><i class="fa-regular fa-folder-open"></i> Files</div>
|
|
310
|
+
</a>
|
|
311
|
+
</div>
|
|
263
312
|
<div class='menu'>
|
|
264
313
|
<% config.menu.forEach((item, index) => { %>
|
|
265
314
|
<% if (item.btn) { %>
|
|
266
|
-
<a data-index="<%=index+
|
|
315
|
+
<a data-index="<%=index+2%>" target="<%=item.src%>" href="<%=item.href%>" class='btn header-item selectable frame-link'>
|
|
267
316
|
<div class='tab'><%-item.btn%></div>
|
|
268
317
|
<% if (item.running) { %>
|
|
269
318
|
<i class='fa-solid fa-spin fa-circle-notch'></i>
|
|
@@ -276,6 +325,18 @@ nav .logo {
|
|
|
276
325
|
<% } %>
|
|
277
326
|
<% }) %>
|
|
278
327
|
</div>
|
|
328
|
+
<div class='temp-menu'>
|
|
329
|
+
<%tabs.forEach((tab) => { %>
|
|
330
|
+
<a target="<%=tab%>" href="<%=tab%>" class="btn header-item frame-link">
|
|
331
|
+
<div class='tab'>
|
|
332
|
+
<i class="fa-solid fa-link"></i><div class='display'><%=tab%></div><div class='flexible'></div><button class='btn2 del'><i class="fa-solid fa-xmark"></i></button>
|
|
333
|
+
</div>
|
|
334
|
+
</a>
|
|
335
|
+
<%})%>
|
|
336
|
+
</div>
|
|
337
|
+
<div id='new-tab' class='btn header-item'>
|
|
338
|
+
<i class="fa-solid fa-plus"></i>
|
|
339
|
+
</div>
|
|
279
340
|
<div class='flexible'></div>
|
|
280
341
|
<div class='grid-btns'>
|
|
281
342
|
<a class='btn2' href="/?mode=explore" id='explore'><div><i class="fa-solid fa-globe"></i></div><div>Discover</div></a>
|
|
@@ -362,52 +423,54 @@ const renderSelection = (e, force) => {
|
|
|
362
423
|
el.classList.remove("selected")
|
|
363
424
|
})
|
|
364
425
|
const target = document.querySelector(`[target='${id}']`)
|
|
365
|
-
target
|
|
426
|
+
if (target) {
|
|
427
|
+
target.classList.add("selected")
|
|
366
428
|
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
if (e) {
|
|
382
|
-
e.preventDefault()
|
|
383
|
-
e.stopPropagation()
|
|
384
|
-
} else {
|
|
385
|
-
console.log("REFRESH")
|
|
386
|
-
if (force) {
|
|
387
|
-
targetFrame.src = target.href
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
} else {
|
|
391
|
-
console.log("load")
|
|
392
|
-
//targetFrame.contentWindow.addEventListener("load", () => {
|
|
393
|
-
console.log("#1")
|
|
429
|
+
// select the iframe
|
|
430
|
+
document.querySelectorAll("iframe").forEach((el) => {
|
|
431
|
+
el.classList.add("hidden")
|
|
432
|
+
})
|
|
433
|
+
let targetFrame = document.querySelector(`iframe[name='${target.target}']`)
|
|
434
|
+
console.log("#4", loaded)
|
|
435
|
+
console.log("targetFrame", targetFrame)
|
|
436
|
+
if (targetFrame) {
|
|
437
|
+
console.log("#5", loaded)
|
|
438
|
+
console.log({ loaded })
|
|
439
|
+
targetFrame.classList.remove("hidden")
|
|
440
|
+
|
|
441
|
+
// if the iframe already exists, do not
|
|
442
|
+
if (loaded[target.target]){
|
|
394
443
|
if (e) {
|
|
395
|
-
|
|
444
|
+
e.preventDefault()
|
|
445
|
+
e.stopPropagation()
|
|
396
446
|
} else {
|
|
397
|
-
|
|
398
|
-
|
|
447
|
+
console.log("REFRESH")
|
|
448
|
+
if (force) {
|
|
449
|
+
targetFrame.src = target.href
|
|
450
|
+
}
|
|
399
451
|
}
|
|
400
|
-
|
|
401
|
-
|
|
452
|
+
} else {
|
|
453
|
+
console.log("load")
|
|
454
|
+
//targetFrame.contentWindow.addEventListener("load", () => {
|
|
455
|
+
console.log("#1")
|
|
456
|
+
if (e) {
|
|
457
|
+
// coming from a click => don't need to set the src
|
|
458
|
+
} else {
|
|
459
|
+
// load without click
|
|
460
|
+
targetFrame.src = target.href
|
|
461
|
+
}
|
|
462
|
+
loaded[target.target] = true
|
|
463
|
+
//});
|
|
464
|
+
}
|
|
465
|
+
} else {
|
|
466
|
+
console.log("#6", loaded)
|
|
467
|
+
let frame = document.createElement("iframe")
|
|
468
|
+
frame.name = target.target
|
|
469
|
+
frame.src = target.href
|
|
470
|
+
document.querySelector("main").appendChild(frame)
|
|
471
|
+
console.log("#2")
|
|
472
|
+
loaded[target.target] = true
|
|
402
473
|
}
|
|
403
|
-
} else {
|
|
404
|
-
console.log("#6", loaded)
|
|
405
|
-
let frame = document.createElement("iframe")
|
|
406
|
-
frame.name = target.target
|
|
407
|
-
frame.src = target.href
|
|
408
|
-
document.querySelector("main").appendChild(frame)
|
|
409
|
-
console.log("#2")
|
|
410
|
-
loaded[target.target] = true
|
|
411
474
|
}
|
|
412
475
|
} else {
|
|
413
476
|
document.querySelector(".bar").classList.add("hidden")
|
|
@@ -427,28 +490,110 @@ document.querySelector("#reload").addEventListener("click", (e) => {
|
|
|
427
490
|
renderSelection(null, true)
|
|
428
491
|
})
|
|
429
492
|
|
|
430
|
-
document.querySelector("
|
|
493
|
+
document.querySelector("#new-tab").addEventListener("click", async (e) => {
|
|
494
|
+
const url = prompt("url")
|
|
495
|
+
|
|
496
|
+
if (url && url.trim().length > 0) {
|
|
497
|
+
console.log("url", url)
|
|
498
|
+
await addTab(url)
|
|
499
|
+
}
|
|
500
|
+
})
|
|
501
|
+
|
|
502
|
+
const syncTabs = async () => {
|
|
503
|
+
let tabs = []
|
|
504
|
+
document.querySelectorAll(".temp-menu .frame-link").forEach((el) => {
|
|
505
|
+
tabs.push(el.href)
|
|
506
|
+
})
|
|
507
|
+
|
|
508
|
+
|
|
509
|
+
// persist
|
|
510
|
+
console.log("sync tabs", tabs)
|
|
511
|
+
|
|
512
|
+
await fetch("/pinokio/tabs", {
|
|
513
|
+
method: "POST",
|
|
514
|
+
headers: {
|
|
515
|
+
"Content-Type": "application/json"
|
|
516
|
+
},
|
|
517
|
+
body: JSON.stringify({
|
|
518
|
+
name: "<%=name%>",
|
|
519
|
+
tabs
|
|
520
|
+
})
|
|
521
|
+
})
|
|
522
|
+
}
|
|
523
|
+
const addTab = async (url) => {
|
|
524
|
+
let item = document.createElement("a")
|
|
525
|
+
//let id = "ts" + Date.now()
|
|
526
|
+
let id = url
|
|
527
|
+
item.target = id
|
|
528
|
+
item.href = url
|
|
529
|
+
item.className = "btn header-item frame-link"
|
|
530
|
+
item.innerHTML = `<div class='tab'><i class="fa-solid fa-link"></i><div class='display'>${url}</div><div class='flexible'></div><button class='btn2 del'><i class="fa-solid fa-xmark"></i></button></div>`
|
|
531
|
+
|
|
532
|
+
document.querySelector(".temp-menu").appendChild(item)
|
|
533
|
+
|
|
534
|
+
let frame = document.createElement("iframe")
|
|
535
|
+
frame.name = id
|
|
536
|
+
document.querySelector("main").appendChild(frame)
|
|
537
|
+
|
|
538
|
+
await syncTabs()
|
|
539
|
+
|
|
540
|
+
|
|
541
|
+
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
|
|
545
|
+
document.querySelector("aside").addEventListener("click", async (e) => {
|
|
431
546
|
let target
|
|
432
547
|
|
|
433
548
|
|
|
434
|
-
|
|
549
|
+
// delete
|
|
550
|
+
if (e.target.classList.contains("del")) {
|
|
435
551
|
target = e.target
|
|
436
552
|
} else {
|
|
437
|
-
target = e.target.closest(".
|
|
553
|
+
target = e.target.closest(".del")
|
|
438
554
|
}
|
|
439
555
|
|
|
556
|
+
if (target) {
|
|
557
|
+
e.preventDefault()
|
|
558
|
+
e.stopPropagation()
|
|
559
|
+
// Delete
|
|
560
|
+
// delete link
|
|
561
|
+
let el = target.closest(".frame-link")
|
|
562
|
+
console.log("target", el.target)
|
|
563
|
+
let iframe = document.querySelector("iframe[name='" + el.target + "']")
|
|
564
|
+
console.log("iframe", iframe)
|
|
565
|
+
if (iframe) {
|
|
566
|
+
// delete iframe
|
|
567
|
+
iframe.remove()
|
|
568
|
+
}
|
|
569
|
+
el.remove()
|
|
570
|
+
// update tabs
|
|
571
|
+
await syncTabs()
|
|
440
572
|
|
|
573
|
+
} else {
|
|
574
|
+
// Select
|
|
575
|
+
if (e.target.classList.contains("frame-link")) {
|
|
576
|
+
target = e.target
|
|
577
|
+
} else {
|
|
578
|
+
target = e.target.closest(".frame-link")
|
|
579
|
+
}
|
|
441
580
|
|
|
442
|
-
if (target) {
|
|
443
581
|
|
|
444
|
-
//location.hash = target.target
|
|
445
|
-
let id = getTarget(target.getAttribute("href"))
|
|
446
|
-
console.log("ID", id, target.href)
|
|
447
|
-
location.hash = id
|
|
448
582
|
|
|
449
|
-
|
|
583
|
+
if (target) {
|
|
450
584
|
|
|
585
|
+
//location.hash = target.target
|
|
586
|
+
let id = getTarget(target.getAttribute("href"))
|
|
587
|
+
console.log("ID", id, target.href)
|
|
588
|
+
location.hash = id
|
|
589
|
+
|
|
590
|
+
renderSelection(e)
|
|
591
|
+
|
|
592
|
+
}
|
|
451
593
|
}
|
|
594
|
+
|
|
595
|
+
|
|
596
|
+
|
|
452
597
|
})
|
|
453
598
|
const refresh = async () => {
|
|
454
599
|
const res = await fetch("<%=sidebar%>").then((res) => {
|
|
@@ -473,9 +618,16 @@ const refresh = async () => {
|
|
|
473
618
|
renderCursor()
|
|
474
619
|
|
|
475
620
|
}
|
|
476
|
-
window.addEventListener('message', (
|
|
621
|
+
window.addEventListener('message', (event) => {
|
|
477
622
|
console.log("Message received from the child: ", event.data); // Message received from child
|
|
478
|
-
|
|
623
|
+
if (event.data && event.data.action) {
|
|
624
|
+
if (event.data.action.type === "newtab") {
|
|
625
|
+
console.log("create tab", event.data.action.url)
|
|
626
|
+
addTab(event.data.action.url)
|
|
627
|
+
}
|
|
628
|
+
} else {
|
|
629
|
+
refresh()
|
|
630
|
+
}
|
|
479
631
|
});
|
|
480
632
|
document.addEventListener("keydown", (e) => {
|
|
481
633
|
let size = document.querySelectorAll(".selectable").length
|
package/server/views/editor.ejs
CHANGED
|
@@ -73,6 +73,9 @@ td.key {
|
|
|
73
73
|
#editor {
|
|
74
74
|
background: var(--dark-bg);
|
|
75
75
|
}
|
|
76
|
+
header .runner {
|
|
77
|
+
padding: 10px 0;
|
|
78
|
+
}
|
|
76
79
|
</style>
|
|
77
80
|
<script>
|
|
78
81
|
document.addEventListener("DOMContentLoaded", async () => {
|
|
@@ -80,6 +83,7 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
80
83
|
document.querySelector(".requirements .content").innerHTML = '<div class="loading"><i class="fa-solid fa-circle-exclamation"></i> <%=error%></div>'
|
|
81
84
|
<% } %>
|
|
82
85
|
<% if (!install_required) { %>
|
|
86
|
+
/*
|
|
83
87
|
document.querySelector("footer").addEventListener("click", (e) => {
|
|
84
88
|
if (e.target.classList.contains("toggle-expand") || e.target.closest(".toggle-expand")) {
|
|
85
89
|
let el = document.querySelector("footer .toggle-expand i")
|
|
@@ -91,6 +95,7 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
91
95
|
document.querySelector("footer").classList.toggle("expanded")
|
|
92
96
|
}
|
|
93
97
|
})
|
|
98
|
+
*/
|
|
94
99
|
<% } %>
|
|
95
100
|
<% if (requirements_pending) { %>
|
|
96
101
|
await new Promise((resolve, reject) => {
|
|
@@ -185,14 +190,16 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
185
190
|
params: {
|
|
186
191
|
//uri: "<%-uri%>",
|
|
187
192
|
//uri: location.pathname.slice(1).replace("api/", ""),
|
|
188
|
-
uri: "~" + location.pathname
|
|
193
|
+
//uri: "~" + location.pathname
|
|
194
|
+
uri: "<%=execUrl%>",
|
|
189
195
|
}
|
|
190
196
|
}, (stream) => {
|
|
191
197
|
})
|
|
192
198
|
}
|
|
193
199
|
save() {
|
|
194
200
|
return new Promise((resolve, reject) => {
|
|
195
|
-
let cwd = "~" + location.pathname
|
|
201
|
+
//let cwd = "~" + location.pathname
|
|
202
|
+
let cwd = "<%=execUrl%>"
|
|
196
203
|
|
|
197
204
|
this.socket.close()
|
|
198
205
|
this.socket.run({
|
|
@@ -220,7 +227,8 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
220
227
|
|
|
221
228
|
this.socket.run({
|
|
222
229
|
//uri: location.pathname.slice(1).replace("api/", ""),
|
|
223
|
-
uri: "~" + location.pathname,
|
|
230
|
+
//uri: "~" + location.pathname,
|
|
231
|
+
uri: "<%=execUrl%>",
|
|
224
232
|
//uri: "<%-uri%>",
|
|
225
233
|
mode,
|
|
226
234
|
input: query,
|
|
@@ -231,32 +239,34 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
231
239
|
}, async (packet) => {
|
|
232
240
|
console.log("packet", packet)
|
|
233
241
|
if (packet.type === 'start') {
|
|
242
|
+
refreshParent(packet)
|
|
243
|
+
reloadMemory()
|
|
234
244
|
if (packet.data && packet.data.description) {
|
|
235
245
|
if ('current' in packet.data) {
|
|
236
246
|
document.querySelector("footer").innerHTML = `<b>
|
|
237
247
|
<i class="fa-solid fa-circle-notch fa-spin"></i>(${packet.data.current+1}/${packet.data.total}) ${packet.data.title ? packet.data.title : ''}
|
|
238
248
|
</b>
|
|
239
|
-
<div class='flexible content'>${packet.data.description}</div
|
|
240
|
-
<div class='toggle-expand'>
|
|
241
|
-
<i class="fa-solid fa-circle-chevron-up"></i>
|
|
242
|
-
</div>`
|
|
249
|
+
<div class='flexible content'>${packet.data.description}</div>`
|
|
250
|
+
// <div class='toggle-expand'>
|
|
251
|
+
// <i class="fa-solid fa-circle-chevron-up"></i>
|
|
252
|
+
// </div>`
|
|
243
253
|
} else {
|
|
244
254
|
document.querySelector("footer").innerHTML = `<b>
|
|
245
255
|
<i class="fa-solid fa-circle-notch fa-spin"></i> ${packet.data.title ? packet.data.title : ''}
|
|
246
256
|
</b>
|
|
247
|
-
<div class='flexible content'></div
|
|
248
|
-
<div class='toggle-expand'>
|
|
249
|
-
<i class="fa-solid fa-circle-chevron-up"></i>
|
|
250
|
-
</div>`
|
|
257
|
+
<div class='flexible content'></div>`
|
|
258
|
+
// <div class='toggle-expand'>
|
|
259
|
+
// <i class="fa-solid fa-circle-chevron-up"></i>
|
|
260
|
+
// </div>`
|
|
251
261
|
}
|
|
252
262
|
} else if (packet.data && packet.data.method) {
|
|
253
263
|
document.querySelector("footer").innerHTML = `<b>
|
|
254
264
|
<i class="fa-solid fa-circle-notch fa-spin"></i> (${packet.data.current+1}/${packet.data.total}) ${packet.data.method}
|
|
255
265
|
</b>
|
|
256
|
-
<div class='flexible content'>${packet.data.params ? JSON.stringify(packet.data.params) : ''}</div
|
|
257
|
-
<div class='toggle-expand'>
|
|
258
|
-
<i class="fa-solid fa-circle-chevron-up"></i>
|
|
259
|
-
</div>`
|
|
266
|
+
<div class='flexible content'>${packet.data.params ? JSON.stringify(packet.data.params) : ''}</div>`
|
|
267
|
+
// <div class='toggle-expand'>
|
|
268
|
+
// <i class="fa-solid fa-circle-chevron-up"></i>
|
|
269
|
+
// </div>`
|
|
260
270
|
}
|
|
261
271
|
} else if (packet.type === "stream") {
|
|
262
272
|
document.querySelector(".containers").classList.add("running")
|
|
@@ -274,10 +284,13 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
274
284
|
document.querySelector(".run .starting").classList.add("hidden")
|
|
275
285
|
document.querySelector(".run .stop").classList.remove("hidden")
|
|
276
286
|
} else if (packet.type === 'disconnect') {
|
|
277
|
-
refreshParent()
|
|
287
|
+
refreshParent(packet)
|
|
288
|
+
reloadMemory()
|
|
278
289
|
this.term.write("\r\nNot connected...\r\n")
|
|
279
290
|
document.querySelector("footer").innerHTML = "<b>Ready</b>"
|
|
280
291
|
this.socket.close()
|
|
292
|
+
document.querySelector(".run .play").classList.remove("hidden")
|
|
293
|
+
document.querySelector(".run .stop").classList.add("hidden")
|
|
281
294
|
} else if (packet.type === 'connect') {
|
|
282
295
|
// document.querySelector(".terminal-container").classList.remove("hidden")
|
|
283
296
|
const message = "..........Connected!\r\n"
|
|
@@ -307,7 +320,7 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
307
320
|
if (input) {
|
|
308
321
|
this.socket.respond({
|
|
309
322
|
response: input,
|
|
310
|
-
uri: "
|
|
323
|
+
uri: "<%=execUrl%>"
|
|
311
324
|
})
|
|
312
325
|
}
|
|
313
326
|
/*
|
|
@@ -331,13 +344,14 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
331
344
|
}
|
|
332
345
|
}
|
|
333
346
|
*/
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
params.
|
|
340
|
-
|
|
347
|
+
///// DEPRECATE browser.open : Pinokio IS the browser. Everything opens in Pinokio. May bring back when necessary
|
|
348
|
+
// refreshParent()
|
|
349
|
+
// let params = packet.data
|
|
350
|
+
// window.open(
|
|
351
|
+
// params.uri,
|
|
352
|
+
// (params.target || "_self"),
|
|
353
|
+
// params.features
|
|
354
|
+
// )
|
|
341
355
|
} else if (packet.type === "browser.close") {
|
|
342
356
|
let params = packet.data
|
|
343
357
|
if (params && params.target) {
|
|
@@ -404,6 +418,8 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
404
418
|
n.Noty(payload)
|
|
405
419
|
}
|
|
406
420
|
} else if (packet.type === "result") {
|
|
421
|
+
refreshParent(packet)
|
|
422
|
+
reloadMemory()
|
|
407
423
|
if (packet.data) {
|
|
408
424
|
// document.querySelector("#response").innerHTML = he.escape(JSON.stringify(packet.data, null, 2))
|
|
409
425
|
}
|
|
@@ -417,10 +433,12 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
417
433
|
// type: "error"
|
|
418
434
|
// })
|
|
419
435
|
this.socket.close()
|
|
436
|
+
refreshParent(packet)
|
|
437
|
+
reloadMemory()
|
|
420
438
|
//document.querySelector("footer").innerHTML = `<b><i class="fa-solid fa-triangle-exclamation"></i> ERROR</b><pre>${packet.data}</pre>`
|
|
421
439
|
document.querySelector("footer .content").innerHTML = document.querySelector("footer .content").innerHTML + `<pre class='error'>${packet.data}</pre>`
|
|
422
|
-
document.querySelector("footer .toggle-expand i").className = "fa-solid fa-circle-chevron-down"
|
|
423
|
-
document.querySelector("footer").classList.add("expanded")
|
|
440
|
+
// document.querySelector("footer .toggle-expand i").className = "fa-solid fa-circle-chevron-down"
|
|
441
|
+
// document.querySelector("footer").classList.add("expanded")
|
|
424
442
|
document.querySelector("footer i").className = "fa-solid fa-triangle-exclamation"
|
|
425
443
|
|
|
426
444
|
document.querySelector(".run .play").classList.remove("hidden")
|
|
@@ -614,7 +632,63 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
614
632
|
location.href = "/?mode=explore"
|
|
615
633
|
})
|
|
616
634
|
Reporter()
|
|
635
|
+
document.querySelector(".memory").addEventListener("click", async (e) => {
|
|
636
|
+
let target = e.target.classList.contains("tunnel") ? e.target : e.target.closest(".tunnel")
|
|
637
|
+
let target2 = e.target.classList.contains("tunnel-stop") ? e.target : e.target.closest(".tunnel-stop")
|
|
638
|
+
if (target) {
|
|
639
|
+
e.preventDefault()
|
|
640
|
+
e.stopPropagation()
|
|
641
|
+
let url = target.getAttribute("data-url")
|
|
642
|
+
let response = await fetch("/pinokio/tunnel", {
|
|
643
|
+
method: "POST",
|
|
644
|
+
headers: {
|
|
645
|
+
"Content-Type": "application/json"
|
|
646
|
+
},
|
|
647
|
+
body: JSON.stringify({ url, action: "start" })
|
|
648
|
+
}).then((res) => {
|
|
649
|
+
return res.json()
|
|
650
|
+
})
|
|
651
|
+
await reloadMemory()
|
|
652
|
+
} else if (target2) {
|
|
653
|
+
console.log("target2", target2)
|
|
654
|
+
e.preventDefault()
|
|
655
|
+
e.stopPropagation()
|
|
656
|
+
let url = target2.getAttribute("data-url")
|
|
657
|
+
let response = await fetch("/pinokio/tunnel", {
|
|
658
|
+
method: "POST",
|
|
659
|
+
headers: {
|
|
660
|
+
"Content-Type": "application/json"
|
|
661
|
+
},
|
|
662
|
+
body: JSON.stringify({ url, action: "stop" })
|
|
663
|
+
}).then((res) => {
|
|
664
|
+
return res.json()
|
|
665
|
+
})
|
|
666
|
+
await reloadMemory()
|
|
667
|
+
}
|
|
668
|
+
})
|
|
617
669
|
})
|
|
670
|
+
const reloadMemory = async () => {
|
|
671
|
+
let url = "/pinokio/memory?filepath=" + encodeURI("<%-filepath%>")
|
|
672
|
+
console.log("Url", url)
|
|
673
|
+
let memory = await fetch(url).then((res) => {
|
|
674
|
+
return res.json()
|
|
675
|
+
})
|
|
676
|
+
console.log("memory", memory)
|
|
677
|
+
document.querySelector(".memory table").innerHTML = memory.map((m) => {
|
|
678
|
+
let html = `<tr><td>${m.key}</td><td>${m.val}</td>`
|
|
679
|
+
if (m.localhost) {
|
|
680
|
+
if (m.tunnel) {
|
|
681
|
+
html += `<td>${m.tunnel}</td>
|
|
682
|
+
<td><a class='btn2' target="_blank" href="${m.tunnel}"><i class="fa-solid fa-arrow-up-right-from-square"></i> Open</a></td>
|
|
683
|
+
<td><button data-url="${m.val}" class='btn2 tunnel-stop'><i class="fa-solid fa-lock-closed"></i> Make Private</button></td>`
|
|
684
|
+
} else {
|
|
685
|
+
html += `<td><button data-url="${m.val}" class='btn2 tunnel'><i class="fa-solid fa-lock-open"></i> Make Public</button></td>`
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
html += "</tr>"
|
|
689
|
+
return html
|
|
690
|
+
}).join("")
|
|
691
|
+
}
|
|
618
692
|
</script>
|
|
619
693
|
</head>
|
|
620
694
|
<% if (install_required) { %>
|
|
@@ -642,15 +716,58 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
642
716
|
<div class='pinokiourl'><i class="fa-solid fa-link"></i><%=pinokioPath%></div>
|
|
643
717
|
<% } %>
|
|
644
718
|
<% if (!install_required) { %>
|
|
719
|
+
<!--
|
|
720
|
+
<div class='runner'>
|
|
721
|
+
<div class='btn run <%= mod && runnable ? "" : "hidden" %>'>
|
|
722
|
+
<span class='play'><i class="fa-solid fa-play"></i> Run</span>
|
|
723
|
+
<span class='starting hidden'><i class="fa-solid fa-circle-notch fa-spin"></i> Starting...</span>
|
|
724
|
+
<span class='stop hidden'><i class="fa-solid fa-stop"></i> Stop</span>
|
|
725
|
+
</div>
|
|
726
|
+
<div id='save' class='btn disabled'>
|
|
727
|
+
<span class='save'><i class="fa-solid fa-check"></i> Save</span>
|
|
728
|
+
</div>
|
|
729
|
+
</div>
|
|
730
|
+
-->
|
|
645
731
|
<div class='runner'>
|
|
646
732
|
<div class='btn run <%= mod && runnable ? "" : "hidden" %>'>
|
|
647
733
|
<span class='play'><i class="fa-solid fa-play"></i> Run</span>
|
|
648
734
|
<span class='starting hidden'><i class="fa-solid fa-circle-notch fa-spin"></i> Starting...</span>
|
|
649
735
|
<span class='stop hidden'><i class="fa-solid fa-stop"></i> Stop</span>
|
|
650
736
|
</div>
|
|
737
|
+
<button class='btn' id='open-fs' data-filepath="<%=filepath%>"><i class="fa-solid fa-eye"></i> View File</button>
|
|
738
|
+
<!--
|
|
739
|
+
<button class='btn' id='source' data-editor-url="<%=editorUrl%>">Navigate</button>
|
|
740
|
+
-->
|
|
741
|
+
<!--
|
|
651
742
|
<div id='save' class='btn disabled'>
|
|
652
743
|
<span class='save'><i class="fa-solid fa-check"></i> Save</span>
|
|
653
744
|
</div>
|
|
745
|
+
-->
|
|
746
|
+
<% if (memory.length > 0) { %>
|
|
747
|
+
<div class='memory'>
|
|
748
|
+
<table>
|
|
749
|
+
<% memory.forEach((m) => { %>
|
|
750
|
+
<tr>
|
|
751
|
+
<td><%=m.key%></td>
|
|
752
|
+
<td><%=m.val%></td>
|
|
753
|
+
<% if (m.localhost) { %>
|
|
754
|
+
<% if (m.tunnel) { %>
|
|
755
|
+
<td><%=m.tunnel%></td>
|
|
756
|
+
<td><a class='btn2' target="_blank" href="<%=m.tunnel%>"><i class="fa-solid fa-arrow-up-right-from-square"></i> Open</a></td>
|
|
757
|
+
<td><button data-url="<%=m.val%>" class='btn2 tunnel-stop'><i class="fa-solid fa-lock-closed"></i> Make Private</button></td>
|
|
758
|
+
<% } else { %>
|
|
759
|
+
<td><button data-url="<%=m.val%>" class='btn2 tunnel'><i class="fa-solid fa-lock-open"></i> Make Public</button></td>
|
|
760
|
+
<% } %>
|
|
761
|
+
<% } %>
|
|
762
|
+
</tr>
|
|
763
|
+
<% }) %>
|
|
764
|
+
</table>
|
|
765
|
+
</div>
|
|
766
|
+
<% } else { %>
|
|
767
|
+
<div class='memory'>
|
|
768
|
+
<table></table>
|
|
769
|
+
</div>
|
|
770
|
+
<% } %>
|
|
654
771
|
</div>
|
|
655
772
|
<% } %>
|
|
656
773
|
</header>
|
|
@@ -247,6 +247,8 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
247
247
|
this.term.write("\r\nDisconnected...\r\n")
|
|
248
248
|
document.querySelector("footer").innerHTML = "<b>Ready</b>"
|
|
249
249
|
this.socket.close()
|
|
250
|
+
document.querySelector(".run .play").classList.remove("hidden")
|
|
251
|
+
document.querySelector(".run .stop").classList.add("hidden")
|
|
250
252
|
} else if (packet.type === 'connect') {
|
|
251
253
|
const message = "..........Connected!\r\n"
|
|
252
254
|
this.term.write(message)
|
|
@@ -263,6 +265,28 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
263
265
|
document.querySelector(".run .play").classList.add("hidden")
|
|
264
266
|
document.querySelector(".run .starting").classList.add("hidden")
|
|
265
267
|
document.querySelector(".run .stop").classList.remove("hidden")
|
|
268
|
+
// } else if (packet.type === "key.set") {
|
|
269
|
+
// let keys = await fetch("/pinokio/keys").then((res) => {
|
|
270
|
+
// return res.json()
|
|
271
|
+
// })
|
|
272
|
+
// let input = await ModalInput({
|
|
273
|
+
// title: "Key",
|
|
274
|
+
// description: "select a key",
|
|
275
|
+
// form: [{
|
|
276
|
+
// key: "key",
|
|
277
|
+
// type: "select",
|
|
278
|
+
// items: keys,
|
|
279
|
+
// }, {
|
|
280
|
+
// key: "password",
|
|
281
|
+
// type: "password",
|
|
282
|
+
// }]
|
|
283
|
+
// })
|
|
284
|
+
// if (input) {
|
|
285
|
+
// this.socket.respond({
|
|
286
|
+
// response: input,
|
|
287
|
+
// uri: "~" + location.pathname,
|
|
288
|
+
// })
|
|
289
|
+
// }
|
|
266
290
|
} else if (packet.type === "input") {
|
|
267
291
|
let params = packet.data
|
|
268
292
|
let type = (params.type ? params.type : "modal")
|
|
@@ -611,6 +635,7 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
611
635
|
})
|
|
612
636
|
await reloadMemory()
|
|
613
637
|
} else if (target2) {
|
|
638
|
+
console.log("target2", target2)
|
|
614
639
|
e.preventDefault()
|
|
615
640
|
e.stopPropagation()
|
|
616
641
|
let url = target2.getAttribute("data-url")
|
|
@@ -626,6 +651,17 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
626
651
|
await reloadMemory()
|
|
627
652
|
}
|
|
628
653
|
})
|
|
654
|
+
/*
|
|
655
|
+
document.querySelector("#source").addEventListener("click", (e) => {
|
|
656
|
+
refreshParent({
|
|
657
|
+
id: "<%=filepath%>",
|
|
658
|
+
action: {
|
|
659
|
+
"type": "newtab",
|
|
660
|
+
"url": e.target.getAttribute("data-editor-url")
|
|
661
|
+
}
|
|
662
|
+
})
|
|
663
|
+
})
|
|
664
|
+
*/
|
|
629
665
|
})
|
|
630
666
|
const reloadMemory = async () => {
|
|
631
667
|
let url = "/pinokio/memory?filepath=" + encodeURI("<%-filepath%>")
|
|
@@ -649,6 +685,7 @@ const reloadMemory = async () => {
|
|
|
649
685
|
return html
|
|
650
686
|
}).join("")
|
|
651
687
|
}
|
|
688
|
+
|
|
652
689
|
</script>
|
|
653
690
|
</head>
|
|
654
691
|
<% if (install_required) { %>
|
|
@@ -684,7 +721,10 @@ const reloadMemory = async () => {
|
|
|
684
721
|
<span class='starting hidden'><i class="fa-solid fa-circle-notch fa-spin"></i> Starting...</span>
|
|
685
722
|
<span class='stop hidden'><i class="fa-solid fa-stop"></i> Stop</span>
|
|
686
723
|
</div>
|
|
687
|
-
<button class='btn' id='open-fs' data-filepath="<%=filepath%>"><i class="fa-
|
|
724
|
+
<button class='btn' id='open-fs' data-filepath="<%=filepath%>"><i class="fa-solid fa-eye"></i> View File</button>
|
|
725
|
+
<!--
|
|
726
|
+
<button class='btn' id='source' data-editor-url="<%=editorUrl%>">Navigate</button>
|
|
727
|
+
-->
|
|
688
728
|
<!--
|
|
689
729
|
<div id='save' class='btn disabled'>
|
|
690
730
|
<span class='save'><i class="fa-solid fa-check"></i> Save</span>
|
package/server/views/index.ejs
CHANGED
|
@@ -116,6 +116,7 @@
|
|
|
116
116
|
<div class='pinokiourl'><i class="fa-solid fa-link"></i><%=pinokioPath%></div>
|
|
117
117
|
<% } %>
|
|
118
118
|
<% } %>
|
|
119
|
+
<!--
|
|
119
120
|
<div class='runner'>
|
|
120
121
|
<% if (display.includes("menu")) { %>
|
|
121
122
|
<% config.menu.forEach((item) => { %>
|
|
@@ -138,6 +139,7 @@
|
|
|
138
139
|
<button id='install' class='btn' data-url="<%=config.install%>"><i class="fa-solid fa-plug"></i> Install</button>
|
|
139
140
|
<% } %>
|
|
140
141
|
</div>
|
|
142
|
+
-->
|
|
141
143
|
<% if (display.includes("dependencies")) { %>
|
|
142
144
|
<div class='dependencies'>
|
|
143
145
|
<h2>Prerequisites</h2>
|
|
@@ -466,31 +468,31 @@ document.querySelector("form input[type=search]").focus()
|
|
|
466
468
|
<% } %>
|
|
467
469
|
|
|
468
470
|
<% if (display.includes("menu")) { %>
|
|
469
|
-
document.querySelector(".runner").addEventListener("click", async (e) => {
|
|
470
|
-
let el = e.target.closest(".btn")
|
|
471
|
-
if (!el) {
|
|
472
|
-
if (el.classList.contains("btn")) {
|
|
473
|
-
el = e.target
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
if (el) {
|
|
478
|
-
let url = el.getAttribute("data-url")
|
|
479
|
-
if (url) {
|
|
480
|
-
let target = el.getAttribute("data-target")
|
|
481
|
-
if (target && target.length > 0) {
|
|
482
|
-
let agent = el.getAttribute("data-agent")
|
|
483
|
-
if (agent && agent.length > 0) {
|
|
484
|
-
window.open(url, target, agent)
|
|
485
|
-
} else {
|
|
486
|
-
window.open(url, target)
|
|
487
|
-
}
|
|
488
|
-
} else {
|
|
489
|
-
location.href = url
|
|
490
|
-
}
|
|
491
|
-
}
|
|
492
|
-
}
|
|
493
|
-
})
|
|
471
|
+
//document.querySelector(".runner").addEventListener("click", async (e) => {
|
|
472
|
+
// let el = e.target.closest(".btn")
|
|
473
|
+
// if (!el) {
|
|
474
|
+
// if (el.classList.contains("btn")) {
|
|
475
|
+
// el = e.target
|
|
476
|
+
// }
|
|
477
|
+
// }
|
|
478
|
+
//
|
|
479
|
+
// if (el) {
|
|
480
|
+
// let url = el.getAttribute("data-url")
|
|
481
|
+
// if (url) {
|
|
482
|
+
// let target = el.getAttribute("data-target")
|
|
483
|
+
// if (target && target.length > 0) {
|
|
484
|
+
// let agent = el.getAttribute("data-agent")
|
|
485
|
+
// if (agent && agent.length > 0) {
|
|
486
|
+
// window.open(url, target, agent)
|
|
487
|
+
// } else {
|
|
488
|
+
// window.open(url, target)
|
|
489
|
+
// }
|
|
490
|
+
// } else {
|
|
491
|
+
// location.href = url
|
|
492
|
+
// }
|
|
493
|
+
// }
|
|
494
|
+
// }
|
|
495
|
+
//})
|
|
494
496
|
<% } %>
|
|
495
497
|
<% if (display.includes("install")) { %>
|
|
496
498
|
document.querySelector("#install").addEventListener("click", async (e) => {
|
|
@@ -504,7 +506,7 @@ document.querySelector("#explore").addEventListener("click", async (e) => {
|
|
|
504
506
|
location.href = "/?mode=explore"
|
|
505
507
|
})
|
|
506
508
|
<% } %>
|
|
507
|
-
Reporter()
|
|
509
|
+
//Reporter()
|
|
508
510
|
/*
|
|
509
511
|
<% if (display.includes("dependencies")) { %>
|
|
510
512
|
document.querySelector(".requirements").addEventListener("click", (e) => {
|