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

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,88 @@ 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
+ if (typeof document !== "undefined" && !document.getElementById("fp-code-syntax-styles")) {
4892
+ const style = document.createElement("style");
4893
+ style.id = "fp-code-syntax-styles";
4894
+ style.textContent = `
4895
+ .fp-code-scroll-wrapper .hljs-keyword { color: #569cd6; font-weight: normal; }
4896
+ .fp-code-scroll-wrapper .hljs-built_in { color: #4ec9b0; }
4897
+ .fp-code-scroll-wrapper .hljs-type { color: #4ec9b0; }
4898
+ .fp-code-scroll-wrapper .hljs-literal { color: #569cd6; }
4899
+ .fp-code-scroll-wrapper .hljs-number { color: #b5cea8; }
4900
+ .fp-code-scroll-wrapper .hljs-regexp { color: #d16969; }
4901
+ .fp-code-scroll-wrapper .hljs-string { color: #ce9178; }
4902
+ .fp-code-scroll-wrapper .hljs-subst { color: #d4d4d4; }
4903
+ .fp-code-scroll-wrapper .hljs-symbol { color: #569cd6; }
4904
+ .fp-code-scroll-wrapper .hljs-class { color: #4ec9b0; }
4905
+ .fp-code-scroll-wrapper .hljs-function { color: #dcdcaa; }
4906
+ .fp-code-scroll-wrapper .hljs-title { color: #dcdcaa; }
4907
+ .fp-code-scroll-wrapper .hljs-params { color: #9cdcfe; }
4908
+ .fp-code-scroll-wrapper .hljs-comment { color: #6a9955; font-style: italic; }
4909
+ .fp-code-scroll-wrapper .hljs-doctag { color: #608b4e; }
4910
+ .fp-code-scroll-wrapper .hljs-meta { color: #9cdcfe; }
4911
+ .fp-code-scroll-wrapper .hljs-section { color: #569cd6; }
4912
+ .fp-code-scroll-wrapper .hljs-tag { color: #569cd6; }
4913
+ .fp-code-scroll-wrapper .hljs-name { color: #569cd6; }
4914
+ .fp-code-scroll-wrapper .hljs-attr { color: #9cdcfe; }
4915
+ .fp-code-scroll-wrapper .hljs-attribute { color: #9cdcfe; }
4916
+ .fp-code-scroll-wrapper .hljs-variable { color: #9cdcfe; }
4917
+ .fp-code-scroll-wrapper .hljs-punctuation { color: #d4d4d4; }
4918
+ `;
4919
+ document.head.appendChild(style);
4920
+ }
4921
+ ctx.container.style.backgroundColor = "#1e1e1e";
4922
+ ctx.container.style.color = "#d4d4d4";
4923
+ scrollWrapper.className = "fp-code-scroll-wrapper";
4924
+ scrollWrapper.style.minWidth = "100%";
4925
+ scrollWrapper.style.minHeight = "100%";
4926
+ scrollWrapper.style.width = "max-content";
4927
+ scrollWrapper.style.height = "max-content";
4928
+ scrollWrapper.style.display = "flex";
4929
+ scrollWrapper.style.alignItems = "flex-start";
4930
+ scrollWrapper.style.padding = "16px 16px 16px 0";
4931
+ scrollWrapper.style.boxSizing = "border-box";
4932
+ const rawLines = fullText.split(/\r?\n/);
4933
+ if (rawLines.length > 1 && rawLines[rawLines.length - 1] === "") {
4934
+ rawLines.pop();
4935
+ }
4936
+ const lineCount = Math.max(1, rawLines.length);
4937
+ const gutterLines = [];
4938
+ for (let i = 1; i <= lineCount; i++) {
4939
+ gutterLines.push(String(i));
4940
+ }
4941
+ lineGutter.className = "fp-code-gutter";
4942
+ lineGutter.style.userSelect = "none";
4943
+ lineGutter.style.textAlign = "right";
4944
+ lineGutter.style.padding = "0 16px";
4945
+ lineGutter.style.margin = "0 16px 0 0";
4946
+ lineGutter.style.borderRight = "1px solid #333333";
4947
+ lineGutter.style.color = "#858585";
4948
+ lineGutter.style.fontFamily = "Consolas, Menlo, Monaco, 'Courier New', monospace";
4949
+ lineGutter.style.fontSize = `${fontSize}px`;
4950
+ lineGutter.style.lineHeight = "1.6";
4951
+ lineGutter.style.whiteSpace = "pre";
4952
+ lineGutter.style.flexShrink = "0";
4953
+ lineGutter.style.position = "sticky";
4954
+ lineGutter.style.left = "0";
4955
+ lineGutter.style.backgroundColor = "#1e1e1e";
4956
+ lineGutter.style.zIndex = "2";
4957
+ lineGutter.style.boxSizing = "border-box";
4958
+ lineGutter.textContent = gutterLines.join("\n");
4782
4959
  pre.style.margin = "0";
