✨(frontend) add pdf outline property to enable bookmarks display
allows pdf viewers like adobe reader to display bookmarks in the sidebar Signed-off-by: Cyril <c.gromoff@gmail.com>
This commit is contained in:
@@ -22,6 +22,11 @@ and this project adheres to
|
|||||||
- ♿(frontend) improve accessibility:
|
- ♿(frontend) improve accessibility:
|
||||||
- ✨ add document visible in list and openable via enter key #1365
|
- ✨ add document visible in list and openable via enter key #1365
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- ♿(frontend) improve accessibility:
|
||||||
|
- ♿ add pdf outline property to enable bookmarks display #1368
|
||||||
|
|
||||||
## [3.7.0] - 2025-09-12
|
## [3.7.0] - 2025-09-12
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
@@ -2,6 +2,26 @@ import { Text } from '@react-pdf/renderer';
|
|||||||
|
|
||||||
import { DocsExporterPDF } from '../types';
|
import { DocsExporterPDF } from '../types';
|
||||||
|
|
||||||
|
// Helper function to extract plain text from block content
|
||||||
|
function extractTextFromBlockContent(content: unknown[]): string {
|
||||||
|
return content
|
||||||
|
.map((item) => {
|
||||||
|
if (
|
||||||
|
typeof item === 'object' &&
|
||||||
|
item !== null &&
|
||||||
|
'type' in item &&
|
||||||
|
'text' in item
|
||||||
|
) {
|
||||||
|
if (item.type === 'text' && typeof item.text === 'string') {
|
||||||
|
return item.text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
})
|
||||||
|
.join('')
|
||||||
|
.trim();
|
||||||
|
}
|
||||||
|
|
||||||
export const blockMappingHeadingPDF: DocsExporterPDF['mappings']['blockMapping']['heading'] =
|
export const blockMappingHeadingPDF: DocsExporterPDF['mappings']['blockMapping']['heading'] =
|
||||||
(block, exporter) => {
|
(block, exporter) => {
|
||||||
const PIXELS_PER_POINT = 0.75;
|
const PIXELS_PER_POINT = 0.75;
|
||||||
@@ -9,9 +29,18 @@ export const blockMappingHeadingPDF: DocsExporterPDF['mappings']['blockMapping']
|
|||||||
const FONT_SIZE = 16;
|
const FONT_SIZE = 16;
|
||||||
const fontSizeEM =
|
const fontSizeEM =
|
||||||
block.props.level === 1 ? 2 : block.props.level === 2 ? 1.5 : 1.17;
|
block.props.level === 1 ? 2 : block.props.level === 2 ? 1.5 : 1.17;
|
||||||
|
|
||||||
|
// Extract plain text for bookmark title
|
||||||
|
const bookmarkTitle =
|
||||||
|
extractTextFromBlockContent(block.content) || 'Untitled';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Text
|
<Text
|
||||||
key={block.id}
|
key={block.id}
|
||||||
|
// @ts-expect-error: bookmark is supported by react-pdf but not typed
|
||||||
|
bookmark={{
|
||||||
|
title: bookmarkTitle,
|
||||||
|
}}
|
||||||
style={{
|
style={{
|
||||||
fontSize: fontSizeEM * FONT_SIZE * PIXELS_PER_POINT,
|
fontSize: fontSizeEM * FONT_SIZE * PIXELS_PER_POINT,
|
||||||
fontWeight: 700,
|
fontWeight: 700,
|
||||||
|
|||||||
@@ -98,9 +98,12 @@ export const ModalExport = ({ onClose, doc }: ModalExportProps) => {
|
|||||||
exportDocument,
|
exportDocument,
|
||||||
)) as React.ReactElement<DocumentProps>;
|
)) as React.ReactElement<DocumentProps>;
|
||||||
|
|
||||||
// Inject language for screen reader support
|
// Inject language for screen reader support and enable outlines (bookmarks)
|
||||||
const pdfDocument = isValidElement(rawPdfDocument)
|
const pdfDocument = isValidElement(rawPdfDocument)
|
||||||
? cloneElement(rawPdfDocument, { language: i18next.language })
|
? cloneElement(rawPdfDocument, {
|
||||||
|
language: i18next.language,
|
||||||
|
pageMode: 'useOutlines',
|
||||||
|
})
|
||||||
: rawPdfDocument;
|
: rawPdfDocument;
|
||||||
|
|
||||||
blobExport = await pdf(pdfDocument).toBlob();
|
blobExport = await pdf(pdfDocument).toBlob();
|
||||||
|
|||||||
Reference in New Issue
Block a user