pinokiod 3.309.0 → 3.310.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.309.0",
3
+ "version": "3.310.0",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/server/index.js CHANGED
@@ -915,7 +915,6 @@ class Server {
915
915
  config = await this.processMenu(name, config)
916
916
  } catch(e) {
917
917
  config.menu = []
918
- err = e.stack
919
918
  }
920
919
 
921
920
  await this.renderMenu(req, uri, name, config, [])
@@ -3521,6 +3520,13 @@ class Server {
3521
3520
 
3522
3521
  // if the home is different from the existing home, go forward
3523
3522
  if (config.home !== home) {
3523
+ const logHomeCheck = (...args) => {
3524
+ try {
3525
+ console.log('[home-check]', ...args)
3526
+ } catch (_) {
3527
+ // ignore logging failures
3528
+ }
3529
+ }
3524
3530
  const basename = path.basename(config.home)
3525
3531
  // check for invalid path
3526
3532
  let isValidPath = (basename !== '' && basename !== config.home)
@@ -3544,12 +3550,26 @@ class Server {
3544
3550
 
3545
3551
  const normalizeMountPath = (p) => {
3546
3552
  if (!p) return null
3553
+ // on Windows, strip extended-length/UNC prefixes so mountpoint matching is consistent
3554
+ if (process.platform === 'win32') {
3555
+ const lower = p.toLowerCase()
3556
+ if (lower.startsWith('\\\\?\\unc\\')) {
3557
+ p = '\\\\' + p.slice(8)
3558
+ } else if (lower.startsWith('\\\\?\\') || lower.startsWith('\\\\.\\')) {
3559
+ p = p.slice(4)
3560
+ }
3561
+ }
3547
3562
  const normalized = path.normalize(p)
3548
3563
  const { root } = path.parse(normalized)
3564
+ let result
3549
3565
  if (normalized === root) {
3550
- return root.replace(/\\/g, '/')
3566
+ result = root.replace(/\\/g, '/')
3567
+ } else {
3568
+ result = normalized.replace(/[\\/]+$/g, '').replace(/\\/g, '/')
3551
3569
  }
3552
- return normalized.replace(/[\\/]+$/g, '').replace(/\\/g, '/')
3570
+ // on Windows, drive letters and UNC hostnames can differ in case between user input and systeminformation
3571
+ // normalize to lowercase for comparisons
3572
+ return process.platform === 'win32' ? result.toLowerCase() : result
3553
3573
  }
3554
3574
 
3555
3575
  const resolvedHome = path.resolve(config.home)
@@ -3557,24 +3577,67 @@ class Server {
3557
3577
  if (!ancestor) {
3558
3578
  throw new Error("Invalid path: unable to locate parent volume for " + config.home)
3559
3579
  }
3580
+ logHomeCheck({ step: 'resolved', resolvedHome, ancestor })
3560
3581
 
3561
3582
  const mounts = await system.fsSize().catch(() => [])
3583
+ const blockDeviceMounts = []
3584
+ const mountTypeLookup = new Map()
3585
+ try {
3586
+ // fsSize() on some platforms can obscure the actual fs type; pull blockDevices for more accurate mount FS info (e.g. exFAT on macOS/Windows)
3587
+ const blockDevices = await system.blockDevices()
3588
+ for (const device of blockDevices || []) {
3589
+ const mountPath = normalizeMountPath(device.mount)
3590
+ if (!mountPath) continue
3591
+ const fsType = (device.fsType || device.type || '').toLowerCase()
3592
+ blockDeviceMounts.push({ mount: mountPath, type: fsType })
3593
+ if (fsType) {
3594
+ mountTypeLookup.set(mountPath.toLowerCase(), fsType)
3595
+ }
3596
+ }
3597
+ } catch (_) {
3598
+ // ignore - fallback to fsSize data only
3599
+ }
3600
+ logHomeCheck({ step: 'mountSources', fsSizeCount: mounts.length, blockDevicesCount: blockDeviceMounts.length })
3601
+
3562
3602
  const normalizedAncestor = normalizeMountPath(ancestor)
3603
+ const isParentMount = (mountPath) => {
3604
+ if (!mountPath || !normalizedAncestor) return false
3605
+ if (mountPath === "/") return normalizedAncestor.startsWith("/")
3606
+ return normalizedAncestor === mountPath || normalizedAncestor.startsWith(mountPath + "/")
3607
+ }
3608
+ const isExfat = (fsType) => {
3609
+ const normalized = (fsType || '').toLowerCase().replace(/[^a-z0-9]/g, '')
3610
+ return normalized.includes('exfat')
3611
+ }
3563
3612
  let bestMount = null
3564
3613
  for (const volume of mounts) {
3565
3614
  const mountPath = normalizeMountPath(volume.mount)
3566
- if (!mountPath || !normalizedAncestor) continue
3567
- const isParent = mountPath === "/" ? normalizedAncestor.startsWith("/") : (normalizedAncestor === mountPath || normalizedAncestor.startsWith(mountPath + "/"))
3568
- if (isParent) {
3569
- if (!bestMount || mountPath.length > bestMount.mount.length) {
3570
- bestMount = { mount: mountPath, type: (volume.type || '').toLowerCase() }
3615
+ if (!isParentMount(mountPath)) continue
3616
+ const blockType = mountTypeLookup.get((mountPath || '').toLowerCase())
3617
+ const detectedType = (blockType || volume.type || '').toLowerCase()
3618
+ if (!bestMount || mountPath.length > bestMount.mount.length) {
3619
+ bestMount = { mount: mountPath, type: detectedType }
3620
+ logHomeCheck({ step: 'candidate', source: 'fsSize', mount: mountPath, type: detectedType })
3621
+ }
3622
+ }
3623
+
3624
+ if (!bestMount) {
3625
+ for (const deviceMount of blockDeviceMounts) {
3626
+ if (!isParentMount(deviceMount.mount)) continue
3627
+ if (!bestMount || deviceMount.mount.length > bestMount.mount.length) {
3628
+ bestMount = { ...deviceMount }
3629
+ logHomeCheck({ step: 'candidate', source: 'blockDevices', mount: deviceMount.mount, type: deviceMount.type })
3571
3630
  }
3572
3631
  }
3573
3632
  }
3574
3633
 
3575
- if (bestMount && bestMount.type.includes("exfat")) {
3634
+ logHomeCheck({ step: 'bestMount', bestMount })
3635
+
3636
+ if (bestMount && bestMount.type && isExfat(bestMount.type)) {
3637
+ logHomeCheck({ step: 'reject', reason: 'exfat', bestMount })
3576
3638
  throw new Error("Pinokio home cannot be located on an exFAT drive. Please choose a different location.")
3577
3639
  }
3640
+ logHomeCheck({ step: 'accept', bestMount })
3578
3641
 
3579
3642
  // // check if the destination already exists => throw error
3580
3643
  // let exists = await fse.pathExists(config.home)
@@ -1057,6 +1057,16 @@ body.columns .containers {
1057
1057
  font-style: normal;
1058
1058
 
1059
1059
  }
1060
+ .xterm,
1061
+ .xterm .xterm-rows,
1062
+ .xterm .xterm-rows span,
1063
+ .xterm .xterm-text-layer,
1064
+ .xterm .xterm-text-layer canvas,
1065
+ .xterm .xterm-cursor-layer,
1066
+ .xterm .xterm-char-measure-element {
1067
+ font-variant-ligatures: none;
1068
+ font-feature-settings: "liga" 0, "clig" 0, "calt" 0, "rlig" 0;
1069
+ }
1060
1070
  .xterm {
1061
1071
  padding: 0 10px !important;
1062
1072
  /*
@@ -1024,6 +1024,10 @@
1024
1024
  }
1025
1025
  const family = typeof this.preferences.fontFamily === 'string' ? this.preferences.fontFamily.trim() : '';
1026
1026
  const size = isFiniteNumber(this.preferences.fontSize) ? this.preferences.fontSize : null;
1027
+ if (!family && !size) {
1028
+ this.removeStyleElement();
1029
+ return;
1030
+ }
1027
1031
  const style = this.ensureStyleElement();
1028
1032
  if (!style) {
1029
1033
  return;
@@ -1037,17 +1041,17 @@
1037
1041
  '.xterm .xterm-cursor-layer',
1038
1042
  '.xterm .xterm-char-measure-element'
1039
1043
  ];
1040
- const declarations = [
1041
- 'font-variant-ligatures: none !important',
1042
- 'font-feature-settings: "liga" 0, "clig" 0, "calt" 0, "rlig" 0 !important'
1043
- ];
1044
+ const declarations = [];
1044
1045
  if (family) {
1045
1046
  declarations.push(`font-family: ${family} !important`);
1046
1047
  }
1047
1048
  if (size) {
1048
1049
  declarations.push(`font-size: ${size}px !important`);
1049
1050
  }
1050
- style.textContent = `${selectors.join(', ')} { ${declarations.join('; ')}; }`;
1051
+ const nextCss = `${selectors.join(', ')} { ${declarations.join('; ')}; }`;
1052
+ if (style.textContent !== nextCss) {
1053
+ style.textContent = nextCss;
1054
+ }
1051
1055
  }
1052
1056
 
1053
1057
  sanitizeTheme(raw, allowUnknown) {