From 098f2badec3adf141944c0946870c99622415410 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20Sz=C3=BCcs?= <127139797+balazs-szucs@users.noreply.github.com> Date: Tue, 23 Dec 2025 00:05:52 +0100 Subject: [PATCH] [V2] feat(getPdfInfo): add attachment, embedded file, and image info display (#5278) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description of Changes This pull request enhances the display of PDF metadata in the "Other" and "Per Page" sections by introducing more detailed and user-friendly rendering of attachments, embedded files, and images. The changes add new helper functions for rendering these lists and extend the type definitions to support richer information, improving the clarity and usefulness of the UI. **Improvements to PDF metadata rendering:** * Added `renderAttachmentsList` and `renderEmbeddedFilesList` helper functions in `OtherSection.tsx` to display detailed information about attachments and embedded files, including name, description, file size, MIME type, and dates. These replace the generic list renderer for these fields. * Added `renderImagesList` helper function in `PerPageSection.tsx` to display images with their name, dimensions, and color space, replacing the generic list renderer for images. **Type definition enhancements:** * Extended `PdfEmbeddedFileInfo` and `PdfAttachmentInfo` in `getPdfInfo.ts` to include additional fields: `FileSize`, `MimeType`, `CreationDate`, and `ModificationDate` for embedded files, and `FileSize` for attachments. image --- ## Checklist ### General - [X] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [X] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md) (if applicable) - [ ] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md) (if applicable) - [X] I have performed a self-review of my own code - [X] My changes generate no new warnings ### Documentation - [ ] I have updated relevant docs on [Stirling-PDF's doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) (if functionality has heavily changed) - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### Translations (if applicable) - [ ] I ran [`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md) ### UI Changes (if applicable) - [X] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [X] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md#6-testing) for more details. --------- Signed-off-by: Balázs Szücs --- .../getPdfInfo/sections/OtherSection.tsx | 42 +++++++++++++++++-- .../getPdfInfo/sections/PerPageSection.tsx | 21 +++++++++- frontend/src/core/types/getPdfInfo.ts | 4 ++ 3 files changed, 62 insertions(+), 5 deletions(-) diff --git a/frontend/src/core/components/tools/getPdfInfo/sections/OtherSection.tsx b/frontend/src/core/components/tools/getPdfInfo/sections/OtherSection.tsx index e7eb8d8b3..3bc515a1a 100644 --- a/frontend/src/core/components/tools/getPdfInfo/sections/OtherSection.tsx +++ b/frontend/src/core/components/tools/getPdfInfo/sections/OtherSection.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { Accordion, Stack, Text } from '@mantine/core'; import { useTranslation } from 'react-i18next'; -import type { PdfOtherInfo } from '@app/types/getPdfInfo'; +import type { PdfOtherInfo, PdfAttachmentInfo, PdfEmbeddedFileInfo } from '@app/types/getPdfInfo'; import SectionBlock from '@app/components/tools/getPdfInfo/shared/SectionBlock'; import ScrollableCodeBlock from '@app/components/tools/getPdfInfo/shared/ScrollableCodeBlock'; import { pdfInfoAccordionStyles } from '@app/components/tools/getPdfInfo/shared/accordionStyles'; @@ -11,6 +11,42 @@ interface OtherSectionProps { other?: PdfOtherInfo | null; } +const renderAttachmentsList = (attachments: PdfAttachmentInfo[] | undefined, emptyText: string) => { + if (!attachments || attachments.length === 0) return {emptyText}; + return ( + + {attachments.map((attachment, idx) => ( +
+ + {attachment.Name || 'Unnamed attachment'} + {attachment.Description && ` - ${attachment.Description}`} + {attachment.FileSize != null && ` (${attachment.FileSize} bytes)`} + +
+ ))} +
+ ); +}; + +const renderEmbeddedFilesList = (embeddedFiles: PdfEmbeddedFileInfo[] | undefined, emptyText: string) => { + if (!embeddedFiles || embeddedFiles.length === 0) return {emptyText}; + return ( + + {embeddedFiles.map((file, idx) => ( +
+ + {file.Name || 'Unnamed file'} + {file.FileSize != null && ` (${file.FileSize} bytes)`} + {file.MimeType && ` - ${file.MimeType}`} + {file.CreationDate && ` - Created: ${file.CreationDate}`} + {file.ModificationDate && ` - Modified: ${file.ModificationDate}`} + +
+ ))} +
+ ); +}; + const renderList = (arr: unknown[] | undefined, emptyText: string) => { if (!arr || arr.length === 0) return {emptyText}; return ( @@ -37,11 +73,11 @@ const OtherSection: React.FC = ({ anchorId, other }) => { {t('getPdfInfo.other.attachments', 'Attachments')} - {renderList(other?.Attachments, noneDetected)} + {renderAttachmentsList(other?.Attachments, noneDetected)} {t('getPdfInfo.other.embeddedFiles', 'Embedded Files')} - {renderList(other?.EmbeddedFiles, noneDetected)} + {renderEmbeddedFilesList(other?.EmbeddedFiles, noneDetected)} {t('getPdfInfo.other.javaScript', 'JavaScript')} diff --git a/frontend/src/core/components/tools/getPdfInfo/sections/PerPageSection.tsx b/frontend/src/core/components/tools/getPdfInfo/sections/PerPageSection.tsx index 4fd257cce..36bd7bf1c 100644 --- a/frontend/src/core/components/tools/getPdfInfo/sections/PerPageSection.tsx +++ b/frontend/src/core/components/tools/getPdfInfo/sections/PerPageSection.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { Accordion, Stack, Text } from '@mantine/core'; import { useTranslation } from 'react-i18next'; -import type { PdfPerPageInfo, PdfPageInfo, PdfFontInfo } from '@app/types/getPdfInfo'; +import type { PdfPerPageInfo, PdfPageInfo, PdfFontInfo, PdfImageInfo } from '@app/types/getPdfInfo'; import SectionBlock from '@app/components/tools/getPdfInfo/shared/SectionBlock'; import KeyValueList from '@app/components/tools/getPdfInfo/shared/KeyValueList'; import { pdfInfoAccordionStyles } from '@app/components/tools/getPdfInfo/shared/accordionStyles'; @@ -11,6 +11,23 @@ interface PerPageSectionProps { perPage?: PdfPerPageInfo | null; } +const renderImagesList = (images: PdfImageInfo[] | undefined, emptyText: string) => { + if (!images || images.length === 0) return {emptyText}; + return ( + + {images.map((image, idx) => ( +
+ + {image.Name ? `${image.Name} ` : 'Image '} + ({image.Width}×{image.Height}px + {image.ColorSpace ? `, ${image.ColorSpace}` : ''}) + +
+ ))} +
+ ); +}; + const renderList = (arr: unknown[] | undefined, emptyText: string) => { if (!arr || arr.length === 0) return {emptyText}; return ( @@ -84,7 +101,7 @@ const PerPageSection: React.FC = ({ anchorId, perPage }) => )} {t('getPdfInfo.perPage.images', 'Images')} - {renderList(pageInfo?.Images, noneDetected)} + {renderImagesList(pageInfo?.Images, noneDetected)} {t('getPdfInfo.perPage.links', 'Links')} diff --git a/frontend/src/core/types/getPdfInfo.ts b/frontend/src/core/types/getPdfInfo.ts index f489cd99a..20442cebc 100644 --- a/frontend/src/core/types/getPdfInfo.ts +++ b/frontend/src/core/types/getPdfInfo.ts @@ -160,12 +160,16 @@ export interface PdfPerPageInfo { export interface PdfEmbeddedFileInfo { Name?: string; FileSize?: number; + MimeType?: string; + CreationDate?: string; + ModificationDate?: string; } /** Attachment info */ export interface PdfAttachmentInfo { Name?: string; Description?: string; + FileSize?: number; } /** JavaScript info */