4783
- pre.style.fontFamily = "Consolas, Menlo, Monaco, monospace";
4960
+ pre.style.padding = "0 16px 0 0";
4961
+ pre.style.fontFamily = "Consolas, Menlo, Monaco, 'Courier New', monospace";
4784
4962
  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";
4963
+ pre.style.lineHeight = "1.6";
4964
+ pre.style.whiteSpace = "pre";
4965
+ pre.style.wordBreak = "normal";
4966
+ pre.style.overflowWrap = "normal";
4967
+ pre.style.flex = "1";
4968
+ code.style.display = "block";
4969
+ code.style.fontFamily = "inherit";
4970
+ code.style.fontSize = "inherit";
4971
+ code.style.lineHeight = "inherit";
4972
+ code.style.whiteSpace = "inherit";
4789
4973
  }
4790
4974
  const ext = (ctx.metadata.extension || "").replace(".", "");
4791
4975
  const renderCodePage = (text) => {
@@ -4805,25 +4989,27 @@ var CodePlugin = class {
4805
4989
  };
4806
4990
  renderCodePage(rawPages[0] || (isTxt ? "" : fullText));
4807
4991
  pre.appendChild(code);
4992
+ ctx.container.innerHTML = "";
4808
4993
  if (isTxt) {
4809
4994
  sizer.appendChild(pre);
4810
4995
  scrollWrapper.appendChild(sizer);
4811
- container.appendChild(scrollWrapper);
4996
+ ctx.container.appendChild(scrollWrapper);
4812
4997
  } else {
4813
- container.appendChild(pre);
4998
+ scrollWrapper.appendChild(lineGutter);
4999
+ scrollWrapper.appendChild(pre);
5000
+ ctx.container.appendChild(scrollWrapper);
4814
5001
  }
4815
5002
  const showPage = (pageNum) => {
4816
5003
  currentPage = Math.max(1, Math.min(totalPages, pageNum));
4817
5004
  renderCodePage(rawPages[currentPage - 1] || (isTxt ? "" : fullText));
4818
- container.scrollTop = 0;
5005
+ ctx.container.scrollTop = 0;
4819
5006
  ctx.emit("page-change", { page: currentPage, total: totalPages });
4820
5007
  };
4821
5008
  if (totalPages > 1) {
4822
5009
  showPage(1);
4823
5010
  }
4824
- ctx.container.appendChild(container);
4825
5011
  const calculateTxtFit = () => {
4826
- const availW = Math.max(280, container.clientWidth - 32);
5012
+ const availW = Math.max(280, ctx.container.clientWidth - 32);
4827
5013
  return Math.max(0.4, Math.min(3, availW / 816));
4828
5014
  };
4829
5015
  const updateTransform = () => {
@@ -4841,6 +5027,7 @@ var CodePlugin = class {
4841
5027
  } else {
4842
5028
  pre.style.transform = `rotate(${rotation}deg)`;
4843
5029
  pre.style.fontSize = `${fontSize}px`;
5030
+ lineGutter.style.fontSize = `${fontSize}px`;
4844
5031
  }
4845
5032
  };
4846
5033
  let resizeObserver = null;
@@ -4855,11 +5042,11 @@ var CodePlugin = class {
4855
5042
  updateTransform();
4856
5043
  }
4857
5044
  }) : null;
4858
- resizeObserver?.observe(container);
5045
+ resizeObserver?.observe(ctx.container);
4859
5046
  }
4860
5047
  const cleanup = () => {
4861
5048
  resizeObserver?.disconnect();
4862
- container.remove();
5049
+ scrollWrapper.remove();
4863
5050
  ctx.container.innerHTML = "";
4864
5051
  };
