@formfeed/engine 0.3.6 → 0.3.7

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/index.cjs CHANGED
@@ -1556,6 +1556,7 @@ function scanBlocks(source, spec) {
1556
1556
  severity: "error",
1557
1557
  code: "unexpected-end-tag",
1558
1558
  message: `Unexpected {% ${keyword} %} without an open block`,
1559
+ args: { keyword },
1559
1560
  range
1560
1561
  });
1561
1562
  } else if (top.keyword !== expected) {
@@ -1563,6 +1564,7 @@ function scanBlocks(source, spec) {
1563
1564
  severity: "error",
1564
1565
  code: "mismatched-end-tag",
1565
1566
  message: `Expected {% end${top.keyword} %} to close the {% ${top.keyword} %} at line ${top.block.open.start.line}, found {% ${keyword} %}`,
1567
+ args: { open: top.keyword, line: top.block.open.start.line, found: keyword },
1566
1568
  range
1567
1569
  });
1568
1570
  const idx = stack.map((s) => s.keyword).lastIndexOf(expected);
@@ -1579,6 +1581,7 @@ function scanBlocks(source, spec) {
1579
1581
  severity: "error",
1580
1582
  code: "unexpected-tag",
1581
1583
  message: `{% ${keyword} %} outside of a block`,
1584
+ args: { keyword },
1582
1585
  range
1583
1586
  });
1584
1587
  }
@@ -1588,6 +1591,7 @@ function scanBlocks(source, spec) {
1588
1591
  severity: "error",
1589
1592
  code: "unclosed-block",
1590
1593
  message: `{% ${open.keyword} %} is never closed; add {% end${open.keyword} %}`,
1594
+ args: { keyword: open.keyword },
1591
1595
  range: open.block.open
1592
1596
  });
1593
1597
  }
@@ -1642,6 +1646,7 @@ function missingPathDiagnostics(variables, sampleData, loopSources, builtinRoots
1642
1646
  severity: "warning",
1643
1647
  code: "unknown-variable",
1644
1648
  message: `"${v.path.join(".")}" is not present in the sample data`,
1649
+ args: { name: v.path.join(".") },
1645
1650
  range: v.range
1646
1651
  });
1647
1652
  }
@@ -1892,6 +1897,7 @@ function analyzeHandlebars(source, opts = {}) {
1892
1897
  severity: "warning",
1893
1898
  code: "deprecated-filter",
1894
1899
  message: `"${f.name}" is a compatibility alias; use "${preferred}"`,
1900
+ args: { name: f.name, preferred },
1895
1901
  range: f.range,
1896
1902
  fix: { title: `Rename to ${preferred}`, replacement: preferred }
1897
1903
  });
@@ -1907,6 +1913,7 @@ function analyzeHandlebars(source, opts = {}) {
1907
1913
  severity: "error",
1908
1914
  code: "unknown-filter",
1909
1915
  message: `Unknown helper "${f.name}"`,
1916
+ args: { name: f.name, kind: "helper" },
1910
1917
  range: f.range
1911
1918
  });
1912
1919
  }
@@ -2701,6 +2708,7 @@ function analyzeJinja2(source, opts = {}) {
2701
2708
  severity: "warning",
2702
2709
  code: "deprecated-filter",
2703
2710
  message: `"${f.name}" is an apitemplate.io compatibility alias; use "${preferred}"`,
2711
+ args: { name: f.name, preferred },
2704
2712
  range: f.range,
2705
2713
  fix: { title: `Rename to ${preferred}`, replacement: preferred }
2706
2714
  });
@@ -2716,6 +2724,7 @@ function analyzeJinja2(source, opts = {}) {
2716
2724
  severity: "error",
2717
2725
  code: "unknown-filter",
2718
2726
  message: `Unknown filter or helper "${f.name}"`,
2727
+ args: { name: f.name, kind: "filter-or-helper" },
2719
2728
  range: f.range
2720
2729
  });
