@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.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,88 @@ 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
+ if (typeof document !== "undefined" && !document.getElementById("fp-code-syntax-styles")) {
4861
+ const style = document.createElement("style");
4862
+ style.id = "fp-code-syntax-styles";
4863
+ style.textContent = `
4864
+ .fp-code-scroll-wrapper .hljs-keyword { color: #569cd6; font-weight: normal; }
4865
+ .fp-code-scroll-wrapper .hljs-built_in { color: #4ec9b0; }
4866
+ .fp-code-scroll-wrapper .hljs-type { color: #4ec9b0; }
4867
+ .fp-code-scroll-wrapper .hljs-literal { color: #569cd6; }
4868
+ .fp-code-scroll-wrapper .hljs-number { color: #b5cea8; }
4869
+ .fp-code-scroll-wrapper .hljs-regexp { color: #d16969; }
4870
+ .fp-code-scroll-wrapper .hljs-string { color: #ce9178; }
4871
+ .fp-code-scroll-wrapper .hljs-subst { color: #d4d4d4; }
4872
+ .fp-code-scroll-wrapper .hljs-symbol { color: #569cd6; }
4873
+ .fp-code-scroll-wrapper .hljs-class { color: #4ec9b0; }
4874
+ .fp-code-scroll-wrapper .hljs-function { color: #dcdcaa; }
4875
+ .fp-code-scroll-wrapper .hljs-title { color: #dcdcaa; }
4876
+ .fp-code-scroll-wrapper .hljs-params { color: #9cdcfe; }
4877
+ .fp-code-scroll-wrapper .hljs-comment { color: #6a9955; font-style: italic; }
4878
+ .fp-code-scroll-wrapper .hljs-doctag { color: #608b4e; }
4879
+ .fp-code-scroll-wrapper .hljs-meta { color: #9cdcfe; }
4880
+ .fp-code-scroll-wrapper .hljs-section { color: #569cd6; }
4881
+ .fp-code-scroll-wrapper .hljs-tag { color: #569cd6; }
4882
+ .fp-code-scroll-wrapper .hljs-name { color: #569cd6; }
4883
+ .fp-code-scroll-wrapper .hljs-attr { color: #9cdcfe; }
4884
+ .fp-code-scroll-wrapper .hljs-attribute { color: #9cdcfe; }
4885
+ .fp-code-scroll-wrapper .hljs-variable { color: #9cdcfe; }
4886
+ .fp-code-scroll-wrapper .hljs-punctuation { color: #d4d4d4; }
4887
+ `;
4888
+ document.head.appendChild(style);
4889
+ }
4890
+ ctx.container.style.backgroundColor = "#1e1e1e";
4891
+ ctx.container.style.color = "#d4d4d4";
4892
+ scrollWrapper.className = "fp-code-scroll-wrapper";
4893
+ scrollWrapper.style.minWidth = "100%";
4894
+ scrollWrapper.style.minHeight = "100%";
4895
+ scrollWrapper.style.width = "max-content";
4896
+ scrollWrapper.style.height = "max-content";
4897
+ scrollWrapper.style.display = "flex";
4898
+ scrollWrapper.style.alignItems = "flex-start";
4899
+ scrollWrapper.style.padding = "16px 16px 16px 0";
4900
+ scrollWrapper.style.boxSizing = "border-box";
4901
+ const rawLines = fullText.split(/\r?\n/);
4902
+ if (rawLines.length > 1 && rawLines[rawLines.length - 1] === "") {
4903
+ rawLines.pop();
4904
+ }
4905
+ const lineCount = Math.max(1, rawLines.length);
4906
+ const gutterLines = [];
4907
+ for (let i = 1; i <= lineCount; i++) {
4908
+ gutterLines.push(String(i));
4909
+ }
4910
+ lineGutter.className = "fp-code-gutter";
4911
+ lineGutter.style.userSelect = "none";
4912
+ lineGutter.style.textAlign = "right";
4913
+ lineGutter.style.padding = "0 16px";
4914
+ lineGutter.style.margin = "0 16px 0 0";
4915
+ lineGutter.style.borderRight = "1px solid #333333";
4916
+ lineGutter.style.color = "#858585";
4917
+ lineGutter.style.fontFamily = "Consolas, Menlo, Monaco, 'Courier New', monospace";
4918
+ lineGutter.style.fontSize = `${fontSize}px`;
4919
+ lineGutter.style.lineHeight = "1.6";
4920
+ lineGutter.style.whiteSpace = "pre";
4921
+ lineGutter.style.flexShrink = "0";
4922
+ lineGutter.style.position = "sticky";
4923
+ lineGutter.style.left = "0";
4924
+ lineGutter.style.backgroundColor = "#1e1e1e";
4925
+ lineGutter.style.zIndex = "2";
4926
+ lineGutter.style.boxSizing = "border-box";
4927
+ lineGutter.textContent = gutterLines.join("\n");
4751
4928
  pre.style.margin = "0";
