pinokiod 3.325.0 → 3.327.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": "3.325.0",
3
+ "version": "3.327.0",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/server/index.js CHANGED
@@ -234,6 +234,11 @@ class Server {
234
234
  dirty = true
235
235
  }
236
236
 
237
+ if (config['credential "helperselector"']) {
238
+ delete config['credential "helperselector"']
239
+ dirty = true
240
+ }
241
+
237
242
  if (dirty) {
238
243
  await fs.promises.writeFile(gitconfigPath, ini.stringify(config))
239
244
  }
@@ -65,15 +65,24 @@ body.dark .url-dropdown {
65
65
  flex-direction: column;
66
66
  gap: 4px;
67
67
  }
68
+ .url-dropdown-item.non-selectable {
69
+ cursor: default;
70
+ }
68
71
  body.dark .url-dropdown-item {
69
72
  border-bottom-color: rgba(255,255,255,0.1);
70
73
  }
71
74
  .url-dropdown-item:hover {
72
75
  background: #f7fafc;
73
76
  }
77
+ .url-dropdown-item.non-selectable:hover {
78
+ background: transparent;
79
+ }
74
80
  body.dark .url-dropdown-item:hover {
75
81
  background: rgba(255,255,255,0.04);
76
82
  }
83
+ body.dark .url-dropdown-item.non-selectable:hover {
84
+ background: transparent;
85
+ }
77
86
  .url-dropdown-item:last-child {
78
87
  border-bottom: none;
79
88
  }
@@ -97,6 +106,9 @@ body.dark .url-dropdown-name {
97
106
  align-items: center;
98
107
  gap: 8px;
99
108
  }
109
+ .url-dropdown-item.current-project .url-dropdown-url {
110
+ margin-bottom: 2px;
111
+ }
100
112
  body.dark .url-dropdown-url {
101
113
  color: #a0aec0;
102
114
  }
@@ -147,6 +159,51 @@ body.dark .url-dropdown-empty {
147
159
  align-items: center;
148
160
  gap: 8px;
149
161
  }
