# @mlightcad/cad-pdf-plugin [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![npm version](https://img.shields.io/npm/v/@mlightcad/cad-pdf-plugin.svg)](https://www.npmjs.com/package/@mlightcad/cad-pdf-plugin) PDF **export** and **import** plugin for [`@mlightcad/cad-simple-viewer`](../cad-simple-viewer). Registers two system commands: | Command | Description | |---------|-------------| | `cpdf` | Export the current drawing to a vector PDF (SVG pipeline → jsPDF) | | `ipdf` | Import vector geometry from a PDF file into model space | The plugin is designed for **lazy loading** so PDF libraries (`jspdf`, `pdfjs-dist`, `svg2pdf.js`) are only downloaded when a user runs `cpdf` or `ipdf`. ## Key features - **Vector PDF export** — renders model-space entities via `@mlightcad/cad-svg-plugin`, then converts SVG to PDF with `svg2pdf.js` - **PDF import** — parses vector paths from the first page of a PDF (lines, polylines, Bézier curves) and appends CAD entities - **Plugin API** — implements `AcApPlugin`; register once with `registerLazyPdfPlugin` - **Framework-agnostic** — no Vue/React dependency; works anywhere `cad-simple-viewer` runs ## Installation ```bash pnpm add @mlightcad/cad-pdf-plugin ``` Peer dependencies: - `@mlightcad/cad-simple-viewer` - `@mlightcad/data-model` - `@mlightcad/cad-svg-plugin` Runtime dependencies (bundled with this package): - `jspdf` - `pdfjs-dist` - `svg2pdf.js` ## Build Produces `dist/index.js` (main library) and `dist/register.js` (lazy-registration entry). ```bash pnpm --filter @mlightcad/cad-pdf-plugin build ``` ## Usage ### Lazy registration (recommended) Register the plugin with the document manager's plugin manager. Import from the `/register` subpath so only the registration stub enters your initial bundle; the main plugin chunk loads on first use of `cpdf` or `ipdf`: ```typescript import { AcApDocManager } from '@mlightcad/cad-simple-viewer' import { registerLazyPdfPlugin } from '@mlightcad/cad-pdf-plugin/register' registerLazyPdfPlugin(AcApDocManager.instance.pluginManager) ``` Do **not** import `registerLazyPdfPlugin` from the package root in application code — that resolves to the full library build and defeats lazy loading. Equivalent manual registration: ```typescript import { createPdfPlugin, PDF_PLUGIN_NAME, PDF_PLUGIN_TRIGGERS } from '@mlightcad/cad-pdf-plugin' AcApDocManager.instance.pluginManager.registerLazyPlugin({ name: PDF_PLUGIN_NAME, triggers: [...PDF_PLUGIN_TRIGGERS], loader: createPdfPlugin }) ``` After registration, users (or your UI) invoke commands through the editor: ```typescript // Export current drawing to PDF await AcApDocManager.instance.editor.executeCommand('cpdf') // Open file picker and import PDF vectors await AcApDocManager.instance.editor.executeCommand('ipdf') ``` `cad-viewer` registers this plugin automatically via `registerLazyPlugins()` in its app bootstrap. ### Eager registration If you prefer loading PDF support up front: ```typescript import { AcApPdfPlugin } from '@mlightcad/cad-pdf-plugin' await AcApDocManager.instance.pluginManager.loadPlugin(new AcApPdfPlugin()) ``` ### Programmatic convertors You can bypass the command layer and call the convertors directly: ```typescript import { AcApContext } from '@mlightcad/cad-simple-viewer' import { AcApPdfConvertor, AcApPdfImportConvertor } from '@mlightcad/cad-pdf-plugin' // Export const context: AcApContext = /* active context */ await new AcApPdfConvertor().convert(context) // Import from bytes const buffer: ArrayBuffer = /* PDF file */ await new AcApPdfImportConvertor().convert(context, buffer, 1) // page 1 ``` ## How it works ### Export (`cpdf`) 1. Iterate model-space entities and render with `AcSvgRenderer` (respects linetype scale, lineweight display, font mapping, background/foreground colors). 2. Parse the SVG and pass it to `svg2pdf.js` inside a `jsPDF` document sized to the SVG viewBox. 3. Trigger a browser download as `drawing.pdf`. ### Import (`ipdf`) 1. Show a native file picker (`.pdf`). 2. Use `pdfjs-dist` to read operator lists from the selected page. 3. Convert path operators (move, line, cubic Bézier, close) into `AcDbLine` / `AcDbPolyline` entities in model space. Import is **vector-only**; raster/scanned PDF pages produce no entities. Only the requested page is processed (default: page 1). ## Main exports | Export | Role | |--------|------| | `createPdfPlugin` | Async factory used by lazy loader | | `PDF_PLUGIN_NAME`, `PDF_PLUGIN_TRIGGERS` | Plugin id and command triggers | | `@mlightcad/cad-pdf-plugin/register` | `registerLazyPdfPlugin` and registration constants | | `AcApPdfPlugin` | `AcApPlugin` implementation | | `AcApConvertToPdfCmd` | `cpdf` command class | | `AcApImportPdfCmd` | `ipdf` command class | | `AcApPdfConvertor` | SVG → PDF export utility | | `AcApPdfImportConvertor` | PDF → CAD entities import utility | ## Project layout | Path | Role | |------|------| | `src/register.ts` | Lazy plugin registration (`/register` entry) and `createPdfPlugin` | | `src/AcApPdfPlugin.ts` | Plugin lifecycle (`onLoad` / `onUnload`) | | `src/AcApConvertToPdfCmd.ts` | `cpdf` command | | `src/AcApImportPdfCmd.ts` | `ipdf` command | | `src/AcApPdfConvertor.ts` | Export pipeline (SVG renderer + jsPDF) | | `src/AcApPdfImportConvertor.ts` | Import pipeline (pdf.js operator parsing) | ## Role in MLightCAD This package extends `cad-simple-viewer` with optional PDF I/O. It depends on `cad-svg-plugin` for export quality parity with the existing SVG export command (`csvg`) and keeps heavy PDF dependencies out of the core viewer bundle through lazy loading. ## License MIT