4865
5052
  ctx.signal.addEventListener("abort", cleanup);
@@ -4904,7 +5091,7 @@ var CodePlugin = class {
4904
5091
  if (isTxt) {
4905
5092
  zoomLevel = Math.min(3.5, zoomLevel + 0.15);
4906
5093
  } else {
4907
- fontSize = Math.min(32, fontSize + 2);
5094
+ fontSize = Math.min(48, fontSize + 2);
4908
5095
  }
4909
5096
  updateTransform();
4910
5097
  },
@@ -4913,7 +5100,7 @@ var CodePlugin = class {
4913
5100
  if (isTxt) {
4914
5101
  zoomLevel = Math.max(0.1, zoomLevel - 0.15);
4915
5102
  } else {
4916
- fontSize = Math.max(8, fontSize - 2);
5103
+ fontSize = Math.max(9, fontSize - 2);
4917
5104
  }
4918
5105
  updateTransform();
4919
5106
  },
@@ -4946,8 +5133,8 @@ var CodePlugin = class {
4946
5133
  fontSize = 13;
4947
5134
  rotation = 0;
4948
5135
  zoomLevel = isTxt ? calculateTxtFit() : 1;
4949
- container.scrollTop = 0;
4950
- container.scrollLeft = 0;
5136
+ ctx.container.scrollTop = 0;
5137
+ ctx.container.scrollLeft = 0;
4951
5138
  updateTransform();
4952
5139
  },