2721
2730
  }
@@ -3116,6 +3125,7 @@ function analyzeLiquid(source, opts = {}) {
3116
3125
  severity: "warning",
3117
3126
  code: "deprecated-filter",
3118
3127
  message: `"${f.name}" is a compatibility alias; use "${preferred}"`,
3128
+ args: { name: f.name, preferred },
3119
3129
  range: f.range,
3120
3130
  fix: { title: `Rename to ${preferred}`, replacement: preferred }
3121
3131
  });
@@ -3131,6 +3141,7 @@ function analyzeLiquid(source, opts = {}) {
3131
3141
  severity: "error",
3132
3142
  code: "unknown-filter",
3133
3143
  message: `Unknown filter "${f.name}"`,
3144
+ args: { name: f.name, kind: "filter" },
3134
3145
  range: f.range
3135
3146
  });
3136
3147
  }
@@ -5663,6 +5674,58 @@ var pageNavScript = `<script>
5663
5674
  }, { passive: true });
5664
5675
  })();
5665
5676
  </script>`;
5677
+ function overflowScript(mode) {
5678
+ return `<script>
5679
+ (function () {
5680
+ var clipped = function (el, stop) {
5681
+ for (var p = el.parentElement; p && p !== stop; p = p.parentElement)
5682
+ if (getComputedStyle(p).overflowX !== 'visible') return true;
5683
+ return false;
5684
+ };
5685
+ var measure = function () {
5686
+ try {
5687
+ var boxes = ${mode === "paged" ? "document.querySelectorAll('.pagedjs_page_content')" : "[document.body]"};
5688
+ var worst = null;
5689
+ for (var i = 0; i < boxes.length; i++) {
5690
+ var box = boxes[i], rect = box.getBoundingClientRect(), style = getComputedStyle(box);
5691
+ var left = rect.left + parseFloat(style.paddingLeft || '0') + parseFloat(style.borderLeftWidth || '0');
5692
+ var right = rect.right - parseFloat(style.paddingRight || '0') - parseFloat(style.borderRightWidth || '0');
5693
+ if (right - left <= 0) continue;
5694
+ var all = box.querySelectorAll('*');
5695
+ for (var j = 0; j < all.length; j++) {
5696
+ var el = all[j];
5697
+ // Paged.js wraps each page's content in a div of its own that spans its layout columns
5698
+ if (${mode === "paged"} && el.parentElement === box && !el.className) continue;
5699
+ if (el.closest('.formfeed-chrome, .ff-running-header, .ff-running-footer, script, style, head')) continue;
5700
+ var over = el.getBoundingClientRect().right - right;
5701
+ if (over <= 1 || (worst && over <= worst.over)) continue;
5702
+ if (getComputedStyle(el).position === 'fixed' || clipped(el, box)) continue;
5703
+ worst = { over: over, width: right - left, el: el };
5704
+ }
5705
+ }
5706
+ var overflow = null;
5707
+ if (worst) {
5708
+ var ref = document.createElement('div');
5709
+ ref.style.cssText = 'position:absolute;visibility:hidden;width:100mm;height:0';
5710
+ document.body.appendChild(ref);
5711
+ var pxPerMm = ref.getBoundingClientRect().width / 100 || 1;
5712
+ ref.remove();
5713
+ var annotated = worst.el.closest('[data-ff-src]');
5714
+ overflow = {
5715
+ overflowMm: Math.round((worst.over / pxPerMm) * 10) / 10,
5716
+ scale: Math.round((worst.width / (worst.width + worst.over)) * 1000) / 1000,
5717
+ tag: worst.el.tagName.toLowerCase(),
5718
+ src: annotated ? annotated.getAttribute('data-ff-src') : null,
5719
+ };
5720
+ }
5721
+ parent.postMessage({ type: 'formfeed:overflow', overflow: overflow }, '*');
5722
+ } catch (e) {}
5723
+ };
5724
+ window.formfeedCheckOverflow = measure;
5725
+ ${mode === "flow" ? "window.addEventListener('load', function () { (document.fonts ? document.fonts.ready : Promise.resolve()).then(measure); });" : ""}
5726
+ })();
5727
+ </script>`;
5728
+ }
5666
5729
  var zoomGestureScript = `<script>
5667
5730
  (function () {
5668
5731
  var say = function (message) { try { parent.postMessage(message, '*'); } catch (e) {} };
@@ -5709,7 +5772,7 @@ body.formfeed-preview { position: relative; box-sizing: border-box; width: ${pap
5709
5772
  </style>` : `<style data-formfeed="preview">html { background: #e5e7eb; } body.formfeed-preview { margin: 24px auto; background: #fff; box-shadow: 0 1px 3px rgba(0,0,0,.2); }</style>`;
