I installed and tried the basic demo as below
mkdir abc && cd $_
yarn init -y
yarn install
touch index.js
const jsPDF = require('jspdf/dist/jspdf.node.debug')
// Default export is a4 paper, portrait, using milimeters for units
var doc = new jsPDF()
doc.text('Hello world!', 10, 10)
doc.save('a4.pdf')
Which gave me this error,
/Users/Downloads/abc/node_modules/jspdf/dist/jspdf.node.debug.js:3543
window.tmp = jsPDF;
^
ReferenceError: window is not defined
at Object.<anonymous> (/Users/Downloads/abc/node_modules/jspdf/dist/jspdf.node.debug.js:3543:1)
at Module._compile (internal/modules/cjs/loader.js:721:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:732:10)
at Module.load (internal/modules/cjs/loader.js:620:32)
at tryModuleLoad (internal/modules/cjs/loader.js:560:12)
at Function.Module._load (internal/modules/cjs/loader.js:552:3)
at Module.require (internal/modules/cjs/loader.js:657:17)
at require (internal/modules/cjs/helpers.js:22:18)
at Object.<anonymous> (/Users/Downloads/abc/index.js:1:77)
at Module._compile (internal/modules/cjs/loader.js:721:30)
I amended the code by doing dummy object declarations for the node env.
global.window = {document: {createElementNS: () => {return {}} }};
global.navigator = {};
global.btoa = () => {};
const jsPDF = require('jspdf/dist/jspdf.node.debug')
// Default export is a4 paper, portrait, using milimeters for units
var doc = new jsPDF()
doc.text('Hello world!', 10, 10)
doc.save('a4.pdf')
error got updated to the following,
/Users/Downloads/abc/node_modules/jspdf/dist/jspdf.node.debug.js:3334
saveAs(getBlob(buildDocument()), filename);
^
ReferenceError: saveAs is not defined
at Object.API.save (/Users/Downloads/abc/node_modules/jspdf/dist/jspdf.node.debug.js:3334:9)
at Object.<anonymous> (/Users/Downloads/abc/index.js:11:5)
at Module._compile (internal/modules/cjs/loader.js:721:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:732:10)
at Module.load (internal/modules/cjs/loader.js:620:32)
at tryModuleLoad (internal/modules/cjs/loader.js:560:12)
at Function.Module._load (internal/modules/cjs/loader.js:552:3)
at Function.Module.runMain (internal/modules/cjs/loader.js:774:12)
at executeUserCode (internal/bootstrap/node.js:342:17)
at startExecution (internal/bootstrap/node.js:276:5)
I build the latest version of jsPDF and used that instead of build from npm.
const jsPDF = require('./dist/jspdf.node.debug')
// Default export is a4 paper, portrait, using milimeters for units
var doc = new jsPDF()
doc.text('Hello world!', 10, 10)
doc.save('a4.pdf')
which gave me the following error,
/Users/muhammadadeel/Downloads/abc/dist/jspdf.node.debug.js:3549
window.tmp = jsPDF;
^
ReferenceError: window is not defined
at Object.<anonymous> (/Users/Downloads/abc/dist/jspdf.node.debug.js:3549:1)
at Module._compile (internal/modules/cjs/loader.js:721:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:732:10)
at Module.load (internal/modules/cjs/loader.js:620:32)
at tryModuleLoad (internal/modules/cjs/loader.js:560:12)
at Function.Module._load (internal/modules/cjs/loader.js:552:3)
at Module.require (internal/modules/cjs/loader.js:657:17)
at require (internal/modules/cjs/helpers.js:22:18)
at Object.<anonymous> (/Users/Downloads/abc/index.js:1:77)
at Module._compile (internal/modules/cjs/loader.js:721:30)
There were previous issues but not as well documented as the one I have provided. Can you please suggest amends.
global.window = {document: {createElementNS: () => {return {}} }};
global.navigator = {};
global.btoa = () => {};
const fs = require('fs')
const jsPDF = require('jspdf/dist/jspdf.node.min')
// Default export is a4 paper, portrait, using milimeters for units
var doc = new jsPDF()
doc.text('Hello world!', 10, 10)
fs.writeFileSync('./output.pdf', doc.output())
// doc.save('a4.pdf')
delete global.window;
delete global.navigator;
delete global.btoa;
Interesting.
@arasabbasi 馃檪 any better way to go around the globals
Well we could try dependency injection.
I am also using the globals. If we do dependency injection, then we also need to inject the definitions from the browser. So eentually is the same but the other way round.
Tbh, i dont understand why btoa is not working,?
Does node not have btoa?
why do we need createElementNS? And why do you need navigator object? They are not used in jspdf?
for btoa there is an npm package as well https://www.npmjs.com/package/btoa
createElementNS don't think so as it's on the document object and specific to the browser.
There is a XMLDOM package on npm to do this https://www.npmjs.com/package/xmldom
Should we add btoa npm to package.json?
better idea wud be to refactor the build to include node.js dependencies separately as amends to existing packages
Yeah, problem is, that jspdf is primarily made for browsers and not for node. So refactor it to fit for node can break everything for the browser targets.
If the polyfill is well documented, it is not a problem. So I would also hesitate to do a big refactoring.
I was referring to having a separate build file (webpack/gulp, package.json) for node, that way you can include/exclude dependencies for particular environments.
Hmm. well. have to dig deeper in this.Maybe replacing atob and btoa in general with the ones in the npm packages?
Hi, I'm also trying to make it work on the server side, but it seems it does not works well when using custom fonts (I need then since I have to be able to display different languages, including RTL Arabic)
I've tryed several samples but the PDF shows an error in Acrobat and does not show the glyphs in Chrome.
I've modified the japanese sample: https://github.com/MrRio/jsPDF/blob/master/examples/js/japanese.js
global.window = {document: {createElementNS: () => {return {}} }};
global.navigator = {};
global.btoa = () => {};
var MouhitsuBold = "AAEAAAASAQAABAAgR1N...
const fs = require('fs');
const jsPDF = require('jspdf/dist/jspdf.node.min');
var doc = new jsPDF();
doc.addFileToVFS("MouhitsuBold.ttf", MouhitsuBold);
doc.addFont('MouhitsuBold.ttf', 'Mouhitsu', 'bold');
doc.setFont('Mouhitsu', 'bold'); // set font
doc.setFontSize(20);
doc.text("銇伀", 20, 20);
var data = doc.output();
fs.writeFileSync('./document.pdf', data);
delete global.window;
delete global.navigator;
delete global.btoa;
But I got an error in Acrobat "Cannot extract the embedded font 'Mouhitsu'. Some characters may not display or print correctly. "
Also, I understand that in server side you could load the font by using directly
doc.addFont('MouhitsuBold.ttf', 'Mouhitsu', 'bold');
Right?
No. addFont doesn't have any filesystem operations
This would be a huge help to be able to have it working well with node. 馃憦 Then I would for sure use it over all the other competitors.
@janteque I also would like to use it server side with Arabic-based RTL language support. Any luck getting it to work?
Added examples in folder examples/node with three in node working snippets
I did put atob and btoa to globals of jsPDF. Any thoughts on this?
In my environment, atob and btoa are included as node module. Why should it be part of jsPDF?
Hi, I cannot replicate the example https://rawgit.com/MrRio/jsPDF/master/ that add an image with nodejs.
Any way to do it?
@pirasalbe
I will update the examples. Be ready for surprises
@Uzlopak nodeJS examples are not working yet. Still throwing error:
/home/geronimops/dev/project-a/node_modules/jspdf/dist/jspdf.node.debug.js:3543
window.tmp = jsPDF;
ReferenceError: window is not defined
at Object.<anonymous> (/home/geronimops/dev/project-a/node_modules/jspdf/dist/jspdf.node.debug.js:3543:1)
1
I installed and tried the basic demo as below
mkdir abc && cd $_ yarn init -y yarn install touch index.jsconst jsPDF = require('jspdf/dist/jspdf.node.debug') // Default export is a4 paper, portrait, using milimeters for units var doc = new jsPDF() doc.text('Hello world!', 10, 10) doc.save('a4.pdf')Which gave me this error,
/Users/Downloads/abc/node_modules/jspdf/dist/jspdf.node.debug.js:3543 window.tmp = jsPDF; ^ ReferenceError: window is not defined at Object.<anonymous> (/Users/Downloads/abc/node_modules/jspdf/dist/jspdf.node.debug.js:3543:1) at Module._compile (internal/modules/cjs/loader.js:721:30) at Object.Module._extensions..js (internal/modules/cjs/loader.js:732:10) at Module.load (internal/modules/cjs/loader.js:620:32) at tryModuleLoad (internal/modules/cjs/loader.js:560:12) at Function.Module._load (internal/modules/cjs/loader.js:552:3) at Module.require (internal/modules/cjs/loader.js:657:17) at require (internal/modules/cjs/helpers.js:22:18) at Object.<anonymous> (/Users/Downloads/abc/index.js:1:77) at Module._compile (internal/modules/cjs/loader.js:721:30)2
I amended the code by doing dummy object declarations for the node env.
global.window = {document: {createElementNS: () => {return {}} }}; global.navigator = {}; global.btoa = () => {}; const jsPDF = require('jspdf/dist/jspdf.node.debug') // Default export is a4 paper, portrait, using milimeters for units var doc = new jsPDF() doc.text('Hello world!', 10, 10) doc.save('a4.pdf')error got updated to the following,
/Users/Downloads/abc/node_modules/jspdf/dist/jspdf.node.debug.js:3334 saveAs(getBlob(buildDocument()), filename); ^ ReferenceError: saveAs is not defined at Object.API.save (/Users/Downloads/abc/node_modules/jspdf/dist/jspdf.node.debug.js:3334:9) at Object.<anonymous> (/Users/Downloads/abc/index.js:11:5) at Module._compile (internal/modules/cjs/loader.js:721:30) at Object.Module._extensions..js (internal/modules/cjs/loader.js:732:10) at Module.load (internal/modules/cjs/loader.js:620:32) at tryModuleLoad (internal/modules/cjs/loader.js:560:12) at Function.Module._load (internal/modules/cjs/loader.js:552:3) at Function.Module.runMain (internal/modules/cjs/loader.js:774:12) at executeUserCode (internal/bootstrap/node.js:342:17) at startExecution (internal/bootstrap/node.js:276:5)3
I build the latest version of jsPDF and used that instead of build from npm.
const jsPDF = require('./dist/jspdf.node.debug') // Default export is a4 paper, portrait, using milimeters for units var doc = new jsPDF() doc.text('Hello world!', 10, 10) doc.save('a4.pdf')which gave me the following error,
/Users/muhammadadeel/Downloads/abc/dist/jspdf.node.debug.js:3549 window.tmp = jsPDF; ^ ReferenceError: window is not defined at Object.<anonymous> (/Users/Downloads/abc/dist/jspdf.node.debug.js:3549:1) at Module._compile (internal/modules/cjs/loader.js:721:30) at Object.Module._extensions..js (internal/modules/cjs/loader.js:732:10) at Module.load (internal/modules/cjs/loader.js:620:32) at tryModuleLoad (internal/modules/cjs/loader.js:560:12) at Function.Module._load (internal/modules/cjs/loader.js:552:3) at Module.require (internal/modules/cjs/loader.js:657:17) at require (internal/modules/cjs/helpers.js:22:18) at Object.<anonymous> (/Users/Downloads/abc/index.js:1:77) at Module._compile (internal/modules/cjs/loader.js:721:30)
There were previous issues but not as well documented as the one I have provided. Can you please suggest amends.
Solution
- On the server side don't use doc.save() declare dummy object references and remove them as below.
- Also note, use the _jspdf.node.min_ instead of plain _jspdf_ referencing
global.window = {document: {createElementNS: () => {return {}} }}; global.navigator = {}; global.btoa = () => {}; const fs = require('fs') const jsPDF = require('jspdf/dist/jspdf.node.min') // Default export is a4 paper, portrait, using milimeters for units var doc = new jsPDF() doc.text('Hello world!', 10, 10) fs.writeFileSync('./output.pdf', doc.output()) // doc.save('a4.pdf') delete global.window; delete global.navigator; delete global.btoa;
Thank you so so much for this solution, you save my weekend.
@TeijiW [email protected] supports nodejs out of the box. No need for any workarounds.