@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.cjs CHANGED
@@ -1713,19 +1713,85 @@ var FilePreviewViewer = class _FilePreviewViewer {
1713
1713
  if (this.wrapperEl?.parentNode) {
1714
1714
  this.wrapperEl.parentNode.removeChild(this.wrapperEl);
1715
1715
  }
1716
+ if (typeof document !== "undefined" && !document.getElementById("fp-core-injected-styles")) {
1717
+ const styleEl = document.createElement("style");
1718
+ styleEl.id = "fp-core-injected-styles";
1719
+ styleEl.textContent = `
1720
+ .fp-viewer {
1721
+ display: flex !important;
1722
+ flex-direction: column !important;
1723
+ width: 100% !important;
1724
+ height: 100% !important;
1725
+ overflow: hidden !important;
1726
+ position: relative !important;
1727
+ box-sizing: border-box !important;
1728
+ }
1729
+ .fp-body {
1730
+ display: flex !important;
1731
+ flex: 1 1 0% !important;
1732
+ min-height: 0 !important;
1733
+ min-width: 0 !important;
1734
+ width: 100% !important;
1735
+ height: 100% !important;
1736
+ overflow: hidden !important;
1737
+ position: relative !important;
1738
+ box-sizing: border-box !important;
1739
+ }
1740
+ .fp-content {
1741
+ flex: 1 1 0% !important;
1742
+ position: relative !important;
1743
+ overflow: auto !important;
1744
+ display: flex !important;
1745
+ flex-direction: column !important;
1746
+ align-items: stretch !important;
1747
+ justify-content: flex-start !important;
1748
+ width: 100% !important;
1749
+ height: 100% !important;
1750
+ min-width: 0 !important;
1751
+ min-height: 0 !important;
1752
+ box-sizing: border-box !important;
1753
+ }
1754
+ `;
1755
+ document.head.appendChild(styleEl);
1756
+ }
1716
1757
  const themeClass = options.theme === "dark" ? "fp-theme-dark" : "";
1717
1758
  const toolbarPos = options.toolbarPosition ?? "top";
1718
1759
  this.wrapperEl = document.createElement("div");
1719
1760
  this.wrapperEl.className = `fp-viewer ${themeClass} ${options.className ?? ""}`.trim();
1720
1761
  this.wrapperEl.tabIndex = 0;
1762
+ this.wrapperEl.style.display = "flex";
1763
+ this.wrapperEl.style.flexDirection = "column";
1764
+ this.wrapperEl.style.width = "100%";
1765
+ this.wrapperEl.style.height = "100%";
1766
+ this.wrapperEl.style.overflow = "hidden";
1767
+ this.wrapperEl.style.position = "relative";
1721
1768
  const toolbarEl = document.createElement("div");
1722
1769
  toolbarEl.className = "fp-toolbar-container";
1723
1770
  this.contentEl = document.createElement("div");
1724
1771
  this.contentEl.className = "fp-content";
1772
+ this.contentEl.style.flex = "1 1 0%";
1773
+ this.contentEl.style.position = "relative";
1774
+ this.contentEl.style.overflow = "auto";
1775
+ this.contentEl.style.display = "flex";
1776
+ this.contentEl.style.flexDirection = "column";
1777
+ this.contentEl.style.alignItems = "stretch";
1778
+ this.contentEl.style.justifyContent = "flex-start";
1779
+ this.contentEl.style.width = "100%";
1780
+ this.contentEl.style.height = "100%";
1781
+ this.contentEl.style.minWidth = "0";
1782
+ this.contentEl.style.minHeight = "0";
1783
+ this.contentEl.style.boxSizing = "border-box";
1725
1784
  const thumbnailEl = document.createElement("div");
1726
1785
  thumbnailEl.className = "fp-thumbnail-container";
1727
1786
  const bodyEl = document.createElement("div");
1728
1787
  bodyEl.className = "fp-body";
1788
+ bodyEl.style.display = "flex";
1789
+ bodyEl.style.flex = "1 1 0%";
1790
+ bodyEl.style.minHeight = "0";
1791
+ bodyEl.style.minWidth = "0";
1792
+ bodyEl.style.width = "100%";
1793
+ bodyEl.style.overflow = "hidden";
1794
+ bodyEl.style.position = "relative";
1729
1795
  bodyEl.appendChild(thumbnailEl);
1730
1796
  bodyEl.appendChild(this.contentEl);
1731
1797
  const titleBarEl = document.createElement("div");
@@ -4519,31 +4585,80 @@ function csvPlugin() {
4519
4585
  }
4520
4586
  var CODE_EXTENSIONS = [
4521
4587
  ".txt",
4588
+ ".log",
4589
+ ".ini",
4590
+ ".cfg",
4591
+ ".conf",
4592
+ ".env",
4522
4593
  ".json",
4594
+ ".jsonc",
4595
+ ".json5",
4523
4596
  ".js",
4524
- ".ts",
4597
+ ".mjs",
4598
+ ".cjs",
4525
4599
  ".jsx",
4600
+ ".ts",
4601
+ ".mts",
4602
+ ".cts",
4526
4603
  ".tsx",
4527
4604
  ".html",
4605
+ ".htm",
4606
+ ".xhtml",
4528
4607
  ".css",
4529
4608
  ".scss",
4609
+ ".sass",
4530
4610
  ".less",
4531
4611
  ".md",
4612
+ ".markdown",
4532
4613
  ".xml",
4614
+ ".svg",
4615
+ ".xaml",
4533
4616
  ".yml",
4534
4617
  ".yaml",
4618
+ ".toml",
4535
4619
  ".sh",
4536
4620
  ".bash",
4621
+ ".zsh",
4622
+ ".fish",
4623
+ ".bat",
4624
+ ".cmd",
4625
+ ".ps1",
4537
4626
  ".py",
4627
+ ".pyw",
4538
4628
  ".java",
4629
+ ".class",
4539
4630
  ".c",
4540
4631
  ".cpp",
4632
+ ".cc",
4633
+ ".cxx",
4541
4634
  ".h",
4635
+ ".hpp",
4636
+ ".hxx",
4542
4637
  ".cs",
4638
+ ".csx",
4543
4639
  ".go",
4544
4640
  ".rs",
4545
4641
  ".sql",
4546
- ".php"
4642
+ ".php",
4643
+ ".phtml",
4644
+ ".rb",
4645
+ ".swift",
4646
+ ".kt",
4647
+ ".kts",
4648
+ ".scala",
4649
+ ".r",
4650
+ ".lua",
4651
+ ".pl",
4652
+ ".pm",
4653
+ ".dart",
4654
+ ".graphql",
4655
+ ".gql",
4656
+ ".proto",
4657
+ ".diff",
4658
+ ".patch",
4659
+ ".dockerfile",
4660
+ ".properties",
4661
+ ".gradle"
4547
4662
  ];
4548
4663
  var CodePlugin = class {
4549
4664
  id = "code";
@@ -4561,34 +4676,36 @@ var CodePlugin = class {
4561
4676
  getToolbarActions(instance) {
4562
4677
  const totalPages = instance.getPageCount?.() ?? 1;
4563
4678
  const actions = [];
4564
- actions.push({
4565
- id: "thumbnails",
4566
- icon: "thumbnails",
4567
- label: "Page Thumbnails",
4568
- type: "button",
4569
- group: "navigation",
4570
- execute: () => instance.toggleThumbnails?.()
4571
- });
4572
- actions.push({
4573
- id: "page-nav",
4574
- icon: "",
4575
- label: "Page Navigation",
4576
- type: "page-nav",
4577
- group: "navigation",
4578
- value: instance.getCurrentPage?.() ?? 1,
4579
- max: totalPages,
4580
- execute: (action, page) => {
4581
- const cur = instance.getCurrentPage?.() ?? 1;
4582
- const max = instance.getPageCount?.() ?? 1;
4583
- if (action === "prev") {
4584
- if (cur > 1) instance.goToPage?.(cur - 1);
4585
- } else if (action === "next") {
4586
- if (cur < max) instance.goToPage?.(cur + 1);
4587
- } else if (typeof page === "number") {
4588
- instance.goToPage?.(page);
4679
+ if (totalPages > 1) {
4680
+ actions.push({
4681
+ id: "thumbnails",
4682
+ icon: "thumbnails",
4683
+ label: "Page Thumbnails",
4684
+ type: "button",
4685
+ group: "navigation",
4686
+ execute: () => instance.toggleThumbnails?.()
4687
+ });
4688
+ actions.push({
4689
+ id: "page-nav",
4690
+ icon: "",
4691
+ label: "Page Navigation",
4692
+ type: "page-nav",
4693
+ group: "navigation",
4694
+ value: instance.getCurrentPage?.() ?? 1,
4695
+ max: totalPages,
4696
+ execute: (action, page) => {
4697
+ const cur = instance.getCurrentPage?.() ?? 1;
4698
+ const max = instance.getPageCount?.() ?? 1;
4699
+ if (action === "prev") {
4700
+ if (cur > 1) instance.goToPage?.(cur - 1);
4701
+ } else if (action === "next") {
4702
+ if (cur < max) instance.goToPage?.(cur + 1);
4703
+ } else if (typeof page === "number") {
4704
+ instance.goToPage?.(page);
4705
+ }
4589
4706
  }
4590
- }
4591
- });
4707
+ });
4708
+ }
4592
4709
  actions.push(
4593
4710
  {
4594
4711
  id: "zoom-out",
@@ -4725,10 +4842,6 @@ var CodePlugin = class {
4725
4842
  }
4726
4843
  const totalPages = Math.max(1, rawPages.length);
4727
4844
  let currentPage = 1;
4728
- const container = document.createElement("div");
4729
- container.style.width = "100%";
4730
- container.style.height = "100%";
4731
- container.style.overflow = "auto";
4732
4845
  let fontSize = 13;
4733
4846
  let rotation = 0;
4734
4847
  let zoomLevel = 1;
@@ -4737,9 +4850,10 @@ var CodePlugin = class {
4737
4850
  const code = document.createElement("code");
4738
4851
  const sizer = document.createElement("div");
4739
4852
  const scrollWrapper = document.createElement("div");
4853
+ const lineGutter = document.createElement("div");
4854
+ ctx.container.style.overflow = "auto";
4740
4855
  if (isTxt) {
4741
- container.style.overflow = "auto";
4742
- container.style.backgroundColor = "#f1f5f9";
4856
+ ctx.container.style.backgroundColor = "#f1f5f9";
4743
4857
  scrollWrapper.className = "fp-code-scroll-wrapper";
4744
4858
  scrollWrapper.style.minWidth = "100%";
4745
4859
  scrollWrapper.style.minHeight = "100%";
@@ -4774,18 +4888,42 @@ var CodePlugin = class {
4774
4888
  pre.style.transition = "transform 0.15s ease";
4775
4889
  pre.style.flexShrink = "0";
4776
4890
  } else {
4777
- container.style.overflow = "auto";
4778
- container.style.backgroundColor = "#1e1e1e";
4779
- container.style.color = "#d4d4d4";
4780
- container.style.padding = "16px";
4781
- container.style.boxSizing = "border-box";
4891
+ ctx.container.style.backgroundColor = "#1e1e1e";
4892
+ ctx.container.style.color = "#d4d4d4";
4893
+ scrollWrapper.className = "fp-code-scroll-wrapper";
4894
+ scrollWrapper.style.minWidth = "100%";
4895
+ scrollWrapper.style.minHeight = "100%";
4896
+ scrollWrapper.style.width = "max-content";
4897
+ scrollWrapper.style.height = "max-content";
4898
+ scrollWrapper.style.display = "flex";
4899
+ scrollWrapper.style.alignItems = "flex-start";
4900
+ scrollWrapper.style.padding = "16px";
4901
+ scrollWrapper.style.boxSizing = "border-box";
4902
+ const lineCount = fullText.split(/\r?\n/).length || 1;
4903
+ const gutterLines = [];
4904
+ for (let i = 1; i <= lineCount; i++) {
4905
+ gutterLines.push(String(i));
4906
+ }
4907
+ lineGutter.className = "fp-code-gutter";
4908
+ lineGutter.style.userSelect = "none";
4909
+ lineGutter.style.textAlign = "right";
4910
+ lineGutter.style.paddingRight = "16px";
4911
+ lineGutter.style.marginRight = "16px";
4912
+ lineGutter.style.borderRight = "1px solid #333333";
4913
+ lineGutter.style.color = "#858585";
4914
+ lineGutter.style.fontFamily = "Consolas, Menlo, Monaco, 'Courier New', monospace";
4915
+ lineGutter.style.fontSize = `${fontSize}px`;
4916
+ lineGutter.style.lineHeight = "1.6";
4917
+ lineGutter.style.flexShrink = "0";
4918
+ lineGutter.textContent = gutterLines.join("\n");
4782
4919
  pre.style.margin = "0";
4783
- pre.style.fontFamily = "Consolas, Menlo, Monaco, monospace";
4920
+ pre.style.fontFamily = "Consolas, Menlo, Monaco, 'Courier New', monospace";
4784
4921
  pre.style.fontSize = `${fontSize}px`;
4785
- pre.style.lineHeight = "1.5";
4786
- pre.style.whiteSpace = "pre-wrap";
4787
- pre.style.wordBreak = "break-all";
4788
- pre.style.transformOrigin = "top left";
4922
+ pre.style.lineHeight = "1.6";
4923
+ pre.style.whiteSpace = "pre";
4924
+ pre.style.wordBreak = "normal";
4925
+ pre.style.overflowWrap = "normal";
4926
+ pre.style.flex = "1";
4789
4927
  }
4790
4928
  const ext = (ctx.metadata.extension || "").replace(".", "");
4791
4929
  const renderCodePage = (text) => {
@@ -4805,25 +4943,27 @@ var CodePlugin = class {
4805
4943
  };
4806
4944
  renderCodePage(rawPages[0] || (isTxt ? "" : fullText));
4807
4945
  pre.appendChild(code);
4946
+ ctx.container.innerHTML = "";
4808
4947
  if (isTxt) {
4809
4948
  sizer.appendChild(pre);
4810
4949
  scrollWrapper.appendChild(sizer);
4811
- container.appendChild(scrollWrapper);
4950
+ ctx.container.appendChild(scrollWrapper);
4812
4951
  } else {
4813
- container.appendChild(pre);
4952
+ scrollWrapper.appendChild(lineGutter);
4953
+ scrollWrapper.appendChild(pre);
4954
+ ctx.container.appendChild(scrollWrapper);
4814
4955
  }
4815
4956
  const showPage = (pageNum) => {
4816
4957
  currentPage = Math.max(1, Math.min(totalPages, pageNum));
4817
4958
  renderCodePage(rawPages[currentPage - 1] || (isTxt ? "" : fullText));
4818
- container.scrollTop = 0;
4959
+ ctx.container.scrollTop = 0;
4819
4960
  ctx.emit("page-change", { page: currentPage, total: totalPages });
4820
4961
  };
4821
4962
  if (totalPages > 1) {
4822
4963
  showPage(1);
4823
4964
  }
4824
- ctx.container.appendChild(container);
4825
4965
  const calculateTxtFit = () => {
4826
- const availW = Math.max(280, container.clientWidth - 32);
4966
+ const availW = Math.max(280, ctx.container.clientWidth - 32);
4827
4967
  return Math.max(0.4, Math.min(3, availW / 816));
4828
4968
  };
4829
4969
  const updateTransform = () => {
@@ -4841,6 +4981,7 @@ var CodePlugin = class {
4841
4981
  } else {
4842
4982
  pre.style.transform = `rotate(${rotation}deg)`;
4843
4983
  pre.style.fontSize = `${fontSize}px`;
4984
+ lineGutter.style.fontSize = `${fontSize}px`;
4844
4985
  }
4845
4986
  };
4846
4987
  let resizeObserver = null;
@@ -4855,11 +4996,11 @@ var CodePlugin = class {
4855
4996
  updateTransform();
4856
4997
  }
4857
4998
  }) : null;
4858
- resizeObserver?.observe(container);
4999
+ resizeObserver?.observe(ctx.container);
4859
5000
  }
4860
5001
  const cleanup = () => {
4861
5002
  resizeObserver?.disconnect();
4862
- container.remove();
5003
+ scrollWrapper.remove();
4863
5004
  ctx.container.innerHTML = "";
4864
5005
  };
4865
5006
  ctx.signal.addEventListener("abort", cleanup);
@@ -4904,7 +5045,7 @@ var CodePlugin = class {
4904
5045
  if (isTxt) {
4905
5046
  zoomLevel = Math.min(3.5, zoomLevel + 0.15);
4906
5047
  } else {
4907
- fontSize = Math.min(32, fontSize + 2);
5048
+ fontSize = Math.min(48, fontSize + 2);
4908
5049
  }
4909
5050
  updateTransform();
4910
5051
  },
@@ -4913,7 +5054,7 @@ var CodePlugin = class {
4913
5054
  if (isTxt) {
4914
5055
  zoomLevel = Math.max(0.1, zoomLevel - 0.15);
4915
5056
  } else {
4916
- fontSize = Math.max(8, fontSize - 2);
5057
+ fontSize = Math.max(9, fontSize - 2);
4917
5058
  }
4918
5059
  updateTransform();
4919
5060
  },
@@ -4946,8 +5087,8 @@ var CodePlugin = class {
4946
5087
  fontSize = 13;
4947
5088
  rotation = 0;
4948
5089
  zoomLevel = isTxt ? calculateTxtFit() : 1;
4949
- container.scrollTop = 0;
4950
- container.scrollLeft = 0;
5090
+ ctx.container.scrollTop = 0;
5091
+ ctx.container.scrollLeft = 0;
4951
5092
  updateTransform();
4952
5093
  },
4953
5094
  rotateCW: () => {
@@ -5269,7 +5410,7 @@ var MarkdownPlugin = class {
5269
5410
  {
5270
5411
  id: "zoom-out",
5271
5412
  icon: "zoom-out",
5272
- label: "Decrease Font",
5413
+ label: "Zoom Out",
5273
5414
  type: "button",
5274
5415
  group: "zoom",
5275
5416
  execute: () => instance.zoomOut?.()
@@ -5277,19 +5418,11 @@ var MarkdownPlugin = class {
5277
5418
  {
5278
5419
  id: "zoom-in",
5279
5420
  icon: "zoom-in",
5280
- label: "Increase Font",
5421
+ label: "Zoom In",
5281
5422
  type: "button",
5282
5423
  group: "zoom",
5283
5424
  execute: () => instance.zoomIn?.()
5284
5425
  },
5285
- {
5286
- id: "fit-page",
5287
- icon: "fit-page",
5288
- label: "Default Size",
5289
- type: "button",
5290
- group: "zoom",
5291
- execute: () => instance.fitToPage?.()
5292
- },
5293
5426
  {
5294
5427
  id: "reset-zoom",
5295
5428
  icon: "reset-zoom",
@@ -5306,6 +5439,14 @@ var MarkdownPlugin = class {
5306
5439
  group: "zoom",
5307
5440
  execute: () => instance.fitToWidth?.()
5308
5441
  },
5442
+ {
5443
+ id: "fit-page",
5444
+ icon: "fit-page",
5445
+ label: "Fit to Page",
5446
+ type: "button",
5447
+ group: "zoom",
5448
+ execute: () => instance.fitToPage?.()
5449
+ },
5309
5450
  {
5310
5451
  id: "copy",
5311
5452
  icon: "copy",
@@ -5329,6 +5470,14 @@ var MarkdownPlugin = class {
5329
5470
  type: "button",
5330
5471
  group: "actions",
5331
5472
  execute: () => instance.print?.()
5473
+ },
5474
+ {
5475
+ id: "open-window",
5476
+ icon: "open-window",
5477
+ label: "Open in Separate Full Window",
5478
+ type: "button",
5479
+ group: "actions",
5480
+ execute: () => instance.openInSeparateWindow?.()
5332
5481
  }
5333
5482
  ];
5334
5483
  }
@@ -5341,35 +5490,57 @@ var MarkdownPlugin = class {
5341
5490
  const cleanHtml = DOMPurify6__default.default.sanitize(rawHtml, {
5342
5491
  USE_PROFILES: { html: true }
5343
5492
  });
5344
- const wrapper = document.createElement("div");
5345
- wrapper.className = "fp-markdown-wrapper";
5346
- wrapper.style.cssText = `
5347
- width: 100%;
5348
- height: 100%;
5349
- overflow: auto;
5350
- padding: 32px 40px;
5493
+ const scrollWrapper = document.createElement("div");
5494
+ scrollWrapper.className = "fp-markdown-scroll-wrapper";
5495
+ scrollWrapper.style.minWidth = "100%";
5496
+ scrollWrapper.style.minHeight = "100%";
5497
+ scrollWrapper.style.width = "max-content";
5498
+ scrollWrapper.style.height = "max-content";
5499
+ scrollWrapper.style.display = "flex";
5500
+ scrollWrapper.style.justifyContent = "center";
5501
+ scrollWrapper.style.alignItems = "flex-start";
5502
+ scrollWrapper.style.padding = "24px 16px";
5503
+ scrollWrapper.style.boxSizing = "border-box";
5504
+ const sizer = document.createElement("div");
5505
+ sizer.className = "fp-markdown-sizer";
5506
+ sizer.style.position = "relative";
5507
+ sizer.style.flexShrink = "0";
5508
+ sizer.style.display = "flex";
5509
+ sizer.style.justifyContent = "center";
5510
+ sizer.style.alignItems = "flex-start";
5511
+ const docCard = document.createElement("div");
5512
+ docCard.className = "fp-markdown-doc-card";
5513
+ docCard.style.cssText = `
5514
+ width: 860px;
5515
+ min-height: 600px;
5516
+ padding: 40px 48px;
5351
5517
  box-sizing: border-box;
5352
5518
  line-height: 1.6;
5353
5519
  font-size: 15px;
5354
5520
  color: var(--fp-text, #24292f);
5355
5521
  background: var(--fp-bg, #ffffff);
5522
+ border-radius: 6px;
5523
+ box-shadow: 0 4px 24px rgba(0, 0, 0, 0.08);
5356
5524
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif;
5525
+ transform-origin: top center;
5526
+ transition: transform 0.15s ease;
5527
+ flex-shrink: 0;
5357
5528
  `;
5358
- wrapper.innerHTML = `
5529
+ docCard.innerHTML = `
5359
5530
  <style>
5360
- .fp-markdown-wrapper h1, .fp-markdown-wrapper h2, .fp-markdown-wrapper h3,
5361
- .fp-markdown-wrapper h4, .fp-markdown-wrapper h5, .fp-markdown-wrapper h6 {
5531
+ .fp-markdown-doc-card h1, .fp-markdown-doc-card h2, .fp-markdown-doc-card h3,
5532
+ .fp-markdown-doc-card h4, .fp-markdown-doc-card h5, .fp-markdown-doc-card h6 {
5362
5533
  margin-top: 24px;
5363
5534
  margin-bottom: 16px;
5364
5535
  font-weight: 600;
5365
5536
  line-height: 1.25;
5366
5537
  color: var(--fp-text, #1f2328);
5367
5538
  }
5368
- .fp-markdown-wrapper h1 { font-size: 2em; padding-bottom: 0.3em; border-bottom: 1px solid var(--fp-border, #d0d7de); }
5369
- .fp-markdown-wrapper h2 { font-size: 1.5em; padding-bottom: 0.3em; border-bottom: 1px solid var(--fp-border, #d0d7de); }
5370
- .fp-markdown-wrapper h3 { font-size: 1.25em; }
5371
- .fp-markdown-wrapper p { margin-top: 0; margin-bottom: 16px; }
5372
- .fp-markdown-wrapper table {
5539
+ .fp-markdown-doc-card h1 { font-size: 2em; padding-bottom: 0.3em; border-bottom: 1px solid var(--fp-border, #d0d7de); }
5540
+ .fp-markdown-doc-card h2 { font-size: 1.5em; padding-bottom: 0.3em; border-bottom: 1px solid var(--fp-border, #d0d7de); }
5541
+ .fp-markdown-doc-card h3 { font-size: 1.25em; }
5542
+ .fp-markdown-doc-card p { margin-top: 0; margin-bottom: 16px; }
5543
+ .fp-markdown-doc-card table {
5373
5544
  border-spacing: 0;
5374
5545
  border-collapse: collapse;
5375
5546
  margin-top: 0;
@@ -5377,20 +5548,20 @@ var MarkdownPlugin = class {
5377
5548
  width: 100%;
5378
5549
  overflow: auto;
5379
5550
  }
5380
- .fp-markdown-wrapper table th, .fp-markdown-wrapper table td {
5551
+ .fp-markdown-doc-card table th, .fp-markdown-doc-card table td {
5381
5552
  padding: 6px 13px;
5382
5553
  border: 1px solid var(--fp-border, #d0d7de);
5383
5554
  }
5384
- .fp-markdown-wrapper table tr:nth-child(2n) {
5555
+ .fp-markdown-doc-card table tr:nth-child(2n) {
5385
5556
  background-color: var(--fp-toolbar-bg, #f6f8fa);
5386
5557
  }
5387
- .fp-markdown-wrapper blockquote {
5558
+ .fp-markdown-doc-card blockquote {
5388
5559
  margin: 0 0 16px 0;
5389
5560
  padding: 0 1em;
5390
5561
  color: var(--fp-text-muted, #59636e);
5391
5562
  border-left: 0.25em solid var(--fp-border, #d0d7de);
5392
5563
  }
5393
- .fp-markdown-wrapper pre {
5564
+ .fp-markdown-doc-card pre {
5394
5565
  padding: 16px;
5395
5566
  overflow: auto;
5396
5567
  font-size: 85%;
@@ -5399,7 +5570,7 @@ var MarkdownPlugin = class {
5399
5570
  border-radius: 6px;
5400
5571
  border: 1px solid var(--fp-border, #d0d7de);
5401
5572
  }
5402
- .fp-markdown-wrapper code {
5573
+ .fp-markdown-doc-card code {
5403
5574
  padding: 0.2em 0.4em;
5404
5575
  margin: 0;
5405
5576
  font-size: 85%;
@@ -5407,16 +5578,16 @@ var MarkdownPlugin = class {
5407
5578
  border-radius: 4px;
5408
5579
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
5409
5580
  }
5410
- .fp-markdown-wrapper pre code {
5581
+ .fp-markdown-doc-card pre code {
5411
5582
  padding: 0;
5412
5583
  background: transparent;
5413
5584
  }
5414
- .fp-markdown-wrapper ul, .fp-markdown-wrapper ol {
5585
+ .fp-markdown-doc-card ul, .fp-markdown-doc-card ol {
5415
5586
  padding-left: 2em;
5416
5587
  margin-top: 0;
5417
5588
  margin-bottom: 16px;
5418
5589
  }
5419
- .fp-markdown-wrapper hr {
5590
+ .fp-markdown-doc-card hr {
5420
5591
  height: 0.25em;
5421
5592
  padding: 0;
5422
5593
  margin: 24px 0;
@@ -5424,50 +5595,95 @@ var MarkdownPlugin = class {
5424
5595
  border: 0;
5425
5596
  }
5426
5597
  </style>
5427
- <div class="fp-markdown-content" style="max-width: 860px; margin: 0 auto;">
5598
+ <div class="fp-markdown-body">
5428
5599
  ${cleanHtml}
5429
5600
  </div>
5430
5601
  `;
5431
- wrapper.querySelectorAll("pre code").forEach((block) => {
5602
+ docCard.querySelectorAll("pre code").forEach((block) => {
5432
5603
  hljs__default.default.highlightElement(block);
5433
5604
  });
5605
+ sizer.appendChild(docCard);
5606
+ scrollWrapper.appendChild(sizer);
5434
5607
  ctx.container.innerHTML = "";
5435
5608
  ctx.container.style.overflow = "auto";
5436
- ctx.container.appendChild(wrapper);
5437
- let fontSize = 15;
5609
+ ctx.container.style.backgroundColor = "#f1f5f9";
5610
+ ctx.container.appendChild(scrollWrapper);
5611
+ let scale = 1;
5612
+ let isUserZoomed = false;
5613
+ const calculateFitScale = () => {
5614
+ const availW = Math.max(280, ctx.container.clientWidth - 48);
5615
+ if (availW < 860) {
5616
+ return Math.max(0.35, availW / 860);
5617
+ }
5618
+ return 1;
5619
+ };
5620
+ const applyTransform = () => {
5621
+ const baseW = 860;
5622
+ const baseH = docCard.offsetHeight || 600;
5623
+ const scaledW = Math.round(baseW * scale);
5624
+ const scaledH = Math.round(baseH * scale);
5625
+ sizer.style.width = `${scaledW}px`;
5626
+ sizer.style.height = `${scaledH}px`;
5627
+ docCard.style.width = `${baseW}px`;
5628
+ docCard.style.transform = `scale(${scale})`;
5629
+ docCard.style.transformOrigin = scaledW > ctx.container.clientWidth - 32 ? "top left" : "top center";
5630
+ };
5631
+ const ro = typeof ResizeObserver !== "undefined" ? new ResizeObserver(() => {
5632
+ if (!isUserZoomed) {
5633
+ scale = calculateFitScale();
5634
+ applyTransform();
5635
+ }
5636
+ }) : null;
5637
+ ro?.observe(ctx.container);
5638
+ requestAnimationFrame(() => {
5639
+ if (!isUserZoomed) {
5640
+ scale = calculateFitScale();
5641
+ }
5642
+ applyTransform();
5643
+ });
5438
5644
  const cleanup = () => {
5439
- wrapper.remove();
5645
+ ro?.disconnect();
5646
+ scrollWrapper.remove();
5440
5647
  ctx.container.innerHTML = "";
5441
5648
  };
5442
5649
  ctx.signal.addEventListener("abort", cleanup);
5443
5650
  return {
5444
5651
  destroy: cleanup,
5445
5652
  zoomIn: () => {
5446
- fontSize = Math.min(28, fontSize + 2);
5447
- wrapper.style.fontSize = `${fontSize}px`;
5653
+ isUserZoomed = true;
5654
+ scale = Math.min(3.5, scale + 0.15);
5655
+ applyTransform();
5448
5656
  },
5449
5657
  zoomOut: () => {
5450
- fontSize = Math.max(10, fontSize - 2);
5451
- wrapper.style.fontSize = `${fontSize}px`;
5658
+ isUserZoomed = true;
5659
+ scale = Math.max(0.25, scale - 0.15);
5660
+ applyTransform();
5452
5661
  },
5453
- getZoom: () => fontSize / 15,
5662
+ getZoom: () => scale,
5454
5663
  setZoom: (level) => {
5455
- fontSize = Math.round(15 * level);
5456
- wrapper.style.fontSize = `${fontSize}px`;
5664
+ isUserZoomed = true;
5665
+ scale = level;
5666
+ applyTransform();
5457
5667
  },
5458
5668
  fitToPage: () => {
5459
- fontSize = 15;
5460
- wrapper.style.fontSize = "15px";
5669
+ isUserZoomed = false;
5670
+ scale = calculateFitScale();
5671
+ applyTransform();
5461
5672
  },
5462
5673
  fitToWidth: () => {
5463
- fontSize = 15;
5464
- wrapper.style.fontSize = "15px";
5674
+ isUserZoomed = false;
5675
+ scale = calculateFitScale();
5676
+ applyTransform();
5465
5677
  },
5466
5678
  resetZoom: () => {
5467
- fontSize = 15;
5468
- wrapper.style.fontSize = "15px";
5679
+ isUserZoomed = false;
5680
+ scale = calculateFitScale();
5469
5681
  ctx.container.scrollTop = 0;
5470
5682
  ctx.container.scrollLeft = 0;
5683
+ applyTransform();
5684
+ },
5685
+ openInSeparateWindow: () => {
5686
+ ctx?.openInSeparateWindow?.();
5471
5687
  },
5472
5688
  download: () => {
5473
5689
  downloadFile(ctx.buffer, ctx.metadata.name || "document.md", "text/markdown");
@@ -6783,14 +6999,6 @@ var HtmlPreviewPlugin = class {
6783
6999
  group: "zoom",
6784
7000
  execute: () => instance.zoomIn?.()
6785
7001
  },
6786
- {
6787
- id: "fit-page",
6788
- icon: "fit-page",
6789
- label: "Fit to Page",
6790
- type: "button",
6791
- group: "zoom",
6792
- execute: () => instance.fitToPage?.()
6793
- },
6794
7002
  {
6795
7003
  id: "reset-zoom",
6796
7004
  icon: "reset-zoom",
@@ -6807,6 +7015,14 @@ var HtmlPreviewPlugin = class {
6807
7015
  group: "zoom",
6808
7016
  execute: () => instance.fitToWidth?.()
6809
7017
  },
7018
+ {
7019
+ id: "fit-page",
7020
+ icon: "fit-page",
7021
+ label: "Fit to Page",
7022
+ type: "button",
7023
+ group: "zoom",
7024
+ execute: () => instance.fitToPage?.()
7025
+ },
6810
7026
  {
6811
7027
  id: "copy",
6812
7028
  icon: "copy",
@@ -6830,6 +7046,14 @@ var HtmlPreviewPlugin = class {
6830
7046
  type: "button",
6831
7047
  group: "actions",
6832
7048
  execute: () => instance.print?.()
7049
+ },
7050
+ {
7051
+ id: "open-window",
7052
+ icon: "open-window",
7053
+ label: "Open in Separate Full Window",
7054
+ type: "button",
7055
+ group: "actions",
7056
+ execute: () => instance.openInSeparateWindow?.()
6833
7057
  }
6834
7058
  ];
6835
7059
  }
@@ -6840,27 +7064,39 @@ var HtmlPreviewPlugin = class {
6840
7064
  ADD_TAGS: ["style", "link"],
6841
7065
  ADD_ATTR: ["target", "rel"]
6842
7066
  });
7067
+ const scrollWrapper = document.createElement("div");
7068
+ scrollWrapper.className = "fp-html-scroll-wrapper";
7069
+ scrollWrapper.style.minWidth = "100%";
7070
+ scrollWrapper.style.minHeight = "100%";
7071
+ scrollWrapper.style.width = "max-content";
7072
+ scrollWrapper.style.height = "max-content";
7073
+ scrollWrapper.style.display = "flex";
7074
+ scrollWrapper.style.justifyContent = "flex-start";
7075
+ scrollWrapper.style.alignItems = "flex-start";
7076
+ scrollWrapper.style.boxSizing = "border-box";
6843
7077
  const sizer = document.createElement("div");
6844
7078
  sizer.className = "fp-html-sizer";
6845
7079
  sizer.style.position = "relative";
7080
+ sizer.style.flexShrink = "0";
6846
7081
  const iframe = document.createElement("iframe");
6847
7082
  iframe.className = "fp-html-iframe";
6848
7083
  iframe.style.border = "none";
6849
7084
  iframe.style.backgroundColor = "#ffffff";
6850
7085
  iframe.style.transformOrigin = "top left";
6851
- iframe.style.transition = "transform 0.2s ease";
7086
+ iframe.style.transition = "transform 0.15s ease";
6852
7087
  iframe.sandbox.add("allow-same-origin");
6853
7088
  sizer.appendChild(iframe);
7089
+ scrollWrapper.appendChild(sizer);
6854
7090
  ctx.container.style.overflow = "auto";
6855
7091
  ctx.container.style.width = "100%";
6856
7092
  ctx.container.style.height = "100%";
6857
7093
  ctx.container.innerHTML = "";
6858
- ctx.container.appendChild(sizer);
7094
+ ctx.container.appendChild(scrollWrapper);
6859
7095
  iframe.srcdoc = sanitized;
6860
7096
  let scale = 1;
7097
+ let baseW = Math.max(600, ctx.container.clientWidth || 800);
7098
+ let baseH = Math.max(400, ctx.container.clientHeight || 600);
6861
7099
  const applyTransform = () => {
6862
- const baseW = Math.max(600, ctx.container.clientWidth || 800);
6863
- const baseH = Math.max(400, ctx.container.clientHeight || 600);
6864
7100
  const scaledW = Math.round(baseW * scale);
6865
7101
  const scaledH = Math.round(baseH * scale);
6866
7102
  sizer.style.width = `${scaledW}px`;
@@ -6873,22 +7109,33 @@ var HtmlPreviewPlugin = class {
6873
7109
  iframe.style.transform = `scale(${scale})`;
6874
7110
  iframe.style.transformOrigin = "top left";
6875
7111
  };
7112
+ const ro = typeof ResizeObserver !== "undefined" ? new ResizeObserver(() => {
7113
+ if (Math.abs(scale - 1) < 0.05) {
7114
+ baseW = Math.max(600, ctx.container.clientWidth || 800);
7115
+ baseH = Math.max(400, ctx.container.clientHeight || 600);
7116
+ applyTransform();
7117
+ }
7118
+ }) : null;
7119
+ ro?.observe(ctx.container);
6876
7120
  requestAnimationFrame(() => {
7121
+ baseW = Math.max(600, ctx.container.clientWidth || 800);
7122
+ baseH = Math.max(400, ctx.container.clientHeight || 600);
6877
7123
  applyTransform();
6878
7124
  });
6879
7125
  const cleanup = () => {
6880
- sizer.remove();
7126
+ ro?.disconnect();
7127
+ scrollWrapper.remove();
6881
7128
  ctx.container.innerHTML = "";
6882
7129
  };
6883
7130
  ctx.signal.addEventListener("abort", cleanup);
6884
7131
  return {
6885
7132
  destroy: cleanup,
6886
7133
  zoomIn: () => {
6887
- scale += 0.1;
7134
+ scale = Math.min(3.5, scale + 0.15);
6888
7135
  applyTransform();
6889
7136
  },
6890
7137
  zoomOut: () => {
6891
- scale = Math.max(0.2, scale - 0.1);
7138
+ scale = Math.max(0.25, scale - 0.15);
6892
7139
  applyTransform();
6893
7140
  },
6894
7141
  getZoom: () => scale,
@@ -6910,8 +7157,11 @@ var HtmlPreviewPlugin = class {
6910
7157
  ctx.container.scrollLeft = 0;
6911
7158
  applyTransform();
6912
7159
  },
7160
+ openInSeparateWindow: () => {
7161
+ ctx?.openInSeparateWindow?.();
7162
+ },
6913
7163
  copy: () => {
6914
- navigator.clipboard.writeText(rawHtml);
7164
+ navigator.clipboard?.writeText(rawHtml);
6915
7165
  },
6916
7166
  download: () => {
6917
7167
  const blob = new Blob([ctx.buffer], { type: "text/html" });