4752
- pre.style.fontFamily = "Consolas, Menlo, Monaco, monospace";
4929
+ pre.style.padding = "0 16px 0 0";
4930
+ pre.style.fontFamily = "Consolas, Menlo, Monaco, 'Courier New', monospace";
4753
4931
  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";
4932
+ pre.style.lineHeight = "1.6";
4933
+ pre.style.whiteSpace = "pre";
4934
+ pre.style.wordBreak = "normal";
4935
+ pre.style.overflowWrap = "normal";
4936
+ pre.style.flex = "1";
4937
+ code.style.display = "block";
4938
+ code.style.fontFamily = "inherit";
4939
+ code.style.fontSize = "inherit";
4940
+ code.style.lineHeight = "inherit";
4941
+ code.style.whiteSpace = "inherit";
4758
4942
  }
4759
4943
  const ext = (ctx.metadata.extension || "").replace(".", "");
4760
4944
  const renderCodePage = (text) => {
@@ -4774,25 +4958,27 @@ var CodePlugin = class {
4774
4958
  };
4775
4959
  renderCodePage(rawPages[0] || (isTxt ? "" : fullText));
4776
4960
  pre.appendChild(code);
4961
+ ctx.container.innerHTML = "";
4777
4962
  if (isTxt) {
4778
4963
  sizer.appendChild(pre);
4779
4964
  scrollWrapper.appendChild(sizer);
4780
- container.appendChild(scrollWrapper);
4965
+ ctx.container.appendChild(scrollWrapper);
4781
4966
  } else {
4782
- container.appendChild(pre);
4967
+ scrollWrapper.appendChild(lineGutter);
4968
+ scrollWrapper.appendChild(pre);
4969
+ ctx.container.appendChild(scrollWrapper);
4783
4970
  }
4784
4971
  const showPage = (pageNum) => {
4785
4972
  currentPage = Math.max(1, Math.min(totalPages, pageNum));
4786
4973
  renderCodePage(rawPages[currentPage - 1] || (isTxt ? "" : fullText));
4787
- container.scrollTop = 0;
4974
+ ctx.container.scrollTop = 0;
4788
4975
  ctx.emit("page-change", { page: currentPage, total: totalPages });
4789
4976
  };
4790
4977
  if (totalPages > 1) {
4791
4978
  showPage(1);
4792
4979
  }
4793
- ctx.container.appendChild(container);
4794
4980
  const calculateTxtFit = () => {
4795
- const availW = Math.max(280, container.clientWidth - 32);
4981
+ const availW = Math.max(280, ctx.container.clientWidth - 32);
4796
4982
  return Math.max(0.4, Math.min(3, availW / 816));
4797
4983
  };
4798
4984
  const updateTransform = () => {
@@ -4810,6 +4996,7 @@ var CodePlugin = class {
4810
4996
  } else {
4811
4997
  pre.style.transform = `rotate(${rotation}deg)`;
4812
4998
  pre.style.fontSize = `${fontSize}px`;
4999
+ lineGutter.style.fontSize = `${fontSize}px`;
4813
5000
  }
4814
5001
  };
4815
5002
  let resizeObserver = null;
@@ -4824,11 +5011,11 @@ var CodePlugin = class {
4824
5011
  updateTransform();
4825
5012
  }
4826
5013
  }) : null;
4827
- resizeObserver?.observe(container);
5014
+ resizeObserver?.observe(ctx.container);
4828
5015
  }
4829
5016
  const cleanup = () => {
4830
5017
  resizeObserver?.disconnect();
4831
- container.remove();
5018
+ scrollWrapper.remove();
4832
5019
  ctx.container.innerHTML = "";
4833
5020
  };
