tabminal 3.0.13 → 3.0.14

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 {
@@ -3343,6 +3406,16 @@ kbd {
3343
3406
  min-width: 0;
3344
3407
  }
3345
3408
 
3409
+ .editor-content.markdown-split-active > .monaco-container {
3410
+ position: relative;
3411
+ flex: 1 1 0;
3412
+ width: auto;
3413
+ height: 100%;
3414
+ min-width: 0;
3415
+ min-height: 0;
3416
+ border-right: 1px solid rgba(148, 163, 184, 0.14);
3417
+ }
3418
+
3346
3419
  .image-preview-container {
3347
3420
  width: 100%;
3348
3421
  height: 100%;
@@ -3367,6 +3440,240 @@ kbd {
3367
3440
  box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
3368
3441
  }
3369
3442
 
3443
+ .pdf-preview-container {
3444
+ position: absolute;
3445
+ inset: 0;
3446
+ display: flex;
3447
+ flex-direction: column;
3448
+ overflow: hidden;
3449
+ min-height: 0;
3450
+ background:
3451
+ linear-gradient(180deg, rgba(7, 54, 66, 0.98), rgba(0, 36, 46, 0.98));
3452
+ }
3453
+
3454
+ .markdown-preview-container {
3455
+ position: absolute;
3456
+ inset: 0;
3457
+ display: flex;
3458
+ flex-direction: column;
3459
+ overflow: hidden;
3460
+ min-height: 0;
3461
+ background:
3462
+ linear-gradient(180deg, rgba(7, 54, 66, 0.98), rgba(0, 36, 46, 0.98));
3463
+ }
3464
+
3465
+ .editor-content.markdown-split-active > .markdown-preview-container {
3466
+ position: relative;
3467
+ inset: auto;
3468
+ flex: 1 1 0;
3469
+ height: 100%;
3470
+ min-width: 0;
3471
+ min-height: 0;
3472
+ }
3473
+
3474
+ .markdown-preview-scroll {
3475
+ flex: 1;
3476
+ overflow: auto;
3477
+ min-height: 0;
3478
+ padding: 18px;
3479
+ overscroll-behavior: contain;
3480
+ -webkit-overflow-scrolling: touch;
3481
+ touch-action: pan-y pinch-zoom;
3482
+ }
3483
+
3484
+ .markdown-preview-sheet.markdown-body {
3485
+ box-sizing: border-box;
3486
+ width: min(960px, 100%);
3487
+ min-height: 100%;
3488
+ margin: 0 auto;
3489
+ padding: 28px 32px 40px;
3490
+ background: #0d1117;
3491
+ color: #c9d1d9;
3492
+ border: 1px solid rgba(229, 237, 239, 0.08);
3493
+ border-radius: 12px;
3494
+ box-shadow: 0 12px 32px rgba(0, 0, 0, 0.28);
3495
+ }
3496
+
3497
+ .editor-content.markdown-split-active
3498
+ > .markdown-preview-container
3499
+ .markdown-preview-scroll {
3500
+ padding: 14px;
3501
+ }
3502
+
3503
+ .editor-content.markdown-split-active
3504
+ > .markdown-preview-container
3505
+ .markdown-preview-sheet.markdown-body {
3506
+ width: min(100%, 860px);
3507
+ padding: 22px 24px 28px;
3508
+ border-radius: 0;
3509
+ border-top: 0;
3510
+ border-right: 0;
3511
+ border-bottom: 0;
3512
+ box-shadow: none;
3513
+ }
3514
+
3515
+ .markdown-preview-sheet.markdown-body img {
3516
+ max-width: 100%;
3517
+ height: auto;
3518
+ border-radius: 8px;
3519
+ }
3520
+
3521
+ .markdown-preview-sheet.markdown-body pre {
3522
+ overflow: auto;
3523
+ }
3524
+
3525
+ .markdown-preview-sheet.markdown-body .task-list-item {
3526
+ list-style: none;
3527
+ }
3528
+
3529
+ .markdown-preview-sheet.markdown-body .task-list-item input {
3530
+ margin-right: 8px;
3531
+ }
3532
+
3533
+ .markdown-preview-error {
3534
+ color: #fca5a5;
3535
+ font-size: 13px;
3536
+ }
3537
+
3538
+ @media (max-width: 767px) {
3539
+ .markdown-preview-scroll {
3540
+ padding: 12px;
3541
+ }
3542
+
3543
+ .markdown-preview-sheet.markdown-body {
3544
+ padding: 18px 16px 28px;
3545
+ border-radius: 10px;
3546
+ }
3547
+ }
3548
+
3549
+ .pdf-preview-status {
3550
+ padding: 14px 18px;
3551
+ color: var(--text-muted);
3552
+ min-height: 22px;
3553
+ display: flex;
3554
+ align-items: center;
3555
+ justify-content: space-between;
3556
+ gap: 16px;
3557
+ }
3558
+
3559
+ .pdf-preview-status.is-empty {
3560
+ display: none;
3561
+ }
3562
+
3563
+ .pdf-preview-status-primary,
3564
+ .pdf-preview-status-secondary {
3565
+ font-size: 12px;
3566
+ line-height: 1.4;
3567
+ white-space: nowrap;
3568
+ }
3569
+
3570
+ .pdf-preview-status-primary {
3571
+ color: var(--text-muted);
3572
+ font-weight: 600;
3573
+ }
3574
+
3575
+ .pdf-preview-status-secondary {
3576
+ color: rgba(229, 237, 239, 0.68);
3577
+ overflow: hidden;
3578
+ text-overflow: ellipsis;
3579
+ text-align: right;
3580
+ }
3581
+
3582
+ .pdf-preview-pages {
3583
+ flex: 1;
3584
+ overflow: auto;
3585
+ min-height: 0;
3586
+ padding: 16px 18px 18px;
3587
+ display: flex;
3588
+ flex-direction: column;
3589
+ align-items: center;
3590
+ gap: 18px;
3591
+ overscroll-behavior: contain;
3592
+ -webkit-overflow-scrolling: touch;
3593
+ touch-action: pan-y pinch-zoom;
3594
+ }
3595
+
3596
+ .pdf-preview-page {
3597
+ width: 100%;
3598
+ flex: 0 0 auto;
3599
+ display: flex;
3600
+ justify-content: center;
3601
+ }
3602
+
3603
+ .pdf-preview-sheet {
3604
+ position: relative;
3605
+ width: fit-content;
3606
+ max-width: 100%;
3607
+ }
3608
+
3609
+ .pdf-preview-page canvas {
3610
+ width: auto;
3611
+ max-width: 100%;
3612
+ height: auto;
3613
+ display: block;
3614
+ background: #ffffff;
3615
+ box-shadow:
3616
+ 0 12px 32px rgba(0, 0, 0, 0.28),
3617
+ 0 0 0 1px rgba(255, 255, 255, 0.05);
3618
+ }
3619
+
3620
+ .pdf-preview-page .textLayer {
3621
+ position: absolute;
3622
+ text-align: initial;
3623
+ inset: 0;
3624
+ overflow: clip;
3625
+ opacity: 1;
3626
+ line-height: 1;
3627
+ text-size-adjust: none;
3628
+ forced-color-adjust: none;
3629
+ transform-origin: 0 0;
3630
+ caret-color: CanvasText;
3631
+ z-index: 1;
3632
+ user-select: text;
3633
+ -webkit-user-select: text;
3634
+ }
3635
+
3636
+ .pdf-preview-page .textLayer:is(.highlighting) {
3637
+ touch-action: none;
3638
+ }
3639
+
3640
+ .pdf-preview-page .textLayer :is(span, br) {
3641
+ color: transparent;
3642
+ position: absolute;
3643
+ white-space: pre;
3644
+ cursor: text;
3645
+ transform-origin: 0 0;
3646
+ }
3647
+
3648
+ .pdf-preview-page .textLayer {
3649
+ --min-font-size: 1;
3650
+ --text-scale-factor:
3651
+ calc(var(--total-scale-factor) * var(--min-font-size));
3652
+ --min-font-size-inv: calc(1 / var(--min-font-size));
3653
+ }
3654
+
3655
+ .pdf-preview-page .textLayer > :not(.markedContent),
3656
+ .pdf-preview-page .textLayer .markedContent span:not(.markedContent) {
3657
+ z-index: 1;
3658
+ --font-height: 0;
3659
+ font-size: calc(var(--text-scale-factor) * var(--font-height));
3660
+ --scale-x: 1;
3661
+ --rotate: 0deg;
3662
+ transform:
3663
+ rotate(var(--rotate))
3664
+ scaleX(var(--scale-x))
3665
+ scale(var(--min-font-size-inv));
3666
+ }
3667
+
3668
+ .pdf-preview-page .textLayer .markedContent {
3669
+ display: contents;
3670
+ }
3671
+
3672
+ .pdf-preview-page .textLayer span[role="img"] {
3673
+ user-select: none;
3674
+ cursor: default;
3675
+ }
3676
+
3370
3677
  .empty-editor-state {
3371
3678
  width: 100%;
3372
3679
  height: 100%;