{"id":21425055,"url":"https://github.com/betterwrite/pdfeasy","last_synced_at":"2025-09-10T00:36:10.109Z","repository":{"id":43819842,"uuid":"457138382","full_name":"betterwrite/pdfeasy","owner":"betterwrite","description":"📕 A JavaScript Client/Server Side PDF-Generator based in PDFKit","archived":false,"fork":false,"pushed_at":"2025-02-14T20:25:53.000Z","size":16325,"stargazers_count":89,"open_issues_count":3,"forks_count":4,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-07-05T09:49:26.977Z","etag":null,"topics":["pdf","pdf-converter","pdf-document","pdf-generation","pdfkit","typescript"],"latest_commit_sha":null,"homepage":"https://betterwrite.github.io/pdfeasy","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/betterwrite.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2022-02-08T23:26:38.000Z","updated_at":"2025-06-30T12:07:42.000Z","dependencies_parsed_at":"2024-06-19T01:44:14.094Z","dependency_job_id":"8d5279bf-f99c-4659-b5c9-ccc4426a6322","html_url":"https://github.com/betterwrite/pdfeasy","commit_stats":{"total_commits":117,"total_committers":1,"mean_commits":117.0,"dds":0.0,"last_synced_commit":"be81eb1d13722aa54a2d9bb1908ed5e526a77f92"},"previous_names":[],"tags_count":26,"template":false,"template_full_name":null,"purl":"pkg:github/betterwrite/pdfeasy","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/betterwrite%2Fpdfeasy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/betterwrite%2Fpdfeasy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/betterwrite%2Fpdfeasy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/betterwrite%2Fpdfeasy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/betterwrite","download_url":"https://codeload.github.com/betterwrite/pdfeasy/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/betterwrite%2Fpdfeasy/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265262631,"owners_count":23736437,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["pdf","pdf-converter","pdf-document","pdf-generation","pdfkit","typescript"],"created_at":"2024-11-22T21:26:34.386Z","updated_at":"2025-09-10T00:36:10.096Z","avatar_url":"https://github.com/betterwrite.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\r\n  \u003cimg src=\"./.github/logo.png\" height=\"260\"\u003e\r\n\u003c/p\u003e\r\n\r\n\u003ch1 align=\"center\"\u003e\r\nPDFEasy\r\n\u003c/h1\u003e\r\n\u003ch4 align=\"center\"\u003e\r\nClient/Server Side PDF-Generator based in PDFKit\r\n\u003ch4\u003e\r\n\u003cbr\u003e\r\n\u003cp align=\"center\"\u003e\r\n  \u003ca\u003e\u003cimg src=\"https://img.shields.io/github/license/Novout/pdfeasy?style=for-the-badge\u0026color=5cb4f8\u0026label=\"\u003e\u003c/a\u003e\r\n\u003cp\u003e\r\n\r\n\u003cbr\u003e\r\n\u003cbr\u003e\r\n\r\n- **✅ Client/Server Side Support**\r\n- **✅ Write in Typescript and Builded with [ESBuild](https://github.com/evanw/esbuild)**\r\n- **✅ Browser STDLib**\r\n- **✅ Custom Fonts \u0026\u0026 Purge Unused Fonts**\r\n- **✅ [Nuxt](./packages/nuxt) \u0026 [Vue](./packages/vue) Support**\r\n- **✅ Plugins Ready!**\r\n\r\n## Setup\r\n\r\n```shell\r\nnpm i pdfeasy\r\n```\r\n\r\n```ts\r\nimport pdfeasy from 'pdfeasy'\r\n\r\npdfeasy.new()\r\n\r\npdfeasy.add([\r\n  { raw: 'PDFEasy!' },\r\n])\r\n\r\npdfeasy.run({\r\n  type: 'client',\r\n  clientEmit: 'blob'\r\n}).then(blobUrl) =\u003e {\r\n  const iframe = document.querySelector('#pdf')\r\n\r\n  iframe.src = blobUrl\r\n}).catch((err) =\u003e {\r\n  // ...\r\n})\r\n```\r\n\r\n### [Vue](./packages/vue)\r\n\r\n```shell\r\nnpm i vue-pdfeasy\r\n```\r\n\r\n```ts\r\nimport { PDFPlugin } from 'vue-pdfeasy';\r\n\r\nconst app = createApp(App);\r\napp.use(PDFPlugin);\r\napp.mount('#app');\r\n\r\n// ...\r\n\r\n\u003cscript setup\u003e\r\nimport { usePDF } from 'vue-pdfeasy';\r\n\r\nconst pdf = usePDF()\r\n\r\npdf.new()\r\n// ...\r\n\u003c/script\u003e\r\n```\r\n\r\n### [Nuxt](./packages/nuxt)\r\n\r\n```bash\r\nnpm i nuxt-pdfeasy\r\n```\r\n\r\n```js\r\n// nuxt.config.ts\r\nmodules: [\r\n  'nuxt-pdfeasy'\r\n]\r\n```\r\n\r\n```ts\r\n\u003cscript setup\u003e\r\nimport { useNuxtApp } from '#app';\r\n\r\nconst { $pdf } = useNuxtApp()\r\n\r\n$pdf.new()\r\n// ...\r\n\u003c/script\u003e\r\n```\r\n\r\n## New\r\n\r\n```ts\r\npdfeasy.new({ \r\n  margins: { \r\n    top: 10, \r\n    bottom: 10, \r\n    left: 10, \r\n    right: 10 \r\n  }, \r\n  size: \"a5\" \r\n});\r\n```\r\n\r\n## Content\r\n\r\n```ts\r\npdfeasy.add([\r\n  { raw: 'Hello PDFEasy!', text: {} }, // common text\r\n  { raw: 'https://i.imgur.com/path.png', image: {} }, // external image\r\n  { stack: [ // stack for paragraph's\r\n    { raw: 'A ', text: {} },\r\n    { raw: 'Simple', text: { bold: true, italic: true } },\r\n    { raw: ' Stack!', text: {} },\r\n  ]},\r\n  { pageBreak: {} }, // page break\r\n  { lineBreak: {} }, // line break\r\n  { raw: 'A checkbox!', checkbox: {} }, // checkbox\r\n  { raw: 'A list!', list: { style: 'circle' } }, // list\r\n  { raw: 'https://link', qrcode: {} }, // use qrcode.js lib\r\n  { table: { // table. Check pdfkit-table package for more explanations\r\n    body: {\r\n      title: \"Title\",\r\n      subtitle: \"subtitle\",\r\n      headers: [ \"Item 1\", \"Item 2\" ],\r\n      rows: [\r\n        [ \"A\", \"100%\" ],\r\n        [ \"B\", \"50%\" ],\r\n      ],\r\n    },\r\n    options: {}\r\n  }},\r\n  { form: [ // dynamic forms\r\n    { name: 'button-field', type: 'button', options: { label: 'Click here!'} },\r\n    { name: 'text-field', type: 'text', options: { value: '' }},\r\n  ]},\r\n])\r\n```\r\n\r\n## Plugins\r\n\r\n```ts\r\npdfeasy.new({\r\n  plugins: [{\r\n    cover: 'https://i.imgur.com/path.png', // cover image (it's ignore default explicit margins insert)\r\n    onBefore: () =\u003e {\r\n      // before contents transform\r\n    },\r\n    onAfter: () =\u003e {\r\n      // after contents transform\r\n    },\r\n    page: [ // render callback in every page AFTER finish contents insert. Not support before at this time.\r\n      // simple counter footer\r\n      ({ Text, Image }, context, current, total) =\u003e {\r\n        // render in every page\r\n        Text(`${current}/${total}`, { fontSize: 20 }, {\r\n          x: context.width / 2,\r\n          y: context.height - context.margins.bottom\r\n        })\r\n\r\n        // Image('https://i.imgur.com/to/path.png', {}, {})\r\n      },\r\n      // simple header\r\n      ({ Text }, context, current, total) =\u003e {\r\n        // render in every page\r\n        Text('A Simple Header', {}, {\r\n          x: context.width / 2,\r\n          // negative number (-20 in case) ignore default pdfkit margins\r\n          y: context.margins.top - 20\r\n        })\r\n      }\r\n    ]\r\n  }]\r\n})\r\n```\r\n\r\n\u003e Plugins runs as a queue.\r\n\r\n## Runner Options\r\n\r\n### Client-Side Setup\r\n\r\n```ts\r\npdfeasy.run({\r\n  type: 'client',\r\n  // 'blob' | 'save' | 'open-link' | 'none'\r\n  clientEmit: 'save',\r\n}).then(() =\u003e {}).catch((err) =\u003e {\r\n  console.error(err)\r\n})\r\n```\r\n\r\n### Server-Side Setup\r\n\r\n```ts\r\npdfeasy.run({\r\n  type: 'server',\r\n  serverPath: '/examples',\r\n}).then(() =\u003e {}).catch((err) =\u003e {\r\n  console.error(err)\r\n})\r\n```\r\n\r\n### Color Schema\r\n\r\nIt is possible to define the color scheme used automatically:\r\n\r\n```ts\r\n// converts all hex color to CMYK\r\npdfeasy.run({ colorSchema: 'CMYK' })\r\n\r\n// preserve hex colors (it's default)\r\npdfeasy.run({ colorSchema: 'RBG' })\r\n```\r\n\r\n## Custom Fonts\r\n\r\n```ts\r\n// or https://path/to/Roboto.ttf\r\npdfeasy.addFonts([\r\n  {\r\n    name: 'Roboto',\r\n    normal: 'fonts/Roboto-Regular.ttf',\r\n    bold: 'fonts/Roboto-Medium.ttf',\r\n    italic: 'fonts/Roboto-Italic.ttf',\r\n    bolditalic: 'fonts/Roboto-BoldItalic.ttf'\r\n  }\r\n])\r\n```\r\n\r\n\u003e **Attention!** Server-Side version not support relative/absolute font paths at this time.\r\n\r\n## Resources\r\n\r\nSee [source demo](./demo) for more explanations\r\n\r\nSee [examples](./packages/core/examples/) for .pdf results.\r\n\r\nSee [scripts](./packages/core/scripts/generate/) for server-side runner.\r\n\r\n## Bundles\r\n\r\n`pdfeasy/dist/client.cjs.js`\r\n\r\n`pdfeasy/dist/client.esm.js`\r\n\r\n`pdfeasy/dist/node.cjs.js`\r\n\r\n`pdfeasy/dist/node.esm.js`\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbetterwrite%2Fpdfeasy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbetterwrite%2Fpdfeasy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbetterwrite%2Fpdfeasy/lists"}