4834
5021
  ctx.signal.addEventListener("abort", cleanup);
@@ -4873,7 +5060,7 @@ var CodePlugin = class {
4873
5060
  if (isTxt) {
4874
5061
  zoomLevel = Math.min(3.5, zoomLevel + 0.15);
4875
5062
  } else {
4876
- fontSize = Math.min(32, fontSize + 2);
5063
+ fontSize = Math.min(48, fontSize + 2);
4877
5064
  }
4878
5065
  updateTransform();
4879
5066
  },
@@ -4882,7 +5069,7 @@ var CodePlugin = class {
4882
5069
  if (isTxt) {
4883
5070
  zoomLevel = Math.max(0.1, zoomLevel - 0.15);
4884
5071
  } else {
4885
- fontSize = Math.max(8, fontSize - 2);
5072
+ fontSize = Math.max(9, fontSize - 2);
4886
5073
  }
4887
5074
  updateTransform();
4888
5075
  },
@@ -4915,8 +5102,8 @@ var CodePlugin = class {
4915
5102
  fontSize = 13;
4916
5103
  rotation = 0;
4917
5104
  zoomLevel = isTxt ? calculateTxtFit() : 1;
4918
- container.scrollTop = 0;
4919
- container.scrollLeft = 0;
5105
+ ctx.container.scrollTop = 0;
5106
+ ctx.container.scrollLeft = 0;
4920
5107
  updateTransform();
4921
5108
  },
