@files-preview-app/preview-file 1.3.8 → 1.3.9

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/dist/index.js CHANGED
@@ -1682,19 +1682,85 @@ var FilePreviewViewer = class _FilePreviewViewer {
1682
1682
  if (this.wrapperEl?.parentNode) {
1683
1683
  this.wrapperEl.parentNode.removeChild(this.wrapperEl);
1684
1684
  }
1685
+ if (typeof document !== "undefined" && !document.getElementById("fp-core-injected-styles")) {
1686
+ const styleEl = document.createElement("style");
1687
+ styleEl.id = "fp-core-injected-styles";
1688
+ styleEl.textContent = `
1689
+ .fp-viewer {
1690
+ display: flex !important;
1691
+ flex-direction: column !important;
1692
+ width: 100% !important;
1693
+ height: 100% !important;
1694
+ overflow: hidden !important;
1695
+ position: relative !important;
1696
+ box-sizing: border-box !important;
1697
+ }
1698
+ .fp-body {
1699
+ display: flex !important;
1700
+ flex: 1 1 0% !important;
1701
+ min-height: 0 !important;
1702
+ min-width: 0 !important;
1703
+ width: 100% !important;
1704
+ height: 100% !important;
1705
+ overflow: hidden !important;
1706
+ position: relative !important;
1707
+ box-sizing: border-box !important;
1708
+ }
1709
+ .fp-content {
1710
+ flex: 1 1 0% !important;
1711
+ position: relative !important;
1712
+ overflow: auto !important;
1713
+ display: flex !important;
1714
+ flex-direction: column !important;
1715
+ align-items: stretch !important;
1716
+ justify-content: flex-start !important;
1717
+ width: 100% !important;
1718
+ height: 100% !important;
1719
+ min-width: 0 !important;
1720
+ min-height: 0 !important;
1721
+ box-sizing: border-box !important;
1722
+ }
1723
+ `;
1724
+ document.head.appendChild(styleEl);
1725
+ }
1685
1726
  const themeClass = options.theme === "dark" ? "fp-theme-dark" : "";
1686
1727
  const toolbarPos = options.toolbarPosition ?? "top";
1687
1728
  this.wrapperEl = document.createElement("div");
1688
1729
  this.wrapperEl.className = `fp-viewer ${themeClass} ${options.className ?? ""}`.trim();
1689
1730
  this.wrapperEl.tabIndex = 0;
1731
+ this.wrapperEl.style.display = "flex";
1732
+ this.wrapperEl.style.flexDirection = "column";
1733
+ this.wrapperEl.style.width = "100%";
1734
+ this.wrapperEl.style.height = "100%";
1735
+ this.wrapperEl.style.overflow = "hidden";
1736
+ this.wrapperEl.style.position = "relative";
1690
1737
  const toolbarEl = document.createElement("div");
1691
1738
  toolbarEl.className = "fp-toolbar-container";
1692
1739
  this.contentEl = document.createElement("div");
1693
1740
  this.contentEl.className = "fp-content";
1741
+ this.contentEl.style.flex = "1 1 0%";
1742
+ this.contentEl.style.position = "relative";
1743
+ this.contentEl.style.overflow = "auto";
1744
+ this.contentEl.style.display = "flex";
1745
+ this.contentEl.style.flexDirection = "column";
1746
+ this.contentEl.style.alignItems = "stretch";
1747
+ this.contentEl.style.justifyContent = "flex-start";
1748
+ this.contentEl.style.width = "100%";
1749
+ this.contentEl.style.height = "100%";
1750
+ this.contentEl.style.minWidth = "0";
1751
+ this.contentEl.style.minHeight = "0";
1752
+ this.contentEl.style.boxSizing = "border-box";
1694
1753
  const thumbnailEl = document.createElement("div");
1695
1754
  thumbnailEl.className = "fp-thumbnail-container";
1696
1755
  const bodyEl = document.createElement("div");
1697
1756
  bodyEl.className = "fp-body";
1757
+ bodyEl.style.display = "flex";
1758
+ bodyEl.style.flex = "1 1 0%";
1759
+ bodyEl.style.minHeight = "0";
1760
+ bodyEl.style.minWidth = "0";
1761
+ bodyEl.style.width = "100%";
1762
+ bodyEl.style.overflow = "hidden";
1763
+ bodyEl.style.position = "relative";
1698
1764
  bodyEl.appendChild(thumbnailEl);
1699
1765
  bodyEl.appendChild(this.contentEl);
1700
1766
  const titleBarEl = document.createElement("div");
@@ -4488,31 +4554,80 @@ function csvPlugin() {
4488
4554
  }
4489
4555
  var CODE_EXTENSIONS = [
4490
4556
  ".txt",
4557
+ ".log",
4558
+ ".ini",
4559
+ ".cfg",
4560
+ ".conf",
4561
+ ".env",
4491
4562
  ".json",
4563
+ ".jsonc",
4564
+ ".json5",
4492
4565
  ".js",
4493
- ".ts",
4566
+ ".mjs",
4567
+ ".cjs",
4494
4568
  ".jsx",
4569
+ ".ts",
4570
+ ".mts",
4571
+ ".cts",
4495
4572
  ".tsx",
4496
4573
  ".html",
4574
+ ".htm",
4575
+ ".xhtml",
4497
4576
  ".css",
4498
4577
  ".scss",
4578
+ ".sass",
4499
4579
  ".less",
4500
4580
  ".md",
4581
+ ".markdown",
4501
4582
  ".xml",
4583
+ ".svg",
4584
+ ".xaml",
4502
4585
  ".yml",
4503
4586
  ".yaml",
4587
+ ".toml",
4504
4588
  ".sh",
4505
4589
  ".bash",
4590
+ ".zsh",
4591
+ ".fish",
4592
+ ".bat",
4593
+ ".cmd",
4594
+ ".ps1",
4506
4595
  ".py",
4596
+ ".pyw",
4507
4597
  ".java",
4598
+ ".class",
4508
4599
  ".c",
4509
4600
  ".cpp",
4601
+ ".cc",
4602
+ ".cxx",
4510
4603
  ".h",
4604
+ ".hpp",
4605
+ ".hxx",
4511
4606
  ".cs",
4607
+ ".csx",
4512
4608
  ".go",
4513
4609
  ".rs",
4514
4610
  ".sql",
4515
- ".php"
4611
+ ".php",
4612
+ ".phtml",
4613
+ ".rb",
4614
+ ".swift",
4615
+ ".kt",
4616
+ ".kts",
4617
+ ".scala",
4618
+ ".r",
4619
+ ".lua",
4620
+ ".pl",
4621
+ ".pm",
4622
+ ".dart",
4623
+ ".graphql",
4624
+ ".gql",
4625
+ ".proto",
4626
+ ".diff",
4627
+ ".patch",
4628
+ ".dockerfile",
4629
+ ".properties",
4630
+ ".gradle"
4516
4631
  ];
4517
4632
  var CodePlugin = class {
4518
4633
  id = "code";
@@ -4530,34 +4645,36 @@ var CodePlugin = class {
4530
4645
  getToolbarActions(instance) {
4531
4646
  const totalPages = instance.getPageCount?.() ?? 1;
4532
4647
  const actions = [];
4533
- actions.push({
4534
- id: "thumbnails",
4535
- icon: "thumbnails",
4536
- label: "Page Thumbnails",
4537
- type: "button",
4538
- group: "navigation",
4539
- execute: () => instance.toggleThumbnails?.()
4540
- });
4541
- actions.push({
4542
- id: "page-nav",
4543
- icon: "",
4544
- label: "Page Navigation",
4545
- type: "page-nav",
4546
- group: "navigation",
4547
- value: instance.getCurrentPage?.() ?? 1,
4548
- max: totalPages,
4549
- execute: (action, page) => {
4550
- const cur = instance.getCurrentPage?.() ?? 1;
4551
- const max = instance.getPageCount?.() ?? 1;
4552
- if (action === "prev") {
4553
- if (cur > 1) instance.goToPage?.(cur - 1);
4554
- } else if (action === "next") {
4555
- if (cur < max) instance.goToPage?.(cur + 1);
4556
- } else if (typeof page === "number") {
4557
- instance.goToPage?.(page);
4648
+ if (totalPages > 1) {
4649
+ actions.push({
4650
+ id: "thumbnails",
4651
+ icon: "thumbnails",
4652
+ label: "Page Thumbnails",
4653
+ type: "button",
4654
+ group: "navigation",
4655
+ execute: () => instance.toggleThumbnails?.()
4656
+ });
4657
+ actions.push({
4658
+ id: "page-nav",
4659
+ icon: "",
4660
+ label: "Page Navigation",
4661
+ type: "page-nav",
4662
+ group: "navigation",
4663
+ value: instance.getCurrentPage?.() ?? 1,
4664
+ max: totalPages,
4665
+ execute: (action, page) => {
4666
+ const cur = instance.getCurrentPage?.() ?? 1;
4667
+ const max = instance.getPageCount?.() ?? 1;
4668
+ if (action === "prev") {
4669
+ if (cur > 1) instance.goToPage?.(cur - 1);
4670
+ } else if (action === "next") {
4671
+ if (cur < max) instance.goToPage?.(cur + 1);
4672
+ } else if (typeof page === "number") {
4673
+ instance.goToPage?.(page);
4674
+ }
4558
4675
  }
4559
- }
4560
- });
4676
+ });
4677
+ }
4561
4678
  actions.push(
4562
4679
  {
4563
4680
  id: "zoom-out",
@@ -4694,10 +4811,6 @@ var CodePlugin = class {
4694
4811
  }
4695
4812
  const totalPages = Math.max(1, rawPages.length);
4696
4813
  let currentPage = 1;
4697
- const container = document.createElement("div");
4698
- container.style.width = "100%";
4699
- container.style.height = "100%";
4700
- container.style.overflow = "auto";
4701
4814
  let fontSize = 13;
4702
4815
  let rotation = 0;
4703
4816
  let zoomLevel = 1;
@@ -4706,9 +4819,10 @@ var CodePlugin = class {
4706
4819
  const code = document.createElement("code");
4707
4820
  const sizer = document.createElement("div");
4708
4821
  const scrollWrapper = document.createElement("div");
4822
+ const lineGutter = document.createElement("div");
4823
+ ctx.container.style.overflow = "auto";
4709
4824
  if (isTxt) {
4710
- container.style.overflow = "auto";
4711
- container.style.backgroundColor = "#f1f5f9";
4825
+ ctx.container.style.backgroundColor = "#f1f5f9";
4712
4826
  scrollWrapper.className = "fp-code-scroll-wrapper";
4713
4827
  scrollWrapper.style.minWidth = "100%";
4714
4828
  scrollWrapper.style.minHeight = "100%";
@@ -4743,18 +4857,42 @@ var CodePlugin = class {
4743
4857
  pre.style.transition = "transform 0.15s ease";
4744
4858
  pre.style.flexShrink = "0";
4745
4859
  } else {
4746
- container.style.overflow = "auto";
4747
- container.style.backgroundColor = "#1e1e1e";
4748
- container.style.color = "#d4d4d4";
4749
- container.style.padding = "16px";
4750
- container.style.boxSizing = "border-box";
4860
+ ctx.container.style.backgroundColor = "#1e1e1e";
4861
+ ctx.container.style.color = "#d4d4d4";
4862
+ scrollWrapper.className = "fp-code-scroll-wrapper";
4863
+ scrollWrapper.style.minWidth = "100%";
4864
+ scrollWrapper.style.minHeight = "100%";
4865
+ scrollWrapper.style.width = "max-content";
4866
+ scrollWrapper.style.height = "max-content";
4867
+ scrollWrapper.style.display = "flex";
4868
+ scrollWrapper.style.alignItems = "flex-start";
4869
+ scrollWrapper.style.padding = "16px";
4870
+ scrollWrapper.style.boxSizing = "border-box";
4871
+ const lineCount = fullText.split(/\r?\n/).length || 1;
4872
+ const gutterLines = [];
4873
+ for (let i = 1; i <= lineCount; i++) {
4874
+ gutterLines.push(String(i));
4875
+ }
4876
+ lineGutter.className = "fp-code-gutter";
4877
+ lineGutter.style.userSelect = "none";
4878
+ lineGutter.style.textAlign = "right";
4879
+ lineGutter.style.paddingRight = "16px";
4880
+ lineGutter.style.marginRight = "16px";
4881
+ lineGutter.style.borderRight = "1px solid #333333";
4882
+ lineGutter.style.color = "#858585";
4883
+ lineGutter.style.fontFamily = "Consolas, Menlo, Monaco, 'Courier New', monospace";
4884
+ lineGutter.style.fontSize = `${fontSize}px`;
4885
+ lineGutter.style.lineHeight = "1.6";
4886
+ lineGutter.style.flexShrink = "0";
4887
+ lineGutter.textContent = gutterLines.join("\n");
4751
4888
  pre.style.margin = "0";
4752
- pre.style.fontFamily = "Consolas, Menlo, Monaco, monospace";
4889
+ pre.style.fontFamily = "Consolas, Menlo, Monaco, 'Courier New', monospace";
4753
4890
  pre.style.fontSize = `${fontSize}px`;
4754
- pre.style.lineHeight = "1.5";
4755
- pre.style.whiteSpace = "pre-wrap";
4756
- pre.style.wordBreak = "break-all";
4757
- pre.style.transformOrigin = "top left";
4891
+ pre.style.lineHeight = "1.6";
4892
+ pre.style.whiteSpace = "pre";
4893
+ pre.style.wordBreak = "normal";
4894
+ pre.style.overflowWrap = "normal";
4895
+ pre.style.flex = "1";
4758
4896
  }
4759
4897
  const ext = (ctx.metadata.extension || "").replace(".", "");
4760
4898
  const renderCodePage = (text) => {
@@ -4774,25 +4912,27 @@ var CodePlugin = class {
4774
4912
  };
4775
4913
  renderCodePage(rawPages[0] || (isTxt ? "" : fullText));
4776
4914
  pre.appendChild(code);
4915
+ ctx.container.innerHTML = "";
4777
4916
  if (isTxt) {
4778
4917
  sizer.appendChild(pre);
4779
4918
  scrollWrapper.appendChild(sizer);
4780
- container.appendChild(scrollWrapper);
4919
+ ctx.container.appendChild(scrollWrapper);
4781
4920
  } else {
4782
- container.appendChild(pre);
4921
+ scrollWrapper.appendChild(lineGutter);
4922
+ scrollWrapper.appendChild(pre);
4923
+ ctx.container.appendChild(scrollWrapper);
4783
4924
  }
4784
4925
  const showPage = (pageNum) => {
4785
4926
  currentPage = Math.max(1, Math.min(totalPages, pageNum));
4786
4927
  renderCodePage(rawPages[currentPage - 1] || (isTxt ? "" : fullText));
4787
- container.scrollTop = 0;
4928
+ ctx.container.scrollTop = 0;
4788
4929
  ctx.emit("page-change", { page: currentPage, total: totalPages });
4789
4930
  };
4790
4931
  if (totalPages > 1) {
4791
4932
  showPage(1);
4792
4933
  }
4793
- ctx.container.appendChild(container);
4794
4934
  const calculateTxtFit = () => {
4795
- const availW = Math.max(280, container.clientWidth - 32);
4935
+ const availW = Math.max(280, ctx.container.clientWidth - 32);
4796
4936
  return Math.max(0.4, Math.min(3, availW / 816));
4797
4937
  };
4798
4938
  const updateTransform = () => {
@@ -4810,6 +4950,7 @@ var CodePlugin = class {
4810
4950
  } else {
4811
4951
  pre.style.transform = `rotate(${rotation}deg)`;
4812
4952
  pre.style.fontSize = `${fontSize}px`;
4953
+ lineGutter.style.fontSize = `${fontSize}px`;
4813
4954
  }
4814
4955
  };
4815
4956
  let resizeObserver = null;
@@ -4824,11 +4965,11 @@ var CodePlugin = class {
4824
4965
  updateTransform();
4825
4966
  }
4826
4967
  }) : null;
4827
- resizeObserver?.observe(container);
4968
+ resizeObserver?.observe(ctx.container);
4828
4969
  }
4829
4970
  const cleanup = () => {
4830
4971
  resizeObserver?.disconnect();
4831
- container.remove();
4972
+ scrollWrapper.remove();
4832
4973
  ctx.container.innerHTML = "";
4833
4974
  };
4834
4975
  ctx.signal.addEventListener("abort", cleanup);
@@ -4873,7 +5014,7 @@ var CodePlugin = class {
4873
5014
  if (isTxt) {
4874
5015
  zoomLevel = Math.min(3.5, zoomLevel + 0.15);
4875
5016
  } else {
4876
- fontSize = Math.min(32, fontSize + 2);
5017
+ fontSize = Math.min(48, fontSize + 2);
4877
5018
  }
4878
5019
  updateTransform();
4879
5020
  },
@@ -4882,7 +5023,7 @@ var CodePlugin = class {
4882
5023
  if (isTxt) {
4883
5024
  zoomLevel = Math.max(0.1, zoomLevel - 0.15);
4884
5025
  } else {
4885
- fontSize = Math.max(8, fontSize - 2);
5026
+ fontSize = Math.max(9, fontSize - 2);
4886
5027
  }
4887
5028
  updateTransform();
4888
5029
  },
@@ -4915,8 +5056,8 @@ var CodePlugin = class {
4915
5056
  fontSize = 13;
4916
5057
  rotation = 0;
4917
5058
  zoomLevel = isTxt ? calculateTxtFit() : 1;
4918
- container.scrollTop = 0;
4919
- container.scrollLeft = 0;
5059
+ ctx.container.scrollTop = 0;
5060
+ ctx.container.scrollLeft = 0;
4920
5061
  updateTransform();
4921
5062
  },
4922
5063
  rotateCW: () => {
@@ -5238,7 +5379,7 @@ var MarkdownPlugin = class {
5238
5379
  {
5239
5380
  id: "zoom-out",
5240
5381
  icon: "zoom-out",
5241
- label: "Decrease Font",
5382
+ label: "Zoom Out",
5242
5383
  type: "button",
5243
5384
  group: "zoom",
5244
5385
  execute: () => instance.zoomOut?.()
@@ -5246,19 +5387,11 @@ var MarkdownPlugin = class {
5246
5387
  {
5247
5388
  id: "zoom-in",
5248
5389
  icon: "zoom-in",
5249
- label: "Increase Font",
5390
+ label: "Zoom In",
5250
5391
  type: "button",
5251
5392
  group: "zoom",
5252
5393
  execute: () => instance.zoomIn?.()
5253
5394
  },
5254
- {
5255
- id: "fit-page",
5256
- icon: "fit-page",
5257
- label: "Default Size",
5258
- type: "button",
5259
- group: "zoom",
5260
- execute: () => instance.fitToPage?.()
5261
- },
5262
5395
  {
5263
5396
  id: "reset-zoom",
5264
5397
  icon: "reset-zoom",
@@ -5275,6 +5408,14 @@ var MarkdownPlugin = class {
5275
5408
  group: "zoom",
5276
5409
  execute: () => instance.fitToWidth?.()
5277
5410
  },
5411
+ {
5412
+ id: "fit-page",
5413
+ icon: "fit-page",
5414
+ label: "Fit to Page",
5415
+ type: "button",
5416
+ group: "zoom",
5417
+ execute: () => instance.fitToPage?.()
5418
+ },
5278
5419
  {
5279
5420
  id: "copy",
5280
5421
  icon: "copy",
@@ -5298,6 +5439,14 @@ var MarkdownPlugin = class {
5298
5439
  type: "button",
5299
5440
  group: "actions",
5300
5441
  execute: () => instance.print?.()
5442
+ },
5443
+ {
5444
+ id: "open-window",
5445
+ icon: "open-window",
5446
+ label: "Open in Separate Full Window",
5447
+ type: "button",
5448
+ group: "actions",
5449
+ execute: () => instance.openInSeparateWindow?.()
5301
5450
  }
5302
5451
  ];
5303
5452
  }
@@ -5310,35 +5459,57 @@ var MarkdownPlugin = class {
5310
5459
  const cleanHtml = DOMPurify6.sanitize(rawHtml, {
5311
5460
  USE_PROFILES: { html: true }
5312
5461
  });
5313
- const wrapper = document.createElement("div");
5314
- wrapper.className = "fp-markdown-wrapper";
5315
- wrapper.style.cssText = `
5316
- width: 100%;
5317
- height: 100%;
5318
- overflow: auto;
5319
- padding: 32px 40px;
5462
+ const scrollWrapper = document.createElement("div");
5463
+ scrollWrapper.className = "fp-markdown-scroll-wrapper";
5464
+ scrollWrapper.style.minWidth = "100%";
5465
+ scrollWrapper.style.minHeight = "100%";
5466
+ scrollWrapper.style.width = "max-content";
5467
+ scrollWrapper.style.height = "max-content";
5468
+ scrollWrapper.style.display = "flex";
5469
+ scrollWrapper.style.justifyContent = "center";
5470
+ scrollWrapper.style.alignItems = "flex-start";
5471
+ scrollWrapper.style.padding = "24px 16px";
5472
+ scrollWrapper.style.boxSizing = "border-box";
5473
+ const sizer = document.createElement("div");
5474
+ sizer.className = "fp-markdown-sizer";
5475
+ sizer.style.position = "relative";
5476
+ sizer.style.flexShrink = "0";
5477
+ sizer.style.display = "flex";
5478
+ sizer.style.justifyContent = "center";
5479
+ sizer.style.alignItems = "flex-start";
5480
+ const docCard = document.createElement("div");
5481
+ docCard.className = "fp-markdown-doc-card";
5482
+ docCard.style.cssText = `
5483
+ width: 860px;
5484
+ min-height: 600px;
5485
+ padding: 40px 48px;
5320
5486
  box-sizing: border-box;
5321
5487
  line-height: 1.6;
5322
5488
  font-size: 15px;
5323
5489
  color: var(--fp-text, #24292f);
5324
5490
  background: var(--fp-bg, #ffffff);
5491
+ border-radius: 6px;
5492
+ box-shadow: 0 4px 24px rgba(0, 0, 0, 0.08);
5325
5493
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif;
5494
+ transform-origin: top center;
5495
+ transition: transform 0.15s ease;
5496
+ flex-shrink: 0;
5326
5497
  `;
5327
- wrapper.innerHTML = `
5498
+ docCard.innerHTML = `
5328
5499
  <style>
5329
- .fp-markdown-wrapper h1, .fp-markdown-wrapper h2, .fp-markdown-wrapper h3,
5330
- .fp-markdown-wrapper h4, .fp-markdown-wrapper h5, .fp-markdown-wrapper h6 {
5500
+ .fp-markdown-doc-card h1, .fp-markdown-doc-card h2, .fp-markdown-doc-card h3,
5501
+ .fp-markdown-doc-card h4, .fp-markdown-doc-card h5, .fp-markdown-doc-card h6 {
5331
5502
  margin-top: 24px;
5332
5503
  margin-bottom: 16px;
5333
5504
  font-weight: 600;
5334
5505
  line-height: 1.25;
5335
5506
  color: var(--fp-text, #1f2328);
5336
5507
  }
5337
- .fp-markdown-wrapper h1 { font-size: 2em; padding-bottom: 0.3em; border-bottom: 1px solid var(--fp-border, #d0d7de); }
5338
- .fp-markdown-wrapper h2 { font-size: 1.5em; padding-bottom: 0.3em; border-bottom: 1px solid var(--fp-border, #d0d7de); }
5339
- .fp-markdown-wrapper h3 { font-size: 1.25em; }
5340
- .fp-markdown-wrapper p { margin-top: 0; margin-bottom: 16px; }
5341
- .fp-markdown-wrapper table {
5508
+ .fp-markdown-doc-card h1 { font-size: 2em; padding-bottom: 0.3em; border-bottom: 1px solid var(--fp-border, #d0d7de); }
5509
+ .fp-markdown-doc-card h2 { font-size: 1.5em; padding-bottom: 0.3em; border-bottom: 1px solid var(--fp-border, #d0d7de); }
5510
+ .fp-markdown-doc-card h3 { font-size: 1.25em; }
5511
+ .fp-markdown-doc-card p { margin-top: 0; margin-bottom: 16px; }
5512
+ .fp-markdown-doc-card table {
5342
5513
  border-spacing: 0;
5343
5514
  border-collapse: collapse;
5344
5515
  margin-top: 0;
@@ -5346,20 +5517,20 @@ var MarkdownPlugin = class {
5346
5517
  width: 100%;
5347
5518
  overflow: auto;
5348
5519
  }
5349
- .fp-markdown-wrapper table th, .fp-markdown-wrapper table td {
5520
+ .fp-markdown-doc-card table th, .fp-markdown-doc-card table td {
5350
5521
  padding: 6px 13px;
5351
5522
  border: 1px solid var(--fp-border, #d0d7de);
5352
5523
  }
5353
- .fp-markdown-wrapper table tr:nth-child(2n) {
5524
+ .fp-markdown-doc-card table tr:nth-child(2n) {
5354
5525
  background-color: var(--fp-toolbar-bg, #f6f8fa);
5355
5526
  }
5356
- .fp-markdown-wrapper blockquote {
5527
+ .fp-markdown-doc-card blockquote {
5357
5528
  margin: 0 0 16px 0;
5358
5529
  padding: 0 1em;
5359
5530
  color: var(--fp-text-muted, #59636e);
5360
5531
  border-left: 0.25em solid var(--fp-border, #d0d7de);
5361
5532
  }
5362
- .fp-markdown-wrapper pre {
5533
+ .fp-markdown-doc-card pre {
5363
5534
  padding: 16px;
5364
5535
  overflow: auto;
5365
5536
  font-size: 85%;
@@ -5368,7 +5539,7 @@ var MarkdownPlugin = class {
5368
5539
  border-radius: 6px;
5369
5540
  border: 1px solid var(--fp-border, #d0d7de);
5370
5541
  }
5371
- .fp-markdown-wrapper code {
5542
+ .fp-markdown-doc-card code {
5372
5543
  padding: 0.2em 0.4em;
5373
5544
  margin: 0;
5374
5545
  font-size: 85%;
@@ -5376,16 +5547,16 @@ var MarkdownPlugin = class {
5376
5547
  border-radius: 4px;
5377
5548
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
5378
5549
  }
5379
- .fp-markdown-wrapper pre code {
5550
+ .fp-markdown-doc-card pre code {
5380
5551
  padding: 0;
5381
5552
  background: transparent;
5382
5553
  }
5383
- .fp-markdown-wrapper ul, .fp-markdown-wrapper ol {
5554
+ .fp-markdown-doc-card ul, .fp-markdown-doc-card ol {
5384
5555
  padding-left: 2em;
5385
5556
  margin-top: 0;
5386
5557
  margin-bottom: 16px;
5387
5558
  }
5388
- .fp-markdown-wrapper hr {
5559
+ .fp-markdown-doc-card hr {
5389
5560
  height: 0.25em;
5390
5561
  padding: 0;
5391
5562
  margin: 24px 0;
@@ -5393,50 +5564,95 @@ var MarkdownPlugin = class {
5393
5564
  border: 0;
5394
5565
  }
5395
5566
  </style>
5396
- <div class="fp-markdown-content" style="max-width: 860px; margin: 0 auto;">
5567
+ <div class="fp-markdown-body">
5397
5568
  ${cleanHtml}
5398
5569
  </div>
5399
5570
  `;
5400
- wrapper.querySelectorAll("pre code").forEach((block) => {
5571
+ docCard.querySelectorAll("pre code").forEach((block) => {
5401
5572
  hljs.highlightElement(block);
5402
5573
  });
5574
+ sizer.appendChild(docCard);
5575
+ scrollWrapper.appendChild(sizer);
5403
5576
  ctx.container.innerHTML = "";
5404
5577
  ctx.container.style.overflow = "auto";
5405
- ctx.container.appendChild(wrapper);
5406
- let fontSize = 15;
5578
+ ctx.container.style.backgroundColor = "#f1f5f9";
5579
+ ctx.container.appendChild(scrollWrapper);
5580
+ let scale = 1;
5581
+ let isUserZoomed = false;
5582
+ const calculateFitScale = () => {
5583
+ const availW = Math.max(280, ctx.container.clientWidth - 48);
5584
+ if (availW < 860) {
5585
+ return Math.max(0.35, availW / 860);
5586
+ }
5587
+ return 1;
5588
+ };
5589
+ const applyTransform = () => {
5590
+ const baseW = 860;
5591
+ const baseH = docCard.offsetHeight || 600;
5592
+ const scaledW = Math.round(baseW * scale);
5593
+ const scaledH = Math.round(baseH * scale);
5594
+ sizer.style.width = `${scaledW}px`;
5595
+ sizer.style.height = `${scaledH}px`;
5596
+ docCard.style.width = `${baseW}px`;
5597
+ docCard.style.transform = `scale(${scale})`;
5598
+ docCard.style.transformOrigin = scaledW > ctx.container.clientWidth - 32 ? "top left" : "top center";
5599
+ };
5600
+ const ro = typeof ResizeObserver !== "undefined" ? new ResizeObserver(() => {
5601
+ if (!isUserZoomed) {
5602
+ scale = calculateFitScale();
5603
+ applyTransform();
5604
+ }
5605
+ }) : null;
5606
+ ro?.observe(ctx.container);
5607
+ requestAnimationFrame(() => {
5608
+ if (!isUserZoomed) {
5609
+ scale = calculateFitScale();
5610
+ }
5611
+ applyTransform();
5612
+ });
5407
5613
  const cleanup = () => {
5408
- wrapper.remove();
5614
+ ro?.disconnect();
5615
+ scrollWrapper.remove();
5409
5616
  ctx.container.innerHTML = "";
5410
5617
  };
5411
5618
  ctx.signal.addEventListener("abort", cleanup);
5412
5619
  return {
5413
5620
  destroy: cleanup,
5414
5621
  zoomIn: () => {
5415
- fontSize = Math.min(28, fontSize + 2);
5416
- wrapper.style.fontSize = `${fontSize}px`;
5622
+ isUserZoomed = true;
5623
+ scale = Math.min(3.5, scale + 0.15);
5624
+ applyTransform();
5417
5625
  },
5418
5626
  zoomOut: () => {
5419
- fontSize = Math.max(10, fontSize - 2);
5420
- wrapper.style.fontSize = `${fontSize}px`;
5627
+ isUserZoomed = true;
5628
+ scale = Math.max(0.25, scale - 0.15);
5629
+ applyTransform();
5421
5630
  },
5422
- getZoom: () => fontSize / 15,
5631
+ getZoom: () => scale,
5423
5632
  setZoom: (level) => {
5424
- fontSize = Math.round(15 * level);
5425
- wrapper.style.fontSize = `${fontSize}px`;
5633
+ isUserZoomed = true;
5634
+ scale = level;
5635
+ applyTransform();
5426
5636
  },
5427
5637
  fitToPage: () => {
5428
- fontSize = 15;
5429
- wrapper.style.fontSize = "15px";
5638
+ isUserZoomed = false;
5639
+ scale = calculateFitScale();
5640
+ applyTransform();
5430
5641
  },
5431
5642
  fitToWidth: () => {
5432
- fontSize = 15;
5433
- wrapper.style.fontSize = "15px";
5643
+ isUserZoomed = false;
5644
+ scale = calculateFitScale();
5645
+ applyTransform();
5434
5646
  },
5435
5647
  resetZoom: () => {
5436
- fontSize = 15;
5437
- wrapper.style.fontSize = "15px";
5648
+ isUserZoomed = false;
5649
+ scale = calculateFitScale();
5438
5650
  ctx.container.scrollTop = 0;
5439
5651
  ctx.container.scrollLeft = 0;
5652
+ applyTransform();
5653
+ },
5654
+ openInSeparateWindow: () => {
5655
+ ctx?.openInSeparateWindow?.();
5440
5656
  },
5441
5657
  download: () => {
5442
5658
  downloadFile(ctx.buffer, ctx.metadata.name || "document.md", "text/markdown");
@@ -6752,14 +6968,6 @@ var HtmlPreviewPlugin = class {
6752
6968
  group: "zoom",
6753
6969
  execute: () => instance.zoomIn?.()
6754
6970
  },
6755
- {
6756
- id: "fit-page",
6757
- icon: "fit-page",
6758
- label: "Fit to Page",
6759
- type: "button",
6760
- group: "zoom",
6761
- execute: () => instance.fitToPage?.()
6762
- },
6763
6971
  {
6764
6972
  id: "reset-zoom",
6765
6973
  icon: "reset-zoom",
@@ -6776,6 +6984,14 @@ var HtmlPreviewPlugin = class {
6776
6984
  group: "zoom",
6777
6985
  execute: () => instance.fitToWidth?.()
6778
6986
  },
6987
+ {
6988
+ id: "fit-page",
6989
+ icon: "fit-page",
6990
+ label: "Fit to Page",
6991
+ type: "button",
6992
+ group: "zoom",
6993
+ execute: () => instance.fitToPage?.()
6994
+ },
6779
6995
  {
6780
6996
  id: "copy",
6781
6997
  icon: "copy",
@@ -6799,6 +7015,14 @@ var HtmlPreviewPlugin = class {
6799
7015
  type: "button",
6800
7016
  group: "actions",
6801
7017
  execute: () => instance.print?.()
7018
+ },
7019
+ {
7020
+ id: "open-window",
7021
+ icon: "open-window",
7022
+ label: "Open in Separate Full Window",
7023
+ type: "button",
7024
+ group: "actions",
7025
+ execute: () => instance.openInSeparateWindow?.()
6802
7026
  }
6803
7027
  ];
6804
7028
  }
@@ -6809,27 +7033,39 @@ var HtmlPreviewPlugin = class {
6809
7033
  ADD_TAGS: ["style", "link"],
6810
7034
  ADD_ATTR: ["target", "rel"]
6811
7035
  });
7036
+ const scrollWrapper = document.createElement("div");
7037
+ scrollWrapper.className = "fp-html-scroll-wrapper";
7038
+ scrollWrapper.style.minWidth = "100%";
7039
+ scrollWrapper.style.minHeight = "100%";
7040
+ scrollWrapper.style.width = "max-content";
7041
+ scrollWrapper.style.height = "max-content";
7042
+ scrollWrapper.style.display = "flex";
7043
+ scrollWrapper.style.justifyContent = "flex-start";
7044
+ scrollWrapper.style.alignItems = "flex-start";
7045
+ scrollWrapper.style.boxSizing = "border-box";
6812
7046
  const sizer = document.createElement("div");
6813
7047
  sizer.className = "fp-html-sizer";
6814
7048
  sizer.style.position = "relative";
7049
+ sizer.style.flexShrink = "0";
6815
7050
  const iframe = document.createElement("iframe");
6816
7051
  iframe.className = "fp-html-iframe";
6817
7052
  iframe.style.border = "none";
6818
7053
  iframe.style.backgroundColor = "#ffffff";
6819
7054
  iframe.style.transformOrigin = "top left";
6820
- iframe.style.transition = "transform 0.2s ease";
7055
+ iframe.style.transition = "transform 0.15s ease";
6821
7056
  iframe.sandbox.add("allow-same-origin");
6822
7057
  sizer.appendChild(iframe);
7058
+ scrollWrapper.appendChild(sizer);
6823
7059
  ctx.container.style.overflow = "auto";
6824
7060
  ctx.container.style.width = "100%";
6825
7061
  ctx.container.style.height = "100%";
6826
7062
  ctx.container.innerHTML = "";
6827
- ctx.container.appendChild(sizer);
7063
+ ctx.container.appendChild(scrollWrapper);
6828
7064
  iframe.srcdoc = sanitized;
6829
7065
  let scale = 1;
7066
+ let baseW = Math.max(600, ctx.container.clientWidth || 800);
7067
+ let baseH = Math.max(400, ctx.container.clientHeight || 600);
6830
7068
  const applyTransform = () => {
6831
- const baseW = Math.max(600, ctx.container.clientWidth || 800);
6832
- const baseH = Math.max(400, ctx.container.clientHeight || 600);
6833
7069
  const scaledW = Math.round(baseW * scale);
6834
7070
  const scaledH = Math.round(baseH * scale);
6835
7071
  sizer.style.width = `${scaledW}px`;
@@ -6842,22 +7078,33 @@ var HtmlPreviewPlugin = class {
6842
7078
  iframe.style.transform = `scale(${scale})`;
6843
7079
  iframe.style.transformOrigin = "top left";
6844
7080
  };
7081
+ const ro = typeof ResizeObserver !== "undefined" ? new ResizeObserver(() => {
7082
+ if (Math.abs(scale - 1) < 0.05) {
7083
+ baseW = Math.max(600, ctx.container.clientWidth || 800);
7084
+ baseH = Math.max(400, ctx.container.clientHeight || 600);
7085
+ applyTransform();
7086
+ }
7087
+ }) : null;
7088
+ ro?.observe(ctx.container);
6845
7089
  requestAnimationFrame(() => {
7090
+ baseW = Math.max(600, ctx.container.clientWidth || 800);
7091
+ baseH = Math.max(400, ctx.container.clientHeight || 600);
6846
7092
  applyTransform();
6847
7093
  });
6848
7094
  const cleanup = () => {
6849
- sizer.remove();
7095
+ ro?.disconnect();
7096
+ scrollWrapper.remove();
6850
7097
  ctx.container.innerHTML = "";
6851
7098
  };
6852
7099
  ctx.signal.addEventListener("abort", cleanup);
6853
7100
  return {
6854
7101
  destroy: cleanup,
6855
7102
  zoomIn: () => {
6856
- scale += 0.1;
7103
+ scale = Math.min(3.5, scale + 0.15);
6857
7104
  applyTransform();
6858
7105
  },
6859
7106
  zoomOut: () => {
6860
- scale = Math.max(0.2, scale - 0.1);
7107
+ scale = Math.max(0.25, scale - 0.15);
6861
7108
  applyTransform();
6862
7109
  },
6863
7110
  getZoom: () => scale,
@@ -6879,8 +7126,11 @@ var HtmlPreviewPlugin = class {
6879
7126
  ctx.container.scrollLeft = 0;
6880
7127
  applyTransform();
6881
7128
  },
7129
+ openInSeparateWindow: () => {
7130
+ ctx?.openInSeparateWindow?.();
7131
+ },
6882
7132
  copy: () => {
6883
- navigator.clipboard.writeText(rawHtml);
7133
+ navigator.clipboard?.writeText(rawHtml);
6884
7134
  },
6885
7135
  download: () => {
6886
7136
  const blob = new Blob([ctx.buffer], { type: "text/html" });