4953
5140
  rotateCW: () => {
@@ -5269,7 +5456,7 @@ var MarkdownPlugin = class {
5269
5456
  {
5270
5457
  id: "zoom-out",
5271
5458
  icon: "zoom-out",
5272
- label: "Decrease Font",
5459
+ label: "Zoom Out",
5273
5460
  type: "button",
5274
5461
  group: "zoom",
5275
5462
  execute: () => instance.zoomOut?.()
@@ -5277,19 +5464,11 @@ var MarkdownPlugin = class {
5277
5464
  {
5278
5465
  id: "zoom-in",
5279
5466
  icon: "zoom-in",
5280
- label: "Increase Font",
5467
+ label: "Zoom In",
5281
5468
  type: "button",
5282
5469
  group: "zoom",
5283
5470
  execute: () => instance.zoomIn?.()
5284
5471
  },
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
5472
  {
5294
5473
  id: "reset-zoom",
5295
5474
  icon: "reset-zoom",
@@ -5306,6 +5485,14 @@ var MarkdownPlugin = class {
5306
5485
  group: "zoom",
5307
5486
  execute: () => instance.fitToWidth?.()
5308
5487
  },
5488
+ {
5489
+ id: "fit-page",
5490
+ icon: "fit-page",
5491
+ label: "Fit to Page",
5492
+ type: "button",
5493
+ group: "zoom",
5494
+ execute: () => instance.fitToPage?.()
5495
+ },
5309
5496
  {
5310
5497
  id: "copy",
5311
5498
  icon: "copy",
@@ -5329,6 +5516,14 @@ var MarkdownPlugin = class {
5329
5516
  type: "button",
5330
5517
  group: "actions",
5331
5518
  execute: () => instance.print?.()
5519
+ },
5520
+ {
5521
+ id: "open-window",
5522
+ icon: "open-window",
5523
+ label: "Open in Separate Full Window",
5524
+ type: "button",
5525
+ group: "actions",
5526
+ execute: () => instance.openInSeparateWindow?.()
5332
5527
  }
5333
5528
  ];
5334
5529
  }
@@ -5341,35 +5536,57 @@ var MarkdownPlugin = class {
5341
5536
  const cleanHtml = DOMPurify6__default.default.sanitize(rawHtml, {
5342
5537
  USE_PROFILES: { html: true }
5343
5538
  });
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;
5539
+ const scrollWrapper = document.createElement("div");
5540
+ scrollWrapper.className = "fp-markdown-scroll-wrapper";
5541
+ scrollWrapper.style.minWidth = "100%";
5542
+ scrollWrapper.style.minHeight = "100%";
5543
+ scrollWrapper.style.width = "max-content";
5544
+ scrollWrapper.style.height = "max-content";
5545
+ scrollWrapper.style.display = "flex";
5546
+ scrollWrapper.style.justifyContent = "center";
5547
+ scrollWrapper.style.alignItems = "flex-start";
5548
+ scrollWrapper.style.padding = "24px 16px";
5549
+ scrollWrapper.style.boxSizing = "border-box";
5550
+ const sizer = document.createElement("div");
5551
+ sizer.className = "fp-markdown-sizer";
5552
+ sizer.style.position = "relative";
5553
+ sizer.style.flexShrink = "0";
5554
+ sizer.style.display = "flex";
5555
+ sizer.style.justifyContent = "center";
5556
+ sizer.style.alignItems = "flex-start";
5557
+ const docCard = document.createElement("div");
5558
+ docCard.className = "fp-markdown-doc-card";
5559
+ docCard.style.cssText = `
5560
+ width: 860px;
5561
+ min-height: 600px;
5562
+ padding: 40px 48px;
5351
5563
  box-sizing: border-box;
5352
5564
  line-height: 1.6;
5353
5565
  font-size: 15px;
5354
5566
  color: var(--fp-text, #24292f);
5355
5567
  background: var(--fp-bg, #ffffff);
5568
+ border-radius: 6px;
5569
+ box-shadow: 0 4px 24px rgba(0, 0, 0, 0.08);
5356
5570
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif;
5571
+ transform-origin: top center;
5572
+ transition: transform 0.15s ease;
5573
+ flex-shrink: 0;
5357
5574
  `;
5358
- wrapper.innerHTML = `
5575
+ docCard.innerHTML = `
5359
5576
  <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 {
5577
+ .fp-markdown-doc-card h1, .fp-markdown-doc-card h2, .fp-markdown-doc-card h3,
5578
+ .fp-markdown-doc-card h4, .fp-markdown-doc-card h5, .fp-markdown-doc-card h6 {
5362
5579
  margin-top: 24px;
5363
5580
  margin-bottom: 16px;
5364
5581
  font-weight: 600;
5365
5582
  line-height: 1.25;
5366
5583
  color: var(--fp-text, #1f2328);
5367
5584
  }
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 {
5585
+ .fp-markdown-doc-card h1 { font-size: 2em; padding-bottom: 0.3em; border-bottom: 1px solid var(--fp-border, #d0d7de); }
5586
+ .fp-markdown-doc-card h2 { font-size: 1.5em; padding-bottom: 0.3em; border-bottom: 1px solid var(--fp-border, #d0d7de); }
5587
+ .fp-markdown-doc-card h3 { font-size: 1.25em; }
5588
+ .fp-markdown-doc-card p { margin-top: 0; margin-bottom: 16px; }
5589
+ .fp-markdown-doc-card table {
5373
5590
  border-spacing: 0;
5374
5591
  border-collapse: collapse;
5375
5592
  margin-top: 0;
@@ -5377,20 +5594,20 @@ var MarkdownPlugin = class {
5377
5594
  width: 100%;
5378
5595
  overflow: auto;
5379
5596
  }
5380
- .fp-markdown-wrapper table th, .fp-markdown-wrapper table td {
5597
+ .fp-markdown-doc-card table th, .fp-markdown-doc-card table td {
5381
5598
  padding: 6px 13px;
5382
5599
  border: 1px solid var(--fp-border, #d0d7de);
5383
5600
  }
5384
- .fp-markdown-wrapper table tr:nth-child(2n) {
5601
+ .fp-markdown-doc-card table tr:nth-child(2n) {
5385
5602
  background-color: var(--fp-toolbar-bg, #f6f8fa);
5386
5603
  }
5387
- .fp-markdown-wrapper blockquote {
5604
+ .fp-markdown-doc-card blockquote {
5388
5605
  margin: 0 0 16px 0;
5389
5606
  padding: 0 1em;
5390
5607
  color: var(--fp-text-muted, #59636e);
5391
5608
  border-left: 0.25em solid var(--fp-border, #d0d7de);
5392
5609
  }
5393
- .fp-markdown-wrapper pre {
5610
+ .fp-markdown-doc-card pre {
5394
5611
  padding: 16px;
5395
5612
  overflow: auto;
5396
5613
  font-size: 85%;
@@ -5399,7 +5616,7 @@ var MarkdownPlugin = class {
5399
5616
  border-radius: 6px;
5400
5617
  border: 1px solid var(--fp-border, #d0d7de);
5401
5618
  }
5402
- .fp-markdown-wrapper code {
5619
+ .fp-markdown-doc-card code {
5403
5620
  padding: 0.2em 0.4em;
5404
5621
  margin: 0;
5405
5622
  font-size: 85%;
@@ -5407,16 +5624,16 @@ var MarkdownPlugin = class {
5407
5624
  border-radius: 4px;
5408
5625
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
5409
5626
  }
5410
- .fp-markdown-wrapper pre code {
5627
+ .fp-markdown-doc-card pre code {
5411
5628
  padding: 0;
5412
5629
  background: transparent;
5413
5630
  }
5414
- .fp-markdown-wrapper ul, .fp-markdown-wrapper ol {
5631
+ .fp-markdown-doc-card ul, .fp-markdown-doc-card ol {
5415
5632
  padding-left: 2em;
5416
5633
  margin-top: 0;
5417
5634
  margin-bottom: 16px;
5418
5635
  }
5419
- .fp-markdown-wrapper hr {
5636
+ .fp-markdown-doc-card hr {
5420
5637
  height: 0.25em;
5421
5638
  padding: 0;
5422
5639
  margin: 24px 0;
@@ -5424,50 +5641,95 @@ var MarkdownPlugin = class {
5424
5641
  border: 0;
5425
5642
  }
5426
5643
  </style>
5427
- <div class="fp-markdown-content" style="max-width: 860px; margin: 0 auto;">
5644
+ <div class="fp-markdown-body">
5428
5645
  ${cleanHtml}
5429
5646
  </div>
5430
5647
  `;
5431
- wrapper.querySelectorAll("pre code").forEach((block) => {
5648
+ docCard.querySelectorAll("pre code").forEach((block) => {
5432
5649
  hljs__default.default.highlightElement(block);
5433
5650
  });
5651
+ sizer.appendChild(docCard);
5652
+ scrollWrapper.appendChild(sizer);
5434
5653
  ctx.container.innerHTML = "";
5435
5654
  ctx.container.style.overflow = "auto";
5436
- ctx.container.appendChild(wrapper);
5437
- let fontSize = 15;
5655
+ ctx.container.style.backgroundColor = "#f1f5f9";
5656
+ ctx.container.appendChild(scrollWrapper);
5657
+ let scale = 1;
5658
+ let isUserZoomed = false;
5659
+ const calculateFitScale = () => {
5660
+ const availW = Math.max(280, ctx.container.clientWidth - 48);
5661
+ if (availW < 860) {
5662
+ return Math.max(0.35, availW / 860);
5663
+ }
5664
+ return 1;
5665
+ };
5666
+ const applyTransform = () => {
5667
+ const baseW = 860;
5668
+ const baseH = docCard.offsetHeight || 600;
5669
+ const scaledW = Math.round(baseW * scale);
5670
+ const scaledH = Math.round(baseH * scale);
5671
+ sizer.style.width = `${scaledW}px`;
5672
+ sizer.style.height = `${scaledH}px`;
5673
+ docCard.style.width = `${baseW}px`;
5674
+ docCard.style.transform = `scale(${scale})`;
5675
+ docCard.style.transformOrigin = scaledW > ctx.container.clientWidth - 32 ? "top left" : "top center";
5676
+ };
5677
+ const ro = typeof ResizeObserver !== "undefined" ? new ResizeObserver(() => {
5678
+ if (!isUserZoomed) {
5679
+ scale = calculateFitScale();
5680
+ applyTransform();
5681
+ }
5682
+ }) : null;
5683
+ ro?.observe(ctx.container);
5684
+ requestAnimationFrame(() => {
5685
+ if (!isUserZoomed) {
5686
+ scale = calculateFitScale();
5687
+ }
5688
+ applyTransform();
5689
+ });
5438
5690
  const cleanup = () => {
5439
- wrapper.remove();
5691
+ ro?.disconnect();
5692
+ scrollWrapper.remove();
5440
5693
  ctx.container.innerHTML = "";
5441
5694
  };
5442
5695
  ctx.signal.addEventListener("abort", cleanup);
5443
5696
  return {
5444
5697
  destroy: cleanup,
5445
5698
  zoomIn: () => {
5446
- fontSize = Math.min(28, fontSize + 2);
5447
- wrapper.style.fontSize = `${fontSize}px`;
5699
+ isUserZoomed = true;
5700
+ scale = Math.min(3.5, scale + 0.15);
5701
+ applyTransform();
5448
5702
  },
5449
5703
  zoomOut: () => {
5450
- fontSize = Math.max(10, fontSize - 2);
5451
- wrapper.style.fontSize = `${fontSize}px`;
5704
+ isUserZoomed = true;
5705
+ scale = Math.max(0.25, scale - 0.15);
5706
+ applyTransform();
5452
5707
  },
5453
- getZoom: () => fontSize / 15,
5708
+ getZoom: () => scale,
5454
5709
  setZoom: (level) => {
5455
- fontSize = Math.round(15 * level);
5456
- wrapper.style.fontSize = `${fontSize}px`;
5710
+ isUserZoomed = true;
5711
+ scale = level;
5712
+ applyTransform();
5457
5713
  },
5458
5714
  fitToPage: () => {
5459
- fontSize = 15;
5460
- wrapper.style.fontSize = "15px";
5715
+ isUserZoomed = false;
5716
+ scale = calculateFitScale();
5717
+ applyTransform();
5461
5718
  },
5462
5719
  fitToWidth: () => {
5463
- fontSize = 15;
5464
- wrapper.style.fontSize = "15px";
5720
+ isUserZoomed = false;
5721
+ scale = calculateFitScale();
5722
+ applyTransform();
5465
5723
  },
5466
5724
  resetZoom: () => {
5467
- fontSize = 15;
5468
- wrapper.style.fontSize = "15px";
5725
+ isUserZoomed = false;
5726
+ scale = calculateFitScale();
5469
5727
  ctx.container.scrollTop = 0;
5470
5728
  ctx.container.scrollLeft = 0;
5729
+ applyTransform();
5730
+ },
5731
+ openInSeparateWindow: () => {
5732
+ ctx?.openInSeparateWindow?.();
5471
5733
  },
5472
5734
  download: () => {
5473
5735
  downloadFile(ctx.buffer, ctx.metadata.name || "document.md", "text/markdown");
@@ -6783,14 +7045,6 @@ var HtmlPreviewPlugin = class {
6783
7045
  group: "zoom",
6784
7046
  execute: () => instance.zoomIn?.()
6785
7047
  },
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
7048
  {
6795
7049
  id: "reset-zoom",
6796
7050
  icon: "reset-zoom",
@@ -6807,6 +7061,14 @@ var HtmlPreviewPlugin = class {
6807
7061
  group: "zoom",
6808
7062
  execute: () => instance.fitToWidth?.()
6809
7063
  },
7064
+ {
7065
+ id: "fit-page",
7066
+ icon: "fit-page",
7067
+ label: "Fit to Page",
7068
+ type: "button",
7069
+ group: "zoom",
7070
+ execute: () => instance.fitToPage?.()
7071
+ },
6810
7072
  {
6811
7073
  id: "copy",
6812
7074
  icon: "copy",
@@ -6830,6 +7092,14 @@ var HtmlPreviewPlugin = class {
6830
7092
  type: "button",
6831
7093
  group: "actions",
6832
7094
  execute: () => instance.print?.()
7095
+ },
7096
+ {
7097
+ id: "open-window",
7098
+ icon: "open-window",
7099
+ label: "Open in Separate Full Window",
7100
+ type: "button",
7101
+ group: "actions",
7102
+ execute: () => instance.openInSeparateWindow?.()
6833
7103
  }
6834
7104
  ];
6835
7105
  }
@@ -6840,27 +7110,39 @@ var HtmlPreviewPlugin = class {
6840
7110
  ADD_TAGS: ["style", "link"],
6841
7111
  ADD_ATTR: ["target", "rel"]
6842
7112
  });
7113
+ const scrollWrapper = document.createElement("div");
7114
+ scrollWrapper.className = "fp-html-scroll-wrapper";
7115
+ scrollWrapper.style.minWidth = "100%";
7116
+ scrollWrapper.style.minHeight = "100%";
7117
+ scrollWrapper.style.width = "max-content";
7118
+ scrollWrapper.style.height = "max-content";
7119
+ scrollWrapper.style.display = "flex";
7120
+ scrollWrapper.style.justifyContent = "flex-start";
7121
+ scrollWrapper.style.alignItems = "flex-start";
7122
+ scrollWrapper.style.boxSizing = "border-box";
6843
7123
  const sizer = document.createElement("div");
6844
7124
  sizer.className = "fp-html-sizer";
6845
7125
  sizer.style.position = "relative";
7126
+ sizer.style.flexShrink = "0";
6846
7127
  const iframe = document.createElement("iframe");
6847
7128
  iframe.className = "fp-html-iframe";
6848
7129
  iframe.style.border = "none";
6849
7130
  iframe.style.backgroundColor = "#ffffff";
6850
7131
  iframe.style.transformOrigin = "top left";
6851
- iframe.style.transition = "transform 0.2s ease";
7132
+ iframe.style.transition = "transform 0.15s ease";
6852
7133
  iframe.sandbox.add("allow-same-origin");
6853
7134
  sizer.appendChild(iframe);
7135
+ scrollWrapper.appendChild(sizer);
6854
7136
  ctx.container.style.overflow = "auto";
6855
7137
  ctx.container.style.width = "100%";
6856
7138
  ctx.container.style.height = "100%";
6857
7139
  ctx.container.innerHTML = "";
6858
- ctx.container.appendChild(sizer);
7140
+ ctx.container.appendChild(scrollWrapper);
6859
7141
  iframe.srcdoc = sanitized;
6860
7142
  let scale = 1;
7143
+ let baseW = Math.max(600, ctx.container.clientWidth || 800);
7144
+ let baseH = Math.max(400, ctx.container.clientHeight || 600);
6861
7145
  const applyTransform = () => {
6862
- const baseW = Math.max(600, ctx.container.clientWidth || 800);
6863
- const baseH = Math.max(400, ctx.container.clientHeight || 600);
6864
7146
  const scaledW = Math.round(baseW * scale);
6865
7147
  const scaledH = Math.round(baseH * scale);
6866
7148
  sizer.style.width = `${scaledW}px`;
@@ -6873,22 +7155,33 @@ var HtmlPreviewPlugin = class {
6873
7155
  iframe.style.transform = `scale(${scale})`;
6874
7156
  iframe.style.transformOrigin = "top left";
6875
7157
  };
7158
+ const ro = typeof ResizeObserver !== "undefined" ? new ResizeObserver(() => {
7159
+ if (Math.abs(scale - 1) < 0.05) {
7160
+ baseW = Math.max(600, ctx.container.clientWidth || 800);
7161
+ baseH = Math.max(400, ctx.container.clientHeight || 600);
7162
+ applyTransform();
7163
+ }
7164
+ }) : null;
7165
+ ro?.observe(ctx.container);
6876
7166
  requestAnimationFrame(() => {
7167
+ baseW = Math.max(600, ctx.container.clientWidth || 800);
7168
+ baseH = Math.max(400, ctx.container.clientHeight || 600);
6877
7169
  applyTransform();
6878
7170
  });
6879
7171
  const cleanup = () => {
6880
- sizer.remove();
7172
+ ro?.disconnect();
7173
+ scrollWrapper.remove();
6881
7174
  ctx.container.innerHTML = "";
6882
7175
  };
6883
7176
  ctx.signal.addEventListener("abort", cleanup);
6884
7177
  return {
6885
7178
  destroy: cleanup,
6886
7179
  zoomIn: () => {
6887
- scale += 0.1;
7180
+ scale = Math.min(3.5, scale + 0.15);
6888
7181
  applyTransform();
6889
7182
  },
6890
7183
  zoomOut: () => {
6891
- scale = Math.max(0.2, scale - 0.1);
7184
+ scale = Math.max(0.25, scale - 0.15);
6892
7185
  applyTransform();
6893
7186
  },
6894
7187
  getZoom: () => scale,
@@ -6910,8 +7203,11 @@ var HtmlPreviewPlugin = class {
6910
7203
  ctx.container.scrollLeft = 0;
6911
7204
  applyTransform();
6912
7205
  },
7206
+ openInSeparateWindow: () => {
7207
+ ctx?.openInSeparateWindow?.();
7208
+ },
6913
7209
  copy: () => {
6914
- navigator.clipboard.writeText(rawHtml);
7210
+ navigator.clipboard?.writeText(rawHtml);
6915
7211
  },
6916
7212
  download: () => {
6917
7213
  const blob = new Blob([ctx.buffer], { type: "text/html" });