Skip to content

fix(export): prevent wide tables from being cut off in PDFs (#15021) - #18341

Open
Florian DeLemarre (delemaf) wants to merge 1 commit into
masterfrom
issue/15021-fix-pdf-table-overflow
Open

Florian DeLemarre (delemaf) wants to merge 1 commit into
masterfrom
issue/15021-fix-pdf-table-overflow

Conversation

@delemaf

Copy link
Copy Markdown
Member

Proposed changes

Prevent tables containing long hashes or URLs from overflowing the printable page in built-in HTML/Markdown and Fintel PDF exports.

  • Replace pdfmake flexible (*) column widths with equal percentage widths. Flexible columns respect long tokens' minimum widths and can exceed the page; constrained widths allow those tokens to wrap.
  • Apply table preparation after Markdown conversion in the built-in export path, as well as in Fintel exports.
  • Count logical columns using colSpan so merged headers do not cause rendering failures.
  • Constrain table images to their cell content width while preserving aspect ratio, accounting for padding and each export's page margins.
  • Preserve source content, link targets, font size, and page orientation.
  • Add real rendered-PDF regression tests and declare the already-used PDF.js parser as a direct development dependency for PDF text, link, and image-bounds assertions.

Related issues

  • Related to fix(export): wide tables embedded in report content are cut off in PDF exports #15021: wide tables embedded in report content are cut off in PDF exports.
  • This PR covers the platform's built-in PDF conversion and Fintel exports. The ExportReportPDF connector uses WeasyPrint in the separate OpenCTI-Platform/connectors repository and requires its own fix. This PR deliberately does not auto-close the issue.
  • Automatic orientation changes are outside this PR's scope.

How to test this PR

  1. Add a four-column table to report content with ordinary prose, a 64-character SHA-256 hash, a long linked URL, and a final status column.
  2. Export using the built-in PDF conversion. Repeat with a Markdown file containing the same table and with a Fintel template containing the table.
  3. Verify that every column is visible inside the page margins, the full hash and URL are present, ordinary words wrap naturally, and the URL remains clickable with its original target.
  4. Add a merged header spanning all four columns and repeat the export. Confirm that PDF generation succeeds.
  5. Add a wide image to the last column. Confirm that it stays inside the cell without aspect-ratio distortion.
  6. Confirm that page orientation and font size remain unchanged.

Automated checks, from opencti-platform/opencti-front:

yarn test src/utils/htmlToPdf/utils/pdfTableWidth.test.ts src/utils/htmlToPdf/htmlToPdf.test.ts src/utils/htmlToPdf/utils/pdfUnnecessarytHtml.test.ts
yarn exec eslint src/utils/htmlToPdf/utils/pdfTableWidth.ts src/utils/htmlToPdf/utils/pdfTableWidth.test.ts src/utils/htmlToPdf/htmlToPdf.ts

Verification:

  • 26 focused frontend PDF tests pass, rerun before publishing.
  • Focused ESLint and editor diagnostics passed during verification.
  • FDS conformity reported 0 issues; library freshness was skipped because its source was unavailable.
  • The MUI regression gate reported 14 existing violations in untouched ingestion/settings files.
  • Full build, project-wide typecheck, and agent-driven live UI export were not run.

Checklist

  • I consider the submitted work as finished
  • I tested the code for its functionality
  • I wrote test cases for the relevant use cases (coverage and e2e)
  • I added/updated the relevant documentation (either on GitHub or on Notion)
  • Where necessary, I refactored code to improve the overall quality

Rendered-PDF regression tests are included; no new browser E2E tests or documentation changes are included.

Copilot AI lite review requested due to automatic review settings September 17, 2026 17:32
@github-actions github-actions Bot added the filigran team Item from the Filigran team. label Sep 17, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

One or more issues must be addressed before approval.

Get a fresh assessment by requesting another Copilot review.

Pull request overview

This PR fixes frontend PDF exports so wide tables wrap within page margins while preserving links, images, orientation, and font sizing.

Changes:

  • Constrains table columns and cell images for HTML, Markdown, and Fintel exports.
  • Handles merged headers using colSpan.
  • Adds rendered-PDF regression tests with PDF.js and declares pdfjs-dist directly.
File summaries
File Description
opencti-platform/opencti-front/yarn.lock Updated as part of this pull request.
opencti-platform/opencti-front/src/utils/htmlToPdf/utils/pdfTableWidth.ts Updated as part of this pull request.
opencti-platform/opencti-front/src/utils/htmlToPdf/utils/pdfTableWidth.test.ts Updated as part of this pull request.
opencti-platform/opencti-front/src/utils/htmlToPdf/htmlToPdf.ts Updated as part of this pull request.
opencti-platform/opencti-front/package.json Updated as part of this pull request.
Review details

Suppressed comments (1)

opencti-platform/opencti-front/src/utils/htmlToPdf/utils/pdfTableWidth.test.ts:37

  • The Markdown branch never sets spanningHeader: true, and the markdown string does not include the heading at all. Consequently, the new post-Markdown-conversion path is not tested with a merged header—the colSpan case this change is intended to support—so a regression in the combined Markdown/merged-header flow could pass these tests. Include a Markdown export containing the equivalent raw HTML merged header.
  const exportCases = ['table helper', 'HTML', 'Markdown', 'Fintel'].flatMap((exportType) => (
    exportType === 'Markdown'
      ? [{ exportType, spanningHeader: false }]
      : [{ exportType, spanningHeader: false }, { exportType, spanningHeader: true }]
  • Files reviewed: 4/5 changed files
  • Comments generated: 2
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +17 to +19
const firstRow = table.rows[0];
if (firstRow) {
const columnCount = Array.from(firstRow.cells).reduce((total, cell) => total + cell.colSpan, 0);
Comment on lines +31 to +33
cell.querySelectorAll('img').forEach((image) => {
if (image.closest('td, th') === cell) image.style.maxWidth = `${cellWidth}pt`;
});
@codecov

codecov Bot commented Sep 17, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 36.65%. Comparing base (ae687f0) to head (4a795c7).
⚠️ Report is 1 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master   #18341      +/-   ##
==========================================
+ Coverage   36.57%   36.65%   +0.08%     
==========================================
  Files        3467     3467              
  Lines      141069   141079      +10     
  Branches    38098    38099       +1     
==========================================
+ Hits        51593    51719     +126     
+ Misses      89476    89360     -116     
Flag Coverage Δ
opencti-client-python 49.85% <ø> (ø)
opencti-front 13.20% <100.00%> (+0.15%) ⬆️
opencti-graphql 71.43% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

filigran team Item from the Filigran team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants