/pdfeasy

📕 A JavaScript Client/Server Side PDF-Generator based in PDFKit

Primary LanguageTypeScriptMIT LicenseMIT

PDFEasy

Client/Server Side PDF-Generator based in PDFKit




  • ✅ Client/Server Side Support
  • ✅ Write in Typescript and Builded with ESBuild
  • ✅ Browser STDLib
  • ✅ Custom Fonts && Purge Unused Fonts
  • ✅ Nuxt & Vue Support
  • ✅ Plugins Ready!

Setup

npm i pdfeasy
import pdfeasy from 'pdfeasy'

pdfeasy.new()

pdfeasy.add([
  { raw: 'PDFEasy!' },
])

pdfeasy.run({
  type: 'client',
  clientEmit: 'blob'
}).then(blobUrl) => {
  const iframe = document.querySelector('#pdf')

  iframe.src = blobUrl
}).catch((err) => {
  // ...
})
npm i vue-pdfeasy
import { PDFPlugin } from 'vue-pdfeasy';

const app = createApp(App);
app.use(PDFPlugin);
app.mount('#app');

// ...

<script setup>
import { usePDF } from 'vue-pdfeasy';

const pdf = usePDF()

pdf.new()
// ...
</script>
npm i nuxt-pdfeasy
// nuxt.config.ts
modules: [
  'nuxt-pdfeasy'
]
<script setup>
import { useNuxtApp } from '#app';

const { $pdf } = useNuxtApp()

$pdf.new()
// ...
</script>

New

pdfeasy.new({ 
  margins: { 
    top: 10, 
    bottom: 10, 
    left: 10, 
    right: 10 
  }, 
  size: "a5" 
});

Content

pdfeasy.add([
  { raw: 'Hello PDFEasy!', text: {} }, // common text
  { raw: 'https://i.imgur.com/path.png', image: {} }, // external image
  { stack: [ // stack for paragraph's
    { raw: 'A ', text: {} },
    { raw: 'Simple', text: { bold: true, italic: true } },
    { raw: ' Stack!', text: {} },
  ]},
  { pageBreak: {} }, // page break
  { lineBreak: {} }, // line break
  { raw: 'A checkbox!', checkbox: {} }, // checkbox
  { raw: 'A list!', list: { style: 'circle' } }, // list
  { raw: 'https://link', qrcode: {} }, // use qrcode.js lib
  { table: { // table. Check pdfkit-table package for more explanations
    body: {
      title: "Title",
      subtitle: "subtitle",
      headers: [ "Item 1", "Item 2" ],
      rows: [
        [ "A", "100%" ],
        [ "B", "50%" ],
      ],
    },
    options: {}
  }},
  { form: [ // dynamic forms
    { name: 'button-field', type: 'button', options: { label: 'Click here!'} },
    { name: 'text-field', type: 'text', options: { value: '' }},
  ]},
])

Plugins

pdfeasy.new({
  plugins: [{
    cover: 'https://i.imgur.com/path.png', // cover image (it's ignore default explicit margins insert)
    onBefore: () => {
      // before contents transform
    },
    onAfter: () => {
      // after contents transform
    },
    page: [ // render callback in every page AFTER finish contents insert. Not support before at this time.
      // simple counter footer
      ({ Text, Image }, context, current, total) => {
        // render in every page
        Text(`${current}/${total}`, { fontSize: 20 }, {
          x: context.width / 2,
          y: context.height - context.margins.bottom
        })

        // Image('https://i.imgur.com/to/path.png', {}, {})
      },
      // simple header
      ({ Text }, context, current, total) => {
        // render in every page
        Text('A Simple Header', {}, {
          x: context.width / 2,
          // negative number (-20 in case) ignore default pdfkit margins
          y: context.margins.top - 20
        })
      }
    ]
  }]
})

Plugins runs as a queue.

Runner Options

Client-Side Setup

pdfeasy.run({
  type: 'client',
  // 'blob' | 'save' | 'open-link' | 'none'
  clientEmit: 'save',
}).then(() => {}).catch((err) => {
  console.error(err)
})

Server-Side Setup

pdfeasy.run({
  type: 'server',
  serverPath: '/examples',
}).then(() => {}).catch((err) => {
  console.error(err)
})

Color Schema

It is possible to define the color scheme used automatically:

// converts all hex color to CMYK
pdfeasy.run({ colorSchema: 'CMYK' })

// preserve hex colors (it's default)
pdfeasy.run({ colorSchema: 'RBG' })

Custom Fonts

// or https://path/to/Roboto.ttf
pdfeasy.addFonts([
  {
    name: 'Roboto',
    normal: 'fonts/Roboto-Regular.ttf',
    bold: 'fonts/Roboto-Medium.ttf',
    italic: 'fonts/Roboto-Italic.ttf',
    bolditalic: 'fonts/Roboto-BoldItalic.ttf'
  }
])

Attention! Server-Side version not support relative/absolute font paths at this time.

Resources

See source demo for more explanations

See examples for .pdf results.

See scripts for server-side runner.

Bundles

pdfeasy/dist/client.cjs.js

pdfeasy/dist/client.esm.js

pdfeasy/dist/node.cjs.js

pdfeasy/dist/node.esm.js