I completely rebuilt the PDF export, removing pdf-lib, saving 800kb on main.js size, and making scene text searchable and links clickable. Big thanks to: @mnaoumov Pdf.ts
Margins and page sizes are now consistently in pixels because Excalidraw measurements are in pixels and it makes sense not to convert between inches, points all the time.
New
- Set local graph to show the links in the embeddable when it is activated / deactivated #2200
- Updated "Export Image" dialog
- 🚀 PDF Export option including tiling of images over multiple pages. Only available on desktop :(
- SVG to clipboard
- More granular setting for padding and scale
Fixed
- Fixed support for *.jfif and *.avif images #2212
- PDF++ selection is not correctly showing after embedded into a drawing (for some specific files) #2213
- iOS 18 can't upload image and library #2182
- Image block references are broken in hover previews #2218
- Mobile elements panel and context menu are not scrollable #2216
- "Local Font" menu disappears when opening a drawing in an Obsidian popout-window #2205
Updates from Excalidraw.com
- Pressing delete on a frame will only delete the children #9011
- New crowfoot arrowheads and a new arrowhead picker #8942
- Fixed some of the arrow binding issues #9010, #2209
- New context menu action: "Wrap selection in frame" #9005
- Elbow arrow segment fixing and positioning #8952
New in ExcalidrawAutomate
- New hook:
onImageFileNameHook
. When set, this callback is triggered when a image is being saved in Excalidraw. - PDF export functions, paving the way for slideshow to export slides to PDF
/**
* Returns the dimensions of a standard page size in pixels.
*
* @param {PageSize} pageSize - The standard page size. Possible values are "A0", "A1", "A2", "A3", "A4", "A5", "Letter", "Legal", "Tabloid".
* @param {PageOrientation} orientation - The orientation of the page. Possible values are "portrait" and "landscape".
* @returns {PageDimensions} - An object containing the width and height of the page in pixels.
*
* @typedef {Object} PageDimensions
* @property {number} width - The width of the page in pixels.
* @property {number} height - The height of the page in pixels.
*
* @example
* const dimensions = getPageDimensions("A4", "portrait");
* console.log(dimensions); // { width: 794.56, height: 1122.56 }
*/
getPagePDFDimensions(pageSize: PageSize, orientation: PageOrientation): PageDimensions;
/**
* Creates a PDF from the provided SVG elements with specified scaling and page properties.
*
* @param {Object} params - The parameters for creating the PDF.
* @param {SVGSVGElement[]} params.SVG - An array of SVG elements to be included in the PDF.
* @param {PDFExportScale} [params.scale={ fitToPage: true, zoom: 1 }] - The scaling options for the SVG elements.
* @param {PDFPageProperties} [params.pageProps] - The properties for the PDF pages.
* @returns {Promise<ArrayBuffer>} - A promise that resolves to an ArrayBuffer containing the PDF data.
*
* @example
* const pdfData = await createToPDF({
* SVG: [svgElement1, svgElement2],
* scale: { fitToPage: true },
* pageProps: {
* dimensions: { width: 794.56, height: 1122.56 },
* backgroundColor: "#ffffff",
* margin: { left: 20, right: 20, top: 20, bottom: 20 },
* alignment: "center",
* }
* });
*/
createPDF({ SVG, scale, pageProps, }: {
SVG: SVGSVGElement[];
scale?: PDFExportScale;
pageProps?: PDFPageProperties;
}): Promise<ArrayBuffer>;
/**
* If set, this callback is triggered when a image is being saved in Excalidraw.
* You can use this callback to customize the naming and path of pasted images to avoid
* default names like "Pasted image 123147170.png" being saved in the attachments folder,
* and instead use more meaningful names based on the Excalidraw file or other criteria,
* plus save the image in a different folder.
*
* If the function returns null or undefined, the normal Excalidraw operation will continue
* with the excalidraw generated name and default path.
* If a filepath is returned, that will be used. Include the full Vault filepath and filename
* with the file extension.
* The currentImageName is the name of the image generated by excalidraw or provided during paste.
*
* @param data - An object containing the following properties:
* @property {string} [currentImageName] - Default name for the image.
* @property {string} drawingFilePath - The file path of the Excalidraw file where the image is being used.
*
* @returns {string} - The new filepath for the image including full vault path and extension.
*
* Example usage:
* onImageFilePathHook: (data) => {
* const { currentImageName, drawingFilePath } = data;
* // Generate a new filepath based on the drawing file name and other criteria
* const ext = currentImageName.split('.').pop();
* return `${drawingFileName} - ${currentImageName || 'image'}.${ext}`;
* }
*/
onImageFilePathHook: (data: {
currentImageName: string; // Excalidraw generated name of the image, or the name received from the file system.
drawingFilePath: string; // The full filepath of the Excalidraw file where the image is being used.
}) => string = null;
```