tabminal 3.0.13 → 3.0.15

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/public/index.html CHANGED
@@ -229,6 +229,10 @@
229
229
  target.classList.contains('file-tree') ||
230
230
  target.classList.contains('tab-file-tree') ||
231
231
  target.classList.contains('editor-content') ||
232
+ target.classList.contains('markdown-preview-container') ||
233
+ target.classList.contains('markdown-preview-scroll') ||
234
+ target.classList.contains('pdf-preview-container') ||
235
+ target.classList.contains('pdf-preview-pages') ||
232
236
  target.classList.contains('agent-panel-transcript') ||
233
237
  target.classList.contains('agent-panel-input') ||
234
238
  target.classList.contains('xterm-viewport') ||
@@ -273,18 +277,82 @@
273
277
  }
274
278
 
275
279
  const runtimeStorageKey = 'tabminal_runtime_boot_id';
276
- let runtimeBootId = '';
277
- try {
278
- runtimeBootId = localStorage.getItem(runtimeStorageKey) || '';
279
- } catch {
280
- runtimeBootId = '';
281
- }
282
- const runtimeAssetKey = runtimeBootId || `cold-${Date.now()}`;
283
- window.__tabminalRuntimeAssetKey = runtimeAssetKey;
284
- const link = document.createElement('link');
285
- link.rel = 'stylesheet';
286
- link.href = `./styles.css?v=${encodeURIComponent(runtimeAssetKey)}`;
287
- document.head.appendChild(link);
280
+ const versionApiUrl = './api/version';
281
+ const runtimeVersionTimeoutMs = 3000;
282
+ const readStoredRuntimeBootId = () => {
283
+ try {
284
+ return localStorage.getItem(runtimeStorageKey) || '';
285
+ } catch {
286
+ return '';
287
+ }
288
+ };
289
+ const persistRuntimeBootId = (bootId) => {
290
+ try {
291
+ localStorage.setItem(runtimeStorageKey, bootId);
292
+ } catch {
293
+ // Ignore storage failures and continue with in-memory key.
294
+ }
295
+ };
296
+ const getStartupFallbackAssetKey = () => {
297
+ return readStoredRuntimeBootId() || `cold-${Date.now()}`;
298
+ };
299
+ window.__tabminalRuntimeAssetKey = getStartupFallbackAssetKey();
300
+
301
+ window.__tabminalResolveRuntimeVersion = (() => {
302
+ let promise = null;
303
+ return () => {
304
+ if (promise) {
305
+ return promise;
306
+ }
307
+ promise = (async () => {
308
+ const controller = (
309
+ typeof AbortController === 'function'
310
+ ? new AbortController()
311
+ : null
312
+ );
313
+ const timeoutId = window.setTimeout(() => {
314
+ if (controller) {
315
+ controller.abort();
316
+ }
317
+ }, runtimeVersionTimeoutMs);
318
+ try {
319
+ const response = await fetch(versionApiUrl, {
320
+ method: 'GET',
321
+ cache: 'no-store',
322
+ credentials: 'same-origin',
323
+ headers: {
324
+ 'accept': 'application/json'
325
+ },
326
+ signal: controller?.signal
327
+ });
328
+ if (!response.ok) {
329
+ throw new Error(`version ${response.status}`);
330
+ }
331
+ const data = await response.json();
332
+ const bootId = String(data?.bootId || '').trim();
333
+ if (!bootId) {
334
+ throw new Error('missing runtime version boot id');
335
+ }
336
+ window.__tabminalRuntimeAssetKey = bootId;
337
+ persistRuntimeBootId(bootId);
338
+ return {
339
+ bootId,
340
+ source: 'api'
341
+ };
342
+ } catch (_err) {
343
+ const bootId = getStartupFallbackAssetKey();
344
+ window.__tabminalRuntimeAssetKey = bootId;
345
+ return {
346
+ bootId,
347
+ source: 'fallback'
348
+ };
349
+ } finally {
350
+ window.clearTimeout(timeoutId);
351
+ }
352
+ })();
353
+ return promise;
354
+ };
355
+ })();
288
356
  })();
289
357
  </script>
290
358
  <script src="https://cdn.jsdelivr.net/npm/monaco-editor@0.44.0/min/vs/loader.js"></script>