5710
5773
  const header = headerHtml ? `<div class="formfeed-chrome" style="${pdf ? flowChromeStyle(settings, "header") : `${chromeBoxStyle(settings, "header")}margin-bottom:8px`}">${headerHtml}</div>` : "";
5711
5774
  const footer = footerHtml ? `<div class="formfeed-chrome" style="${pdf ? flowChromeStyle(settings, "footer") : `${chromeBoxStyle(settings, "footer")}margin-top:8px`}">${pageNumberSpans(footerHtml, "1", "1")}</div>` : "";
5712
- return intoHead(draft.document, `${chrome}${inspectScript}${zoomGestureScript}`).replace(/(<body[^>]*>)/, `$1${header}`).replace("</body>", `${footer}</body>`);
5775
+ return intoHead(draft.document, `${chrome}${inspectScript}${zoomGestureScript}${pdf ? overflowScript("flow") : ""}`).replace(/(<body[^>]*>)/, `$1${header}`).replace("</body>", `${footer}</body>`);
5713
5776
  }
5714
5777
  function pagedDocument(draft, options) {
5715
5778
  const { headerHtml, footerHtml, settings } = draft;
@@ -5731,13 +5794,13 @@ html { background: #e5e7eb; }
5731
5794
  `;
5732
5795
  const selectorGuard = `<script>(function(){var q=DocumentFragment.prototype.querySelectorAll;DocumentFragment.prototype.querySelectorAll=function(s){try{return q.call(this,s);}catch(e){console.warn('formfeed paged preview: skipped a selector Paged.js could not use:',s);return q.call(this,':not(*)');}};})();</script>`;
5733
5796
  const boxSizingGuard = `<script>(function(){var rule='.pagedjs_pagebox *';var o=new MutationObserver(function(ms){ms.forEach(function(m){m.addedNodes.forEach(function(n){if(n.nodeName==='STYLE'&&n.textContent&&n.textContent.indexOf(rule)>=0){n.textContent=n.textContent.split(rule).join('.pagedjs_pagebox [class*="pagedjs_"]');o.disconnect();}});});});o.observe(document.documentElement,{childList:true,subtree:true});})();</script>`;
5734
- const config = `<script>window.PagedConfig = { auto: true, after: function (flow) { try { if (window.formfeedDrawCharts) window.formfeedDrawCharts(); } catch (e) {} try { parent.postMessage({ type: 'formfeed:pages', pages: flow.total }, '*'); } catch (e) {} } };</script>`;
5797
+ const config = `<script>window.PagedConfig = { auto: true, after: function (flow) { try { if (window.formfeedDrawCharts) window.formfeedDrawCharts(); } catch (e) {} try { parent.postMessage({ type: 'formfeed:pages', pages: flow.total }, '*'); } catch (e) {} if (window.formfeedCheckOverflow) window.formfeedCheckOverflow(); } };</script>`;
5735
5798
  const script = `<script src="${options.pagedScriptUrl}"></script>`;
5736
5799
  const header = headerHtml ? `<div class="ff-running-header">${pageNumberSpans(headerHtml, '<span class="ff-page-no"></span>', '<span class="ff-page-total"></span>')}</div>` : "";
5737
5800
  const footer = footerHtml ? `<div class="ff-running-footer">${pageNumberSpans(footerHtml, '<span class="ff-page-no"></span>', '<span class="ff-page-total"></span>')}</div>` : "";
5738
5801
  return intoHead(
5739
5802
  draft.document,
5740
- `<style data-formfeed="paged">${runningCss}</style>${selectorGuard}${boxSizingGuard}${config}${script}${inspectScript}${pageNavScript}${zoomGestureScript}`
5803
+ `<style data-formfeed="paged">${runningCss}</style>${selectorGuard}${boxSizingGuard}${overflowScript("paged")}${config}${script}${inspectScript}${pageNavScript}${zoomGestureScript}`
5741
5804
  ).replace(/(<body[^>]*>)/, `$1${header}${footer}`);
5742
5805
  }
5743
5806
 
package/index.js CHANGED
@@ -1421,6 +1421,7 @@ function scanBlocks(source, spec) {
1421
1421
  severity: "error",
1422
1422
  code: "unexpected-end-tag",
1423
1423
  message: `Unexpected {% ${keyword} %} without an open block`,
1424
+ args: { keyword },
1424
1425
  range
1425
1426
  });
1426
1427
  } else if (top.keyword !== expected) {
@@ -1428,6 +1429,7 @@ function scanBlocks(source, spec) {
1428
1429
  severity: "error",
1429
1430
  code: "mismatched-end-tag",
1430
1431
  message: `Expected {% end${top.keyword} %} to close the {% ${top.keyword} %} at line ${top.block.open.start.line}, found {% ${keyword} %}`,
1432
+ args: { open: top.keyword, line: top.block.open.start.line, found: keyword },
1431
1433
  range
1432
1434
  });
1433
1435
  const idx = stack.map((s) => s.keyword).lastIndexOf(expected);
@@ -1444,6 +1446,7 @@ function scanBlocks(source, spec) {
1444
1446
  severity: "error",
1445
1447
  code: "unexpected-tag",
1446
1448
  message: `{% ${keyword} %} outside of a block`,
1449
+ args: { keyword },
1447
1450
  range
1448
1451
  });
1449
1452
  }
@@ -1453,6 +1456,7 @@ function scanBlocks(source, spec) {
1453
1456
  severity: "error",
1454
1457
  code: "unclosed-block",
1455
1458
  message: `{% ${open.keyword} %} is never closed; add {% end${open.keyword} %}`,
1459
+ args: { keyword: open.keyword },
1456
1460
  range: open.block.open
1457
1461
  });
1458
1462
  }
@@ -1507,6 +1511,7 @@ function missingPathDiagnostics(variables, sampleData, loopSources, builtinRoots
1507
1511
  severity: "warning",
1508
1512
  code: "unknown-variable",
1509
1513
  message: `"${v.path.join(".")}" is not present in the sample data`,
1514
+ args: { name: v.path.join(".") },
1510
1515
  range: v.range
1511
1516
  });
1512
1517
  }
@@ -1757,6 +1762,7 @@ function analyzeHandlebars(source, opts = {}) {
1757
1762
  severity: "warning",
1758
1763
  code: "deprecated-filter",
1759
1764
  message: `"${f.name}" is a compatibility alias; use "${preferred}"`,
1765
+ args: { name: f.name, preferred },
1760
1766
  range: f.range,
1761
1767
  fix: { title: `Rename to ${preferred}`, replacement: preferred }
1762
1768
  });
@@ -1772,6 +1778,7 @@ function analyzeHandlebars(source, opts = {}) {
1772
1778
  severity: "error",
1773
1779
  code: "unknown-filter",
1774
1780
  message: `Unknown helper "${f.name}"`,
1781
+ args: { name: f.name, kind: "helper" },
1775
1782
  range: f.range
1776
1783
  });
1777
1784
  }
@@ -2566,6 +2573,7 @@ function analyzeJinja2(source, opts = {}) {
2566
2573
  severity: "warning",
2567
2574
  code: "deprecated-filter",
2568
2575
  message: `"${f.name}" is an apitemplate.io compatibility alias; use "${preferred}"`,
2576
+ args: { name: f.name, preferred },
2569
2577
  range: f.range,
2570
2578
  fix: { title: `Rename to ${preferred}`, replacement: preferred }
2571
2579
  });
@@ -2581,6 +2589,7 @@ function analyzeJinja2(source, opts = {}) {
2581
2589
  severity: "error",
2582
2590
  code: "unknown-filter",
2583
2591
  message: `Unknown filter or helper "${f.name}"`,
2592
+ args: { name: f.name, kind: "filter-or-helper" },
2584
2593
  range: f.range
2585
2594
  });
2586
2595
  }
@@ -2981,6 +2990,7 @@ function analyzeLiquid(source, opts = {}) {
2981
2990
  severity: "warning",
2982
2991
  code: "deprecated-filter",
2983
2992
  message: `"${f.name}" is a compatibility alias; use "${preferred}"`,
2993
+ args: { name: f.name, preferred },
2984
2994
  range: f.range,
2985
2995
  fix: { title: `Rename to ${preferred}`, replacement: preferred }
2986
2996
  });
@@ -2996,6 +3006,7 @@ function analyzeLiquid(source, opts = {}) {
2996
3006
  severity: "error",
2997
3007
  code: "unknown-filter",
2998
3008
  message: `Unknown filter "${f.name}"`,
3009
+ args: { name: f.name, kind: "filter" },
2999
3010
  range: f.range
3000
3011
  });
3001
3012
  }
@@ -5528,6 +5539,58 @@ var pageNavScript = `<script>
5528
5539
  }, { passive: true });
