pinokiod 3.19.79 → 3.19.81
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/bin/cli.js +9 -14
- package/kernel/bin/setup.js +3 -0
- package/kernel/connect/providers/github/README.md +0 -4
- package/kernel/prototype.js +5 -5
- package/package.json +1 -1
- package/server/index.js +135 -67
- package/server/public/style.css +1 -1
- package/server/views/app.ejs +78 -29
- package/server/views/editor.ejs +13 -5
- package/server/views/git.ejs +161 -28
- package/server/views/github.ejs +76 -39
- package/server/views/mini.ejs +2 -0
- package/server/views/partials/ai.ejs +5 -0
- package/server/views/prototype/init.ejs +57 -13
package/kernel/bin/cli.js
CHANGED
|
@@ -9,36 +9,31 @@ class CLI {
|
|
|
9
9
|
}, ondata)
|
|
10
10
|
}
|
|
11
11
|
async installed(req, ondata) {
|
|
12
|
-
console.log("Check CLI installed")
|
|
13
|
-
|
|
14
12
|
let exists
|
|
15
|
-
console.log("platform", this.kernel.platform)
|
|
16
13
|
if (this.kernel.platform === "win32") {
|
|
17
14
|
exists = await Util.exists(this.kernel.path("bin/npm/pterm"))
|
|
18
|
-
console.log("Exists", exists)
|
|
19
15
|
} else {
|
|
20
16
|
exists = await Util.exists(this.kernel.path("bin/npm/bin/pterm"))
|
|
21
|
-
console.log("Exists", exists)
|
|
22
17
|
}
|
|
23
|
-
|
|
24
18
|
if (exists) {
|
|
25
19
|
let p = this.kernel.which("pterm")
|
|
26
20
|
if (p) {
|
|
27
21
|
let res = await this.kernel.exec({
|
|
28
22
|
message: "pterm version terminal"
|
|
29
23
|
}, ondata)
|
|
30
|
-
let
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
24
|
+
let e = /pterm@([0-9.]+)/.exec(res.stdout)
|
|
25
|
+
if (e && e.length > 0) {
|
|
26
|
+
let v = e[1]
|
|
27
|
+
let coerced = semver.coerce(v)
|
|
28
|
+
if (semver.satisfies(coerced, this.version)) {
|
|
29
|
+
return true
|
|
30
|
+
} else {
|
|
31
|
+
return false
|
|
32
|
+
}
|
|
36
33
|
} else {
|
|
37
|
-
console.log("Not Installed")
|
|
38
34
|
return false
|
|
39
35
|
}
|
|
40
36
|
} else {
|
|
41
|
-
console.log("FALSE")
|
|
42
37
|
return false
|
|
43
38
|
}
|
|
44
39
|
} else {
|
package/kernel/bin/setup.js
CHANGED
|
@@ -122,12 +122,15 @@ module.exports = {
|
|
|
122
122
|
{ name: "node", },
|
|
123
123
|
{ name: "cli", },
|
|
124
124
|
{ name: "uv", },
|
|
125
|
+
{ name: "caddy", },
|
|
126
|
+
{ name: "py", },
|
|
125
127
|
])
|
|
126
128
|
let conda_requirements = [
|
|
127
129
|
zip_cmd,
|
|
128
130
|
"uv",
|
|
129
131
|
"node",
|
|
130
132
|
"git",
|
|
133
|
+
"caddy",
|
|
131
134
|
]
|
|
132
135
|
if (platform === "win32") {
|
|
133
136
|
requirements.push({ name: "registry" })
|
package/kernel/prototype.js
CHANGED
|
@@ -36,12 +36,12 @@ class Proto {
|
|
|
36
36
|
process.stdout.write(e.raw)
|
|
37
37
|
})
|
|
38
38
|
}
|
|
39
|
-
let exists3 = await this.kernel.exists("prototype/
|
|
39
|
+
let exists3 = await this.kernel.exists("prototype/PTERM.md")
|
|
40
40
|
if (!exists3) {
|
|
41
41
|
await this.kernel.download({
|
|
42
42
|
uri: "https://raw.githubusercontent.com/pinokiocomputer/pterm/refs/heads/main/README.md",
|
|
43
43
|
path: this.kernel.path("prototype"),
|
|
44
|
-
filename: "
|
|
44
|
+
filename: "PTERM.md"
|
|
45
45
|
}, (e) => {
|
|
46
46
|
process.stdout.write(e.raw)
|
|
47
47
|
})
|
|
@@ -73,9 +73,9 @@ class Proto {
|
|
|
73
73
|
let readme_path = this.kernel.path("prototype/PINOKIO.md")
|
|
74
74
|
await fs.promises.cp(readme_path, path.resolve(cwd, name, "PINOKIO.md"))
|
|
75
75
|
|
|
76
|
-
// copy
|
|
77
|
-
let cli_readme_path = this.kernel.path("prototype/
|
|
78
|
-
await fs.promises.cp(cli_readme_path, path.resolve(cwd, name, "
|
|
76
|
+
// copy pterm.md
|
|
77
|
+
let cli_readme_path = this.kernel.path("prototype/PTERM.md")
|
|
78
|
+
await fs.promises.cp(cli_readme_path, path.resolve(cwd, name, "PTERM.md"))
|
|
79
79
|
|
|
80
80
|
|
|
81
81
|
return { success: "/p/" + name }
|
package/package.json
CHANGED
package/server/index.js
CHANGED
|
@@ -367,7 +367,7 @@ class Server {
|
|
|
367
367
|
|
|
368
368
|
async chrome(req, res, type) {
|
|
369
369
|
let d = Date.now()
|
|
370
|
-
console.time("1 chrome " + d)
|
|
370
|
+
// console.time("1 chrome " + d)
|
|
371
371
|
let { requirements, install_required, requirements_pending, error } = await this.kernel.bin.check({
|
|
372
372
|
bin: this.kernel.bin.preset("dev"),
|
|
373
373
|
})
|
|
@@ -375,7 +375,7 @@ class Server {
|
|
|
375
375
|
res.redirect(`/setup/dev?callback=${req.originalUrl}`)
|
|
376
376
|
return
|
|
377
377
|
}
|
|
378
|
-
console.timeEnd("1 chrome " + d)
|
|
378
|
+
// console.timeEnd("1 chrome " + d)
|
|
379
379
|
|
|
380
380
|
let name = req.params.name
|
|
381
381
|
let config = await this.kernel.api.meta(name)
|
|
@@ -490,22 +490,22 @@ class Server {
|
|
|
490
490
|
// }
|
|
491
491
|
// }
|
|
492
492
|
|
|
493
|
-
console.time("2 chrome " + d)
|
|
493
|
+
// console.time("2 chrome " + d)
|
|
494
494
|
await this.init_env("api/" + name)
|
|
495
|
-
console.timeEnd("2 chrome " + d)
|
|
495
|
+
// console.timeEnd("2 chrome " + d)
|
|
496
496
|
|
|
497
|
-
console.time("3 chrome " + d)
|
|
497
|
+
// console.time("3 chrome " + d)
|
|
498
498
|
let mode = "run"
|
|
499
499
|
if (req.query && req.query.mode) {
|
|
500
500
|
mode = req.query.mode
|
|
501
501
|
}
|
|
502
502
|
const env = await this.kernel.env("api/" + name)
|
|
503
|
-
console.timeEnd("3 chrome " + d)
|
|
503
|
+
// console.timeEnd("3 chrome " + d)
|
|
504
504
|
|
|
505
505
|
// profile + feed
|
|
506
506
|
const repositoryPath = path.resolve(this.kernel.api.userdir, name)
|
|
507
507
|
|
|
508
|
-
console.time("4 chrome " + d)
|
|
508
|
+
// console.time("4 chrome " + d)
|
|
509
509
|
try {
|
|
510
510
|
await git.resolveRef({ fs, dir: repositoryPath, ref: 'HEAD' });
|
|
511
511
|
} catch (err) {
|
|
@@ -514,9 +514,9 @@ class Server {
|
|
|
514
514
|
await git.init({ fs, dir: repositoryPath });
|
|
515
515
|
}
|
|
516
516
|
|
|
517
|
-
console.timeEnd("4 chrome " + d)
|
|
517
|
+
// console.timeEnd("4 chrome " + d)
|
|
518
518
|
|
|
519
|
-
console.time("5 chrome " + d)
|
|
519
|
+
// console.time("5 chrome " + d)
|
|
520
520
|
let gitRemote = await git.getConfig({ fs, http, dir: repositoryPath, path: 'remote.origin.url' })
|
|
521
521
|
let profile
|
|
522
522
|
let feed
|
|
@@ -530,20 +530,24 @@ class Server {
|
|
|
530
530
|
profile = this.profile(gitRemote)
|
|
531
531
|
feed = this.newsfeed(gitRemote)
|
|
532
532
|
}
|
|
533
|
-
console.timeEnd("5 chrome " + d)
|
|
533
|
+
// console.timeEnd("5 chrome " + d)
|
|
534
534
|
|
|
535
535
|
// git
|
|
536
536
|
|
|
537
537
|
let c = this.kernel.path("api", name)
|
|
538
538
|
|
|
539
|
-
console.time("6 chrome " + d)
|
|
539
|
+
// console.time("6 chrome " + d)
|
|
540
540
|
await this.kernel.plugin.init()
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
541
|
+
// console.timeEnd("6 chrome " + d)
|
|
542
|
+
// console.time("7 chrome " + d)
|
|
543
|
+
// let plugin = await this.getPlugin(name)
|
|
544
|
+
// console.timeEnd("7 chrome " + d)
|
|
545
|
+
// console.time("8 chrome " + d)
|
|
546
|
+
// let plugin_menu = null
|
|
547
|
+
// if (plugin && plugin.menu && Array.isArray(plugin.menu)) {
|
|
548
|
+
// let running_dynamic = this.running_dynamic(name, plugin.menu)
|
|
549
|
+
// plugin_menu = plugin.menu.concat(running_dynamic)
|
|
550
|
+
// }
|
|
547
551
|
|
|
548
552
|
|
|
549
553
|
let current_urls = await this.current_urls(req.originalUrl.slice(1))
|
|
@@ -553,7 +557,7 @@ class Server {
|
|
|
553
557
|
current_urls,
|
|
554
558
|
path: this.kernel.path("api", name),
|
|
555
559
|
log_path: this.kernel.path("api", name, "logs"),
|
|
556
|
-
plugin_menu,
|
|
560
|
+
plugin_menu: null,
|
|
557
561
|
portal: this.portal,
|
|
558
562
|
install: this.install,
|
|
559
563
|
error: err,
|
|
@@ -567,6 +571,7 @@ class Server {
|
|
|
567
571
|
memory: this.kernel.memory,
|
|
568
572
|
sidebar: "/pinokio/sidebar/" + name,
|
|
569
573
|
repos: "/pinokio/repos/" + name,
|
|
574
|
+
ai: "/pinokio/ai/" + name,
|
|
570
575
|
dynamic: "/pinokio/dynamic/" + name,
|
|
571
576
|
// dynamic: "/pinokio/dynamic/" + name,
|
|
572
577
|
dynamic_content: null,
|
|
@@ -585,12 +590,12 @@ class Server {
|
|
|
585
590
|
execUrl: "/api/" + name,
|
|
586
591
|
// rawpath,
|
|
587
592
|
}
|
|
588
|
-
console.timeEnd("
|
|
589
|
-
console.time("
|
|
590
|
-
if (!this.kernel.proto.config) {
|
|
591
|
-
await this.kernel.proto.init()
|
|
592
|
-
}
|
|
593
|
-
console.timeEnd("
|
|
593
|
+
// console.timeEnd("8 chrome " + d)
|
|
594
|
+
// console.time("9 chrome " + d)
|
|
595
|
+
// if (!this.kernel.proto.config) {
|
|
596
|
+
// await this.kernel.proto.init()
|
|
597
|
+
// }
|
|
598
|
+
// console.timeEnd("9 chrome " + d)
|
|
594
599
|
res.render("app", result)
|
|
595
600
|
}
|
|
596
601
|
getVariationUrls(req) {
|
|
@@ -2443,6 +2448,9 @@ class Server {
|
|
|
2443
2448
|
}
|
|
2444
2449
|
}
|
|
2445
2450
|
async getPluginGlobal(filepath) {
|
|
2451
|
+
if (!this.kernel.plugin.config) {
|
|
2452
|
+
await this.kernel.plugin.init()
|
|
2453
|
+
}
|
|
2446
2454
|
if (this.kernel.plugin.config) {
|
|
2447
2455
|
try {
|
|
2448
2456
|
let info = new Info(this.kernel)
|
|
@@ -2468,17 +2476,16 @@ class Server {
|
|
|
2468
2476
|
return plugin
|
|
2469
2477
|
} catch (e) {
|
|
2470
2478
|
console.log("getPlugin ERROR", e)
|
|
2471
|
-
return
|
|
2472
|
-
menu: []
|
|
2473
|
-
}
|
|
2479
|
+
return null
|
|
2474
2480
|
}
|
|
2475
2481
|
} else {
|
|
2476
|
-
return
|
|
2477
|
-
menu: []
|
|
2478
|
-
}
|
|
2482
|
+
return null
|
|
2479
2483
|
}
|
|
2480
2484
|
}
|
|
2481
2485
|
async getPlugin(name) {
|
|
2486
|
+
if (!this.kernel.plugin.config) {
|
|
2487
|
+
await this.kernel.plugin.init()
|
|
2488
|
+
}
|
|
2482
2489
|
if (this.kernel.plugin.config) {
|
|
2483
2490
|
try {
|
|
2484
2491
|
let info = new Info(this.kernel)
|
|
@@ -2492,15 +2499,10 @@ class Server {
|
|
|
2492
2499
|
return plugin
|
|
2493
2500
|
} catch (e) {
|
|
2494
2501
|
console.log("getPlugin ERROR", e)
|
|
2495
|
-
return
|
|
2496
|
-
menu: []
|
|
2497
|
-
}
|
|
2502
|
+
return null
|
|
2498
2503
|
}
|
|
2499
2504
|
} else {
|
|
2500
|
-
return
|
|
2501
|
-
menu: []
|
|
2502
|
-
}
|
|
2503
|
-
|
|
2505
|
+
return null
|
|
2504
2506
|
}
|
|
2505
2507
|
}
|
|
2506
2508
|
async check_router_up() {
|
|
@@ -4422,6 +4424,22 @@ class Server {
|
|
|
4422
4424
|
let dir = this.kernel.path("api", req.params[0])
|
|
4423
4425
|
let config = await this.kernel.git.config(dir)
|
|
4424
4426
|
|
|
4427
|
+
let hosts = ""
|
|
4428
|
+
let hosts_file = this.kernel.path("config/gh/hosts.yml")
|
|
4429
|
+
let e = await this.exists(hosts_file)
|
|
4430
|
+
console.log({ hosts_file, e })
|
|
4431
|
+
if (e) {
|
|
4432
|
+
hosts = await fs.promises.readFile(hosts_file, "utf8")
|
|
4433
|
+
console.log( { hosts: `#${hosts}#` })
|
|
4434
|
+
if (hosts.startsWith("{}")) {
|
|
4435
|
+
hosts = ""
|
|
4436
|
+
}
|
|
4437
|
+
}
|
|
4438
|
+
console.log("hosts", hosts)
|
|
4439
|
+
|
|
4440
|
+
let connected = (hosts.length > 0)
|
|
4441
|
+
|
|
4442
|
+
|
|
4425
4443
|
let remote = null
|
|
4426
4444
|
if (config["remote \"origin\""]) {
|
|
4427
4445
|
remote = config["remote \"origin\""].url
|
|
@@ -4489,6 +4507,7 @@ class Server {
|
|
|
4489
4507
|
}
|
|
4490
4508
|
|
|
4491
4509
|
res.render("git", {
|
|
4510
|
+
connected,
|
|
4492
4511
|
changes,
|
|
4493
4512
|
dir,
|
|
4494
4513
|
config,
|
|
@@ -4499,6 +4518,7 @@ class Server {
|
|
|
4499
4518
|
})
|
|
4500
4519
|
}))
|
|
4501
4520
|
this.app.get("/dev/*", ex(async (req, res) => {
|
|
4521
|
+
console.log("GET /dev/*", req.params)
|
|
4502
4522
|
let { requirements, install_required, requirements_pending, error } = await this.kernel.bin.check({
|
|
4503
4523
|
bin: this.kernel.bin.preset("dev"),
|
|
4504
4524
|
})
|
|
@@ -4507,19 +4527,19 @@ class Server {
|
|
|
4507
4527
|
return
|
|
4508
4528
|
}
|
|
4509
4529
|
let platform = os.platform()
|
|
4510
|
-
await this.kernel.plugin.init()
|
|
4530
|
+
// await this.kernel.plugin.init()
|
|
4511
4531
|
let filepath = Util.u2p(req.params[0])
|
|
4512
|
-
let plugin = await this.getPluginGlobal(filepath)
|
|
4532
|
+
// let plugin = await this.getPluginGlobal(filepath)
|
|
4513
4533
|
let current_urls = await this.current_urls(req.originalUrl.slice(1))
|
|
4514
|
-
let plugin_menu
|
|
4515
|
-
try {
|
|
4516
|
-
plugin_menu = plugin.menu[0].menu
|
|
4517
|
-
} catch (e) {
|
|
4518
|
-
plugin_menu = []
|
|
4519
|
-
}
|
|
4534
|
+
// let plugin_menu
|
|
4535
|
+
// try {
|
|
4536
|
+
// plugin_menu = plugin.menu[0].menu
|
|
4537
|
+
// } catch (e) {
|
|
4538
|
+
// plugin_menu = []
|
|
4539
|
+
// }
|
|
4520
4540
|
const result = {
|
|
4521
4541
|
current_urls,
|
|
4522
|
-
plugin_menu,
|
|
4542
|
+
plugin_menu: null,
|
|
4523
4543
|
portal: this.portal,
|
|
4524
4544
|
install: this.install,
|
|
4525
4545
|
port: this.port,
|
|
@@ -4616,35 +4636,83 @@ class Server {
|
|
|
4616
4636
|
}))
|
|
4617
4637
|
this.app.get("/pinokio/dynamic_global/*", ex(async (req, res) => {
|
|
4618
4638
|
let plugin = await this.getPluginGlobal("/" + req.params[0])
|
|
4619
|
-
|
|
4620
|
-
|
|
4621
|
-
|
|
4622
|
-
|
|
4623
|
-
|
|
4624
|
-
|
|
4625
|
-
|
|
4626
|
-
|
|
4627
|
-
|
|
4628
|
-
|
|
4629
|
-
resolve(html)
|
|
4639
|
+
if (plugin) {
|
|
4640
|
+
let html = ""
|
|
4641
|
+
if (plugin && plugin.menu) {
|
|
4642
|
+
let plugin_menu
|
|
4643
|
+
try {
|
|
4644
|
+
plugin_menu = plugin.menu[0].menu
|
|
4645
|
+
} catch (e) {
|
|
4646
|
+
plugin_menu = []
|
|
4647
|
+
}
|
|
4648
|
+
html = await new Promise((resolve, reject) => {
|
|
4649
|
+
ejs.renderFile(path.resolve(__dirname, "views/partials/dynamic.ejs"), { dynamic: plugin_menu }, (err, html) => {
|
|
4650
|
+
resolve(html)
|
|
4651
|
+
})
|
|
4630
4652
|
})
|
|
4631
|
-
}
|
|
4653
|
+
}
|
|
4654
|
+
res.send(html)
|
|
4655
|
+
} else {
|
|
4656
|
+
res.send("")
|
|
4632
4657
|
}
|
|
4633
|
-
res.send(html)
|
|
4634
4658
|
}))
|
|
4635
4659
|
this.app.get("/pinokio/dynamic/:name", ex(async (req, res) => {
|
|
4636
4660
|
// await this.kernel.plugin.init()
|
|
4637
4661
|
let plugin = await this.getPlugin(req.params.name)
|
|
4638
|
-
|
|
4639
|
-
|
|
4640
|
-
|
|
4641
|
-
|
|
4642
|
-
|
|
4643
|
-
|
|
4644
|
-
resolve(html)
|
|
4662
|
+
if (plugin) {
|
|
4663
|
+
let html = ""
|
|
4664
|
+
if (plugin && plugin.menu && Array.isArray(plugin.menu)) {
|
|
4665
|
+
let running_dynamic = this.running_dynamic(req.params.name, plugin.menu)
|
|
4666
|
+
plugin.menu = plugin.menu.concat(running_dynamic)
|
|
4667
|
+
html = await new Promise((resolve, reject) => {
|
|
4668
|
+
ejs.renderFile(path.resolve(__dirname, "views/partials/dynamic.ejs"), { dynamic: plugin.menu }, (err, html) => {
|
|
4669
|
+
resolve(html)
|
|
4670
|
+
})
|
|
4645
4671
|
})
|
|
4646
|
-
}
|
|
4672
|
+
}
|
|
4673
|
+
res.send(html)
|
|
4674
|
+
} else {
|
|
4675
|
+
res.send("")
|
|
4676
|
+
}
|
|
4677
|
+
}))
|
|
4678
|
+
this.app.get("/pinokio/ai/:name", ex(async (req, res) => {
|
|
4679
|
+
/*
|
|
4680
|
+
link to
|
|
4681
|
+
README.md
|
|
4682
|
+
AGENTS.md
|
|
4683
|
+
CLAUDE.md
|
|
4684
|
+
GEMINI.md
|
|
4685
|
+
*/
|
|
4686
|
+
let c = this.kernel.path("api", req.params.name, "README.md")
|
|
4687
|
+
let readme_exists = await this.exists(c)
|
|
4688
|
+
let files
|
|
4689
|
+
if (readme_exists) {
|
|
4690
|
+
files = [
|
|
4691
|
+
"README.md",
|
|
4692
|
+
"AGENTS.md",
|
|
4693
|
+
"CLAUDE.md",
|
|
4694
|
+
"GEMINI.md"
|
|
4695
|
+
]
|
|
4696
|
+
} else {
|
|
4697
|
+
files = [
|
|
4698
|
+
"AGENTS.md",
|
|
4699
|
+
"CLAUDE.md",
|
|
4700
|
+
"GEMINI.md"
|
|
4701
|
+
]
|
|
4647
4702
|
}
|
|
4703
|
+
|
|
4704
|
+
|
|
4705
|
+
let items = files.map((item) => {
|
|
4706
|
+
return {
|
|
4707
|
+
text: item,
|
|
4708
|
+
href: `/_api/${req.params.name}/${item}`
|
|
4709
|
+
}
|
|
4710
|
+
})
|
|
4711
|
+
let html = await new Promise((resolve, reject) => {
|
|
4712
|
+
ejs.renderFile(path.resolve(__dirname, "views/partials/ai.ejs"), { items }, (err, html) => {
|
|
4713
|
+
resolve(html)
|
|
4714
|
+
})
|
|
4715
|
+
})
|
|
4648
4716
|
res.send(html)
|
|
4649
4717
|
}))
|
|
4650
4718
|
this.app.get("/pinokio/repos/:name", ex(async (req, res) => {
|
package/server/public/style.css
CHANGED
package/server/views/app.ejs
CHANGED
|
@@ -840,12 +840,6 @@ body.dark .appcanvas {
|
|
|
840
840
|
</div>
|
|
841
841
|
<div class='disk-usage' data-path="/"></div>
|
|
842
842
|
</a>
|
|
843
|
-
<a target="<%=logs%>" href="<%=logs%>" class='btn header-item frame-link' data-index="1" data-mode="refresh">
|
|
844
|
-
<div class='tab'>
|
|
845
|
-
<i class="fa-solid fa-clock-rotate-left"></i> Logs
|
|
846
|
-
</div>
|
|
847
|
-
<div class='disk-usage' data-path="/logs"></div>
|
|
848
|
-
</a>
|
|
849
843
|
<% if (profile || feed) { %>
|
|
850
844
|
<div class='btn header-item frame-link revealer' data-group='.info-group'>
|
|
851
845
|
<div class='tab'>
|
|
@@ -866,13 +860,18 @@ body.dark .appcanvas {
|
|
|
866
860
|
<% } %>
|
|
867
861
|
</div>
|
|
868
862
|
<% } %>
|
|
869
|
-
<div class=
|
|
870
|
-
<% if (
|
|
871
|
-
|
|
863
|
+
<div class="dynamic <%=type==='run' ? '' : 'selected'%>">
|
|
864
|
+
<% if (type !== "run") { %>
|
|
865
|
+
<div class="nested-menu">
|
|
866
|
+
<div class="btn header-item frame-link selected">
|
|
867
|
+
<div class="tab"><i class="fa-solid fa-code"></i> Dev</div>
|
|
868
|
+
<div class="loader"><i class="fa-solid fa-circle-notch fa-spin"></i></div>
|
|
869
|
+
</div>
|
|
870
|
+
</div>
|
|
872
871
|
<% } %>
|
|
873
872
|
</div>
|
|
874
873
|
<% if (type === "browse") { %>
|
|
875
|
-
<div class='nested-menu selected git'>
|
|
874
|
+
<div class='nested-menu selected git blue'>
|
|
876
875
|
<div class='btn header-item frame-link reveal'>
|
|
877
876
|
<div class='tab'><i class="fa-solid fa-cloud"></i> Git</div>
|
|
878
877
|
<div class='loader'><i class="fa-solid fa-angle-down"></i><i class="fa-solid fa-angle-up hidden"></i></div>
|
|
@@ -880,6 +879,22 @@ body.dark .appcanvas {
|
|
|
880
879
|
<div class='submenu' id='git-repos'>
|
|
881
880
|
</div>
|
|
882
881
|
</div>
|
|
882
|
+
<div class='nested-menu selected blue'>
|
|
883
|
+
<a target="<%=logs%>" href="<%=logs%>" class='btn header-item frame-link' data-index="1" data-mode="refresh">
|
|
884
|
+
<div class='tab'>
|
|
885
|
+
<i class="fa-solid fa-clock-rotate-left"></i> Logs
|
|
886
|
+
</div>
|
|
887
|
+
<div class='disk-usage' data-path="/logs"></div>
|
|
888
|
+
</a>
|
|
889
|
+
</div>
|
|
890
|
+
<div class='nested-menu selected blue'>
|
|
891
|
+
<div class='btn header-item frame-link reveal'>
|
|
892
|
+
<div class='tab'><i class="fa-solid fa-robot"></i> AI Recipes</div>
|
|
893
|
+
<div class='loader'><i class="fa-solid fa-angle-down"></i><i class="fa-solid fa-angle-up hidden"></i></div>
|
|
894
|
+
</div>
|
|
895
|
+
<div class='submenu hidden' id='ai-prompts'>
|
|
896
|
+
</div>
|
|
897
|
+
</div>
|
|
883
898
|
<% } %>
|
|
884
899
|
<div class='btn header-item frame-link revealer' data-group='.config-group'>
|
|
885
900
|
<div class='tab'>
|
|
@@ -915,7 +930,9 @@ body.dark .appcanvas {
|
|
|
915
930
|
<div class='app-info'>
|
|
916
931
|
<% if (type === 'run') { %>
|
|
917
932
|
<div class='mode-section'>
|
|
933
|
+
<!--
|
|
918
934
|
<h3><i class='fa-solid fa-circle-play'></i> Run mode</h3>
|
|
935
|
+
-->
|
|
919
936
|
<div class='desc'>Switch to dev mode to make changes to the app.</div>
|
|
920
937
|
<a class='btn' href="<%=home.endsWith("/") ? home : home + "/" %>dev"><i class="fa-solid fa-code"></i> Switch to Dev mode</a>
|
|
921
938
|
</div>
|
|
@@ -1491,7 +1508,6 @@ body.dark .appcanvas {
|
|
|
1491
1508
|
edit: true,
|
|
1492
1509
|
redirect: (new_path) => {
|
|
1493
1510
|
let u = location.href.replace(/(\/pinokio\/browser\/)[^\/]+(?=\/|$)/, `$1${new_path}`)
|
|
1494
|
-
debugger
|
|
1495
1511
|
return u
|
|
1496
1512
|
}
|
|
1497
1513
|
})
|
|
@@ -1510,7 +1526,6 @@ body.dark .appcanvas {
|
|
|
1510
1526
|
edit: true,
|
|
1511
1527
|
redirect: (new_path) => {
|
|
1512
1528
|
let u = location.href.replace(/(\/pinokio\/browser\/)[^\/]+(?=\/|$)/, `$1${new_path}`)
|
|
1513
|
-
debugger
|
|
1514
1529
|
return u
|
|
1515
1530
|
}
|
|
1516
1531
|
})
|
|
@@ -1530,7 +1545,6 @@ body.dark .appcanvas {
|
|
|
1530
1545
|
edit: true,
|
|
1531
1546
|
redirect: (new_path) => {
|
|
1532
1547
|
let u = location.href.replace(/(\/pinokio\/browser\/)[^\/]+(?=\/|$)/, `$1${new_path}`)
|
|
1533
|
-
debugger
|
|
1534
1548
|
return u
|
|
1535
1549
|
}
|
|
1536
1550
|
})
|
|
@@ -1671,7 +1685,6 @@ body.dark .appcanvas {
|
|
|
1671
1685
|
e.stopPropagation()
|
|
1672
1686
|
let shell = target.closest("[data-shell]")
|
|
1673
1687
|
if (shell) {
|
|
1674
|
-
debugger
|
|
1675
1688
|
let shell_id = shell.getAttribute("data-shell")
|
|
1676
1689
|
n.Noty({
|
|
1677
1690
|
text: `stopping shell`,
|
|
@@ -1728,7 +1741,6 @@ body.dark .appcanvas {
|
|
|
1728
1741
|
})
|
|
1729
1742
|
} else {
|
|
1730
1743
|
let link = target.closest("[href]")
|
|
1731
|
-
debugger
|
|
1732
1744
|
if (link) {
|
|
1733
1745
|
let src = new URL(link.href).pathname
|
|
1734
1746
|
target.querySelector("i.fa-square").className = "fa-solid fa-check"
|
|
@@ -1835,7 +1847,7 @@ body.dark .appcanvas {
|
|
|
1835
1847
|
<% } else { %>
|
|
1836
1848
|
// dev mode => already dev. reveal the hidden menu
|
|
1837
1849
|
if (target.closest(".dynamic")) {
|
|
1838
|
-
target.closest(".dynamic").classList.
|
|
1850
|
+
target.closest(".dynamic").classList.add("selected")
|
|
1839
1851
|
target.closest(".nested-menu").querySelector(".submenu").classList.toggle("hidden")
|
|
1840
1852
|
target.querySelector(".loader .fa-angle-down").classList.toggle("hidden")
|
|
1841
1853
|
target.querySelector(".loader .fa-angle-up").classList.toggle("hidden")
|
|
@@ -1910,8 +1922,45 @@ body.dark .appcanvas {
|
|
|
1910
1922
|
}
|
|
1911
1923
|
})
|
|
1912
1924
|
}
|
|
1913
|
-
const refresh = async (silent, options) => {
|
|
1914
1925
|
|
|
1926
|
+
let dynamic_loaded = false
|
|
1927
|
+
|
|
1928
|
+
const try_dynamic = async () => {
|
|
1929
|
+
console.log("Try_dynamic")
|
|
1930
|
+
let rendered
|
|
1931
|
+
const dynamic = await fetch("<%=dynamic%>").then((res) => {
|
|
1932
|
+
return res.text()
|
|
1933
|
+
})
|
|
1934
|
+
if (dynamic && dynamic.length > 0) {
|
|
1935
|
+
console.log({ dynamic })
|
|
1936
|
+
if (document.querySelector(".dynamic")) {
|
|
1937
|
+
document.querySelector(".dynamic").innerHTML = dynamic
|
|
1938
|
+
}
|
|
1939
|
+
rendered = true
|
|
1940
|
+
} else {
|
|
1941
|
+
rendered = false
|
|
1942
|
+
}
|
|
1943
|
+
console.log({ rendered, dynamic_loaded })
|
|
1944
|
+
if (rendered) {
|
|
1945
|
+
if (dynamic_loaded) {
|
|
1946
|
+
// already loaded, don't touch the UI
|
|
1947
|
+
} else {
|
|
1948
|
+
// first time being loaded
|
|
1949
|
+
dynamic_loaded = true
|
|
1950
|
+
if (document.querySelector(".dynamic .reveal")) {
|
|
1951
|
+
console.log("click")
|
|
1952
|
+
|
|
1953
|
+
document.querySelector(".dynamic .reveal").click()
|
|
1954
|
+
}
|
|
1955
|
+
}
|
|
1956
|
+
} else {
|
|
1957
|
+
console.log("Not yet rendered. Try again")
|
|
1958
|
+
setTimeout(() => {
|
|
1959
|
+
try_dynamic()
|
|
1960
|
+
}, 1000)
|
|
1961
|
+
}
|
|
1962
|
+
}
|
|
1963
|
+
const refresh = async (silent, options) => {
|
|
1915
1964
|
|
|
1916
1965
|
if (options && options.nodelay) {
|
|
1917
1966
|
} else {
|
|
@@ -1926,14 +1975,9 @@ body.dark .appcanvas {
|
|
|
1926
1975
|
})
|
|
1927
1976
|
document.querySelector(".menu").innerHTML = html
|
|
1928
1977
|
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
}
|
|
1932
|
-
console.log({ dynamic })
|
|
1933
|
-
if (document.querySelector(".dynamic")) {
|
|
1934
|
-
document.querySelector(".dynamic").innerHTML = dynamic
|
|
1935
|
-
}
|
|
1936
|
-
|
|
1978
|
+
<% if (type !== 'run') { %>
|
|
1979
|
+
try_dynamic()
|
|
1980
|
+
<% } %>
|
|
1937
1981
|
|
|
1938
1982
|
const repos = await fetch("<%=repos%>").then((res) => {
|
|
1939
1983
|
return res.text()
|
|
@@ -1942,6 +1986,14 @@ body.dark .appcanvas {
|
|
|
1942
1986
|
document.querySelector("#git-repos").innerHTML = repos
|
|
1943
1987
|
}
|
|
1944
1988
|
|
|
1989
|
+
const ai = await fetch("<%=ai%>").then((res) => {
|
|
1990
|
+
return res.text()
|
|
1991
|
+
})
|
|
1992
|
+
console.log({ ai })
|
|
1993
|
+
if (document.querySelector("#ai-prompts")) {
|
|
1994
|
+
document.querySelector("#ai-prompts").innerHTML = ai
|
|
1995
|
+
}
|
|
1996
|
+
|
|
1945
1997
|
location.hash = ""
|
|
1946
1998
|
|
|
1947
1999
|
// render the selected frame only if not silent
|
|
@@ -2053,7 +2105,6 @@ body.dark .appcanvas {
|
|
|
2053
2105
|
refresh_du()
|
|
2054
2106
|
refresh_du("logs")
|
|
2055
2107
|
<% if (type !== 'run') { %>
|
|
2056
|
-
debugger
|
|
2057
2108
|
fetch("<%=repos%>").then((res) => {
|
|
2058
2109
|
return res.text()
|
|
2059
2110
|
}).then((repos) => {
|
|
@@ -2061,9 +2112,7 @@ body.dark .appcanvas {
|
|
|
2061
2112
|
document.querySelector("#git-repos").innerHTML = repos
|
|
2062
2113
|
}
|
|
2063
2114
|
})
|
|
2064
|
-
|
|
2065
|
-
document.querySelector(".dynamic .reveal").click()
|
|
2066
|
-
}
|
|
2115
|
+
refresh()
|
|
2067
2116
|
<% } %>
|
|
2068
2117
|
/*
|
|
2069
2118
|
document.addEventListener("keydown", (e) => {
|
package/server/views/editor.ejs
CHANGED
|
@@ -155,13 +155,17 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
155
155
|
<% } %>
|
|
156
156
|
<% if (!install_required) { %>
|
|
157
157
|
let editor = ace.edit("editor");
|
|
158
|
-
editor.setTheme("ace/theme/tomorrow");
|
|
159
158
|
//editor.setTheme("ace/theme/github_light_default");
|
|
160
159
|
//editor.setTheme("ace/theme/ambiance");
|
|
161
|
-
|
|
160
|
+
<% if (theme === "dark") { %>
|
|
161
|
+
editor.setTheme("ace/theme/idle_fingers");
|
|
162
|
+
<% } else { %>
|
|
163
|
+
editor.setTheme("ace/theme/tomorrow");
|
|
164
|
+
<% } %>
|
|
162
165
|
//editor.setTheme("ace/theme/nord_dark");
|
|
163
166
|
//editor.setTheme("ace/theme/textmate");
|
|
164
167
|
editor.setOptions({
|
|
168
|
+
wrap: true,
|
|
165
169
|
// maxLines: Infinity, // set to a large number
|
|
166
170
|
minLines: 1 // set to a small number
|
|
167
171
|
});
|
|
@@ -228,10 +232,12 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
228
232
|
document.querySelector(".run .starting").classList.add("hidden")
|
|
229
233
|
}
|
|
230
234
|
stop() {
|
|
235
|
+
let cwd = "<%-JSON.stringify(execUrl).slice(1, -1)%>"
|
|
231
236
|
this.socket.run({
|
|
232
237
|
method: "kernel.api.stop",
|
|
233
238
|
params: {
|
|
234
|
-
uri: "<%=execUrl%>",
|
|
239
|
+
//uri: "<%=execUrl%>",
|
|
240
|
+
uri: cwd,
|
|
235
241
|
//uri: "~" + location.pathname
|
|
236
242
|
}
|
|
237
243
|
}, (stream) => {
|
|
@@ -239,7 +245,8 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
239
245
|
}
|
|
240
246
|
save() {
|
|
241
247
|
return new Promise((resolve, reject) => {
|
|
242
|
-
let cwd = "
|
|
248
|
+
let cwd = "<%-JSON.stringify(execUrl).slice(1, -1)%>"
|
|
249
|
+
//let cwd = "<%=execUrl%>"
|
|
243
250
|
//let cwd = "~" + location.pathname
|
|
244
251
|
this.socket.close()
|
|
245
252
|
this.socket.run({
|
|
@@ -269,7 +276,8 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
269
276
|
this.socket.run({
|
|
270
277
|
//uri: location.pathname.slice(1).replace("api/", ""),
|
|
271
278
|
//uri: "~" + location.pathname,
|
|
272
|
-
uri: "
|
|
279
|
+
uri: "<%-JSON.stringify(execUrl).slice(1, -1)%>",
|
|
280
|
+
//uri: "<%=execUrl%>",
|
|
273
281
|
//uri: "~" + location.pathname,
|
|
274
282
|
mode,
|
|
275
283
|
input: query,
|
package/server/views/git.ejs
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<link href="/css/solid.min.css" rel="stylesheet">
|
|
5
5
|
<link href="/css/regular.min.css" rel="stylesheet">
|
|
6
6
|
<link href="/css/brands.min.css" rel="stylesheet">
|
|
7
|
-
<
|
|
7
|
+
<script src="/opener.js"></script>
|
|
8
8
|
<% if (agent === "electron") { %>
|
|
9
9
|
<link href="/electron.css" rel="stylesheet"/>
|
|
10
10
|
<% } %>
|
|
@@ -14,10 +14,43 @@
|
|
|
14
14
|
max-width: 800px;
|
|
15
15
|
box-sizing: border-box;
|
|
16
16
|
}
|
|
17
|
+
body {
|
|
18
|
+
margin: 0;
|
|
19
|
+
font-family: Sans-serif;
|
|
20
|
+
font-size: 14px;
|
|
21
|
+
display: flex;
|
|
22
|
+
flex-direction: column;
|
|
23
|
+
height: 100%;
|
|
24
|
+
}
|
|
25
|
+
aside {
|
|
26
|
+
min-width: 200px;
|
|
27
|
+
position: sticky;
|
|
28
|
+
top: 0;
|
|
29
|
+
}
|
|
30
|
+
aside .item.selected {
|
|
31
|
+
background: royalblue;
|
|
32
|
+
color: white;
|
|
33
|
+
}
|
|
34
|
+
aside .item {
|
|
35
|
+
display: block;
|
|
36
|
+
text-decoration: none;
|
|
37
|
+
color: royalblue;
|
|
38
|
+
padding: 10px;
|
|
39
|
+
background: rgba(0,0,0,0.1);
|
|
40
|
+
}
|
|
41
|
+
nav {
|
|
42
|
+
padding: 10px;
|
|
43
|
+
display: flex;
|
|
44
|
+
}
|
|
45
|
+
/*
|
|
17
46
|
nav {
|
|
18
47
|
position: sticky;
|
|
19
48
|
top: 0;
|
|
20
49
|
}
|
|
50
|
+
*/
|
|
51
|
+
body.dark nav a.btn, nav a.btn {
|
|
52
|
+
background: royalblue;
|
|
53
|
+
}
|
|
21
54
|
nav a {
|
|
22
55
|
display: block;
|
|
23
56
|
padding: 10px;
|
|
@@ -27,12 +60,18 @@ label {
|
|
|
27
60
|
display: block;
|
|
28
61
|
padding: 10px;
|
|
29
62
|
}
|
|
63
|
+
body.dark nav {
|
|
64
|
+
background: rgba(0,0,0,0.4);
|
|
65
|
+
}
|
|
30
66
|
nav label {
|
|
31
67
|
display: block;
|
|
32
68
|
padding: 10px;
|
|
33
69
|
}
|
|
34
70
|
main {
|
|
35
|
-
|
|
71
|
+
display: flex;
|
|
72
|
+
overflow: auto;
|
|
73
|
+
scroll-behavior: smooth;
|
|
74
|
+
flex-grow: 1;
|
|
36
75
|
}
|
|
37
76
|
main iframe {
|
|
38
77
|
width: 100%;
|
|
@@ -42,7 +81,16 @@ main img {
|
|
|
42
81
|
width: 100%;
|
|
43
82
|
}
|
|
44
83
|
main h2 {
|
|
45
|
-
|
|
84
|
+
padding: 20px 10px;
|
|
85
|
+
margin: 0;
|
|
86
|
+
font-size: 16px;
|
|
87
|
+
}
|
|
88
|
+
body.dark .changes {
|
|
89
|
+
color: white;
|
|
90
|
+
}
|
|
91
|
+
.changes {
|
|
92
|
+
height: 100%;
|
|
93
|
+
flex-grow: 1;
|
|
46
94
|
}
|
|
47
95
|
pre.l {
|
|
48
96
|
/*
|
|
@@ -90,61 +138,146 @@ pre.l {
|
|
|
90
138
|
color: #555;
|
|
91
139
|
}
|
|
92
140
|
.diff-block {
|
|
93
|
-
max-height: 300px;
|
|
94
141
|
background: rgba(0, 0, 0, 0.04);
|
|
95
|
-
padding: 0 20px 20px;
|
|
96
142
|
overflow: auto;
|
|
97
143
|
}
|
|
144
|
+
body.dark h2 {
|
|
145
|
+
color: white;
|
|
146
|
+
}
|
|
147
|
+
body.dark main h3 {
|
|
148
|
+
color: white;
|
|
149
|
+
}
|
|
98
150
|
main h3 {
|
|
99
151
|
margin: 0;
|
|
100
152
|
background: rgba(0, 0, 0, 0.04);
|
|
101
153
|
padding: 15px;
|
|
102
|
-
margin-top: 30px;
|
|
103
154
|
font-size: 14px;
|
|
104
155
|
}
|
|
156
|
+
body.dark .chunk {
|
|
157
|
+
border: 10px solid white;
|
|
158
|
+
}
|
|
159
|
+
.chunk {
|
|
160
|
+
border: 10px solid silver;
|
|
161
|
+
margin-bottom: 10px;
|
|
162
|
+
}
|
|
163
|
+
.filler {
|
|
164
|
+
height: 100%;
|
|
165
|
+
}
|
|
166
|
+
.chunk.selected, body.dark .chunk.selected {
|
|
167
|
+
border: 10px solid royalblue;
|
|
168
|
+
}
|
|
105
169
|
|
|
106
170
|
.add { background: #e6ffed; color: green; }
|
|
107
171
|
.del { background: #ffeef0; color: red; }
|
|
108
172
|
.context { background: #f8f8f8; }
|
|
109
173
|
.btn {
|
|
110
174
|
margin-right: 10px;
|
|
175
|
+
cursor: pointer;
|
|
176
|
+
border: none;
|
|
177
|
+
text-decoration: none;
|
|
178
|
+
padding: 10px;
|
|
179
|
+
border-radius: 3px;
|
|
180
|
+
background: black;
|
|
181
|
+
color: white;
|
|
182
|
+
font-size: 12px;
|
|
183
|
+
display: inline-block;
|
|
184
|
+
}
|
|
185
|
+
body.dark .empty {
|
|
186
|
+
background: rgba(255,255,255,0.1);
|
|
187
|
+
}
|
|
188
|
+
.empty {
|
|
189
|
+
text-align: center;
|
|
190
|
+
padding: 200px 40px;
|
|
191
|
+
opacity: 0.5;
|
|
192
|
+
background: rgba(0,0,0,0.04);
|
|
111
193
|
}
|
|
112
194
|
</style>
|
|
113
195
|
</head>
|
|
114
196
|
<body class='<%=theme%>' data-platform="<%=platform%>" data-agent="<%=agent%>">
|
|
115
197
|
<nav>
|
|
116
198
|
<% if (remote) { %>
|
|
117
|
-
|
|
199
|
+
<% if (connected) { %>
|
|
200
|
+
<a href="/run/scripts/git/push.json?cwd=<%=encodeURIComponent(dir)%>" class='btn'><i class="fa-brands fa-github"></i> Publish to GitHub</a>
|
|
201
|
+
<% } else { %>
|
|
202
|
+
<a class='btn' href="/github" target="_blank">Publish to GitHub</a>
|
|
203
|
+
<% } %>
|
|
118
204
|
<a href="/run/scripts/git/commit.json?cwd=<%=encodeURIComponent(dir)%>" class='btn'><i class="fa-solid fa-floppy-disk"></i> Commit (Save the current version)</a>
|
|
119
205
|
<a href="<%=remote%>" target="_blank"><%=remote%></a>
|
|
120
206
|
<% } else { %>
|
|
121
|
-
|
|
207
|
+
<% if (connected) { %>
|
|
208
|
+
<a href="/run/scripts/git/create.json?cwd=<%=encodeURIComponent(dir)%>" class='btn'><i class="fa-brands fa-github"></i> Create on GitHub</a>
|
|
209
|
+
<% } else { %>
|
|
210
|
+
<a class='btn' href="/github" target="_blank">Create on GitHub</a>
|
|
211
|
+
<% } %>
|
|
122
212
|
<a href="/run/scripts/git/commit.json?cwd=<%=encodeURIComponent(dir)%>" class='btn'><i class="fa-solid fa-floppy-disk"></i> Commit (Save the current version)</a>
|
|
123
213
|
<% } %>
|
|
124
214
|
</nav>
|
|
125
215
|
<main>
|
|
126
|
-
<
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
216
|
+
<aside>
|
|
217
|
+
<h2><i class="fa-solid fa-code-compare"></i> Changes</h2>
|
|
218
|
+
<% if (changes && changes.length > 0) { %>
|
|
219
|
+
<% changes.forEach(({ file, status, binary, diff, webpath }) => { %>
|
|
220
|
+
<a class='item' data-selector="<%=file%>" href="#<%=file%>"><%=file%></a>
|
|
221
|
+
<% }) %>
|
|
222
|
+
<% } %>
|
|
223
|
+
</aside>
|
|
224
|
+
<div class='changes'>
|
|
225
|
+
<% if (changes && changes.length > 0) { %>
|
|
226
|
+
<% changes.forEach(({ file, status, binary, diff, webpath }) => { %>
|
|
227
|
+
<div id="<%=file%>" class='chunk' data-selection="<%=file%>">
|
|
228
|
+
<h3>[<%= status %>] <%= file %></h3>
|
|
229
|
+
<% if (binary) { %>
|
|
230
|
+
<div class="binary-notice">[Binary file <%= status %>]</div>
|
|
231
|
+
<iframe src="<%=webpath%>"></iframe>
|
|
232
|
+
<% } else { %>
|
|
233
|
+
<div class="diff-block">
|
|
234
|
+
<% diff.forEach(({ line, lineOld, lineNew, type }) => { %>
|
|
235
|
+
<div class="diff-line <%= type %>">
|
|
236
|
+
<span class="lnum old"><%= lineOld !== '' ? lineOld : '' %></span>
|
|
237
|
+
<span class="lnum new"><%= lineNew !== '' ? lineNew : '' %></span>
|
|
238
|
+
<span class="code"><%= (type === 'add' ? '+ ' : type === 'del' ? '- ' : ' ') + line %></span>
|
|
239
|
+
</div>
|
|
240
|
+
<% }); %>
|
|
241
|
+
</div>
|
|
242
|
+
<% } %>
|
|
243
|
+
</div>
|
|
244
|
+
<% }); %>
|
|
245
|
+
<div class='filler'></div>
|
|
133
246
|
<% } else { %>
|
|
134
|
-
<div class=
|
|
135
|
-
<% diff.forEach(({ line, lineOld, lineNew, type }) => { %>
|
|
136
|
-
<div class="diff-line <%= type %>">
|
|
137
|
-
<span class="lnum old"><%= lineOld !== '' ? lineOld : '' %></span>
|
|
138
|
-
<span class="lnum new"><%= lineNew !== '' ? lineNew : '' %></span>
|
|
139
|
-
<span class="code"><%= (type === 'add' ? '+ ' : type === 'del' ? '- ' : ' ') + line %></span>
|
|
140
|
-
</div>
|
|
141
|
-
<% }); %>
|
|
142
|
-
</div>
|
|
247
|
+
<div class='empty'>No changes</div>
|
|
143
248
|
<% } %>
|
|
144
|
-
|
|
145
|
-
<% } else { %>
|
|
146
|
-
<div class='empty'>No changes</div>
|
|
147
|
-
<% } %>
|
|
249
|
+
</div>
|
|
148
250
|
</main>
|
|
251
|
+
<script>
|
|
252
|
+
document.querySelector("nav").addEventListener("click", (e) => {
|
|
253
|
+
let redirect = e.target.getAttribute("href")
|
|
254
|
+
if (redirect) {
|
|
255
|
+
const c = confirm("Please connect with GitHub first")
|
|
256
|
+
if (c) {
|
|
257
|
+
console.log("redirect")
|
|
258
|
+
} else {
|
|
259
|
+
e.preventDefault()
|
|
260
|
+
e.stopPropagation()
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
})
|
|
264
|
+
document.querySelector("aside").addEventListener("click", (e) => {
|
|
265
|
+
if (e.target.classList.contains("item")) {
|
|
266
|
+
document.querySelectorAll(".item").forEach((el) => {
|
|
267
|
+
el.classList.remove("selected")
|
|
268
|
+
})
|
|
269
|
+
e.target.classList.add("selected")
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
let selector = e.target.getAttribute("data-selector")
|
|
274
|
+
console.log({ selector })
|
|
275
|
+
document.querySelectorAll(".chunk").forEach((el) => {
|
|
276
|
+
el.classList.remove("selected")
|
|
277
|
+
})
|
|
278
|
+
document.querySelector(`[data-selection='${selector}']`).classList.add("selected")
|
|
279
|
+
}
|
|
280
|
+
})
|
|
281
|
+
</script>
|
|
149
282
|
</body>
|
|
150
283
|
</html>
|
package/server/views/github.ejs
CHANGED
|
@@ -61,8 +61,6 @@ body {
|
|
|
61
61
|
align-items: center;
|
|
62
62
|
}
|
|
63
63
|
.btn {
|
|
64
|
-
margin: 5px;
|
|
65
|
-
width: 100px;
|
|
66
64
|
text-align: center;
|
|
67
65
|
padding: 10px;
|
|
68
66
|
background: black;
|
|
@@ -108,7 +106,9 @@ main {
|
|
|
108
106
|
display: flex;
|
|
109
107
|
justify-content: center;
|
|
110
108
|
margin: 0 auto;
|
|
109
|
+
/*
|
|
111
110
|
max-width: 800px;
|
|
111
|
+
*/
|
|
112
112
|
width: 100%;
|
|
113
113
|
align-items: center;
|
|
114
114
|
}
|
|
@@ -126,20 +126,26 @@ main {
|
|
|
126
126
|
display: block;
|
|
127
127
|
margin-bottom: 5px;
|
|
128
128
|
}
|
|
129
|
-
.setup-items .gitconfig-footer
|
|
130
|
-
|
|
129
|
+
.setup-items .gitconfig-footer {
|
|
130
|
+
text-align: center;
|
|
131
|
+
}
|
|
132
|
+
.setup-items .btn {
|
|
133
|
+
width: 100%;
|
|
134
|
+
margin-bottom: 10px;
|
|
131
135
|
}
|
|
132
136
|
.setup-items .gitconfig {
|
|
133
137
|
flex-grow: 1;
|
|
134
|
-
padding: 30px;
|
|
135
|
-
background: rgba(0,0,0,0.04) !important;
|
|
136
138
|
margin-bottom: 20px;
|
|
137
139
|
}
|
|
138
|
-
.setup-items pre {
|
|
140
|
+
body.dark .setup-items pre, body.dark .setup-items .pre {
|
|
141
|
+
background: rgba(255,255,255,0.04) !important;
|
|
142
|
+
}
|
|
143
|
+
.setup-items pre, .setup-items .pre {
|
|
144
|
+
box-sizing: border-box;
|
|
145
|
+
margin: 10px 0 20px;
|
|
139
146
|
width: 100%;
|
|
140
|
-
padding:
|
|
147
|
+
padding: 20px;
|
|
141
148
|
background: rgba(0,0,0,0.04) !important;
|
|
142
|
-
margin-bottom: 20px;
|
|
143
149
|
}
|
|
144
150
|
.head {
|
|
145
151
|
padding: 30px;
|
|
@@ -194,7 +200,28 @@ hr {
|
|
|
194
200
|
}
|
|
195
201
|
#readme {
|
|
196
202
|
flex-grow: 1;
|
|
197
|
-
|
|
203
|
+
}
|
|
204
|
+
.cols {
|
|
205
|
+
max-width: 1000px;
|
|
206
|
+
margin: 0 auto;
|
|
207
|
+
display: flex;
|
|
208
|
+
}
|
|
209
|
+
body.dark .column {
|
|
210
|
+
background: rgba(0,0,0,0.1);
|
|
211
|
+
}
|
|
212
|
+
.column {
|
|
213
|
+
background: rgba(0,0,0,0.04);
|
|
214
|
+
margin: 10px;
|
|
215
|
+
width: 50%;
|
|
216
|
+
padding: 20px;
|
|
217
|
+
box-sizing: border-box;
|
|
218
|
+
}
|
|
219
|
+
.column h1 {
|
|
220
|
+
padding: 5px;
|
|
221
|
+
letter-spacing: -1px;
|
|
222
|
+
}
|
|
223
|
+
ol {
|
|
224
|
+
padding-inline-start: 20px;
|
|
198
225
|
}
|
|
199
226
|
</style>
|
|
200
227
|
<script src="/hotkeys.min.js"></script>
|
|
@@ -226,38 +253,48 @@ hr {
|
|
|
226
253
|
<div class='head'>
|
|
227
254
|
<h3><i class="fa-brands fa-github"></i><br><br>Connect with Github</h3>
|
|
228
255
|
</div>
|
|
229
|
-
<div class='
|
|
230
|
-
<
|
|
231
|
-
<
|
|
232
|
-
|
|
233
|
-
|
|
256
|
+
<div class='cols'>
|
|
257
|
+
<div class='column'>
|
|
258
|
+
<h1>GitHub</h1>
|
|
259
|
+
<div class='setup-items'>
|
|
260
|
+
<% if (hosts.length > 0) { %>
|
|
261
|
+
<pre><%=hosts%></pre>
|
|
262
|
+
<% } else { %>
|
|
263
|
+
<pre>not logged in</pre>
|
|
264
|
+
<% } %>
|
|
234
265
|
</div>
|
|
235
|
-
<div class='
|
|
236
|
-
|
|
237
|
-
|
|
266
|
+
<div class='setup-items'>
|
|
267
|
+
<% items.forEach((item) => { %>
|
|
268
|
+
<a class='btn' href="<%=item.url%>">
|
|
269
|
+
<i class="<%=item.icon%>"></i> <%=item.title%>
|
|
270
|
+
</a>
|
|
271
|
+
<% }) %>
|
|
238
272
|
</div>
|
|
239
|
-
<div class='
|
|
240
|
-
<
|
|
241
|
-
<div>gitconfig stored in ~/pinokio/gitconfig file </div>
|
|
273
|
+
<div class='setup-items'>
|
|
274
|
+
<div id='readme'><%-readme%></div>
|
|
242
275
|
</div>
|
|
243
|
-
</
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
276
|
+
</div>
|
|
277
|
+
<div class='column'>
|
|
278
|
+
<h1>Git Config</h1>
|
|
279
|
+
<div class='setup-items'>
|
|
280
|
+
<form class='gitconfig'>
|
|
281
|
+
<div class='pre'>
|
|
282
|
+
<div class='field'>
|
|
283
|
+
<label>username</label>
|
|
284
|
+
<input id='username' type='text' value="<%=gitconfig.user && gitconfig.user.name ? gitconfig.user.name : ''%>">
|
|
285
|
+
</div>
|
|
286
|
+
<div class='field'>
|
|
287
|
+
<label>email</label>
|
|
288
|
+
<input id='email' type='text' value="<%=gitconfig.user && gitconfig.user.email ? gitconfig.user.email : ''%>">
|
|
289
|
+
</div>
|
|
290
|
+
</div>
|
|
291
|
+
<div class='gitconfig-footer'>
|
|
292
|
+
<button class='btn'><i class="fa-solid fa-check"></i> Update</button>
|
|
293
|
+
<div>gitconfig stored in ~/pinokio/gitconfig file </div>
|
|
294
|
+
</div>
|
|
295
|
+
</form>
|
|
296
|
+
</div>
|
|
297
|
+
</div>
|
|
261
298
|
</div>
|
|
262
299
|
</main>
|
|
263
300
|
<script>
|
package/server/views/mini.ejs
CHANGED
|
@@ -1454,6 +1454,7 @@ body.dark .appcanvas {
|
|
|
1454
1454
|
|
|
1455
1455
|
})
|
|
1456
1456
|
const refresh = async (silent, options) => {
|
|
1457
|
+
debugger
|
|
1457
1458
|
console.log("REFRESH")
|
|
1458
1459
|
const dynamic = await fetch("<%=dynamic%>").then((res) => {
|
|
1459
1460
|
return res.text()
|
|
@@ -1537,6 +1538,7 @@ body.dark .appcanvas {
|
|
|
1537
1538
|
if (document.querySelector(".dynamic .reveal")) {
|
|
1538
1539
|
document.querySelector(".dynamic .reveal").click()
|
|
1539
1540
|
}
|
|
1541
|
+
refresh()
|
|
1540
1542
|
</script>
|
|
1541
1543
|
</body>
|
|
1542
1544
|
</html>
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
img.appicon {
|
|
26
26
|
width: 40px;
|
|
27
27
|
height: 40px;
|
|
28
|
-
margin-right:
|
|
28
|
+
margin-right: 5px;
|
|
29
29
|
padding: 5px;
|
|
30
30
|
border-radius: 4px;
|
|
31
31
|
background: white;
|
|
@@ -53,7 +53,7 @@ h4 {
|
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
h2 {
|
|
56
|
-
font-size:
|
|
56
|
+
font-size: 30px;
|
|
57
57
|
}
|
|
58
58
|
h1 {
|
|
59
59
|
letter-spacing: 0px;
|
|
@@ -145,6 +145,11 @@ body.dark .radio-group label {
|
|
|
145
145
|
}
|
|
146
146
|
|
|
147
147
|
.radio-group label span {
|
|
148
|
+
font-size: 16px;
|
|
149
|
+
/*
|
|
150
|
+
font-weight: lighter;
|
|
151
|
+
*/
|
|
152
|
+
margin-left: 5px;
|
|
148
153
|
font-weight: bold;
|
|
149
154
|
flex: 1;
|
|
150
155
|
}
|
|
@@ -152,6 +157,10 @@ body.dark .radio-group label {
|
|
|
152
157
|
.radio-group label .description {
|
|
153
158
|
opacity: 0.7;
|
|
154
159
|
margin-left: 0.5rem;
|
|
160
|
+
/*
|
|
161
|
+
width: 350px;
|
|
162
|
+
text-align: right;
|
|
163
|
+
*/
|
|
155
164
|
}
|
|
156
165
|
|
|
157
166
|
.checkbox-group {
|
|
@@ -184,6 +193,35 @@ body.dark .conditional-options {
|
|
|
184
193
|
*/
|
|
185
194
|
display: none;
|
|
186
195
|
}
|
|
196
|
+
#step-1 .radio-group {
|
|
197
|
+
display: flex;
|
|
198
|
+
}
|
|
199
|
+
#step-1 .radio-group label:hover {
|
|
200
|
+
color: royalblue;
|
|
201
|
+
}
|
|
202
|
+
#step-1 .radio-group label .description {
|
|
203
|
+
margin: 0;
|
|
204
|
+
}
|
|
205
|
+
#step-1 .radio-group label .col {
|
|
206
|
+
flex-grow: 1;
|
|
207
|
+
}
|
|
208
|
+
#step-1 .radio-group label {
|
|
209
|
+
display: flex;
|
|
210
|
+
padding: 30px;
|
|
211
|
+
text-align: left;
|
|
212
|
+
}
|
|
213
|
+
#step-1 .radio-group label i {
|
|
214
|
+
padding-right: 15px;
|
|
215
|
+
display: block;
|
|
216
|
+
font-size: 40px;
|
|
217
|
+
}
|
|
218
|
+
#step-1 .radio-group input[type=radio] {
|
|
219
|
+
display: none;
|
|
220
|
+
}
|
|
221
|
+
#step-1 .radio-group label span {
|
|
222
|
+
margin: 0;
|
|
223
|
+
font-size: 20px;
|
|
224
|
+
}
|
|
187
225
|
|
|
188
226
|
/*
|
|
189
227
|
.conditional-options .radio-group label, .conditional-options .checkbox-group label {
|
|
@@ -1051,24 +1089,30 @@ body.dark .command-fields {
|
|
|
1051
1089
|
<form id="bootstrap-form">
|
|
1052
1090
|
<!-- Step 1: New vs Clone -->
|
|
1053
1091
|
<div class="step-content active" id="step-1">
|
|
1054
|
-
<h2>
|
|
1092
|
+
<h2>What do you want to build?</h2>
|
|
1055
1093
|
<div class="radio-group">
|
|
1056
1094
|
<label>
|
|
1057
|
-
<input type="radio" name="startType" value="
|
|
1058
|
-
<
|
|
1059
|
-
<
|
|
1095
|
+
<input type="radio" name="startType" value="clone" required>
|
|
1096
|
+
<i class="fa-solid fa-rocket"></i>
|
|
1097
|
+
<div class='col'>
|
|
1098
|
+
<span>1-Click Launcher</span>
|
|
1099
|
+
<p class="description">Build a 1-click launcher for an existing app (from git)</p>
|
|
1100
|
+
</div>
|
|
1060
1101
|
</label>
|
|
1061
1102
|
<label>
|
|
1062
|
-
<input type="radio" name="startType" value="
|
|
1063
|
-
<
|
|
1064
|
-
<
|
|
1103
|
+
<input type="radio" name="startType" value="new" required>
|
|
1104
|
+
<i class="fa-solid fa-code"></i>
|
|
1105
|
+
<div class='col'>
|
|
1106
|
+
<span> New Project</span>
|
|
1107
|
+
<p class="description">Build a new app with a built-in 1-click launcher</p>
|
|
1108
|
+
</div>
|
|
1065
1109
|
</label>
|
|
1066
1110
|
</div>
|
|
1067
1111
|
</div>
|
|
1068
1112
|
|
|
1069
1113
|
<!-- Step 2: Project Type -->
|
|
1070
1114
|
<div class="step-content" id="step-2">
|
|
1071
|
-
<h2>
|
|
1115
|
+
<h2>Select Project Type</h2>
|
|
1072
1116
|
|
|
1073
1117
|
<!-- Clone Project Options -->
|
|
1074
1118
|
<div id="clone-options" class="project-options">
|
|
@@ -1077,19 +1121,19 @@ body.dark .command-fields {
|
|
|
1077
1121
|
<input type="radio" name="projectType" value="nodejs">
|
|
1078
1122
|
<img class='appicon' src="/asset/prototype/system/nodejs/icon.png"/>
|
|
1079
1123
|
<span>Node.js</span>
|
|
1080
|
-
<p class="description">
|
|
1124
|
+
<p class="description">Build a 1-click launcher for a node.js project.</p>
|
|
1081
1125
|
</label>
|
|
1082
1126
|
<label>
|
|
1083
1127
|
<input type="radio" name="projectType" value="python">
|
|
1084
1128
|
<img class='appicon' src="/asset/prototype/system/python/icon.png"/>
|
|
1085
1129
|
<span>Python</span>
|
|
1086
|
-
<p class='description'>
|
|
1130
|
+
<p class='description'>Build a 1-click launcher for a python project.</p>
|
|
1087
1131
|
</label>
|
|
1088
1132
|
<label>
|
|
1089
1133
|
<input type="radio" name="projectType" value="empty">
|
|
1090
1134
|
<img class='appicon' src="/asset/prototype/system/empty/icon.png"/>
|
|
1091
1135
|
<span>Any</span>
|
|
1092
|
-
<p class='description'>
|
|
1136
|
+
<p class='description'>Build a 1-click launcher for anything else or to customize on your own.</p>
|
|
1093
1137
|
</label>
|
|
1094
1138
|
</div>
|
|
1095
1139
|
|