@@ -327,6 +395,27 @@
327
395
  <div id="image-preview-container" class="image-preview-container" style="display: none;">
328
396
  <img id="image-preview" src="" alt="Preview">
329
397
  </div>
398
+ <div id="pdf-preview-container" class="pdf-preview-container" style="display: none;">
399
+ <div id="pdf-preview-status" class="pdf-preview-status">
400
+ <span
401
+ id="pdf-preview-status-primary"
402
+ class="pdf-preview-status-primary"
403
+ ></span>
404
+ <span
405
+ id="pdf-preview-status-secondary"
406
+ class="pdf-preview-status-secondary"
407
+ ></span>
408
+ </div>
409
+ <div id="pdf-preview-pages" class="pdf-preview-pages"></div>
410
+ </div>
411
+ <div id="markdown-preview-container" class="markdown-preview-container" style="display: none;">
412
+ <div id="markdown-preview-scroll" class="markdown-preview-scroll">
413
+ <article
414
+ id="markdown-preview-content"
415
+ class="markdown-preview-sheet markdown-body"
416
+ ></article>
417
+ </div>
418
+ </div>
330
419
  <div id="empty-editor-state" class="empty-editor-state">
331
420
  Select a file to view
332
421
  </div>
@@ -565,25 +654,29 @@
565
654
  </div>
566
655
  <script>
