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.
@@ -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.32",
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
- // items: items.map((x) => {
960
- // //let name = (x.name.startsWith("0x") ? Buffer.from(x.name.slice(2), "hex").toString() : x.name)
961
- // let name
962
- // let description
963
- // let icon
964
- // let uri
965
- // if (meta) {
966
- // let m = meta[x.name]
967
- // name = (m && m.title ? m.title : x.name)
968
- // description = (m && m.description ? m.description : "")
969
- // if (m && m.icon) {
970
- // icon = m.icon
971
- // } else {
972
- // icon = null
973
- // }
974
- // uri = x.name
975
- // } else {
976
- // if (x.isDirectory()) {
977
- // icon = "fa-solid fa-folder"
978
- // } else {
979
- // icon = "fa-regular fa-file"
980
- // }
981
- // name = x.name
982
- // description = ""
983
- // }
984
- // return {
985
- // icon,
986
- // menu: x.menu,
987
- // //icon: (x.isDirectory() ? "fa-solid fa-folder" : "fa-regular fa-file"),
988
- // name,
989
- // uri,
990
- // //description: x.path,
991
- // description,
992
- // url: p + "/" + x.name,
993
- // browser_url: "/pinokio/browser/" + x.name
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
  }
@@ -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);
@@ -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+1%>" target="<%=item.src%>" href="<%=item.href%>" class='btn header-item selectable frame-link'>
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.classList.add("selected")
426
+ if (target) {
427
+ target.classList.add("selected")
366
428
 
367
- // select the iframe
368
- document.querySelectorAll("iframe").forEach((el) => {
369
- el.classList.add("hidden")
370
- })
371
- let targetFrame = document.querySelector(`iframe[name='${target.target}']`)
372
- console.log("#4", loaded)
373
- console.log("targetFrame", targetFrame)
374
- if (targetFrame) {
375
- console.log("#5", loaded)
376
- console.log({ loaded })
377
- targetFrame.classList.remove("hidden")
378
-
379
- // if the iframe already exists, do not
380
- if (loaded[target.target]){
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
- // coming from a click => don't need to set the src
444
+ e.preventDefault()
445
+ e.stopPropagation()
396
446
  } else {
397
- // load without click
398
- targetFrame.src = target.href
447
+ console.log("REFRESH")
448
+ if (force) {
449
+ targetFrame.src = target.href
450
+ }
399
451
  }
400
- loaded[target.target] = true
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("aside").addEventListener("click", (e) => {
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
- if (e.target.classList.contains("frame-link")) {
549
+ // delete
550
+ if (e.target.classList.contains("del")) {
435
551
  target = e.target
436
552
  } else {
437
- target = e.target.closest(".frame-link")
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
- renderSelection(e)
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', (e) => {
621
+ window.addEventListener('message', (event) => {
477
622
  console.log("Message received from the child: ", event.data); // Message received from child
478
- refresh()
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
@@ -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: "~" + location.pathname,
323
+ uri: "<%=execUrl%>"
311
324
  })
312
325
  }
313
326
  /*
@@ -331,13 +344,14 @@ document.addEventListener("DOMContentLoaded", async () => {
331
344
  }
332
345
  }
333
346
  */
334
- refreshParent()
335
- let params = packet.data
336
- window.open(
337
- params.uri,
338
- (params.target || "_self"),
339
- params.features
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-regular fa-folder-open"></i> View File</button>
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>
@@ -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) => {