162
+ .url-mode-buttons {
163
+ display: flex;
164
+ flex-wrap: wrap;
165
+ gap: 6px;
166
+ }
167
+ .url-mode-button {
168
+ display: inline-flex;
169
+ align-items: center;
170
+ gap: 6px;
171
+ padding: 7px 10px;
172
+ border-radius: 8px;
173
+ border: 1px solid rgba(15, 23, 42, 0.08);
174
+ background: rgba(127, 91, 243, 0.08);
175
+ color: #1f2937;
176
+ font-size: 12px;
177
+ font-weight: 600;
178
+ cursor: pointer;
179
+ transition: background 0.15s ease, border-color 0.15s ease, transform 0.1s ease;
180
+ }
181
+ .url-mode-button:hover {
182
+ background: rgba(127, 91, 243, 0.14);
183
+ border-color: rgba(15, 23, 42, 0.12);
184
+ }
185
+ .url-mode-button:active {
186
+ transform: translateY(1px);
187
+ }
188
+ .url-mode-button.active {
189
+ background: black;
190
+ border-color: black;
191
+ color: white;
192
+ }
193
+ body.dark .url-mode-button {
194
+ background: rgba(255,255,255,0.04);
195
+ border-color: rgba(255,255,255,0.08);
196
+ color: #e2e8f0;
197
+ }
198
+ body.dark .url-mode-button:hover {
199
+ background: rgba(255,255,255,0.08);
200
+ border-color: rgba(255,255,255,0.12);
201
+ }
202
+ body.dark .url-mode-button.active {
203
+ background: rgba(127, 91, 243, 0.8);
204
+ border-color: rgba(127, 91, 243, 0.8);
205
+ color: white;
206
+ }
150
207
  .url-dropdown-create-button {
151
208
  padding: 8px 18px;
152
209
  border-radius: 6px;
@@ -169,6 +169,55 @@ function initUrlDropdown(config = {}) {
169
169
  return url.replace(/^https?:\/\//i, '');
170
170
  };
171
171
 
172
+ const parseProjectContext = (url) => {
173
+ if (!url || typeof url !== 'string') return null;
174
+ let parsed;
175
+ try {
176
+ parsed = new URL(url, (typeof window !== 'undefined' && window.location) ? window.location.origin : undefined);
177
+ } catch (_) {
178
+ return null;
179
+ }
180
+ const pathname = parsed.pathname || '';
181
+ const match = pathname.match(/^\/p\/([^/]+)(?:\/(dev|files|review))?\/?$/i);
182
+ if (!match) return null;
183
+ const project = match[1];
184
+ const currentMode = match[2] || 'run';
185
+ return {
186
+ origin: parsed.origin || '',
187
+ project,
188
+ basePath: `/p/${project}`,
189
+ currentMode
190
+ };
191
+ };
192
+
193
+ const buildProjectModeButtons = (projectCtx) => {
194
+ if (!projectCtx) return '';
195
+ const modes = [
196
+ { key: 'run', label: 'Run', icon: 'fa-solid fa-circle-play', suffix: '' },
197
+ { key: 'dev', label: 'Dev', icon: 'fa-solid fa-code', suffix: '/dev' },
198
+ { key: 'files', label: 'Files', icon: 'fa-solid fa-file-lines', suffix: '/files' },
199
+ { key: 'review', label: 'Forum', icon: 'fa-regular fa-message', suffix: '/review' },
200
+ ];
201
+
202
+ const buildTarget = (suffix) => {
203
+ const targetPath = `${projectCtx.basePath}${suffix}`;
204
+ return projectCtx.origin ? `${projectCtx.origin}${targetPath}` : targetPath;
205
+ };
206
+
207
+ const buttonsHtml = modes.map((mode) => {
208
+ const target = buildTarget(mode.suffix);
209
+ const isActive = mode.key === projectCtx.currentMode;
210
+ return `
211
+ <button type="button" class="url-mode-button${isActive ? ' active' : ''}" data-url="${escapeAttribute(target)}" data-host-type="current">
212
+ <i class="${mode.icon}"></i>
213
+ <span>${mode.label}</span>
214
+ </button>
215
+ `;
216
+ }).join('');
217
+
218
+ return `<div class="url-mode-buttons" role="group" aria-label="Project views">${buttonsHtml}</div>`;
219
+ };
220
+
172
221
  let isDropdownVisible = false;
173
222
  let allProcesses = []; // Store all processes for filtering
174
223
  let filteredProcesses = []; // Store currently filtered processes
@@ -480,25 +529,36 @@ function initUrlDropdown(config = {}) {
480
529
  const buildDropdownHtml = (processes, { includeCurrentTab = true, inputElement } = {}) => {
481
530
  const currentUrl = typeof window !== 'undefined' ? window.location.href : '';
482
531
  const currentTitle = typeof document !== 'undefined' ? (document.title || 'Current tab') : 'Current tab';
532
+ const currentProject = parseProjectContext(currentUrl);
483
533
 
484
534
  let html = '';
485
535
  if (includeCurrentTab && currentUrl) {
486
536
  const schemeLabel = currentUrl.startsWith('https://') ? 'HTTPS' : 'HTTP';
537
+ const currentPathLabel = currentProject ? currentProject.basePath : formatUrlLabel(currentUrl) || currentUrl;
538
+ const projectButtons = currentProject ? buildProjectModeButtons(currentProject) : '';
487
539
  html += `
488
540
  <div class="url-dropdown-host-header current-tab">
489
541
  <span class="host-name">Current tab</span>
490
542
  </div>
491
- <div class="url-dropdown-item" data-url="${escapeAttribute(currentUrl)}" data-host-type="current">
543
+ <div class="url-dropdown-item${currentProject ? ' non-selectable current-project' : ''}" data-url="${escapeAttribute(currentUrl)}" data-host-type="current">
492
544
  <div class="url-dropdown-name">
493
545
  <span>
494
546
  <i class="fa-solid fa-clone"></i>
495
547
  ${escapeHtml(currentTitle)}
496
548
  </span>
497
549
  </div>
498
- <div class="url-dropdown-url">
499
- <span class="url-scheme ${schemeLabel === 'HTTPS' ? 'https' : 'http'}">${schemeLabel}</span>
500
- <span class="url-address">${escapeHtml(formatUrlLabel(currentUrl) || currentUrl)}</span>
501
- </div>
550
+ ${currentProject ? `
551
+ <div class="url-dropdown-url">
552
+ <span class="url-scheme ${schemeLabel === 'HTTPS' ? 'https' : 'http'}">${schemeLabel}</span>
553
+ <span class="url-address">${escapeHtml(currentPathLabel)}</span>
554
+ </div>
555
+ ${projectButtons}
556
+ ` : `
557
+ <div class="url-dropdown-url">
558
+ <span class="url-scheme ${schemeLabel === 'HTTPS' ? 'https' : 'http'}">${schemeLabel}</span>
559
+ <span class="url-address">${escapeHtml(currentPathLabel)}</span>
560
+ </div>
561
+ `}
502
562
  </div>
503
563
  `;
504
564
  }
@@ -546,6 +606,14 @@ function initUrlDropdown(config = {}) {
546
606
  }
547
607
  });
548
608
  });
609
+ container.querySelectorAll('.url-mode-button').forEach(button => {
610
+ button.addEventListener('click', function(event) {
611
+ event.stopPropagation();
612
+ const url = this.getAttribute('data-url');
613
+ const type = this.getAttribute('data-host-type') || 'current';
614
+ onSelect(url, type, selectionOptions);
615
+ });
616
+ });
549
617
  container.querySelectorAll('.peer-network-button').forEach(button => {
550
618
  button.addEventListener('click', function(event) {
551
619
  event.stopPropagation();