lexical-pdf
v0.1.5
Published
Convert Lexical editor content to PDF - Core function and React component
Maintainers
Readme
⭐ If you find this useful, please consider starring the repo!
It helps others discover the project and motivates continued development.
🤝 Looking for contributors! Whether it's bug fixes, new features, or documentation improvements, all contributions are welcome. See Contributing below to get started.
lexical-pdf
Convert Lexical editor content to PDF with ease in the browser. This package provides both a core function for any frontend framework (Vue, Svelte, Angular, vanilla JS) and a ready-to-use React component.
Features
- 🔧 Core Function: Use with any frontend framework (Vue, Svelte, Angular, vanilla JS)
- ⚛️ React Component: Drop-in PDF download button with customizable styling
- 📄 High Quality: Uses html2canvas and jsPDF for crisp PDF generation
- 🎨 Customizable: Configure page size, orientation, scaling, and more
- 🔒 Type Safe: Full TypeScript support with comprehensive types
- 📦 Lightweight: Minimal dependencies, optional React support
Installation
For React Usage
npm install lexical-pdf lexical @lexical/html react @lexical/react lucide-reactFor Core Usage (Vue, Svelte, Angular, Vanilla JS)
npm install lexical-pdf lexical @lexical/htmlUsage
React Component
Use the DownloadPDFPlugin component in your Lexical React setup:
import { LexicalComposer } from "@lexical/react/LexicalComposer";
import { RichTextPlugin } from "@lexical/react/LexicalRichTextPlugin";
import { ContentEditable } from "@lexical/react/LexicalContentEditable";
import { DownloadPDFPlugin } from "lexical-pdf/react";
function MyEditor() {
return (
<LexicalComposer initialConfig={editorConfig}>
<div className="editor-container">
<RichTextPlugin
contentEditable={<ContentEditable />}
placeholder={<div>Enter some text...</div>}
ErrorBoundary={ErrorBoundary}
/>
{/* PDF Export Button */}
<DownloadPDFPlugin filename="my-document.pdf" />
{/* Custom PDF Button with fast compression */}
<DownloadPDFPlugin
filename="custom.pdf"
containerClassName="flex justify-center"
compression="FAST"
>
<button className="px-4 py-2 bg-blue-500 text-white rounded">
Export PDF
</button>
</DownloadPDFPlugin>
{/* Custom icon styling */}
<DownloadPDFPlugin
filename="styled-icon.pdf"
iconSize={24}
iconColor="#3b82f6"
iconStrokeWidth={2}
/>
</div>
</LexicalComposer>
);
}Core Function
Use the core exportToPdf function with any frontend framework:
import { exportToPdf } from "lexical-pdf";
import { LexicalEditor } from "lexical";
// Basic usage
await exportToPdf(editor);
// With custom options
await exportToPdf(editor, {
filename: "my-document.pdf",
orientation: "landscape",
format: "a4",
scale: 2,
compression: "FAST",
});Vue Example
<template>
<div>
<div ref="editorContainer"></div>
<button @click="exportPdf">Export PDF</button>
</div>
</template>
<script>
import { exportToPdf } from "lexical-pdf";
export default {
methods: {
async exportPdf() {
try {
await exportToPdf(this.lexicalEditor, {
filename: "vue-document.pdf",
});
} catch (error) {
console.error("Export failed:", error);
}
},
},
};
</script>Svelte Example
<script>
import { exportToPdf } from 'lexical-pdf';
let lexicalEditor;
async function handleExportPdf() {
try {
await exportToPdf(lexicalEditor, {
filename: 'svelte-document.pdf'
});
} catch (error) {
console.error('Export failed:', error);
}
}
</script>
<div>
<div bind:this={editorContainer}></div>
<button on:click={handleExportPdf}>Export PDF</button>
</div>Angular Example
// component.ts
import { Component } from "@angular/core";
import { exportToPdf } from "lexical-pdf";
@Component({
selector: "app-editor",
template: `
<div #editorContainer></div>
<button (click)="exportPdf()">Export PDF</button>
`,
})
export class EditorComponent {
lexicalEditor: any; // Your Lexical editor instance
async exportPdf() {
try {
await exportToPdf(this.lexicalEditor, {
filename: "angular-document.pdf",
});
} catch (error) {
console.error("Export failed:", error);
}
}
}API Reference
exportToPdf(editor, options?)
Parameters
editor(LexicalEditor): The Lexical editor instanceoptions(ExportToPdfOptions, optional): Configuration options
Options
interface ExportToPdfOptions {
filename?: string; // Default: "document.pdf"
containerWidth?: string; // Default: "816px" (letter width)
containerHeight?: string; // Default: "1056px" (letter height)
containerPadding?: string; // Default: "30px"
orientation?: "portrait" | "landscape"; // Default: "portrait"
format?: string | number[]; // Default: "letter" (jsPDF formats)
scale?: number; // Default: 3 (higher = better quality)
compression?: "NONE" | "FAST" | "MEDIUM" | "SLOW"; // Default: "SLOW"
}Returns
Promise<void>: Resolves when PDF is generated and downloaded
DownloadPDFPlugin React Component
Props
interface DownloadPDFPluginProps {
filename?: string; // Default: "document.pdf"
children?: ReactNode; // Custom button content
containerClassName?: string; // Default: "flex w-full justify-end"
containerWidth?: string; // Default: "816px"
containerHeight?: string; // Default: "1056px"
containerPadding?: string; // Default: "30px"
compression?: "NONE" | "FAST" | "MEDIUM" | "SLOW"; // Default: "SLOW"
iconSize?: number; // Default: 18
iconColor?: string; // Default: undefined (uses theme)
iconStrokeWidth?: number; // Default: undefined (uses lucide default)
}Advanced Examples
Custom Page Formats
// A4 landscape
await exportToPdf(editor, {
format: "a4",
orientation: "landscape",
});
// Custom size (width, height in points)
await exportToPdf(editor, {
format: [595, 842], // A4 in points
orientation: "portrait",
});
// Legal size
await exportToPdf(editor, {
format: "legal",
});
// Fast compression for smaller files
await exportToPdf(editor, {
compression: "FAST", // Smaller file, lower quality
});
// High quality compression (default)
await exportToPdf(editor, {
compression: "SLOW", // Larger file, higher quality
});Compression Options
Choose the right compression level based on your needs:
// No compression - fastest processing, largest files
await exportToPdf(editor, { compression: "NONE" });
// Fast compression - quick processing, smaller files, lower quality
await exportToPdf(editor, { compression: "FAST" });
// Medium compression - balanced processing time and quality
await exportToPdf(editor, { compression: "MEDIUM" });
// Slow compression - longer processing, highest quality (default)
await exportToPdf(editor, { compression: "SLOW" });When to use each:
- NONE: Large documents where file size isn't a concern
- FAST: Quick exports, email attachments, draft documents
- MEDIUM: General purpose, good balance of quality and size
- SLOW: Final documents, presentations, archival purposes
Error Handling
try {
await exportToPdf(editor, { filename: "my-doc.pdf" });
console.log("PDF exported successfully!");
} catch (error) {
console.error("Export failed:", error.message);
// Handle error (show user notification, etc.)
}React with Custom Styling
{
/* Custom button with children */
}
<DownloadPDFPlugin
filename="styled-document.pdf"
containerClassName="flex items-center gap-2"
containerWidth="800px"
containerPadding="40px"
>
<div className="flex items-center gap-2 px-3 py-2 bg-green-600 text-white rounded-lg hover:bg-green-700 transition-colors">
<DownloadIcon size={16} />
Download PDF
</div>
</DownloadPDFPlugin>;
{
/* Default button with custom icon styling */
}
<DownloadPDFPlugin
filename="custom-icon.pdf"
iconSize={20}
iconColor="#ef4444"
iconStrokeWidth={2.5}
/>;How It Works
- Extract HTML: Uses
@lexical/htmlto convert editor state to HTML - Render Off-screen: Creates a temporary DOM container with your content
- Capture Canvas: Uses
html2canvas-proto render HTML to canvas - Generate PDF: Uses
jsPDFto create PDF from canvas image - Download: Automatically triggers browser download
Environment Support
Browser Support
- Chrome/Edge: ✅ Full support
- Firefox: ✅ Full support
- Safari: ✅ Full support
- IE11: ❌ Not supported
Framework Support
- React: ✅ Dedicated component included
- Vue: ✅ Use core function
- Svelte: ✅ Use core function
- Angular: ✅ Use core function
- Vanilla JS: ✅ Use core function
Node.js Support
❌ Not supported - This package requires browser DOM APIs (document, html2canvas, etc.)
For server-side PDF generation, consider:
- Puppeteer - Controls headless Chrome
- Playwright - Cross-browser automation
- PDFKit - Pure JavaScript PDF generation
- jsPDF with Node.js canvas libraries
Peer Dependencies
This package requires:
lexical: >=0.12.0 <1.0.0 (always required)@lexical/html: >=0.12.0 <1.0.0 (always required)react: ^18.0.0 || ^19.0.0 (only for React component usage)@lexical/react: >=0.12.0 <1.0.0 (only for React component usage)lucide-react: ^0.200.0 (only for React component usage)
Contributing
Contributions are welcome! Here are some areas where we'd especially appreciate help:
- 🐛 Bug fixes - Found an issue? PRs welcome!
- ✨ New features - Pagination support, more export formats, better compression algorithms
- 🧩 Framework components - Vue, Angular, Svelte components (we currently only have React)
- 📚 Documentation - Examples, tutorials, translations
- 🧪 Testing - Unit tests and integration tests
- 🎨 Styling options - More customization for the React component
How to Contribute
- Fork the repository
- Create your feature branch:
git checkout -b feature/amazing-feature - Commit your changes:
git commit -m 'Add amazing feature' - Push to the branch:
git push origin feature/amazing-feature - Open a Pull Request
License
MIT © Stefan Leoussis
Changelog
0.1.5
- Updated jspdf from ^3.0.3 to ^4.0.0 to avoid security vulnerabilities.
0.1.4
- Update @lexical/html and @lexical/react to v0.38.2 for latest features and bug fixes
- Improved stability and compatibility with Lexical ecosystem
0.1.3
- Breaking Fix: Move @lexical/html to peerDependencies to prevent version conflicts
0.1.2
- Security Fix: Update jsPDF to v3.0.3 (fixes moderate/high security vulnerabilities)
- Update all dependencies to latest versions for better security and compatibility
- Update development dependencies: TypeScript 5.9.3, React 19, Node types 22.9.1
- Improve peer dependency constraints: lexical >=0.12.0 <1.0.0
- Support both React 18 and React 19
- Fix Lexical editor state compatibility issues
0.1.1
- Fix peer dependency compatibility with newer Lexical versions (now supports >=0.12.0)
- Support for Lexical v0.35.0 and beyond
0.1.0
- Initial release
- Core
exportToPdffunction with configurable compression - React
DownloadPDFPlugincomponent with customizable icon - TypeScript support with full ES module compatibility
- Comprehensive error handling
- Support for all major frontend frameworks (React, Vue, Svelte, Angular)