567
656
  function getRuntimeAssetKey() {
568
- const runtimeStorageKey = 'tabminal_runtime_boot_id';
569
- try {
570
- const bootId = localStorage.getItem(runtimeStorageKey) || '';
571
- if (bootId) {
572
- return bootId;
573
- }
574
- } catch {
575
- // Fall through to cold key.
576
- }
577
- if (window.__tabminalRuntimeAssetKey) {
578
- return window.__tabminalRuntimeAssetKey;
657
+ const assetKey = window.__tabminalRuntimeAssetKey;
658
+ if (typeof assetKey === 'string' && assetKey) {
659
+ return assetKey;
579
660
  }
580
661
  const coldKey = `cold-${Date.now()}`;
581
662
  window.__tabminalRuntimeAssetKey = coldKey;
582
663
  return coldKey;
583
664
  }
584
665
 
585
- (function() {
586
- const runtimeBootId = getRuntimeAssetKey();
666
+ (async function() {
667
+ const runtimeVersion = (
668
+ window.__tabminalResolveRuntimeVersion
669
+ ? await window.__tabminalResolveRuntimeVersion()
670
+ : getRuntimeAssetKey()
671
+ );
672
+ const runtimeBootId = typeof runtimeVersion === 'string'
673
+ ? runtimeVersion
674
+ : (runtimeVersion?.bootId || getRuntimeAssetKey());
675
+ window.__tabminalRuntimeAssetKey = runtimeBootId;
676
+ const link = document.createElement('link');
677
+ link.rel = 'stylesheet';
678
+ link.href = `./styles.css?v=${encodeURIComponent(runtimeBootId)}`;
679
+ document.head.appendChild(link);
587
680
  const script = document.createElement('script');
588
681
  script.type = 'module';
589
682
  script.src = `./app.js?v=${encodeURIComponent(runtimeBootId)}`;
@@ -592,16 +685,25 @@
592
685
 
593
686
  if ('serviceWorker' in navigator) {
594
687
  window.addEventListener('load', () => {
595
- const runtimeBootId = getRuntimeAssetKey();
596
- navigator.serviceWorker.register(
597
- `/sw.js?rt=${encodeURIComponent(runtimeBootId)}`
598
- )
599
- .then(registration => {
600
- console.log('ServiceWorker registration successful with scope: ', registration.scope);
601
- })
602
- .catch(err => {
603
- console.log('ServiceWorker registration failed: ', err);
604
- });
688
+ (async () => {
689
+ const runtimeVersion = (
690
+ window.__tabminalResolveRuntimeVersion
691
+ ? await window.__tabminalResolveRuntimeVersion()
692
+ : getRuntimeAssetKey()
693
+ );
694
+ const runtimeBootId = typeof runtimeVersion === 'string'
695
+ ? runtimeVersion
696
+ : (runtimeVersion?.bootId || getRuntimeAssetKey());
697
+ navigator.serviceWorker.register(
698
+ `/sw.js?rt=${encodeURIComponent(runtimeBootId)}`
699
+ )
700
+ .then(registration => {
701
+ console.log('ServiceWorker registration successful with scope: ', registration.scope);
702
+ })
703
+ .catch(err => {
704
+ console.log('ServiceWorker registration failed: ', err);
705
+ });
706
+ })();
605
707
  });
606
708
  }
607
709
  </script>
package/public/styles.css CHANGED
@@ -1711,6 +1711,57 @@ kbd {
1711
1711
  border-top: 2px solid var(--accent-color);
1712
1712
  }
1713
1713
 
1714
+ .editor-tab.bound-tab-primary {
1715
+ border-right: 0;
1716
+ }
1717
+
1718
+ .editor-tab.bound-tab-secondary {
1719
+ min-width: 0;
1720
+ padding-left: 10px;
1721
+ padding-right: 12px;
1722
+ }
1723
+
1724
+ .markdown-preview-tab {
1725
+ color: rgba(229, 237, 239, 0.76);
1726
+ }
1727
+
1728
+ .editor-tab.is-split {
1729
+ border-top-color: rgba(38, 139, 210, 0.55);
1730
+ }
1731
+
1732
+ .editor-tab .tab-action-btn {
1733
+ margin-left: 8px;
1734
+ color: rgba(229, 237, 239, 0.72);
1735
+ border-radius: 6px;
1736
+ width: 20px;
1737
+ height: 20px;
1738
+ display: inline-flex;
1739
+ align-items: center;
1740
+ justify-content: center;
1741
+ flex: 0 0 20px;
1742
+ opacity: 0.78;
1743
+ cursor: pointer;
1744
+ }
1745
+
1746
+ .editor-tab:hover .tab-action-btn,
1747
+ .editor-tab.active .tab-action-btn {
1748
+ opacity: 1;
1749
+ }
1750
+
1751
+ .editor-tab .tab-action-btn:hover {
1752
+ background-color: rgba(38, 139, 210, 0.16);
1753
+ color: var(--text-highlight);
1754
+ }
1755
+
1756
+ .markdown-split-btn,
1757
+ .markdown-unsplit-btn {
1758
+ margin-left: auto;
1759
+ }
1760
+
1761
+ .markdown-unsplit-btn + .close-btn {
1762
+ margin-left: 6px;
1763
+ }
1764
+
1714
1765
  .editor-tab .close-btn {
1715
1766
  margin-left: auto;
1716
1767
  font-size: 14px;
@@ -1751,6 +1802,18 @@ kbd {
1751
1802
  position: relative;
1752
1803
  overflow: hidden;
1753
1804
  min-width: 0;
1805
+ min-height: 0;
1806
+ }
1807
+
1808
+ .editor-content.markdown-split-active {
1809
+ position: absolute;
1810
+ inset: 36px 0 0;
1811
+ flex: 1 1 0%;
1812
+ height: auto;
1813
+ min-height: 0;
1814
+ display: flex;
1815
+ align-items: stretch;
1816
+ gap: 0;
1754
1817
  }
1755
1818
 
1756
1819
  .terminal-tab-host {
@@ -2417,6 +2480,7 @@ kbd {
2417
2480
  justify-content: space-between;
2418
2481
  gap: 10px;
2419
2482
  flex-wrap: wrap;
2483
+ min-width: 0;
2420
2484
  }
2421
2485
 
2422
2486
  .agent-tool-call-title,
@@ -2424,12 +2488,18 @@ kbd {
2424
2488
  color: var(--text-highlight);
2425
2489
  font-weight: 600;
2426
2490
  font-size: 12px;
2491
+ min-width: 0;
2492
+ flex: 1 1 auto;
2493
+ overflow-wrap: anywhere;
2494
+ word-break: break-word;
2427
2495
  }
2428
2496
 
2429
2497
  .agent-tool-call-meta {
2430
2498
  color: var(--text-muted);
2431
2499
  font-size: 10px;
2432
2500
  margin-top: 4px;
2501
+ overflow-wrap: anywhere;
2502
+ word-break: break-word;
2433
2503
  }
2434
2504
 
2435
2505
  .agent-path-links {
@@ -2853,10 +2923,28 @@ kbd {
2853
2923
  margin: 0 0 8px;
2854
2924
  }
2855
2925
 
2926
+ .agent-message-body.markdown h1,
2927
+ .agent-message-body.markdown h2,
2928
+ .agent-message-body.markdown h3,
2929
+ .agent-message-body.markdown h4,
2930
+ .agent-message-body.markdown h5,
2931
+ .agent-message-body.markdown h6 {
2932
+ margin: 0 0 10px;
2933
+ color: var(--text-highlight);
2934
+ line-height: 1.35;
2935
+ }
2936
+
2856
2937
  .agent-message-body.markdown ul {
2857
2938
  padding-left: 18px;
2858
2939
  }
2859
2940
 
2941
+ .agent-message-body.markdown blockquote {
2942
+ margin: 0 0 10px;
2943
+ padding: 2px 0 2px 12px;
2944
+ border-left: 3px solid rgba(38, 139, 210, 0.34);
2945
+ color: var(--text-muted);
2946
+ }
2947
+
2860
2948
  .agent-message-body.markdown code {
2861
2949
  font: inherit;
2862
2950
  font-size: 11px;
@@ -2864,6 +2952,8 @@ kbd {
2864
2952
  border: 1px solid rgba(131, 148, 150, 0.18);
2865
2953
  border-radius: 6px;
2866
2954
  padding: 1px 4px;
2955
+ overflow-wrap: anywhere;
2956
+ word-break: break-word;
2867
2957
  }
2868
2958
 
2869
2959
  .agent-message-body.markdown pre {
@@ -2886,6 +2976,52 @@ kbd {
2886
2976
  color: var(--accent-primary);
2887
2977
  text-decoration: underline;
2888
2978
  text-underline-offset: 2px;
2979
+ overflow-wrap: anywhere;
2980
+ word-break: break-word;
2981
+ }
2982
+
2983
+ .agent-message-body.markdown img {
2984
+ display: block;
2985
+ max-width: 100%;
2986
+ height: auto;
2987
+ margin: 0 0 10px;
2988
+ border-radius: 8px;
2989
+ }
2990
+
2991
+ .agent-message-body.markdown table {
2992
+ display: block;
2993
+ width: max-content;
2994
+ max-width: 100%;
2995
+ overflow-x: auto;
2996
+ border-collapse: collapse;
2997
+ margin: 0 0 10px;
2998
+ }
2999
+
3000
+ .agent-message-body.markdown th,
3001
+ .agent-message-body.markdown td {
3002
+ border: 1px solid rgba(131, 148, 150, 0.2);
3003
+ padding: 6px 8px;
3004
+ text-align: left;
3005
+ }
3006
+
3007
+ .agent-message-body.markdown hr {
3008
+ border: 0;
3009
+ border-top: 1px solid rgba(131, 148, 150, 0.18);
3010
+ margin: 10px 0;
3011
+ }
3012
+
3013
+ .agent-message-body.markdown .task-list-item {
3014
+ list-style: none;
3015
+ }
3016
+
3017
+ .agent-message-body.markdown .task-list-item input {
3018
+ margin-right: 8px;
3019
+ }
3020
+
3021
+ .agent-message-body.markdown .katex-display {
3022
+ overflow-x: auto;
3023
+ overflow-y: hidden;
3024
+ margin: 0 0 10px;
2889
3025
  }
2890
3026
 
2891
3027
  .agent-message-attachments {
@@ -3343,6 +3479,16 @@ kbd {
3343
3479
  min-width: 0;
3344
3480
  }
3345
3481
 
3482
+ .editor-content.markdown-split-active > .monaco-container {
3483
+ position: relative;
3484
+ flex: 1 1 0;
3485
+ width: auto;
3486
+ height: 100%;
3487
+ min-width: 0;
3488
+ min-height: 0;
3489
+ border-right: 1px solid rgba(148, 163, 184, 0.14);
3490
+ }
3491
+
3346
3492
  .image-preview-container {
3347
3493
  width: 100%;
3348
3494
  height: 100%;
@@ -3367,6 +3513,240 @@ kbd {
3367
3513
  box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
3368
3514
  }
3369
3515
 
3516
+ .pdf-preview-container {
3517
+ position: absolute;
3518
+ inset: 0;
3519
+ display: flex;
3520
+ flex-direction: column;
3521
+ overflow: hidden;
3522
+ min-height: 0;
3523
+ background:
3524
+ linear-gradient(180deg, rgba(7, 54, 66, 0.98), rgba(0, 36, 46, 0.98));
3525
+ }
3526
+
3527
+ .markdown-preview-container {
3528
+ position: absolute;
3529
+ inset: 0;
3530
+ display: flex;
3531
+ flex-direction: column;
3532
+ overflow: hidden;
3533
+ min-height: 0;
3534
+ background:
3535
+ linear-gradient(180deg, rgba(7, 54, 66, 0.98), rgba(0, 36, 46, 0.98));
3536
+ }
3537
+
3538
+ .editor-content.markdown-split-active > .markdown-preview-container {
3539
+ position: relative;
3540
+ inset: auto;
3541
+ flex: 1 1 0;
3542
+ height: 100%;
3543
+ min-width: 0;
3544
+ min-height: 0;
3545
+ }
3546
+
3547
+ .markdown-preview-scroll {
3548
+ flex: 1;
3549
+ overflow: auto;
3550
+ min-height: 0;
3551
+ padding: 18px;
3552
+ overscroll-behavior: contain;
3553
+ -webkit-overflow-scrolling: touch;
3554
+ touch-action: pan-y pinch-zoom;
3555
+ }
3556
+
3557
+ .markdown-preview-sheet.markdown-body {
3558
+ box-sizing: border-box;
3559
+ width: min(960px, 100%);
3560
+ min-height: 100%;
3561
+ margin: 0 auto;
3562
+ padding: 28px 32px 40px;
3563
+ background: #0d1117;
3564
+ color: #c9d1d9;
3565
+ border: 1px solid rgba(229, 237, 239, 0.08);
3566
+ border-radius: 12px;
3567
+ box-shadow: 0 12px 32px rgba(0, 0, 0, 0.28);
3568
+ }
3569
+
3570
+ .editor-content.markdown-split-active
3571
+ > .markdown-preview-container
3572
+ .markdown-preview-scroll {
3573
+ padding: 14px;
3574
+ }
3575
+
3576
+ .editor-content.markdown-split-active
3577
+ > .markdown-preview-container
3578
+ .markdown-preview-sheet.markdown-body {
3579
+ width: min(100%, 860px);
3580
+ padding: 22px 24px 28px;
3581
+ border-radius: 0;
3582
+ border-top: 0;
3583
+ border-right: 0;
3584
+ border-bottom: 0;
3585
+ box-shadow: none;
3586
+ }
3587
+
3588
+ .markdown-preview-sheet.markdown-body img {
3589
+ max-width: 100%;
3590
+ height: auto;
3591
+ border-radius: 8px;
3592
+ }
3593
+
3594
+ .markdown-preview-sheet.markdown-body pre {
3595
+ overflow: auto;
3596
+ }
3597
+
3598
+ .markdown-preview-sheet.markdown-body .task-list-item {
3599
+ list-style: none;
3600
+ }
3601
+
3602
+ .markdown-preview-sheet.markdown-body .task-list-item input {
3603
+ margin-right: 8px;
3604
+ }
3605
+
3606
+ .markdown-preview-error {
3607
+ color: #fca5a5;
3608
+ font-size: 13px;
3609
+ }
3610
+
3611
+ @media (max-width: 767px) {
3612
+ .markdown-preview-scroll {
3613
+ padding: 12px;
3614
+ }
3615
+
3616
+ .markdown-preview-sheet.markdown-body {
3617
+ padding: 18px 16px 28px;
3618
+ border-radius: 10px;
3619
+ }
3620
+ }
3621
+
3622
+ .pdf-preview-status {
3623
+ padding: 14px 18px;
3624
+ color: var(--text-muted);
3625
+ min-height: 22px;
3626
+ display: flex;
3627
+ align-items: center;
3628
+ justify-content: space-between;
3629
+ gap: 16px;
3630
+ }
3631
+
3632
+ .pdf-preview-status.is-empty {
3633
+ display: none;
3634
+ }
3635
+
3636
+ .pdf-preview-status-primary,
3637
+ .pdf-preview-status-secondary {
3638
+ font-size: 12px;
3639
+ line-height: 1.4;
3640
+ white-space: nowrap;
3641
+ }
3642
+
3643
+ .pdf-preview-status-primary {
3644
+ color: var(--text-muted);
3645
+ font-weight: 600;
3646
+ }
3647
+
3648
+ .pdf-preview-status-secondary {
3649
+ color: rgba(229, 237, 239, 0.68);
3650
+ overflow: hidden;
3651
+ text-overflow: ellipsis;
3652
+ text-align: right;
3653
+ }
3654
+
3655
+ .pdf-preview-pages {
3656
+ flex: 1;
3657
+ overflow: auto;
3658
+ min-height: 0;
3659
+ padding: 16px 18px 18px;
3660
+ display: flex;
3661
+ flex-direction: column;
3662
+ align-items: center;
3663
+ gap: 18px;
3664
+ overscroll-behavior: contain;
3665
+ -webkit-overflow-scrolling: touch;
3666
+ touch-action: pan-y pinch-zoom;
3667
+ }
3668
+
3669
+ .pdf-preview-page {
3670
+ width: 100%;
3671
+ flex: 0 0 auto;
3672
+ display: flex;
3673
+ justify-content: center;
3674
+ }
3675
+
3676
+ .pdf-preview-sheet {
3677
+ position: relative;
3678
+ width: fit-content;
3679
+ max-width: 100%;
3680
+ }
3681
+
3682
+ .pdf-preview-page canvas {
3683
+ width: auto;
3684
+ max-width: 100%;
3685
+ height: auto;
3686
+ display: block;
3687
+ background: #ffffff;
3688
+ box-shadow:
3689
+ 0 12px 32px rgba(0, 0, 0, 0.28),
3690
+ 0 0 0 1px rgba(255, 255, 255, 0.05);
3691
+ }
3692
+
3693
+ .pdf-preview-page .textLayer {
3694
+ position: absolute;
3695
+ text-align: initial;
3696
+ inset: 0;
3697
+ overflow: clip;
3698
+ opacity: 1;
3699
+ line-height: 1;
3700
+ text-size-adjust: none;
3701
+ forced-color-adjust: none;
3702
+ transform-origin: 0 0;
3703
+ caret-color: CanvasText;
3704
+ z-index: 1;
3705
+ user-select: text;
3706
+ -webkit-user-select: text;
3707
+ }
3708
+
3709
+ .pdf-preview-page .textLayer:is(.highlighting) {
3710
+ touch-action: none;
3711
+ }
3712
+
3713
+ .pdf-preview-page .textLayer :is(span, br) {
3714
+ color: transparent;
3715
+ position: absolute;
3716
+ white-space: pre;
3717
+ cursor: text;
3718
+ transform-origin: 0 0;
3719
+ }
3720
+
3721
+ .pdf-preview-page .textLayer {
3722
+ --min-font-size: 1;
3723
+ --text-scale-factor:
3724
+ calc(var(--total-scale-factor) * var(--min-font-size));
3725
+ --min-font-size-inv: calc(1 / var(--min-font-size));
3726
+ }
3727
+
3728
+ .pdf-preview-page .textLayer > :not(.markedContent),
3729
+ .pdf-preview-page .textLayer .markedContent span:not(.markedContent) {
3730
+ z-index: 1;
3731
+ --font-height: 0;
3732
+ font-size: calc(var(--text-scale-factor) * var(--font-height));
3733
+ --scale-x: 1;
3734
+ --rotate: 0deg;
3735
+ transform:
3736
+ rotate(var(--rotate))
3737
+ scaleX(var(--scale-x))
3738
+ scale(var(--min-font-size-inv));
3739
+ }
3740
+
3741
+ .pdf-preview-page .textLayer .markedContent {
3742
+ display: contents;
3743
+ }
3744
+
3745
+ .pdf-preview-page .textLayer span[role="img"] {
3746
+ user-select: none;
3747
+ cursor: default;
3748
+ }
3749
+
3370
3750
  .empty-editor-state {
3371
3751
  width: 100%;
3372
3752
  height: 100%;