feat(web): add multi-format report export (Markdown, HTML, PDF, Word,… (#756)

* feat(web): add multi-format report export (Markdown, HTML, PDF, Word, Image)

* fix: correct import order for docx (lint error)

* fix(web): address Copilot review comments for multi-format export

- Add i18n support for dropdown menu items (en/zh)

- Add DOMPurify for HTML sanitization (XSS protection)

- Fix async handling for canvas.toBlob with Promise wrapper

- Add toast notifications for export errors

- Fix Tooltip + DropdownMenuTrigger nesting (accessibility)

- Ensure container cleanup in finally block

* fix(web): enhance markdown parsing for PDF and Word export

- Add list support (bullet and numbered) for PDF export
- Add parseInlineMarkdown helper for Word export to handle bold, italic, code, links
- Add list support for Word export (bullet and numbered)
- Address Copilot review comments from PR #756

* fix(web): address PR review feedback for multi-format export

- Extract PDF formatting magic numbers into PDF_CONSTANTS

- Add Tooltip wrapper for download dropdown button

- Reduce triggerDownload cleanup timeout from 1000ms to 100ms

- Use marked.Lexer.lexInline for robust markdown parsing

- Add console.warn for image export cleanup errors

- Add numbering config for Word document ordered lists

- Fix CSS class typo: px-5pb-20 -> px-5 pb-20

- Remove unreachable dead code in parseInlineMarkdown

---------

Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
This commit is contained in:
Jiahe Wu
2025-12-16 09:06:24 +08:00
committed by GitHub
parent 2a97170b6c
commit a4f64abd1f
5 changed files with 1083 additions and 113 deletions

View File

@@ -49,21 +49,28 @@
"@tiptap/extension-table-row": "^2.11.7",
"@tiptap/extension-text": "^2.12.0",
"@tiptap/react": "^2.11.7",
"@types/dompurify": "^3.2.0",
"@types/js-cookie": "^3.0.6",
"@xyflow/react": "^12.6.0",
"best-effort-json-parser": "^1.1.3",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"cmdk": "^1.1.1",
"docx": "^9.5.1",
"dompurify": "^3.3.1",
"file-saver": "^2.0.5",
"framer-motion": "^12.6.5",
"hast": "^1.0.0",
"highlight.js": "^11.11.1",
"html2canvas": "^1.4.1",
"immer": "^10.1.1",
"js-cookie": "^3.0.5",
"jspdf": "^3.0.4",
"katex": "^0.16.21",
"lowlight": "^3.3.0",
"lru-cache": "^11.1.0",
"lucide-react": "^0.487.0",
"marked": "^17.0.1",
"motion": "^12.7.4",
"nanoid": "^5.1.5",
"next": "^15.4.10",
@@ -94,6 +101,7 @@
"@tailwindcss/postcss": "^4.0.15",
"@testing-library/dom": "^10.4.1",
"@testing-library/react": "^16.3.0",
"@types/file-saver": "^2.0.7",
"@types/hast": "^3.0.4",
"@types/jest": "^30.0.0",
"@types/node": "^20.14.10",