5529
5540
  })();
5530
5541
  </script>`;
5542
+ function overflowScript(mode) {
5543
+ return `<script>
5544
+ (function () {
5545
+ var clipped = function (el, stop) {
5546
+ for (var p = el.parentElement; p && p !== stop; p = p.parentElement)
5547
+ if (getComputedStyle(p).overflowX !== 'visible') return true;
5548
+ return false;
5549
+ };
5550
+ var measure = function () {
5551
+ try {
5552
+ var boxes = ${mode === "paged" ? "document.querySelectorAll('.pagedjs_page_content')" : "[document.body]"};
5553
+ var worst = null;
5554
+ for (var i = 0; i < boxes.length; i++) {
5555
+ var box = boxes[i], rect = box.getBoundingClientRect(), style = getComputedStyle(box);
5556
+ var left = rect.left + parseFloat(style.paddingLeft || '0') + parseFloat(style.borderLeftWidth || '0');
5557
+ var right = rect.right - parseFloat(style.paddingRight || '0') - parseFloat(style.borderRightWidth || '0');
5558
+ if (right - left <= 0) continue;
5559
+ var all = box.querySelectorAll('*');
5560
+ for (var j = 0; j < all.length; j++) {
5561
+ var el = all[j];
5562
+ // Paged.js wraps each page's content in a div of its own that spans its layout columns
5563
+ if (${mode === "paged"} && el.parentElement === box && !el.className) continue;
5564
+ if (el.closest('.formfeed-chrome, .ff-running-header, .ff-running-footer, script, style, head')) continue;
5565
+ var over = el.getBoundingClientRect().right - right;
5566
+ if (over <= 1 || (worst && over <= worst.over)) continue;
5567
+ if (getComputedStyle(el).position === 'fixed' || clipped(el, box)) continue;
5568
+ worst = { over: over, width: right - left, el: el };
5569
+ }
5570
+ }
5571
+ var overflow = null;
5572
+ if (worst) {
5573
+ var ref = document.createElement('div');
5574
+ ref.style.cssText = 'position:absolute;visibility:hidden;width:100mm;height:0';
5575
+ document.body.appendChild(ref);
5576
+ var pxPerMm = ref.getBoundingClientRect().width / 100 || 1;
5577
+ ref.remove();
5578
+ var annotated = worst.el.closest('[data-ff-src]');
5579
+ overflow = {
5580
+ overflowMm: Math.round((worst.over / pxPerMm) * 10) / 10,
5581
+ scale: Math.round((worst.width / (worst.width + worst.over)) * 1000) / 1000,
5582
+ tag: worst.el.tagName.toLowerCase(),
5583
+ src: annotated ? annotated.getAttribute('data-ff-src') : null,
5584
+ };
5585
+ }
5586
+ parent.postMessage({ type: 'formfeed:overflow', overflow: overflow }, '*');
5587
+ } catch (e) {}
5588
+ };
5589
+ window.formfeedCheckOverflow = measure;
5590
+ ${mode === "flow" ? "window.addEventListener('load', function () { (document.fonts ? document.fonts.ready : Promise.resolve()).then(measure); });" : ""}
5591
+ })();
5592
+ </script>`;
5593
+ }
5531
5594
  var zoomGestureScript = `<script>
