@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/react.js CHANGED
@@ -1599,19 +1599,85 @@ var FilePreviewViewer = class _FilePreviewViewer {
1599
1599
  if (this.wrapperEl?.parentNode) {
1600
1600
  this.wrapperEl.parentNode.removeChild(this.wrapperEl);
1601
1601
  }
1602
+ if (typeof document !== "undefined" && !document.getElementById("fp-core-injected-styles")) {
1603
+ const styleEl = document.createElement("style");
1604
+ styleEl.id = "fp-core-injected-styles";
1605
+ styleEl.textContent = `
1606
+ .fp-viewer {
1607
+ display: flex !important;
1608
+ flex-direction: column !important;
1609
+ width: 100% !important;
1610
+ height: 100% !important;
1611
+ overflow: hidden !important;
1612
+ position: relative !important;
1613
+ box-sizing: border-box !important;
1614
+ }
1615
+ .fp-body {
1616
+ display: flex !important;
1617
+ flex: 1 1 0% !important;
1618
+ min-height: 0 !important;
1619
+ min-width: 0 !important;
1620
+ width: 100% !important;
1621
+ height: 100% !important;
1622
+ overflow: hidden !important;
1623
+ position: relative !important;
1624
+ box-sizing: border-box !important;
1625
+ }
1626
+ .fp-content {
1627
+ flex: 1 1 0% !important;
1628
+ position: relative !important;
1629
+ overflow: auto !important;
1630
+ display: flex !important;
1631
+ flex-direction: column !important;
1632
+ align-items: stretch !important;
1633
+ justify-content: flex-start !important;
1634
+ width: 100% !important;
1635
+ height: 100% !important;
1636
+ min-width: 0 !important;
1637
+ min-height: 0 !important;
1638
+ box-sizing: border-box !important;
1639
+ }
1640
+ `;
1641
+ document.head.appendChild(styleEl);
1642
+ }
1602
1643
  const themeClass = options.theme === "dark" ? "fp-theme-dark" : "";
1603
1644
  const toolbarPos = options.toolbarPosition ?? "top";
1604
1645
  this.wrapperEl = document.createElement("div");
1605
1646
  this.wrapperEl.className = `fp-viewer ${themeClass} ${options.className ?? ""}`.trim();
1606
1647
  this.wrapperEl.tabIndex = 0;
1648
+ this.wrapperEl.style.display = "flex";
1649
+ this.wrapperEl.style.flexDirection = "column";
1650
+ this.wrapperEl.style.width = "100%";
1651
+ this.wrapperEl.style.height = "100%";
1652
+ this.wrapperEl.style.overflow = "hidden";
1653
+ this.wrapperEl.style.position = "relative";
1607
1654
  const toolbarEl = document.createElement("div");
1608
1655
  toolbarEl.className = "fp-toolbar-container";
1609
1656
  this.contentEl = document.createElement("div");
1610
1657
  this.contentEl.className = "fp-content";
1658
+ this.contentEl.style.flex = "1 1 0%";
1659
+ this.contentEl.style.position = "relative";
1660
+ this.contentEl.style.overflow = "auto";
1661
+ this.contentEl.style.display = "flex";
1662
+ this.contentEl.style.flexDirection = "column";
1663
+ this.contentEl.style.alignItems = "stretch";
1664
+ this.contentEl.style.justifyContent = "flex-start";
1665
+ this.contentEl.style.width = "100%";
1666
+ this.contentEl.style.height = "100%";
1667
+ this.contentEl.style.minWidth = "0";
1668
+ this.contentEl.style.minHeight = "0";
1669
+ this.contentEl.style.boxSizing = "border-box";
1611
1670
  const thumbnailEl = document.createElement("div");
1612
1671
  thumbnailEl.className = "fp-thumbnail-container";
1613
1672
  const bodyEl = document.createElement("div");
1614
1673
  bodyEl.className = "fp-body";
1674
+ bodyEl.style.display = "flex";
1675
+ bodyEl.style.flex = "1 1 0%";
1676
+ bodyEl.style.minHeight = "0";
1677
+ bodyEl.style.minWidth = "0";
1678
+ bodyEl.style.width = "100%";
1679
+ bodyEl.style.overflow = "hidden";
1680
+ bodyEl.style.position = "relative";
1615
1681
  bodyEl.appendChild(thumbnailEl);
1616
1682
  bodyEl.appendChild(this.contentEl);
1617
1683
  const titleBarEl = document.createElement("div");
@@ -4405,31 +4471,80 @@ function csvPlugin() {
4405
4471
  }
4406
4472
  var CODE_EXTENSIONS = [
4407
4473
  ".txt",
4474
+ ".log",
4475
+ ".ini",
4476
+ ".cfg",
4477
+ ".conf",
4478
+ ".env",
4408
4479
  ".json",
4480
+ ".jsonc",
4481
+ ".json5",
4409
4482
  ".js",
4410
- ".ts",
4483
+ ".mjs",
4484
+ ".cjs",
4411
4485
  ".jsx",
4486
+ ".ts",
4487
+ ".mts",
4488
+ ".cts",
4412
4489
  ".tsx",
4413
4490
  ".html",
4491
+ ".htm",
4492
+ ".xhtml",
4414
4493
  ".css",
4415
4494
  ".scss",
4495
+ ".sass",
4416
4496
  ".less",
4417
4497
  ".md",
4498
+ ".markdown",
4418
4499
  ".xml",
4500
+ ".svg",
4501
+ ".xaml",
4419
4502
  ".yml",
4420
4503
  ".yaml",
4504
+ ".toml",
4421
4505
  ".sh",
4422
4506
  ".bash",
4507
+ ".zsh",
4508
+ ".fish",
4509
+ ".bat",
4510
+ ".cmd",
4511
+ ".ps1",
4423
4512
  ".py",
4513
+ ".pyw",
4424
4514
  ".java",
4515
+ ".class",
4425
4516
  ".c",
4426
4517
  ".cpp",
4518
+ ".cc",
4519
+ ".cxx",
4427
4520
  ".h",
4521
+ ".hpp",
4522
+ ".hxx",
4428
4523
  ".cs",
4524
+ ".csx",
4429
4525
  ".go",
4430
4526
  ".rs",
4431
4527
  ".sql",
4432
- ".php"
4528
+ ".php",
4529
+ ".phtml",
4530
+ ".rb",
4531
+ ".swift",
4532
+ ".kt",
4533
+ ".kts",
4534
+ ".scala",
4535
+ ".r",
4536
+ ".lua",
4537
+ ".pl",
4538
+ ".pm",
4539
+ ".dart",
4540
+ ".graphql",
4541
+ ".gql",
4542
+ ".proto",
4543
+ ".diff",
4544
+ ".patch",
4545
+ ".dockerfile",
4546
+ ".properties",
4547
+ ".gradle"
4433
4548
  ];
4434
4549
  var CodePlugin = class {
4435
4550
  id = "code";
@@ -4447,34 +4562,36 @@ var CodePlugin = class {
4447
4562
  getToolbarActions(instance) {
4448
4563
  const totalPages = instance.getPageCount?.() ?? 1;
4449
4564
  const actions = [];
4450
- actions.push({
4451
- id: "thumbnails",
4452
- icon: "thumbnails",
4453
- label: "Page Thumbnails",
4454
- type: "button",
4455
- group: "navigation",
4456
- execute: () => instance.toggleThumbnails?.()
4457
- });
4458
- actions.push({
4459
- id: "page-nav",
4460
- icon: "",
4461
- label: "Page Navigation",
4462
- type: "page-nav",
4463
- group: "navigation",
4464
- value: instance.getCurrentPage?.() ?? 1,
4465
- max: totalPages,
4466
- execute: (action, page) => {
4467
- const cur = instance.getCurrentPage?.() ?? 1;
4468
- const max = instance.getPageCount?.() ?? 1;
4469
- if (action === "prev") {
4470
- if (cur > 1) instance.goToPage?.(cur - 1);
4471
- } else if (action === "next") {
4472
- if (cur < max) instance.goToPage?.(cur + 1);
4473
- } else if (typeof page === "number") {
4474
- instance.goToPage?.(page);
4565
+ if (totalPages > 1) {
4566
+ actions.push({
4567
+ id: "thumbnails",
4568
+ icon: "thumbnails",
4569
+ label: "Page Thumbnails",
4570
+ type: "button",
4571
+ group: "navigation",
4572
+ execute: () => instance.toggleThumbnails?.()
4573
+ });
4574
+ actions.push({
4575
+ id: "page-nav",
4576
+ icon: "",
4577
+ label: "Page Navigation",
4578
+ type: "page-nav",
4579
+ group: "navigation",
4580
+ value: instance.getCurrentPage?.() ?? 1,
4581
+ max: totalPages,
4582
+ execute: (action, page) => {
4583
+ const cur = instance.getCurrentPage?.() ?? 1;
4584
+ const max = instance.getPageCount?.() ?? 1;
4585
+ if (action === "prev") {
4586
+ if (cur > 1) instance.goToPage?.(cur - 1);
4587
+ } else if (action === "next") {
4588
+ if (cur < max) instance.goToPage?.(cur + 1);
4589
+ } else if (typeof page === "number") {
4590
+ instance.goToPage?.(page);
4591
+ }
4475
4592
  }
4476
- }
4477
- });
4593
+ });
4594
+ }
4478
4595
  actions.push(
4479
4596
  {
4480
4597
  id: "zoom-out",
@@ -4611,10 +4728,6 @@ var CodePlugin = class {
4611
4728
  }
4612
4729
  const totalPages = Math.max(1, rawPages.length);
4613
4730
  let currentPage = 1;
4614
- const container = document.createElement("div");
4615
- container.style.width = "100%";
4616
- container.style.height = "100%";
4617
- container.style.overflow = "auto";
4618
4731
  let fontSize = 13;
4619
4732
  let rotation = 0;
4620
4733
  let zoomLevel = 1;
@@ -4623,9 +4736,10 @@ var CodePlugin = class {
4623
4736
  const code = document.createElement("code");
4624
4737
  const sizer = document.createElement("div");
4625
4738
  const scrollWrapper = document.createElement("div");
4739
+ const lineGutter = document.createElement("div");
4740
+ ctx.container.style.overflow = "auto";
4626
4741
  if (isTxt) {
4627
- container.style.overflow = "auto";
4628
- container.style.backgroundColor = "#f1f5f9";
4742
+ ctx.container.style.backgroundColor = "#f1f5f9";
4629
4743
  scrollWrapper.className = "fp-code-scroll-wrapper";
4630
4744
  scrollWrapper.style.minWidth = "100%";
4631
4745
  scrollWrapper.style.minHeight = "100%";
@@ -4660,18 +4774,88 @@ var CodePlugin = class {
4660
4774
  pre.style.transition = "transform 0.15s ease";
4661
4775
  pre.style.flexShrink = "0";
4662
4776
  } else {
4663
- container.style.overflow = "auto";
4664
- container.style.backgroundColor = "#1e1e1e";
4665
- container.style.color = "#d4d4d4";
4666
- container.style.padding = "16px";
4667
- container.style.boxSizing = "border-box";
4777
+ if (typeof document !== "undefined" && !document.getElementById("fp-code-syntax-styles")) {
4778
+ const style = document.createElement("style");
4779
+ style.id = "fp-code-syntax-styles";
4780
+ style.textContent = `
4781
+ .fp-code-scroll-wrapper .hljs-keyword { color: #569cd6; font-weight: normal; }
4782
+ .fp-code-scroll-wrapper .hljs-built_in { color: #4ec9b0; }
4783
+ .fp-code-scroll-wrapper .hljs-type { color: #4ec9b0; }
4784
+ .fp-code-scroll-wrapper .hljs-literal { color: #569cd6; }
4785
+ .fp-code-scroll-wrapper .hljs-number { color: #b5cea8; }
4786
+ .fp-code-scroll-wrapper .hljs-regexp { color: #d16969; }
4787
+ .fp-code-scroll-wrapper .hljs-string { color: #ce9178; }
4788
+ .fp-code-scroll-wrapper .hljs-subst { color: #d4d4d4; }
4789
+ .fp-code-scroll-wrapper .hljs-symbol { color: #569cd6; }
4790
+ .fp-code-scroll-wrapper .hljs-class { color: #4ec9b0; }
4791
+ .fp-code-scroll-wrapper .hljs-function { color: #dcdcaa; }
4792
+ .fp-code-scroll-wrapper .hljs-title { color: #dcdcaa; }
4793
+ .fp-code-scroll-wrapper .hljs-params { color: #9cdcfe; }
4794
+ .fp-code-scroll-wrapper .hljs-comment { color: #6a9955; font-style: italic; }
4795
+ .fp-code-scroll-wrapper .hljs-doctag { color: #608b4e; }
4796
+ .fp-code-scroll-wrapper .hljs-meta { color: #9cdcfe; }
4797
+ .fp-code-scroll-wrapper .hljs-section { color: #569cd6; }
4798
+ .fp-code-scroll-wrapper .hljs-tag { color: #569cd6; }
4799
+ .fp-code-scroll-wrapper .hljs-name { color: #569cd6; }
4800
+ .fp-code-scroll-wrapper .hljs-attr { color: #9cdcfe; }
4801
+ .fp-code-scroll-wrapper .hljs-attribute { color: #9cdcfe; }
4802
+ .fp-code-scroll-wrapper .hljs-variable { color: #9cdcfe; }
4803
+ .fp-code-scroll-wrapper .hljs-punctuation { color: #d4d4d4; }
4804
+ `;
4805
+ document.head.appendChild(style);
4806
+ }
4807
+ ctx.container.style.backgroundColor = "#1e1e1e";
4808
+ ctx.container.style.color = "#d4d4d4";
4809
+ scrollWrapper.className = "fp-code-scroll-wrapper";
4810
+ scrollWrapper.style.minWidth = "100%";
4811
+ scrollWrapper.style.minHeight = "100%";
4812
+ scrollWrapper.style.width = "max-content";
4813
+ scrollWrapper.style.height = "max-content";
4814
+ scrollWrapper.style.display = "flex";
4815
+ scrollWrapper.style.alignItems = "flex-start";
4816
+ scrollWrapper.style.padding = "16px 16px 16px 0";
4817
+ scrollWrapper.style.boxSizing = "border-box";
4818
+ const rawLines = fullText.split(/\r?\n/);
4819
+ if (rawLines.length > 1 && rawLines[rawLines.length - 1] === "") {
4820
+ rawLines.pop();
4821
+ }
4822
+ const lineCount = Math.max(1, rawLines.length);
4823
+ const gutterLines = [];
4824
+ for (let i = 1; i <= lineCount; i++) {
4825
+ gutterLines.push(String(i));
4826
+ }
4827
+ lineGutter.className = "fp-code-gutter";
4828
+ lineGutter.style.userSelect = "none";
4829
+ lineGutter.style.textAlign = "right";
4830
+ lineGutter.style.padding = "0 16px";
4831
+ lineGutter.style.margin = "0 16px 0 0";
4832
+ lineGutter.style.borderRight = "1px solid #333333";
4833
+ lineGutter.style.color = "#858585";
4834
+ lineGutter.style.fontFamily = "Consolas, Menlo, Monaco, 'Courier New', monospace";
4835
+ lineGutter.style.fontSize = `${fontSize}px`;
4836
+ lineGutter.style.lineHeight = "1.6";
4837
+ lineGutter.style.whiteSpace = "pre";
4838
+ lineGutter.style.flexShrink = "0";
4839
+ lineGutter.style.position = "sticky";
4840
+ lineGutter.style.left = "0";
4841
+ lineGutter.style.backgroundColor = "#1e1e1e";
4842
+ lineGutter.style.zIndex = "2";
4843
+ lineGutter.style.boxSizing = "border-box";
4844
+ lineGutter.textContent = gutterLines.join("\n");
4668
4845
  pre.style.margin = "0";
4669
- pre.style.fontFamily = "Consolas, Menlo, Monaco, monospace";
4846
+ pre.style.padding = "0 16px 0 0";
4847
+ pre.style.fontFamily = "Consolas, Menlo, Monaco, 'Courier New', monospace";
4670
4848
  pre.style.fontSize = `${fontSize}px`;
4671
- pre.style.lineHeight = "1.5";
4672
- pre.style.whiteSpace = "pre-wrap";
4673
- pre.style.wordBreak = "break-all";
4674
- pre.style.transformOrigin = "top left";
4849
+ pre.style.lineHeight = "1.6";
4850
+ pre.style.whiteSpace = "pre";
4851
+ pre.style.wordBreak = "normal";
4852
+ pre.style.overflowWrap = "normal";
4853
+ pre.style.flex = "1";
4854
+ code.style.display = "block";
4855
+ code.style.fontFamily = "inherit";
4856
+ code.style.fontSize = "inherit";
4857
+ code.style.lineHeight = "inherit";
4858
+ code.style.whiteSpace = "inherit";
4675
4859
  }
4676
4860
  const ext = (ctx.metadata.extension || "").replace(".", "");
4677
4861
  const renderCodePage = (text) => {
@@ -4691,25 +4875,27 @@ var CodePlugin = class {
4691
4875
  };
4692
4876
  renderCodePage(rawPages[0] || (isTxt ? "" : fullText));
4693
4877
  pre.appendChild(code);
4878
+ ctx.container.innerHTML = "";
4694
4879
  if (isTxt) {
4695
4880
  sizer.appendChild(pre);
4696
4881
  scrollWrapper.appendChild(sizer);
4697
- container.appendChild(scrollWrapper);
4882
+ ctx.container.appendChild(scrollWrapper);
4698
4883
  } else {
4699
- container.appendChild(pre);
4884
+ scrollWrapper.appendChild(lineGutter);
4885
+ scrollWrapper.appendChild(pre);
4886
+ ctx.container.appendChild(scrollWrapper);
4700
4887
  }
4701
4888
  const showPage = (pageNum) => {
4702
4889
  currentPage = Math.max(1, Math.min(totalPages, pageNum));
4703
4890
  renderCodePage(rawPages[currentPage - 1] || (isTxt ? "" : fullText));
4704
- container.scrollTop = 0;
4891
+ ctx.container.scrollTop = 0;
4705
4892
  ctx.emit("page-change", { page: currentPage, total: totalPages });
4706
4893
  };
4707
4894
  if (totalPages > 1) {
4708
4895
  showPage(1);
4709
4896
  }
4710
- ctx.container.appendChild(container);
4711
4897
  const calculateTxtFit = () => {
4712
- const availW = Math.max(280, container.clientWidth - 32);
4898
+ const availW = Math.max(280, ctx.container.clientWidth - 32);
4713
4899
  return Math.max(0.4, Math.min(3, availW / 816));
4714
4900
  };
4715
4901
  const updateTransform = () => {
@@ -4727,6 +4913,7 @@ var CodePlugin = class {
4727
4913
  } else {
4728
4914
  pre.style.transform = `rotate(${rotation}deg)`;
4729
4915
  pre.style.fontSize = `${fontSize}px`;
4916
+ lineGutter.style.fontSize = `${fontSize}px`;
4730
4917
  }
4731
4918
  };
4732
4919
  let resizeObserver = null;
@@ -4741,11 +4928,11 @@ var CodePlugin = class {
4741
4928
  updateTransform();
4742
4929
  }
4743
4930
  }) : null;
4744
- resizeObserver?.observe(container);
4931
+ resizeObserver?.observe(ctx.container);
4745
4932
  }
4746
4933
  const cleanup = () => {
4747
4934
  resizeObserver?.disconnect();
4748
- container.remove();
4935
+ scrollWrapper.remove();
4749
4936
  ctx.container.innerHTML = "";
4750
4937
  };
4751
4938
  ctx.signal.addEventListener("abort", cleanup);
@@ -4790,7 +4977,7 @@ var CodePlugin = class {
4790
4977
  if (isTxt) {
4791
4978
  zoomLevel = Math.min(3.5, zoomLevel + 0.15);
4792
4979
  } else {
4793
- fontSize = Math.min(32, fontSize + 2);
4980
+ fontSize = Math.min(48, fontSize + 2);
4794
4981
  }
4795
4982
  updateTransform();
4796
4983
  },
@@ -4799,7 +4986,7 @@ var CodePlugin = class {
4799
4986
  if (isTxt) {
4800
4987
  zoomLevel = Math.max(0.1, zoomLevel - 0.15);
4801
4988
  } else {
4802
- fontSize = Math.max(8, fontSize - 2);
4989
+ fontSize = Math.max(9, fontSize - 2);
4803
4990
  }
4804
4991
  updateTransform();
4805
4992
  },
@@ -4832,8 +5019,8 @@ var CodePlugin = class {
4832
5019
  fontSize = 13;
4833
5020
  rotation = 0;
4834
5021
  zoomLevel = isTxt ? calculateTxtFit() : 1;
4835
- container.scrollTop = 0;
4836
- container.scrollLeft = 0;
5022
+ ctx.container.scrollTop = 0;
5023
+ ctx.container.scrollLeft = 0;
4837
5024
  updateTransform();
4838
5025
  },
4839
5026
  rotateCW: () => {
@@ -5155,7 +5342,7 @@ var MarkdownPlugin = class {
5155
5342
  {
5156
5343
  id: "zoom-out",
5157
5344
  icon: "zoom-out",
5158
- label: "Decrease Font",
5345
+ label: "Zoom Out",
5159
5346
  type: "button",
5160
5347
  group: "zoom",
5161
5348
  execute: () => instance.zoomOut?.()
@@ -5163,19 +5350,11 @@ var MarkdownPlugin = class {
5163
5350
  {
5164
5351
  id: "zoom-in",
5165
5352
  icon: "zoom-in",
5166
- label: "Increase Font",
5353
+ label: "Zoom In",
5167
5354
  type: "button",
5168
5355
  group: "zoom",
5169
5356
  execute: () => instance.zoomIn?.()
5170
5357
  },
5171
- {
5172
- id: "fit-page",
5173
- icon: "fit-page",
5174
- label: "Default Size",
5175
- type: "button",
5176
- group: "zoom",
5177
- execute: () => instance.fitToPage?.()
5178
- },
5179
5358
  {
5180
5359
  id: "reset-zoom",
5181
5360
  icon: "reset-zoom",
@@ -5192,6 +5371,14 @@ var MarkdownPlugin = class {
5192
5371
  group: "zoom",
5193
5372
  execute: () => instance.fitToWidth?.()
5194
5373
  },
5374
+ {
5375
+ id: "fit-page",
5376
+ icon: "fit-page",
5377
+ label: "Fit to Page",
5378
+ type: "button",
5379
+ group: "zoom",
5380
+ execute: () => instance.fitToPage?.()
5381
+ },
5195
5382
  {
5196
5383
  id: "copy",
5197
5384
  icon: "copy",
@@ -5215,6 +5402,14 @@ var MarkdownPlugin = class {
5215
5402
  type: "button",
5216
5403
  group: "actions",
5217
5404
  execute: () => instance.print?.()
5405
+ },
5406
+ {
5407
+ id: "open-window",
5408
+ icon: "open-window",
5409
+ label: "Open in Separate Full Window",
5410
+ type: "button",
5411
+ group: "actions",
5412
+ execute: () => instance.openInSeparateWindow?.()
5218
5413
  }
5219
5414
  ];
5220
5415
  }
@@ -5227,35 +5422,57 @@ var MarkdownPlugin = class {
5227
5422
  const cleanHtml = DOMPurify6.sanitize(rawHtml, {
5228
5423
  USE_PROFILES: { html: true }
5229
5424
  });
5230
- const wrapper = document.createElement("div");
5231
- wrapper.className = "fp-markdown-wrapper";
5232
- wrapper.style.cssText = `
5233
- width: 100%;
5234
- height: 100%;
5235
- overflow: auto;
5236
- padding: 32px 40px;
5425
+ const scrollWrapper = document.createElement("div");
5426
+ scrollWrapper.className = "fp-markdown-scroll-wrapper";
5427
+ scrollWrapper.style.minWidth = "100%";
5428
+ scrollWrapper.style.minHeight = "100%";
5429
+ scrollWrapper.style.width = "max-content";
5430
+ scrollWrapper.style.height = "max-content";
5431
+ scrollWrapper.style.display = "flex";
5432
+ scrollWrapper.style.justifyContent = "center";
5433
+ scrollWrapper.style.alignItems = "flex-start";
5434
+ scrollWrapper.style.padding = "24px 16px";
5435
+ scrollWrapper.style.boxSizing = "border-box";
5436
+ const sizer = document.createElement("div");
5437
+ sizer.className = "fp-markdown-sizer";
5438
+ sizer.style.position = "relative";
5439
+ sizer.style.flexShrink = "0";
5440
+ sizer.style.display = "flex";
5441
+ sizer.style.justifyContent = "center";
5442
+ sizer.style.alignItems = "flex-start";
5443
+ const docCard = document.createElement("div");
5444
+ docCard.className = "fp-markdown-doc-card";
5445
+ docCard.style.cssText = `
5446
+ width: 860px;
5447
+ min-height: 600px;
5448
+ padding: 40px 48px;
5237
5449
  box-sizing: border-box;
5238
5450
  line-height: 1.6;
5239
5451
  font-size: 15px;
5240
5452
  color: var(--fp-text, #24292f);
5241
5453
  background: var(--fp-bg, #ffffff);
5454
+ border-radius: 6px;
5455
+ box-shadow: 0 4px 24px rgba(0, 0, 0, 0.08);
5242
5456
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", Helvetica, Arial, sans-serif;
5457
+ transform-origin: top center;
5458
+ transition: transform 0.15s ease;
5459
+ flex-shrink: 0;
5243
5460
  `;
5244
- wrapper.innerHTML = `
5461
+ docCard.innerHTML = `
5245
5462
  <style>
5246
- .fp-markdown-wrapper h1, .fp-markdown-wrapper h2, .fp-markdown-wrapper h3,
5247
- .fp-markdown-wrapper h4, .fp-markdown-wrapper h5, .fp-markdown-wrapper h6 {
5463
+ .fp-markdown-doc-card h1, .fp-markdown-doc-card h2, .fp-markdown-doc-card h3,
5464
+ .fp-markdown-doc-card h4, .fp-markdown-doc-card h5, .fp-markdown-doc-card h6 {
5248
5465
  margin-top: 24px;
5249
5466
  margin-bottom: 16px;
5250
5467
  font-weight: 600;
5251
5468
  line-height: 1.25;
5252
5469
  color: var(--fp-text, #1f2328);
5253
5470
  }
5254
- .fp-markdown-wrapper h1 { font-size: 2em; padding-bottom: 0.3em; border-bottom: 1px solid var(--fp-border, #d0d7de); }
5255
- .fp-markdown-wrapper h2 { font-size: 1.5em; padding-bottom: 0.3em; border-bottom: 1px solid var(--fp-border, #d0d7de); }
5256
- .fp-markdown-wrapper h3 { font-size: 1.25em; }
5257
- .fp-markdown-wrapper p { margin-top: 0; margin-bottom: 16px; }
5258
- .fp-markdown-wrapper table {
5471
+ .fp-markdown-doc-card h1 { font-size: 2em; padding-bottom: 0.3em; border-bottom: 1px solid var(--fp-border, #d0d7de); }
5472
+ .fp-markdown-doc-card h2 { font-size: 1.5em; padding-bottom: 0.3em; border-bottom: 1px solid var(--fp-border, #d0d7de); }
5473
+ .fp-markdown-doc-card h3 { font-size: 1.25em; }
5474
+ .fp-markdown-doc-card p { margin-top: 0; margin-bottom: 16px; }
5475
+ .fp-markdown-doc-card table {
5259
5476
  border-spacing: 0;
5260
5477
  border-collapse: collapse;
5261
5478
  margin-top: 0;
@@ -5263,20 +5480,20 @@ var MarkdownPlugin = class {
5263
5480
  width: 100%;
5264
5481
  overflow: auto;
5265
5482
  }
5266
- .fp-markdown-wrapper table th, .fp-markdown-wrapper table td {
5483
+ .fp-markdown-doc-card table th, .fp-markdown-doc-card table td {
5267
5484
  padding: 6px 13px;
5268
5485
  border: 1px solid var(--fp-border, #d0d7de);
5269
5486
  }
5270
- .fp-markdown-wrapper table tr:nth-child(2n) {
5487
+ .fp-markdown-doc-card table tr:nth-child(2n) {
5271
5488
  background-color: var(--fp-toolbar-bg, #f6f8fa);
5272
5489
  }
5273
- .fp-markdown-wrapper blockquote {
5490
+ .fp-markdown-doc-card blockquote {
5274
5491
  margin: 0 0 16px 0;
5275
5492
  padding: 0 1em;
5276
5493
  color: var(--fp-text-muted, #59636e);
5277
5494
  border-left: 0.25em solid var(--fp-border, #d0d7de);
5278
5495
  }
5279
- .fp-markdown-wrapper pre {
5496
+ .fp-markdown-doc-card pre {
5280
5497
  padding: 16px;
5281
5498
  overflow: auto;
5282
5499
  font-size: 85%;
@@ -5285,7 +5502,7 @@ var MarkdownPlugin = class {
5285
5502
  border-radius: 6px;
5286
5503
  border: 1px solid var(--fp-border, #d0d7de);
5287
5504
  }
5288
- .fp-markdown-wrapper code {
5505
+ .fp-markdown-doc-card code {
5289
5506
  padding: 0.2em 0.4em;
5290
5507
  margin: 0;
5291
5508
  font-size: 85%;
@@ -5293,16 +5510,16 @@ var MarkdownPlugin = class {
5293
5510
  border-radius: 4px;
5294
5511
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
5295
5512
  }
5296
- .fp-markdown-wrapper pre code {
5513
+ .fp-markdown-doc-card pre code {
5297
5514
  padding: 0;
5298
5515
  background: transparent;
5299
5516
  }
5300
- .fp-markdown-wrapper ul, .fp-markdown-wrapper ol {
5517
+ .fp-markdown-doc-card ul, .fp-markdown-doc-card ol {
5301
5518
  padding-left: 2em;
5302
5519
  margin-top: 0;
5303
5520
  margin-bottom: 16px;
5304
5521
  }
5305
- .fp-markdown-wrapper hr {
5522
+ .fp-markdown-doc-card hr {
5306
5523
  height: 0.25em;
5307
5524
  padding: 0;
5308
5525
  margin: 24px 0;
@@ -5310,50 +5527,95 @@ var MarkdownPlugin = class {
5310
5527
  border: 0;
5311
5528
  }
5312
5529
  </style>
5313
- <div class="fp-markdown-content" style="max-width: 860px; margin: 0 auto;">
5530
+ <div class="fp-markdown-body">
5314
5531
  ${cleanHtml}
5315
5532
  </div>
5316
5533
  `;
5317
- wrapper.querySelectorAll("pre code").forEach((block) => {
5534
+ docCard.querySelectorAll("pre code").forEach((block) => {
5318
5535
  hljs.highlightElement(block);
5319
5536
  });
5537
+ sizer.appendChild(docCard);
5538
+ scrollWrapper.appendChild(sizer);
5320
5539
  ctx.container.innerHTML = "";
5321
5540
  ctx.container.style.overflow = "auto";
5322
- ctx.container.appendChild(wrapper);
5323
- let fontSize = 15;
5541
+ ctx.container.style.backgroundColor = "#f1f5f9";
5542
+ ctx.container.appendChild(scrollWrapper);
5543
+ let scale = 1;
5544
+ let isUserZoomed = false;
5545
+ const calculateFitScale = () => {
5546
+ const availW = Math.max(280, ctx.container.clientWidth - 48);
5547
+ if (availW < 860) {
5548
+ return Math.max(0.35, availW / 860);
5549
+ }
5550
+ return 1;
5551
+ };
5552
+ const applyTransform = () => {
5553
+ const baseW = 860;
5554
+ const baseH = docCard.offsetHeight || 600;
5555
+ const scaledW = Math.round(baseW * scale);
5556
+ const scaledH = Math.round(baseH * scale);
5557
+ sizer.style.width = `${scaledW}px`;
5558
+ sizer.style.height = `${scaledH}px`;
5559
+ docCard.style.width = `${baseW}px`;
5560
+ docCard.style.transform = `scale(${scale})`;
5561
+ docCard.style.transformOrigin = scaledW > ctx.container.clientWidth - 32 ? "top left" : "top center";
5562
+ };
5563
+ const ro = typeof ResizeObserver !== "undefined" ? new ResizeObserver(() => {
5564
+ if (!isUserZoomed) {
5565
+ scale = calculateFitScale();
5566
+ applyTransform();
5567
+ }
5568
+ }) : null;
5569
+ ro?.observe(ctx.container);
5570
+ requestAnimationFrame(() => {
5571
+ if (!isUserZoomed) {
5572
+ scale = calculateFitScale();
5573
+ }
5574
+ applyTransform();
5575
+ });
5324
5576
  const cleanup = () => {
5325
- wrapper.remove();
5577
+ ro?.disconnect();
5578
+ scrollWrapper.remove();
5326
5579
  ctx.container.innerHTML = "";
5327
5580
  };
5328
5581
  ctx.signal.addEventListener("abort", cleanup);
5329
5582
  return {
5330
5583
  destroy: cleanup,
5331
5584
  zoomIn: () => {
5332
- fontSize = Math.min(28, fontSize + 2);
5333
- wrapper.style.fontSize = `${fontSize}px`;
5585
+ isUserZoomed = true;
5586
+ scale = Math.min(3.5, scale + 0.15);
5587
+ applyTransform();
5334
5588
  },
5335
5589
  zoomOut: () => {
5336
- fontSize = Math.max(10, fontSize - 2);
5337
- wrapper.style.fontSize = `${fontSize}px`;
5590
+ isUserZoomed = true;
5591
+ scale = Math.max(0.25, scale - 0.15);
5592
+ applyTransform();
5338
5593
  },
5339
- getZoom: () => fontSize / 15,
5594
+ getZoom: () => scale,
5340
5595
  setZoom: (level) => {
5341
- fontSize = Math.round(15 * level);
5342
- wrapper.style.fontSize = `${fontSize}px`;
5596
+ isUserZoomed = true;
5597
+ scale = level;
5598
+ applyTransform();
5343
5599
  },
5344
5600
  fitToPage: () => {
5345
- fontSize = 15;
5346
- wrapper.style.fontSize = "15px";
5601
+ isUserZoomed = false;
5602
+ scale = calculateFitScale();
5603
+ applyTransform();
5347
5604
  },
5348
5605
  fitToWidth: () => {
5349
- fontSize = 15;
5350
- wrapper.style.fontSize = "15px";
5606
+ isUserZoomed = false;
5607
+ scale = calculateFitScale();
5608
+ applyTransform();
5351
5609
  },
5352
5610
  resetZoom: () => {
5353
- fontSize = 15;
5354
- wrapper.style.fontSize = "15px";
5611
+ isUserZoomed = false;
5612
+ scale = calculateFitScale();
5355
5613
  ctx.container.scrollTop = 0;
5356
5614
  ctx.container.scrollLeft = 0;
5615
+ applyTransform();
5616
+ },
5617
+ openInSeparateWindow: () => {
5618
+ ctx?.openInSeparateWindow?.();
5357
5619
  },
5358
5620
  download: () => {
5359
5621
  downloadFile(ctx.buffer, ctx.metadata.name || "document.md", "text/markdown");
@@ -6669,14 +6931,6 @@ var HtmlPreviewPlugin = class {
6669
6931
  group: "zoom",
6670
6932
  execute: () => instance.zoomIn?.()
6671
6933
  },
6672
- {
6673
- id: "fit-page",
6674
- icon: "fit-page",
6675
- label: "Fit to Page",
6676
- type: "button",
6677
- group: "zoom",
6678
- execute: () => instance.fitToPage?.()
6679
- },
6680
6934
  {
6681
6935
  id: "reset-zoom",
6682
6936
  icon: "reset-zoom",
@@ -6693,6 +6947,14 @@ var HtmlPreviewPlugin = class {
6693
6947
  group: "zoom",
6694
6948
  execute: () => instance.fitToWidth?.()
6695
6949
  },
6950
+ {
6951
+ id: "fit-page",
6952
+ icon: "fit-page",
6953
+ label: "Fit to Page",
6954
+ type: "button",
6955
+ group: "zoom",
6956
+ execute: () => instance.fitToPage?.()
6957
+ },
6696
6958
  {
6697
6959
  id: "copy",
6698
6960
  icon: "copy",
@@ -6716,6 +6978,14 @@ var HtmlPreviewPlugin = class {
6716
6978
  type: "button",
6717
6979
  group: "actions",
6718
6980
  execute: () => instance.print?.()
6981
+ },
6982
+ {
6983
+ id: "open-window",
6984
+ icon: "open-window",
6985
+ label: "Open in Separate Full Window",
6986
+ type: "button",
6987
+ group: "actions",
6988
+ execute: () => instance.openInSeparateWindow?.()
6719
6989
  }
6720
6990
  ];
6721
6991
  }
@@ -6726,27 +6996,39 @@ var HtmlPreviewPlugin = class {
6726
6996
  ADD_TAGS: ["style", "link"],
6727
6997
  ADD_ATTR: ["target", "rel"]
6728
6998
  });
6999
+ const scrollWrapper = document.createElement("div");
7000
+ scrollWrapper.className = "fp-html-scroll-wrapper";
7001
+ scrollWrapper.style.minWidth = "100%";
7002
+ scrollWrapper.style.minHeight = "100%";
7003
+ scrollWrapper.style.width = "max-content";
7004
+ scrollWrapper.style.height = "max-content";
7005
+ scrollWrapper.style.display = "flex";
7006
+ scrollWrapper.style.justifyContent = "flex-start";
7007
+ scrollWrapper.style.alignItems = "flex-start";
7008
+ scrollWrapper.style.boxSizing = "border-box";
6729
7009
  const sizer = document.createElement("div");
6730
7010
  sizer.className = "fp-html-sizer";
6731
7011
  sizer.style.position = "relative";
7012
+ sizer.style.flexShrink = "0";
6732
7013
  const iframe = document.createElement("iframe");
6733
7014
  iframe.className = "fp-html-iframe";
6734
7015
  iframe.style.border = "none";
6735
7016
  iframe.style.backgroundColor = "#ffffff";
6736
7017
  iframe.style.transformOrigin = "top left";
6737
- iframe.style.transition = "transform 0.2s ease";
7018
+ iframe.style.transition = "transform 0.15s ease";
6738
7019
  iframe.sandbox.add("allow-same-origin");
6739
7020
  sizer.appendChild(iframe);
7021
+ scrollWrapper.appendChild(sizer);
6740
7022
  ctx.container.style.overflow = "auto";
6741
7023
  ctx.container.style.width = "100%";
6742
7024
  ctx.container.style.height = "100%";
6743
7025
  ctx.container.innerHTML = "";
6744
- ctx.container.appendChild(sizer);
7026
+ ctx.container.appendChild(scrollWrapper);
6745
7027
  iframe.srcdoc = sanitized;
6746
7028
  let scale = 1;
7029
+ let baseW = Math.max(600, ctx.container.clientWidth || 800);
7030
+ let baseH = Math.max(400, ctx.container.clientHeight || 600);
6747
7031
  const applyTransform = () => {
6748
- const baseW = Math.max(600, ctx.container.clientWidth || 800);
6749
- const baseH = Math.max(400, ctx.container.clientHeight || 600);
6750
7032
  const scaledW = Math.round(baseW * scale);
6751
7033
  const scaledH = Math.round(baseH * scale);
6752
7034
  sizer.style.width = `${scaledW}px`;
@@ -6759,22 +7041,33 @@ var HtmlPreviewPlugin = class {
6759
7041
  iframe.style.transform = `scale(${scale})`;
6760
7042
  iframe.style.transformOrigin = "top left";
6761
7043
  };
7044
+ const ro = typeof ResizeObserver !== "undefined" ? new ResizeObserver(() => {
7045
+ if (Math.abs(scale - 1) < 0.05) {
7046
+ baseW = Math.max(600, ctx.container.clientWidth || 800);
7047
+ baseH = Math.max(400, ctx.container.clientHeight || 600);
7048
+ applyTransform();
7049
+ }
7050
+ }) : null;
7051
+ ro?.observe(ctx.container);
6762
7052
  requestAnimationFrame(() => {
7053
+ baseW = Math.max(600, ctx.container.clientWidth || 800);
7054
+ baseH = Math.max(400, ctx.container.clientHeight || 600);
6763
7055
  applyTransform();
6764
7056
  });
6765
7057
  const cleanup = () => {
6766
- sizer.remove();
7058
+ ro?.disconnect();
7059
+ scrollWrapper.remove();
6767
7060
  ctx.container.innerHTML = "";
6768
7061
  };
6769
7062
  ctx.signal.addEventListener("abort", cleanup);
6770
7063
  return {
6771
7064
  destroy: cleanup,
6772
7065
  zoomIn: () => {
6773
- scale += 0.1;
7066
+ scale = Math.min(3.5, scale + 0.15);
6774
7067
  applyTransform();
6775
7068
  },
6776
7069
  zoomOut: () => {
6777
- scale = Math.max(0.2, scale - 0.1);
7070
+ scale = Math.max(0.25, scale - 0.15);
6778
7071
  applyTransform();
6779
7072
  },
6780
7073
  getZoom: () => scale,
@@ -6796,8 +7089,11 @@ var HtmlPreviewPlugin = class {
6796
7089
  ctx.container.scrollLeft = 0;
6797
7090
  applyTransform();
6798
7091
  },
7092
+ openInSeparateWindow: () => {
7093
+ ctx?.openInSeparateWindow?.();
7094
+ },
6799
7095
  copy: () => {
6800
- navigator.clipboard.writeText(rawHtml);
7096
+ navigator.clipboard?.writeText(rawHtml);
6801
7097
  },
6802
7098
  download: () => {
6803
7099
  const blob = new Blob([ctx.buffer], { type: "text/html" });
@@ -8918,7 +9214,7 @@ var FilePreview = memo(forwardRef(
8918
9214
  {
8919
9215
  ref: containerRef,
8920
9216
  className,
8921
- style: { width: "100%", height: "100%", position: "relative", ...style }
9217
+ style: { width: "100%", height: "100%", position: "relative", overflow: "hidden", ...style }
8922
9218
  }
8923
9219
  );
8924
9220
  }