Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[v4-breaking] Propose new exporting API for better ESM & Typescript support #997

Open
mmghv opened this issue Sep 28, 2023 · 15 comments
Open
Assignees

Comments

@mmghv
Copy link
Collaborator

mmghv commented Sep 28, 2023

I was looking into fixing some of the autoTable is not defined issues and improving ESM support, and also typescript issues, It all came down to the hack we do to apply the plugin to the current jspdf instance, we are using require() here to wrap it with a try-catch, this cannot be transpiled to import so it causes a problem with rollup in some version of vite/vue/angular and requires setting a flag (vitejs/vite#5759)

The solution

I propose we don't apply the plugin to jsPDF, we don't even supply applyPlugin(), so there will be no doc.autoTable* we just export the functions needed to work on a jspdf doc, currently there's autoTable(doc, ...) we make this the only way and export any other function needed like setDefaults(), so the proposed API is like this :

// ESM imports
import { jsPDF } from 'jspdf'
import { autoTable } from 'jspdf-autotable'

// commonjs (node)
const { jsPDF } = require('jspdf')
const { autoTable } = require('jspdf-autotable')

// in the browser (with a <script> tag)
const { jsPDF } = window.jspdf
const { autoTable } = window['jspdf-autotable']

// Usage
const doc = new jsPDF()
const table = autoTable(doc, {/* options */})

doc.save()

// you can access anything regarding the created table
table.finalY
table.pageNumber
table.settings
// ...

// no applyPlugin()
// no jsPDF.autoTable*
// no jsPDF.lastAutoTable

// other autotable exported functions
import { autoTable, setDefaults, htmlToJson } from 'jspdf-autotable'

setDefaults({/* ... */})
htmlToJson(/* ... */)

What makes this a breaking change is instead of default export import autoTable from 'jspdf-autotable' we change to named exports import { autoTable } from 'jspdf-autotable' to allow us to export other parts like setDefault so we don't need to extend jspdf (doc.autoTable*) and importing become consistent in all environments, That's actually also what jspdf did from v1 to v2 :

// v1
import jsPDF from "jspdf";

// v2
import { jsPDF } from "jspdf";

The benefits

This solves many problems :

  1. No need for any require() hacks, so the source code is pure ESM which makes it much easier to transpile to any format without problems (fixes TypeError: c.autoTable is not a function #860 and many more).
  2. The new API is fully ESM compliant and tree-shakable with a suitable build (fixes Official ECMAScript version #706).
  3. Consistent usage between all environments, and only one way to create the table.
  4. Ability to use any version of jspdf, you just pass the doc created to autoTable.
  5. Solves the typescript (doc as any).autoTable problem (Improve TypeScript Compatibility #994, lastAutoTable not part of index.d.ts #848) because we won't extend jspdf, we just import the correct doc type from jspdf and use it, and we have a type for the returned table which can be used to access any info regarding the table like finalY so no need for doc.lastAutotable

The downside

  • No ease of use in the browser where you could just link the script and doc.autoTable().
  • This is a breaking change so will need a major version bump (v4?)

But we could use this opportunity and remove the deprecated parts and improve the other parts, we can study the other improvements that could be done, if some need API breaking changes we do it so we don't have to do breaking changes again in the future.

@simonbengtsson What do you think? I'm ready to tackle this, if this is going to happen, I think we should create a v4 branch, do all the work there and merge when we are ready. but first I'll work a bit on the current version, go through the issues, fix what I can and take notes of things need breaking changes to do it in v4.

@simonbengtsson
Copy link
Owner

Sounds great! Time for a proper modernization! 🎉

@simonbengtsson
Copy link
Owner

I played around with this a bit now in the newly pushed v4 branch and I think I were able to implement everything exactly as your proposal above @mmghv. Great stuff!

  • Only the autoTable(doc, {...}) usage style is now supported and doc.autoTable({...}) has been removed
  • Removed setting default options as this can just as easily and with more flexibility be done outside of the plugin
  • Removed old deprecations

@simonbengtsson
Copy link
Owner

Remaining is also to change so that autoTable returns a Table instance and remove assignment of jspdf.lastAutotable etc. Something else you have thought of @mmghv?

@mmghv
Copy link
Collaborator Author

mmghv commented Feb 8, 2024

Sorry been busy for a while, just need one week to finish a task then I'll test & review the changes along with the list of todos I was planning for v4, I was hopping to take the chance to plan any breaking changes we need to do for other features/fixes/changes to introduce with this major version bump.

@simonbengtsson
Copy link
Owner

Sounds great. No rush 👍

@hrueger
Copy link

hrueger commented Feb 14, 2024

Really looking forward to this as my dev environment broke with one of the last vite updates...
If I can help testing, let me know 👍

@mmghv
Copy link
Collaborator Author

mmghv commented Feb 22, 2024

We currently target ES5 when transpiling, is it time to upgrade to ES6 (ES2015) with v4? I hate seeing all the vars and .prototype stuff especially in the es build.

ES6 adds support for const/let, classes, arrow functions and more, this results in a cleaner and a little bit smaller code:

Output file ES5 size ES6 size
jspdf.plugin.autotable.js 85KB 75KB
jspdf.plugin.autotable.min.js 33KB 28KB
jspdf.plugin.autotable.mjs 76KB 71KB

But IE11 doesn't fully support ES6:
https://caniuse.com/?search=es6

I'm not actually sure if jsPDF or autoTable fully supports IE11, and everyone is dropping support for it.
@simonbengtsson what do you think?

@simonbengtsson
Copy link
Owner

Sounds good to me! If there is anyone who still supports IE11 they can always tick with v3.

@mmghv
Copy link
Collaborator Author

mmghv commented Feb 28, 2024

Hey @hrueger, you can test v4 right now to verify that it solves the problem you're having with v3.
First, verify that you still have a problem with v3 in your dev environment then do the following:

1- Clone the v4 repo:

git clone -b v4 https://github.com/simonbengtsson/jsPDF-AutoTable.git

2- Edit package.json of autotable and change the name field to "jspdf-autotable4"

3- Link autotable v4 as a global package, inside the repo run:

npm link

4- Inside your project, install the linked v4 package:

npm link jspdf-autotable4

Now you can test v4 in your project, just remember to import from jspdf-autotable4:

import { jsPDF } from 'jspdf'
import { autoTable } from 'jspdf-autotable4'

const doc = new jsPDF()
const table = autoTable(doc, {/* options */})

console.log(table.finalY)
doc.save()

After you're done testing, unlink the v4 package, Inside your project, run these two commands:

npm unlink --global jspdf-autotable4
npm unlink jspdf-autotable4

@hrueger
Copy link

hrueger commented Feb 29, 2024

Hi @mmghv,
thanks for the detailed instructions. I tested it and it works just fine 👍

@mmghv
Copy link
Collaborator Author

mmghv commented Feb 29, 2024

@hrueger Forgot to add instructions to build the dist files because they were not updated yet, the module system should have worked with you but the return table (table.finalY) shouldn't.

Either re-clone the repo or run npm install and npm run build in the v4 repo to build the new dist files.
If the module system is all you wanted to test and it solved your problem then you don't have to do anything else.
Thanks for taking the time to test v4!

@hrueger
Copy link

hrueger commented Feb 29, 2024

@mmghv Thanks for the clarification. I actually did not follow your instructions one by one, because I had some trouble with yarn link (I'm not using npm in my project). So I checked out the v4 branch, used npm run build and npm pack to generate a .tgz file and installed that in my project. Therefore, I'm pretty sure I already tested with the latest changes 👍
table.finalY also worked fine.

@mmghv
Copy link
Collaborator Author

mmghv commented Feb 29, 2024

@hrueger Great! thanks for taking the time 👍

@oliverkan
Copy link

Hi, is there any plan to release an alpha version on v4 soon?

@mmghv
Copy link
Collaborator Author

mmghv commented Sep 19, 2024

I believe an alpha release would be beneficial for testing v4 and for early adopters as long as they expect some breaking changing before the stable release.

All of the v4 goals have been met, however, there is still significant work to be done in the colspan/rowspan area and possibly horizontalPageBreak that could lead to some breaking changes in the API.

@simonbengtsson What are your thoughts?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants