pinokiod 7.0.12 → 7.1.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pinokiod",
3
- "version": "7.0.12",
3
+ "version": "7.1.0",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/server/index.js CHANGED
@@ -4771,17 +4771,33 @@ class Server {
4771
4771
  async terminals(filepath) {
4772
4772
  let venvs = await Util.find_venv(filepath)
4773
4773
  let terminal
4774
+ const createRawTerminal = () => {
4775
+ return this.renderShell(filepath, 0, 0, {
4776
+ icon: "fa-solid fa-terminal",
4777
+ title: "Project Terminal",
4778
+ subtitle: "No Python environment activated",
4779
+ text: "Terminal",
4780
+ type: "Start",
4781
+ shell: {
4782
+ input: true
4783
+ }
4784
+ })
4785
+ }
4774
4786
  if (venvs.length > 0) {
4775
- let terminals = []
4787
+ let terminals = [createRawTerminal()]
4776
4788
  try {
4777
4789
  for(let i=0; i<venvs.length; i++) {
4778
4790
  let venv = venvs[i]
4779
4791
  let parsed = path.parse(venv)
4780
- terminals.push(this.renderShell(filepath, i, 0, {
4792
+ let relativeVenv = path.relative(filepath, venv)
4793
+ if (!relativeVenv || relativeVenv.startsWith("..")) {
4794
+ relativeVenv = parsed.base || path.basename(venv)
4795
+ }
4796
+ terminals.push(this.renderShell(filepath, i + 1, 0, {
4781
4797
  icon: "fa-brands fa-python",
4782
- title: "Python virtual environment",
4783
- subtitle: this.kernel.path("api", parsed.name),
4784
- text: `[venv] ${parsed.name}`,
4798
+ title: "Python Terminal",
4799
+ subtitle: `Activates ${relativeVenv}`,
4800
+ text: `Python: ${relativeVenv}`,
4785
4801
  type: "Start",
4786
4802
  shell: {
4787
4803
  venv: venv,
@@ -4794,25 +4810,16 @@ class Server {
4794
4810
  }
4795
4811
  terminal = {
4796
4812
  icon: "fa-solid fa-terminal",
4797
- title: "Shell",
4798
- subtitle: "Open an interactive terminal in the browser",
4813
+ title: "Terminals",
4814
+ subtitle: "Open a project shell, with or without Python activated.",
4799
4815
  menu: terminals
4800
4816
  }
4801
4817
  } else {
4802
4818
  terminal = {
4803
4819
  icon: "fa-solid fa-terminal",
4804
- title: "User Terminal",
4805
- subtitle: "Work with the terminal directly in the browser",
4806
- menu: [this.renderShell(filepath, 0, 0, {
4807
- icon: "fa-solid fa-terminal",
4808
- title: "Terminal",
4809
- subtitle: filepath,
4810
- text: `Terminal`,
4811
- type: "Start",
4812
- shell: {
4813
- input: true
4814
- }
4815
- })]
4820
+ title: "Terminals",
4821
+ subtitle: "Open a project shell in the browser.",
4822
+ menu: [createRawTerminal()]
4816
4823
  }
4817
4824
  }
4818
4825
  return terminal
@@ -10755,18 +10762,22 @@ class Server {
10755
10762
  terminal.menus = href_menus
10756
10763
  sortNestedMenus(terminal.menu)
10757
10764
  sortNestedMenus(terminal.menus)
10758
- let dynamic = [
10765
+ let dynamic = [
10759
10766
  terminal,
10760
10767
  {
10761
10768
  icon: "fa-solid fa-plug-circle-bolt",
10762
- title: "Terminal Plugins",
10763
- subtitle: "Start a session in Pinokio",
10769
+ title: "Terminal Apps",
10770
+ subtitle: "Terminal apps provided by your installed",
10771
+ subtitle_link_href: "/plugins",
10772
+ subtitle_link_label: "plugins",
10764
10773
  menu: shell_menus
10765
10774
  },
10766
10775
  {
10767
10776
  icon: "fa-solid fa-arrow-up-right-from-square",
10768
- title: "Desktop Plugins",
10769
- subtitle: "Open the project in external desktop apps",
10777
+ title: "Desktop Apps",
10778
+ subtitle: "Desktop apps provided by your installed",
10779
+ subtitle_link_href: "/plugins",
10780
+ subtitle_link_label: "plugins",
10770
10781
  menu: exec_menus
10771
10782
  },
10772
10783
  ]
@@ -48,6 +48,7 @@ main {
48
48
  overflow: hidden;
49
49
  box-sizing: border-box;
50
50
  align-items: center;
51
+ min-width: 0;
51
52
  gap: 10px;
52
53
  padding: 10px;
53
54
  cursor: pointer;
@@ -79,12 +80,39 @@ body.dark .tab:focus-visible {
79
80
  font-weight: normal;
80
81
  font-size: 14px;
81
82
  }
83
+ .tab-copy {
84
+ min-width: 0;
85
+ flex: 1 1 auto;
86
+ display: flex;
87
+ flex-direction: column;
88
+ gap: 2px;
89
+ }
90
+ .tab-title {
91
+ min-width: 0;
92
+ line-height: 1.15;
93
+ overflow-wrap: anywhere;
94
+ }
95
+ .tab-subtitle {
96
+ min-width: 0;
97
+ line-height: 1.2;
98
+ white-space: nowrap;
99
+ overflow: hidden;
100
+ text-overflow: ellipsis;
101
+ }
102
+ .tab-actions {
103
+ display: inline-flex;
104
+ align-items: center;
105
+ gap: 2px;
106
+ flex: 0 0 auto;
107
+ margin-inline-start: auto;
108
+ padding-inline-start: 6px;
109
+ }
82
110
  .tab .col {
83
111
  flex-grow: 1;
84
112
  margin-left: 10px;
85
113
  }
86
114
  .tab i.img {
87
- flex-shrink: 0;
115
+ flex: 0 0 40px;
88
116
  height: 40px;
89
117
  width: 40px;
90
118
  background: white;
@@ -96,10 +124,12 @@ body.dark .tab:focus-visible {
96
124
  border-radius: 40px;
97
125
  }
98
126
  .tab img {
127
+ flex: 0 0 40px;
99
128
  border-radius: 40px;
100
129
  height: 40px;
101
130
  width: 40px;
102
131
  background: white;
132
+ object-fit: cover;
103
133
  }
104
134
  .tab .disclosure-indicator {
105
135
  display: inline-flex;
@@ -131,22 +161,34 @@ body.dark .tab:hover .disclosure-indicator,
131
161
  body.dark .tab:focus-visible .disclosure-indicator {
132
162
  color: rgba(255, 255, 255, 0.9);
133
163
  }
164
+ .tab-action-link,
134
165
  .ai-perm-link {
135
166
  border: none;
136
167
  background: none;
168
+ display: inline-flex;
169
+ align-items: center;
170
+ justify-content: center;
171
+ width: 30px;
172
+ height: 30px;
137
173
  color: rgba(0, 0, 0, 0.55);
138
- padding: 6px;
174
+ padding: 0;
139
175
  border-radius: 8px;
140
176
  cursor: pointer;
177
+ flex: 0 0 auto;
141
178
  }
179
+ .tab-action-link:hover,
180
+ .tab-action-link:focus-visible,
142
181
  .ai-perm-link:hover,
143
182
  .ai-perm-link:focus-visible {
144
183
  background: rgba(0, 0, 0, 0.08);
145
184
  color: rgba(0, 0, 0, 0.85);
146
185
  }
186
+ body.dark .tab-action-link,
147
187
  body.dark .ai-perm-link {
148
188
  color: rgba(255, 255, 255, 0.75);
149
189
  }
190
+ body.dark .tab-action-link:hover,
191
+ body.dark .tab-action-link:focus-visible,
150
192
  body.dark .ai-perm-link:hover,
151
193
  body.dark .ai-perm-link:focus-visible {
152
194
  background: rgba(255, 255, 255, 0.12);
@@ -187,17 +229,47 @@ body.dark .menu-container {
187
229
  font-size: 12px;
188
230
  opacity: 0.7;
189
231
  padding: 8px 10px 0;
232
+ min-height: 2.8em;
233
+ line-height: 1.35;
190
234
  }
191
235
  body.dark .column-subtitle {
192
236
  color: rgba(255, 255, 255, 0.75);
193
237
  }
238
+ .column-subtitle-link {
239
+ display: inline;
240
+ font-size: inherit;
241
+ font-weight: 700;
242
+ letter-spacing: 0.01em;
243
+ color: rgba(0, 0, 0, 0.75);
244
+ text-decoration: underline;
245
+ text-underline-offset: 0.12em;
246
+ text-decoration-thickness: 1px;
247
+ }
248
+ .column-subtitle-link:hover,
249
+ .column-subtitle-link:focus-visible {
250
+ color: rgba(0, 0, 0, 0.95);
251
+ }
252
+ body.dark .column-subtitle-link {
253
+ color: rgba(255, 255, 255, 0.8);
254
+ }
255
+ body.dark .column-subtitle-link:hover,
256
+ body.dark .column-subtitle-link:focus-visible {
257
+ color: rgba(255, 255, 255, 0.98);
258
+ }
194
259
  .menu-grid {
195
260
  display: grid;
196
261
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
262
+ align-items: start;
263
+ }
264
+ .menu-grid.menu-grid--triptych {
265
+ grid-template-columns: repeat(3, minmax(0, 1fr));
197
266
  }
198
267
  .menu-column {
268
+ display: flex;
269
+ flex-direction: column;
199
270
  border: 1px solid rgba(0, 0, 0, 0.05);
200
271
  overflow: hidden;
272
+ min-width: 0;
201
273
  }
202
274
  body.dark .menu-column {
203
275
  border-color: rgba(255, 255, 255, 0.08);
@@ -215,12 +287,19 @@ body.dark .menu-column .tab-header {
215
287
  flex-wrap: nowrap;
216
288
  align-items: stretch;
217
289
  gap: 4px;
290
+ min-width: 0;
218
291
  }
219
292
  .menu-column .tab-content .tab {
220
293
  flex: 0 0 auto;
221
294
  }
295
+ @media (max-width: 920px) {
296
+ .menu-grid.menu-grid--triptych {
297
+ grid-template-columns: 1fr;
298
+ }
299
+ }
222
300
  @media (max-width: 700px) {
223
- .menu-grid {
301
+ .menu-grid,
302
+ .menu-grid.menu-grid--triptych {
224
303
  grid-template-columns: 1fr;
225
304
  }
226
305
  }
@@ -433,23 +512,31 @@ body.dark #update-spec {
433
512
  <%
434
513
  let index = 0;
435
514
  const userTerminal = dynamic && dynamic.length ? dynamic[0] : null;
436
- const cliMenu = dynamic.find((item) => item && item.title === "Terminal Plugins");
437
- const ideMenu = dynamic.find((item) => item && item.title === "Desktop Plugins");
515
+ const cliMenu = dynamic.find((item) => item && item.title === "Terminal Apps");
516
+ const ideMenu = dynamic.find((item) => item && item.title === "Desktop Apps");
438
517
  const handled = new Set();
518
+ const primaryColumnCount = [userTerminal, cliMenu, ideMenu].filter((item) => item && item.menu && item.menu.length).length;
439
519
  if (userTerminal) handled.add(userTerminal);
440
520
  if (cliMenu) handled.add(cliMenu);
441
521
  if (ideMenu) handled.add(ideMenu);
442
522
  const remaining = dynamic.filter((item) => !handled.has(item));
443
523
  %>
444
524
 
445
- <div class='menu-grid'>
525
+ <div class='menu-grid <%= primaryColumnCount === 3 ? "menu-grid--triptych" : "" %>'>
446
526
  <% if (userTerminal && userTerminal.menu && userTerminal.menu.length) { %>
447
527
  <div class='menu-container menu-column user-terminal'>
448
528
  <div class='tab-header'>
449
529
  <h3><i class='<%= userTerminal.icon %>'></i> <%= userTerminal.title %></h3>
450
530
  </div>
451
- <% if (userTerminal.subtitle) { %>
452
- <div class='column-subtitle'><%= userTerminal.subtitle %></div>
531
+ <% if (userTerminal.subtitle || userTerminal.subtitle_link_href) { %>
532
+ <div class='column-subtitle'>
533
+ <% if (userTerminal.subtitle) { %>
534
+ <span><%= userTerminal.subtitle %></span><% if (userTerminal.subtitle_link_href && userTerminal.subtitle_link_label) { %> <% } %>
535
+ <% } %>
536
+ <% if (userTerminal.subtitle_link_href && userTerminal.subtitle_link_label) { %>
537
+ <a class='column-subtitle-link' href="<%= userTerminal.subtitle_link_href %>" target="_parent"><%= userTerminal.subtitle_link_label %></a>
538
+ <% } %>
539
+ </div>
453
540
  <% } %>
454
541
  <div class='tab-content'>
455
542
  <% userTerminal.menu.forEach((i) => { %>
@@ -459,19 +546,24 @@ body.dark #update-spec {
459
546
  <% } else if (i.icon) { %>
460
547
  <i class="img <%= i.icon %>"></i>
461
548
  <% } %>
462
- <h2><%= i.title %></h2>
463
- <% if (i.subtitle) { %>
464
- <div class='subtitle'><%= i.subtitle %></div>
465
- <% } %>
466
- <div class='flexible'></div>
467
- <% if (i.link) { %>
468
- <div target="_blank" data-href="<%= i.link %>" title="Open docs" data-tippy-content="Open docs"><i class="fa-solid fa-circle-info"></i></div>
469
- <% } %>
470
- <button class="ai-perm-link" type="button" data-ai-consent="<%= i.href %>" title="AI permissions" data-tippy-content="AI permissions">
471
- <i class="fa-solid fa-shield-halved"></i>
472
- </button>
473
- <div class='disclosure-indicator' aria-hidden="true">
474
- <i class="fa-solid fa-chevron-right"></i>
549
+ <div class='tab-copy'>
550
+ <h2 class='tab-title'><%= i.title %></h2>
551
+ <% if (i.subtitle) { %>
552
+ <div class='tab-subtitle subtitle'><%= i.subtitle %></div>
553
+ <% } %>
554
+ </div>
555
+ <div class='tab-actions'>
556
+ <% if (i.link) { %>
557
+ <button class="tab-action-link" type="button" data-doc-link="true" data-href="<%= i.link %>" title="Open docs" data-tippy-content="Open docs" aria-label="Open docs">
558
+ <i class="fa-solid fa-circle-info"></i>
559
+ </button>
560
+ <% } %>
561
+ <button class="ai-perm-link" type="button" data-ai-consent="<%= i.href %>" title="AI permissions" data-tippy-content="AI permissions" aria-label="AI permissions">
562
+ <i class="fa-solid fa-shield-halved"></i>
563
+ </button>
564
+ <div class='disclosure-indicator' aria-hidden="true">
565
+ <i class="fa-solid fa-chevron-right"></i>
566
+ </div>
475
567
  </div>
476
568
  </div>
477
569
  <% }) %>
@@ -482,10 +574,17 @@ body.dark #update-spec {
482
574
  <% if (cliMenu && cliMenu.menu && cliMenu.menu.length) { %>
483
575
  <div class='menu-container menu-column cli-column'>
484
576
  <div class='tab-header'>
485
- <h3><i class='<%= cliMenu.icon %>'></i> Terminal Plugins</h3>
577
+ <h3><i class='<%= cliMenu.icon %>'></i> <%= cliMenu.title %></h3>
486
578
  </div>
487
- <% if (cliMenu.subtitle) { %>
488
- <div class='column-subtitle'><%= cliMenu.subtitle %></div>
579
+ <% if (cliMenu.subtitle || cliMenu.subtitle_link_href) { %>
580
+ <div class='column-subtitle'>
581
+ <% if (cliMenu.subtitle) { %>
582
+ <span><%= cliMenu.subtitle %></span><% if (cliMenu.subtitle_link_href && cliMenu.subtitle_link_label) { %> <% } %>
583
+ <% } %>
584
+ <% if (cliMenu.subtitle_link_href && cliMenu.subtitle_link_label) { %>
585
+ <a class='column-subtitle-link' href="<%= cliMenu.subtitle_link_href %>" target="_parent"><%= cliMenu.subtitle_link_label %></a>
586
+ <% } %>
587
+ </div>
489
588
  <% } %>
490
589
  <div class='tab-content'>
491
590
  <% cliMenu.menu.forEach((i) => { %>
@@ -495,19 +594,24 @@ body.dark #update-spec {
495
594
  <% } else if (i.icon) { %>
496
595
  <i class="img <%= i.icon %>"></i>
497
596
  <% } %>
498
- <h2><%= i.title %></h2>
499
- <% if (i.subtitle) { %>
500
- <div class='subtitle'><%= i.subtitle %></div>
501
- <% } %>
502
- <div class='flexible'></div>
503
- <% if (i.link) { %>
504
- <div target="_blank" data-href="<%= i.link %>" title="Open docs" data-tippy-content="Open docs"><i class="fa-solid fa-circle-info"></i></div>
505
- <% } %>
506
- <button class="ai-perm-link" type="button" data-ai-consent="<%= i.href %>" title="AI permissions" data-tippy-content="AI permissions">
507
- <i class="fa-solid fa-shield-halved"></i>
508
- </button>
509
- <div class='disclosure-indicator' aria-hidden="true">
510
- <i class="fa-solid fa-chevron-right"></i>
597
+ <div class='tab-copy'>
598
+ <h2 class='tab-title'><%= i.title %></h2>
599
+ <% if (i.subtitle) { %>
600
+ <div class='tab-subtitle subtitle'><%= i.subtitle %></div>
601
+ <% } %>
602
+ </div>
603
+ <div class='tab-actions'>
604
+ <% if (i.link) { %>
605
+ <button class="tab-action-link" type="button" data-doc-link="true" data-href="<%= i.link %>" title="Open docs" data-tippy-content="Open docs" aria-label="Open docs">
606
+ <i class="fa-solid fa-circle-info"></i>
607
+ </button>
608
+ <% } %>
609
+ <button class="ai-perm-link" type="button" data-ai-consent="<%= i.href %>" title="AI permissions" data-tippy-content="AI permissions" aria-label="AI permissions">
610
+ <i class="fa-solid fa-shield-halved"></i>
611
+ </button>
612
+ <div class='disclosure-indicator' aria-hidden="true">
613
+ <i class="fa-solid fa-chevron-right"></i>
614
+ </div>
511
615
  </div>
512
616
  </div>
513
617
  <% }) %>
@@ -518,10 +622,17 @@ body.dark #update-spec {
518
622
  <% if (ideMenu && ideMenu.menu && ideMenu.menu.length) { %>
519
623
  <div class='menu-container menu-column ide-column'>
520
624
  <div class='tab-header'>
521
- <h3><i class='<%= ideMenu.icon %>'></i> Desktop Plugins</h3>
625
+ <h3><i class='<%= ideMenu.icon %>'></i> <%= ideMenu.title %></h3>
522
626
  </div>
523
- <% if (ideMenu.subtitle) { %>
524
- <div class='column-subtitle'><%= ideMenu.subtitle %></div>
627
+ <% if (ideMenu.subtitle || ideMenu.subtitle_link_href) { %>
628
+ <div class='column-subtitle'>
629
+ <% if (ideMenu.subtitle) { %>
630
+ <span><%= ideMenu.subtitle %></span><% if (ideMenu.subtitle_link_href && ideMenu.subtitle_link_label) { %> <% } %>
631
+ <% } %>
632
+ <% if (ideMenu.subtitle_link_href && ideMenu.subtitle_link_label) { %>
633
+ <a class='column-subtitle-link' href="<%= ideMenu.subtitle_link_href %>" target="_parent"><%= ideMenu.subtitle_link_label %></a>
634
+ <% } %>
635
+ </div>
525
636
  <% } %>
526
637
  <div class='tab-content'>
527
638
  <% ideMenu.menu.forEach((i) => { %>
@@ -531,19 +642,24 @@ body.dark #update-spec {
531
642
  <% } else if (i.icon) { %>
532
643
  <i class="img <%= i.icon %>"></i>
533
644
  <% } %>
534
- <h2><%= i.title %></h2>
535
- <% if (i.subtitle) { %>
536
- <div class='subtitle'><%= i.subtitle %></div>
537
- <% } %>
538
- <div class='flexible'></div>
539
- <% if (i.link) { %>
540
- <div target="_blank" data-href="<%= i.link %>" title="Open docs" data-tippy-content="Open docs"><i class="fa-solid fa-circle-info"></i></div>
541
- <% } %>
542
- <button class="ai-perm-link" type="button" data-ai-consent="<%= i.href %>" title="AI permissions" data-tippy-content="AI permissions">
543
- <i class="fa-solid fa-shield-halved"></i>
544
- </button>
545
- <div class='disclosure-indicator' aria-hidden="true">
546
- <i class="fa-solid fa-chevron-right"></i>
645
+ <div class='tab-copy'>
646
+ <h2 class='tab-title'><%= i.title %></h2>
647
+ <% if (i.subtitle) { %>
648
+ <div class='tab-subtitle subtitle'><%= i.subtitle %></div>
649
+ <% } %>
650
+ </div>
651
+ <div class='tab-actions'>
652
+ <% if (i.link) { %>
653
+ <button class="tab-action-link" type="button" data-doc-link="true" data-href="<%= i.link %>" title="Open docs" data-tippy-content="Open docs" aria-label="Open docs">
654
+ <i class="fa-solid fa-circle-info"></i>
655
+ </button>
656
+ <% } %>
657
+ <button class="ai-perm-link" type="button" data-ai-consent="<%= i.href %>" title="AI permissions" data-tippy-content="AI permissions" aria-label="AI permissions">
658
+ <i class="fa-solid fa-shield-halved"></i>
659
+ </button>
660
+ <div class='disclosure-indicator' aria-hidden="true">
661
+ <i class="fa-solid fa-chevron-right"></i>
662
+ </div>
547
663
  </div>
548
664
  </div>
549
665
  <% }) %>
@@ -566,19 +682,24 @@ body.dark #update-spec {
566
682
  <% } else if (i.icon) { %>
567
683
  <i class="img <%= i.icon %>"></i>
568
684
  <% } %>
569
- <h2><%= i.title %></h2>
570
- <% if (i.subtitle) { %>
571
- <div class='subtitle'><%= i.subtitle %></div>
572
- <% } %>
573
- <div class='flexible'></div>
574
- <% if (i.link) { %>
575
- <div target="_blank" data-href="<%= i.link %>" title="Open docs" data-tippy-content="Open docs"><i class="fa-solid fa-circle-info"></i></div>
576
- <% } %>
577
- <button class="ai-perm-link" type="button" data-ai-consent="<%= i.href %>" title="AI permissions" data-tippy-content="AI permissions">
578
- <i class="fa-solid fa-shield-halved"></i>
579
- </button>
580
- <div class='disclosure-indicator' aria-hidden="true">
581
- <i class="fa-solid fa-chevron-right"></i>
685
+ <div class='tab-copy'>
686
+ <h2 class='tab-title'><%= i.title %></h2>
687
+ <% if (i.subtitle) { %>
688
+ <div class='tab-subtitle subtitle'><%= i.subtitle %></div>
689
+ <% } %>
690
+ </div>
691
+ <div class='tab-actions'>
692
+ <% if (i.link) { %>
693
+ <button class="tab-action-link" type="button" data-doc-link="true" data-href="<%= i.link %>" title="Open docs" data-tippy-content="Open docs" aria-label="Open docs">
694
+ <i class="fa-solid fa-circle-info"></i>
695
+ </button>
696
+ <% } %>
697
+ <button class="ai-perm-link" type="button" data-ai-consent="<%= i.href %>" title="AI permissions" data-tippy-content="AI permissions" aria-label="AI permissions">
698
+ <i class="fa-solid fa-shield-halved"></i>
699
+ </button>
700
+ <div class='disclosure-indicator' aria-hidden="true">
701
+ <i class="fa-solid fa-chevron-right"></i>
702
+ </div>
582
703
  </div>
583
704
  </div>
584
705
  <% }) %>
@@ -868,7 +989,7 @@ document.addEventListener("click", (e) => {
868
989
  return
869
990
  }
870
991
 
871
- const infoTarget = e.target.closest('[data-href][target="_blank"]')
992
+ const infoTarget = e.target.closest('[data-doc-link][data-href]')
872
993
  if (infoTarget) {
873
994
  e.preventDefault()
874
995
  e.stopPropagation()