A PDF generation library for Node.js with comprehensive text, graphics, and form support
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Tagged PDF support, structure elements, and accessibility features for creating inclusive documents that comply with PDF/UA and accessibility standards.
Create structured content with semantic meaning for screen readers and assistive technology.
/**
* Create structure element
* @param type - Structure type
* @param options - Structure options
* @param children - Child structure elements
* @returns Structure element
*/
struct(type: StructureType, options?: StructureOptions, children?: StructureElement[]): StructureElement;
/**
* Add structure element to document
* @param structElem - Structure element to add
* @returns Document instance for chaining
*/
addStructure(structElem: StructureElement): PDFDocument;
type StructureType =
// Root elements
| 'Document' | 'Part' | 'Art' | 'Sect' | 'Div'
// Headings
| 'H' | 'H1' | 'H2' | 'H3' | 'H4' | 'H5' | 'H6'
// Paragraphs and text
| 'P' | 'Span'
// Lists
| 'L' | 'LI' | 'Lbl' | 'LBody'
// Tables
| 'Table' | 'TR' | 'TH' | 'TD' | 'THead' | 'TBody' | 'TFoot'
// Links and references
| 'Link' | 'Annot' | 'Ruby' | 'RB' | 'RT' | 'RP'
// Figures and media
| 'Figure' | 'Formula' | 'Form'
// Quotes and citations
| 'Quote' | 'Note' | 'Reference' | 'BibEntry'
// Code
| 'Code'
// Inline elements
| 'Em' | 'Strong';
interface StructureOptions {
/** Alternative text description */
Alt?: string;
/** Actual text content */
ActualText?: string;
/** Language specification */
Lang?: string;
/** Expansion of abbreviation */
E?: string;
/** Structure title */
T?: string;
/** Structure ID */
ID?: string;
/** Bounding box */
BBox?: [number, number, number, number];
}Usage Examples:
// Enable tagged PDF
const doc = new PDFDocument({ tagged: true });
// Document structure
const docStruct = doc.struct('Document');
// Heading structure
const heading = doc.struct('H1', {
Alt: 'Main document title',
T: 'Introduction'
});
// Paragraph structure
const paragraph = doc.struct('P', {
Lang: 'en-US'
});
// Add structures to document
doc.addStructure(docStruct);
docStruct.add(heading);
docStruct.add(paragraph);Mark content sections with semantic tags for accessibility.
/**
* Begin marked content sequence
* @param tag - Content tag
* @param options - Marking options
* @returns Document instance for chaining
*/
markContent(tag: string, options?: MarkingOptions): PDFDocument;
/**
* Mark structure content
* @param tag - Structure tag
* @param options - Structure options
* @returns Document instance for chaining
*/
markStructureContent(tag: StructureType, options?: StructureMarkingOptions): PDFDocument;
/**
* End marked content sequence
* @returns Document instance for chaining
*/
endMarkedContent(): PDFDocument;
interface MarkingOptions {
/** Properties dictionary */
properties?: any;
/** MCID (Marked Content ID) */
MCID?: number;
}
interface StructureMarkingOptions extends MarkingOptions {
/** Structure element reference */
structElem?: StructureElement;
/** Alternative text */
Alt?: string;
/** Actual text */
ActualText?: string;
/** Language */
Lang?: string;
}Usage Examples:
// Mark heading content
doc.markStructureContent('H1', {
Alt: 'Document title',
Lang: 'en'
});
doc.fontSize(24)
.text('Welcome to Our Guide', 100, 100);
doc.endMarkedContent();
// Mark paragraph content
doc.markStructureContent('P');
doc.fontSize(12)
.text('This paragraph contains important information about accessibility.', 100, 150, {
width: 400
});
doc.endMarkedContent();
// Mark artifacts (decorative content)
doc.markContent('Artifact', {
properties: { Type: 'Layout' }
});
doc.rect(50, 50, 500, 2)
.fill('gray'); // Decorative line
doc.endMarkedContent();Set document properties that enhance accessibility.
// Document with accessibility metadata
const doc = new PDFDocument({
tagged: true,
lang: 'en-US',
displayTitle: true,
info: {
Title: 'Accessible Document Example',
Author: 'John Doe',
Subject: 'Demonstrating PDF accessibility features',
Keywords: 'accessibility, PDF/UA, tagged PDF'
}
});Provide alternative text descriptions for images.
// Image with alternative text
doc.markStructureContent('Figure', {
Alt: 'A bar chart showing quarterly sales data with Q1 at $100k, Q2 at $150k, Q3 at $200k, and Q4 at $180k',
ActualText: 'Sales Chart Q1-Q4'
});
doc.image('sales-chart.png', 100, 200, {
width: 300,
height: 200
});
doc.endMarkedContent();Create structured tables that are accessible to screen readers.
// Table structure
doc.markStructureContent('Table');
// Table header
doc.markStructureContent('THead');
doc.markStructureContent('TR');
doc.markStructureContent('TH', {
Alt: 'Product name column header'
});
doc.text('Product', 100, 300);
doc.endMarkedContent();
doc.markStructureContent('TH', {
Alt: 'Price column header'
});
doc.text('Price', 200, 300);
doc.endMarkedContent();
doc.endMarkedContent(); // End TR
doc.endMarkedContent(); // End THead
// Table body
doc.markStructureContent('TBody');
doc.markStructureContent('TR');
doc.markStructureContent('TD');
doc.text('Widget A', 100, 320);
doc.endMarkedContent();
doc.markStructureContent('TD');
doc.text('$19.99', 200, 320);
doc.endMarkedContent();
doc.endMarkedContent(); // End TR
doc.endMarkedContent(); // End TBody
doc.endMarkedContent(); // End TableCreate properly structured lists with semantic markup.
// Ordered list structure
doc.markStructureContent('L');
// First list item
doc.markStructureContent('LI');
doc.markStructureContent('Lbl');
doc.text('1.', 100, 100);
doc.endMarkedContent();
doc.markStructureContent('LBody');
doc.text('First item in the list', 120, 100);
doc.endMarkedContent();
doc.endMarkedContent();
// Second list item
doc.markStructureContent('LI');
doc.markStructureContent('Lbl');
doc.text('2.', 100, 120);
doc.endMarkedContent();
doc.markStructureContent('LBody');
doc.text('Second item in the list', 120, 120);
doc.endMarkedContent();
doc.endMarkedContent();
doc.endMarkedContent(); // End LCreate links with proper structure and alternative text.
// Link with structure
doc.markStructureContent('Link', {
Alt: 'External link to company website'
});
doc.fillColor('blue')
.text('Visit our website', 100, 150, {
link: 'https://example.com',
underline: true
});
doc.endMarkedContent();
// Internal link
doc.markStructureContent('Link', {
Alt: 'Link to appendix section'
});
doc.fillColor('blue')
.text('See Appendix A', 100, 180, {
goTo: 'appendixA',
underline: true
});
doc.endMarkedContent();Specify language for text content to assist screen readers.
// Document-level language (in constructor)
const doc = new PDFDocument({
tagged: true,
lang: 'en-US'
});
// Paragraph with different language
doc.markStructureContent('P', {
Lang: 'es-ES'
});
doc.text('Hola, mundo!', 100, 100);
doc.endMarkedContent();
// Back to English
doc.markStructureContent('P', {
Lang: 'en-US'
});
doc.text('Hello, world!', 100, 120);
doc.endMarkedContent();Control the reading order of content for screen readers.
// Create structure tree to define reading order
const docStruct = doc.struct('Document');
// Add content in logical reading order
const title = doc.struct('H1');
const intro = doc.struct('P');
const section1 = doc.struct('Sect');
const section1Title = doc.struct('H2');
const section1Text = doc.struct('P');
// Build hierarchy
docStruct.add(title);
docStruct.add(intro);
docStruct.add(section1);
section1.add(section1Title);
section1.add(section1Text);
doc.addStructure(docStruct);Features for PDF/UA (Universal Accessibility) compliance.
// PDF/UA compliant document
const doc = new PDFDocument({
tagged: true,
subset: 'PDF/UA',
lang: 'en-US',
displayTitle: true,
info: {
Title: 'Accessible Document'
}
});tagged: trueinfo.Title and displayTitle: truelang property// Check document compliance
doc.on('end', () => {
console.log('Document structure:', doc.structureTree);
console.log('Tagged content count:', doc.taggedContentCount);
});PDFKit supports compliance with:
These features ensure that PDFs created with PDFKit can be used effectively by people with disabilities and assistive technologies.
Install with Tessl CLI
npx tessl i tessl/npm-pdfkit