4922
5109
  rotateCW: () => {
@@ -5238,7 +5425,7 @@ var MarkdownPlugin = class {
5238
5425
  {
5239
5426
  id: "zoom-out",
5240
5427
  icon: "zoom-out",
5241
- label: "Decrease Font",
5428
+ label: "Zoom Out",
5242
5429
  type: "button",
5243
5430
  group: "zoom",
5244
5431
  execute: () => instance.zoomOut?.()
@@ -5246,19 +5433,11 @@ var MarkdownPlugin = class {
5246
5433
  {
5247
5434
  id: "zoom-in",
5248
5435
  icon: "zoom-in",
5249
- label: "Increase Font",
5436
+ label: "Zoom In",
5250
5437
  type: "button",
5251
5438
  group: "zoom",
5252
5439
  execute: () => instance.zoomIn?.()
5253
5440
  },
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
5441
  {
5263
5442
  id: "reset-zoom",
5264
5443
  icon: "reset-zoom",
@@ -5275,6 +5454,14 @@ var MarkdownPlugin = class {
5275
5454
  group: "zoom",
5276
5455
  execute: () => instance.fitToWidth?.()
5277
5456
  },
5457
+ {
5458
+ id: "fit-page",
5459
+ icon: "fit-page",
5460
+ label: "Fit to Page",
5461
+ type: "button",
5462
+ group: "zoom",
5463
+ execute: () => instance.fitToPage?.()
5464
+ },
5278
5465
  {
5279
5466
  id: "copy",
5280
5467
  icon: "copy",
@@ -5298,6 +5485,14 @@ var MarkdownPlugin = class {
5298
5485
  type: "button",
5299
5486
  group: "actions",
5300
5487
  execute: () => instance.print?.()
5488
+ },
5489
+ {
5490
+ id: "open-window",
5491
+ icon: "open-window",
5492
+ label: "Open in Separate Full Window",
5493
+ type: "button",
5494
+ group: "actions",
5495
+ execute: () => instance.openInSeparateWindow?.()
5301
5496
  }
5302
5497
  ];
5303
5498
  }
@@ -5310,35 +5505,57 @@ var MarkdownPlugin = class {
5310
5505
  const cleanHtml = DOMPurify6.sanitize(rawHtml, {
5311
5506
  USE_PROFILES: { html: true }
5312
5507
  });
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;
5508
+ const scrollWrapper = document.createElement("div");
5509
+ scrollWrapper.className = "fp-markdown-scroll-wrapper";
5510
+ scrollWrapper.style.minWidth = "100%";
5511
+ scrollWrapper.style.minHeight = "100%";
5512
+ scrollWrapper.style.width = "max-content";
5513
+ scrollWrapper.style.height = "max-content";
5514
+ scrollWrapper.style.display = "flex";
5515
+ scrollWrapper.style.justifyContent = "center";
5516
+ scrollWrapper.style.alignItems = "flex-start";
5517
+ scrollWrapper.style.padding = "24px 16px";
5518
+ scrollWrapper.style.boxSizing = "border-box";
5519
+ const sizer = document.createElement("div");
5520
+ sizer.className = "fp-markdown-sizer";
5521
+ sizer.style.position = "relative";
5522
+ sizer.style.flexShrink = "0";
5523
+ sizer.style.display = "flex";
5524
+ sizer.style.justifyContent = "center";
5525
+ sizer.style.alignItems = "flex-start";
5526
+ const docCard = document.createElement("div");
5527
+ docCard.className = "fp-markdown-doc-card";
5528
+ docCard.style.cssText = `
5529
+ width: 860px;
5530
+ min-height: 600px;
5531
+ padding: 40px 48px;
5320
5532
  box-sizing: border-box;
5321
5533
  line-height: 1.6;
5322
5534
  font-size: 15px;
5323
5535
  color: var(--fp-text, #24292f);
5324
5536
  background: var(--fp-bg, #ffffff);
5537
+ border-radius: 6px;
5538
+ box-shadow: 0 4px 24px rgba(0, 0, 0, 0.08);
5325
5539
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif;
5540
+ transform-origin: top center;
5541
+ transition: transform 0.15s ease;
5542
+ flex-shrink: 0;
5326
5543
  `;
5327
- wrapper.innerHTML = `
5544
+ docCard.innerHTML = `
5328
5545
  <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 {
5546
+ .fp-markdown-doc-card h1, .fp-markdown-doc-card h2, .fp-markdown-doc-card h3,
5547
+ .fp-markdown-doc-card h4, .fp-markdown-doc-card h5, .fp-markdown-doc-card h6 {
5331
5548
  margin-top: 24px;
5332
5549
  margin-bottom: 16px;
5333
5550
  font-weight: 600;
5334
5551
  line-height: 1.25;
5335
5552
  color: var(--fp-text, #1f2328);
5336
5553
  }
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 {
5554
+ .fp-markdown-doc-card h1 { font-size: 2em; padding-bottom: 0.3em; border-bottom: 1px solid var(--fp-border, #d0d7de); }
5555
+ .fp-markdown-doc-card h2 { font-size: 1.5em; padding-bottom: 0.3em; border-bottom: 1px solid var(--fp-border, #d0d7de); }
5556
+ .fp-markdown-doc-card h3 { font-size: 1.25em; }
5557
+ .fp-markdown-doc-card p { margin-top: 0; margin-bottom: 16px; }
5558
+ .fp-markdown-doc-card table {
5342
5559
  border-spacing: 0;
5343
5560
  border-collapse: collapse;
5344
5561
  margin-top: 0;
@@ -5346,20 +5563,20 @@ var MarkdownPlugin = class {
5346
5563
  width: 100%;
5347
5564
  overflow: auto;
5348
5565
  }
5349
- .fp-markdown-wrapper table th, .fp-markdown-wrapper table td {
5566
+ .fp-markdown-doc-card table th, .fp-markdown-doc-card table td {
5350
5567
  padding: 6px 13px;
5351
5568
  border: 1px solid var(--fp-border, #d0d7de);
5352
5569
  }
5353
- .fp-markdown-wrapper table tr:nth-child(2n) {
5570
+ .fp-markdown-doc-card table tr:nth-child(2n) {
5354
5571
  background-color: var(--fp-toolbar-bg, #f6f8fa);
5355
5572
  }
5356
- .fp-markdown-wrapper blockquote {
5573
+ .fp-markdown-doc-card blockquote {
5357
5574
  margin: 0 0 16px 0;
5358
5575
  padding: 0 1em;
5359
5576
  color: var(--fp-text-muted, #59636e);
5360
5577
  border-left: 0.25em solid var(--fp-border, #d0d7de);
5361
5578
  }
5362
- .fp-markdown-wrapper pre {
5579
+ .fp-markdown-doc-card pre {
5363
5580
  padding: 16px;
5364
5581
  overflow: auto;
5365
5582
  font-size: 85%;
@@ -5368,7 +5585,7 @@ var MarkdownPlugin = class {
5368
5585
  border-radius: 6px;
5369
5586
  border: 1px solid var(--fp-border, #d0d7de);
5370
5587
  }
5371
- .fp-markdown-wrapper code {
5588
+ .fp-markdown-doc-card code {
5372
5589
  padding: 0.2em 0.4em;
5373
5590
  margin: 0;
5374
5591
  font-size: 85%;
@@ -5376,16 +5593,16 @@ var MarkdownPlugin = class {
5376
5593
  border-radius: 4px;
5377
5594
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
5378
5595
  }
5379
- .fp-markdown-wrapper pre code {
5596
+ .fp-markdown-doc-card pre code {
5380
5597
  padding: 0;
5381
5598
  background: transparent;
5382
5599
  }
5383
- .fp-markdown-wrapper ul, .fp-markdown-wrapper ol {
5600
+ .fp-markdown-doc-card ul, .fp-markdown-doc-card ol {
5384
5601
  padding-left: 2em;
5385
5602
  margin-top: 0;
5386
5603
  margin-bottom: 16px;
5387
5604
  }
5388
- .fp-markdown-wrapper hr {
5605
+ .fp-markdown-doc-card hr {
5389
5606
  height: 0.25em;
5390
5607
  padding: 0;
5391
5608
  margin: 24px 0;
@@ -5393,50 +5610,95 @@ var MarkdownPlugin = class {
5393
5610
  border: 0;
5394
5611
  }
5395
5612
  </style>
5396
- <div class="fp-markdown-content" style="max-width: 860px; margin: 0 auto;">
5613
+ <div class="fp-markdown-body">
5397
5614
  ${cleanHtml}
5398
5615
  </div>
5399
5616
  `;
5400
- wrapper.querySelectorAll("pre code").forEach((block) => {
5617
+ docCard.querySelectorAll("pre code").forEach((block) => {
5401
5618
  hljs.highlightElement(block);
5402
5619
  });
5620
+ sizer.appendChild(docCard);
5621
+ scrollWrapper.appendChild(sizer);
5403
5622
  ctx.container.innerHTML = "";
5404
5623
  ctx.container.style.overflow = "auto";
5405
- ctx.container.appendChild(wrapper);
5406
- let fontSize = 15;
5624
+ ctx.container.style.backgroundColor = "#f1f5f9";
5625
+ ctx.container.appendChild(scrollWrapper);
5626
+ let scale = 1;
5627
+ let isUserZoomed = false;
5628
+ const calculateFitScale = () => {
5629
+ const availW = Math.max(280, ctx.container.clientWidth - 48);
5630
+ if (availW < 860) {
5631
+ return Math.max(0.35, availW / 860);
5632
+ }
5633
+ return 1;
5634
+ };
5635
+ const applyTransform = () => {
5636
+ const baseW = 860;
5637
+ const baseH = docCard.offsetHeight || 600;
5638
+ const scaledW = Math.round(baseW * scale);
5639
+ const scaledH = Math.round(baseH * scale);
5640
+ sizer.style.width = `${scaledW}px`;
5641
+ sizer.style.height = `${scaledH}px`;
5642
+ docCard.style.width = `${baseW}px`;
5643
+ docCard.style.transform = `scale(${scale})`;
5644
+ docCard.style.transformOrigin = scaledW > ctx.container.clientWidth - 32 ? "top left" : "top center";
5645
+ };
5646
+ const ro = typeof ResizeObserver !== "undefined" ? new ResizeObserver(() => {
5647
+ if (!isUserZoomed) {
5648
+ scale = calculateFitScale();
5649
+ applyTransform();
5650
+ }
5651
+ }) : null;
5652
+ ro?.observe(ctx.container);
5653
+ requestAnimationFrame(() => {
5654
+ if (!isUserZoomed) {
5655
+ scale = calculateFitScale();
5656
+ }
5657
+ applyTransform();
5658
+ });
5407
5659
  const cleanup = () => {
5408
- wrapper.remove();
5660
+ ro?.disconnect();
5661
+ scrollWrapper.remove();
5409
5662
  ctx.container.innerHTML = "";
5410
5663
  };
5411
5664
  ctx.signal.addEventListener("abort", cleanup);
5412
5665
  return {
5413
5666
  destroy: cleanup,
5414
5667
  zoomIn: () => {
5415
- fontSize = Math.min(28, fontSize + 2);
5416
- wrapper.style.fontSize = `${fontSize}px`;
5668
+ isUserZoomed = true;
5669
+ scale = Math.min(3.5, scale + 0.15);
5670
+ applyTransform();
5417
5671
  },
5418
5672
  zoomOut: () => {
5419
- fontSize = Math.max(10, fontSize - 2);
5420
- wrapper.style.fontSize = `${fontSize}px`;
5673
+ isUserZoomed = true;
5674
+ scale = Math.max(0.25, scale - 0.15);
5675
+ applyTransform();
5421
5676
  },
5422
- getZoom: () => fontSize / 15,
5677
+ getZoom: () => scale,
5423
5678
  setZoom: (level) => {
5424
- fontSize = Math.round(15 * level);
5425
- wrapper.style.fontSize = `${fontSize}px`;
5679
+ isUserZoomed = true;
5680
+ scale = level;
5681
+ applyTransform();
5426
5682
  },
5427
5683
  fitToPage: () => {
5428
- fontSize = 15;
5429
- wrapper.style.fontSize = "15px";
5684
+ isUserZoomed = false;
5685
+ scale = calculateFitScale();
5686
+ applyTransform();
5430
5687
  },
5431
5688
  fitToWidth: () => {
5432
- fontSize = 15;
5433
- wrapper.style.fontSize = "15px";
5689
+ isUserZoomed = false;
5690
+ scale = calculateFitScale();
5691
+ applyTransform();
5434
5692
  },
5435
5693
  resetZoom: () => {
5436
- fontSize = 15;
5437
- wrapper.style.fontSize = "15px";
5694
+ isUserZoomed = false;
5695
+ scale = calculateFitScale();
5438
5696
  ctx.container.scrollTop = 0;
5439
5697
  ctx.container.scrollLeft = 0;
5698
+ applyTransform();
5699
+ },
5700
+ openInSeparateWindow: () => {
5701
+ ctx?.openInSeparateWindow?.();
5440
5702
  },
5441
5703
  download: () => {
5442
5704
  downloadFile(ctx.buffer, ctx.metadata.name || "document.md", "text/markdown");
@@ -6752,14 +7014,6 @@ var HtmlPreviewPlugin = class {
6752
7014
  group: "zoom",
6753
7015
  execute: () => instance.zoomIn?.()
6754
7016
  },
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
7017
  {
6764
7018
  id: "reset-zoom",
6765
7019
  icon: "reset-zoom",
@@ -6776,6 +7030,14 @@ var HtmlPreviewPlugin = class {
6776
7030
  group: "zoom",
6777
7031
  execute: () => instance.fitToWidth?.()
6778
7032
  },
7033
+ {
7034
+ id: "fit-page",
7035
+ icon: "fit-page",
7036
+ label: "Fit to Page",
7037
+ type: "button",
7038
+ group: "zoom",
7039
+ execute: () => instance.fitToPage?.()
7040
+ },
6779
7041
  {
6780
7042
  id: "copy",
6781
7043
  icon: "copy",
@@ -6799,6 +7061,14 @@ var HtmlPreviewPlugin = class {
6799
7061
  type: "button",
6800
7062
  group: "actions",
6801
7063
  execute: () => instance.print?.()
7064
+ },
7065
+ {
7066
+ id: "open-window",
7067
+ icon: "open-window",
7068
+ label: "Open in Separate Full Window",
7069
+ type: "button",
7070
+ group: "actions",
7071
+ execute: () => instance.openInSeparateWindow?.()
6802
7072
  }
6803
7073
  ];
6804
7074
  }
@@ -6809,27 +7079,39 @@ var HtmlPreviewPlugin = class {
6809
7079
  ADD_TAGS: ["style", "link"],
6810
7080
  ADD_ATTR: ["target", "rel"]
6811
7081
  });
7082
+ const scrollWrapper = document.createElement("div");
7083
+ scrollWrapper.className = "fp-html-scroll-wrapper";
7084
+ scrollWrapper.style.minWidth = "100%";
7085
+ scrollWrapper.style.minHeight = "100%";
7086
+ scrollWrapper.style.width = "max-content";
7087
+ scrollWrapper.style.height = "max-content";
7088
+ scrollWrapper.style.display = "flex";
7089
+ scrollWrapper.style.justifyContent = "flex-start";
7090
+ scrollWrapper.style.alignItems = "flex-start";
7091
+ scrollWrapper.style.boxSizing = "border-box";
6812
7092
  const sizer = document.createElement("div");
6813
7093
  sizer.className = "fp-html-sizer";
6814
7094
  sizer.style.position = "relative";
7095
+ sizer.style.flexShrink = "0";
6815
7096
  const iframe = document.createElement("iframe");
6816
7097
  iframe.className = "fp-html-iframe";
6817
7098
  iframe.style.border = "none";
6818
7099
  iframe.style.backgroundColor = "#ffffff";
6819
7100
  iframe.style.transformOrigin = "top left";
6820
- iframe.style.transition = "transform 0.2s ease";
7101
+ iframe.style.transition = "transform 0.15s ease";
6821
7102
  iframe.sandbox.add("allow-same-origin");
6822
7103
  sizer.appendChild(iframe);
7104
+ scrollWrapper.appendChild(sizer);
6823
7105
  ctx.container.style.overflow = "auto";
6824
7106
  ctx.container.style.width = "100%";
6825
7107
  ctx.container.style.height = "100%";
6826
7108
  ctx.container.innerHTML = "";
6827
- ctx.container.appendChild(sizer);
7109
+ ctx.container.appendChild(scrollWrapper);
6828
7110
  iframe.srcdoc = sanitized;
6829
7111
  let scale = 1;
7112
+ let baseW = Math.max(600, ctx.container.clientWidth || 800);
7113
+ let baseH = Math.max(400, ctx.container.clientHeight || 600);
6830
7114
  const applyTransform = () => {
6831
- const baseW = Math.max(600, ctx.container.clientWidth || 800);
6832
- const baseH = Math.max(400, ctx.container.clientHeight || 600);
6833
7115
  const scaledW = Math.round(baseW * scale);
6834
7116
  const scaledH = Math.round(baseH * scale);
6835
7117
  sizer.style.width = `${scaledW}px`;
@@ -6842,22 +7124,33 @@ var HtmlPreviewPlugin = class {
6842
7124
  iframe.style.transform = `scale(${scale})`;
6843
7125
  iframe.style.transformOrigin = "top left";
6844
7126
  };
7127
+ const ro = typeof ResizeObserver !== "undefined" ? new ResizeObserver(() => {
7128
+ if (Math.abs(scale - 1) < 0.05) {
7129
+ baseW = Math.max(600, ctx.container.clientWidth || 800);
7130
+ baseH = Math.max(400, ctx.container.clientHeight || 600);
7131
+ applyTransform();
7132
+ }
7133
+ }) : null;
7134
+ ro?.observe(ctx.container);
6845
7135
  requestAnimationFrame(() => {
7136
+ baseW = Math.max(600, ctx.container.clientWidth || 800);
7137
+ baseH = Math.max(400, ctx.container.clientHeight || 600);
6846
7138
  applyTransform();
6847
7139
  });
6848
7140
  const cleanup = () => {
6849
- sizer.remove();
7141
+ ro?.disconnect();
7142
+ scrollWrapper.remove();
6850
7143
  ctx.container.innerHTML = "";
6851
7144
  };
6852
7145
  ctx.signal.addEventListener("abort", cleanup);
6853
7146
  return {
6854
7147
  destroy: cleanup,
6855
7148
  zoomIn: () => {
6856
- scale += 0.1;
7149
+ scale = Math.min(3.5, scale + 0.15);
6857
7150
  applyTransform();
6858
7151
  },
6859
7152
  zoomOut: () => {
6860
- scale = Math.max(0.2, scale - 0.1);
7153
+ scale = Math.max(0.25, scale - 0.15);
6861
7154
  applyTransform();
6862
7155
  },
6863
7156
  getZoom: () => scale,
@@ -6879,8 +7172,11 @@ var HtmlPreviewPlugin = class {
6879
7172
  ctx.container.scrollLeft = 0;
6880
7173
  applyTransform();
6881
7174
  },
7175
+ openInSeparateWindow: () => {
7176
+ ctx?.openInSeparateWindow?.();
7177
+ },
6882
7178
  copy: () => {
6883
- navigator.clipboard.writeText(rawHtml);
7179
+ navigator.clipboard?.writeText(rawHtml);
6884
7180
  },
6885
7181
  download: () => {
6886
7182
  const blob = new Blob([ctx.buffer], { type: "text/html" });