5532
5595
  (function () {
5533
5596
  var say = function (message) { try { parent.postMessage(message, '*'); } catch (e) {} };
@@ -5574,7 +5637,7 @@ body.formfeed-preview { position: relative; box-sizing: border-box; width: ${pap
5574
5637
  </style>` : `<style data-formfeed="preview">html { background: #e5e7eb; } body.formfeed-preview { margin: 24px auto; background: #fff; box-shadow: 0 1px 3px rgba(0,0,0,.2); }</style>`;
5575
5638
  const header = headerHtml ? `<div class="formfeed-chrome" style="${pdf ? flowChromeStyle(settings, "header") : `${chromeBoxStyle(settings, "header")}margin-bottom:8px`}">${headerHtml}</div>` : "";
5576
5639
  const footer = footerHtml ? `<div class="formfeed-chrome" style="${pdf ? flowChromeStyle(settings, "footer") : `${chromeBoxStyle(settings, "footer")}margin-top:8px`}">${pageNumberSpans(footerHtml, "1", "1")}</div>` : "";
5577
- return intoHead(draft.document, `${chrome}${inspectScript}${zoomGestureScript}`).replace(/(<body[^>]*>)/, `$1${header}`).replace("</body>", `${footer}</body>`);
5640
+ return intoHead(draft.document, `${chrome}${inspectScript}${zoomGestureScript}${pdf ? overflowScript("flow") : ""}`).replace(/(<body[^>]*>)/, `$1${header}`).replace("</body>", `${footer}</body>`);
5578
5641
  }
5579
5642
  function pagedDocument(draft, options) {
5580
5643
  const { headerHtml, footerHtml, settings } = draft;
@@ -5596,13 +5659,13 @@ html { background: #e5e7eb; }
5596
5659
  `;
5597
5660
  const selectorGuard = `<script>(function(){var q=DocumentFragment.prototype.querySelectorAll;DocumentFragment.prototype.querySelectorAll=function(s){try{return q.call(this,s);}catch(e){console.warn('formfeed paged preview: skipped a selector Paged.js could not use:',s);return q.call(this,':not(*)');}};})();</script>`;
5598
5661
  const boxSizingGuard = `<script>(function(){var rule='.pagedjs_pagebox *';var o=new MutationObserver(function(ms){ms.forEach(function(m){m.addedNodes.forEach(function(n){if(n.nodeName==='STYLE'&&n.textContent&&n.textContent.indexOf(rule)>=0){n.textContent=n.textContent.split(rule).join('.pagedjs_pagebox [class*="pagedjs_"]');o.disconnect();}});});});o.observe(document.documentElement,{childList:true,subtree:true});})();</script>`;
5599
- const config = `<script>window.PagedConfig = { auto: true, after: function (flow) { try { if (window.formfeedDrawCharts) window.formfeedDrawCharts(); } catch (e) {} try { parent.postMessage({ type: 'formfeed:pages', pages: flow.total }, '*'); } catch (e) {} } };</script>`;
5662
+ const config = `<script>window.PagedConfig = { auto: true, after: function (flow) { try { if (window.formfeedDrawCharts) window.formfeedDrawCharts(); } catch (e) {} try { parent.postMessage({ type: 'formfeed:pages', pages: flow.total }, '*'); } catch (e) {} if (window.formfeedCheckOverflow) window.formfeedCheckOverflow(); } };</script>`;
5600
5663
  const script = `<script src="${options.pagedScriptUrl}"></script>`;
5601
5664
  const header = headerHtml ? `<div class="ff-running-header">${pageNumberSpans(headerHtml, '<span class="ff-page-no"></span>', '<span class="ff-page-total"></span>')}</div>` : "";
5602
5665
  const footer = footerHtml ? `<div class="ff-running-footer">${pageNumberSpans(footerHtml, '<span class="ff-page-no"></span>', '<span class="ff-page-total"></span>')}</div>` : "";
5603
5666
  return intoHead(
5604
5667
  draft.document,
5605
- `<style data-formfeed="paged">${runningCss}</style>${selectorGuard}${boxSizingGuard}${config}${script}${inspectScript}${pageNavScript}${zoomGestureScript}`
5668
+ `<style data-formfeed="paged">${runningCss}</style>${selectorGuard}${boxSizingGuard}${overflowScript("paged")}${config}${script}${inspectScript}${pageNavScript}${zoomGestureScript}`
5606
5669
  ).replace(/(<body[^>]*>)/, `$1${header}${footer}`);
5607
5670
  }
5608
5671
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@formfeed/engine",
3
- "version": "0.3.6",
3
+ "version": "0.3.7",
4
4
  "description": "The Formfeed template engine (Jinja2, Liquid, Handlebars) for the browser and Node.",
5
5
  "license": "MIT",
6
6
  "type": "module",
package/types/index.d.cts CHANGED
@@ -22,7 +22,7 @@ export type { JsonSchema, SchemaChange, SchemaChangeKind, SchemaDiff } from './l
22
22
  export { DEFAULT_CHROME_PADDING, assembleDocument, chartInitScript, defaultSettings, fontFaceCss, mergeSettings, pageSize, printReset, renderVersion, } from './lib/assemble.cjs';
23
23
  export type { ChartSpec, ImageOptions } from './lib/helpers/index.cjs';
24
24
  export { flowDocument, pagedDocument, pageNumberSpans, paperOf, zoomGestureScript } from './lib/preview.cjs';
25
- export type { PagedOptions, RenderedDraft } from './lib/preview.cjs';
25
+ export type { PagedOptions, PreviewOverflow, RenderedDraft } from './lib/preview.cjs';
26
26
  export { annotateSourcePositions, parseSourceAttribute, sourceAttribute, } from './lib/source-positions.cjs';
27
27
  export type { SourceFile, SourceLocation } from './lib/source-positions.cjs';
28
28
  export type { AssembleExtras, AssembleInput, AssembleVendor, FontFace, HeaderFooterSettings, RenderedDocument, TemplateKind, TemplateSettings, VersionSource, } from './lib/assemble.cjs';
package/types/index.d.ts CHANGED
@@ -22,7 +22,7 @@ export type { JsonSchema, SchemaChange, SchemaChangeKind, SchemaDiff } from './l
22
22
  export { DEFAULT_CHROME_PADDING, assembleDocument, chartInitScript, defaultSettings, fontFaceCss, mergeSettings, pageSize, printReset, renderVersion, } from './lib/assemble.js';
23
23
  export type { ChartSpec, ImageOptions } from './lib/helpers/index.js';
24
24
  export { flowDocument, pagedDocument, pageNumberSpans, paperOf, zoomGestureScript } from './lib/preview.js';
25
- export type { PagedOptions, RenderedDraft } from './lib/preview.js';
25
+ export type { PagedOptions, PreviewOverflow, RenderedDraft } from './lib/preview.js';
26
26
  export { annotateSourcePositions, parseSourceAttribute, sourceAttribute, } from './lib/source-positions.js';
27
27
  export type { SourceFile, SourceLocation } from './lib/source-positions.js';
28
28
  export type { AssembleExtras, AssembleInput, AssembleVendor, FontFace, HeaderFooterSettings, RenderedDocument, TemplateKind, TemplateSettings, VersionSource, } from './lib/assemble.js';
@@ -22,6 +22,19 @@ export declare function paperOf(settings: TemplateSettings): {
22
22
  * the element stays so its styling applies.
23
23
  */
24
24
  export declare const pageNumberSpans: (html: string, page: string, total: string) => string;
25
+ /** What the preview frame reports about content wider than the page, or `null` when nothing is. */
26
+ export interface PreviewOverflow {
27
+ /** How far the widest element reaches past the right edge of the page's content area. */
28
+ overflowMm: number;
29
+ /**
30
+ * The factor Chromium shrinks every page of the PDF by to fit that element: the content width
31
+ * divided by the width the element needs.
32
+ */
33
+ scale: number;
34
+ tag: string;
35
+ /** `data-ff-src` of the element or its nearest annotated ancestor, as click-to-source reports it. */
36
+ src: string | null;
37
+ }
25
38
  /**
26
39
  * Zoom gestures inside a preview frame: Ctrl+wheel (a touchpad pinch arrives as one too) and
27
40
  * Ctrl+plus/minus/0 would zoom the whole app, and the sandboxed frame's events never reach the app,
@@ -22,6 +22,19 @@ export declare function paperOf(settings: TemplateSettings): {
22
22
  * the element stays so its styling applies.
23
23
  */
24
24
  export declare const pageNumberSpans: (html: string, page: string, total: string) => string;
25
+ /** What the preview frame reports about content wider than the page, or `null` when nothing is. */
26
+ export interface PreviewOverflow {
27
+ /** How far the widest element reaches past the right edge of the page's content area. */
28
+ overflowMm: number;
29
+ /**
30
+ * The factor Chromium shrinks every page of the PDF by to fit that element: the content width
31
+ * divided by the width the element needs.
32
+ */
33
+ scale: number;
34
+ tag: string;
35
+ /** `data-ff-src` of the element or its nearest annotated ancestor, as click-to-source reports it. */
36
+ src: string | null;
37
+ }
25
38
  /**
26
39
  * Zoom gestures inside a preview frame: Ctrl+wheel (a touchpad pinch arrives as one too) and
27
40
  * Ctrl+plus/minus/0 would zoom the whole app, and the sandboxed frame's events never reach the app,
@@ -25,6 +25,11 @@ export interface Diagnostic {
25
25
  title: string;
26
26
  replacement: string;
27
27
  };
28
+ /**
29
+ * The values `message` was built from (a variable path, a helper name, a block keyword), so the
30
+ * editor can say the same in the reader's language; `message` stays the English text.
31
+ */
32
+ args?: Record<string, string | number>;
28
33
  }
29
34
  export interface VariableRef {
30
35
  path: string[];
@@ -25,6 +25,11 @@ export interface Diagnostic {
25
25
  title: string;
26
26
  replacement: string;
27
27
  };
28
+ /**
29
+ * The values `message` was built from (a variable path, a helper name, a block keyword), so the
30
+ * editor can say the same in the reader's language; `message` stays the English text.
31
+ */
32
+ args?: Record<string, string | number>;
28
33
  }
29
34
  export interface VariableRef {
30
35
  path: string[];