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

Convert html to pdf: utf-8 works only with text, but not html (unicode/cyrillic not working) #2968

Open
potapovnikita opened this issue Oct 18, 2020 · 50 comments
Labels

Comments

@potapovnikita
Copy link

I'm opening this issue again.

I need to convert html to pdf with jsPDF. It contains UTF-8 symbols (cyrillic). I used fontconverter to generate js-file for my custom font as written here: https://github.com/MrRio/jsPDF

So now example with text works like a charm (from https://github.com/MrRio/jsPDF/blob/master/examples/js/russian.js)

var pdf = new jsPDF('p', 'pt', 'letter');
doc.setFont('PTSans');
doc.setFontSize(10);
doc.text("А ну чики брики и в дамки!", 10, 10);

And example with html ignores my custom font and exports incorrect symbols.

var pdf = new jsPDF('p', 'pt', 'letter');
doc.setFont('PTSans');
doc.setFontSize(10);
pdf.html( "<html>А ну чики брики и в дамки!</html>", { callback: function (pdf) {
    var iframe = document.createElement('iframe');
    iframe.setAttribute('style', 'position:absolute;right:0; top:0; bottom:0; height:100%; width:500px');
    document.body.appendChild(iframe);
    iframe.src = pdf.output('datauristring');
    }
});

What I need to do to export html to pdf with unicode symbols?

@HackbrettXXX
Copy link
Collaborator

Please try setting the font name also in the html markup. E.g.

<html style="font-family: PTSans;">А ну чики брики и в дамки!</html>

@potapovnikita
Copy link
Author

potapovnikita commented Oct 21, 2020

not working
`createCert() {

  this.doc.addFileToVFS("MyFont.ttf", myFont);
  this.doc.addFont("MyFont.ttf", "MyFont", "normal");
  this.doc.setFont("MyFont");
  const html = "<html style=\"font-family: 'MyFont';\">А ну чики брики и в дамки!</html>"
  this.doc.html(html, {
    callback: (doc) => {
      doc.save("a4.pdf");
    },
    x: 10,
    y: 10
  });
}`

@HackbrettXXX
Copy link
Collaborator

Then I guess it's a bug...

@LucaCode92
Copy link

@HackbrettXXX the same with Polish signs :(
Is there any chance for a quick fix of this problem?

I'm tring to create pdf in this way:

window.jsPDF = window.jspdf.jsPDF
var doc = new jsPDF('p', 'px', 'a4');

var elementToPrint = document.getElementById('printPDFtest');
doc.html(elementToPrint, {
        html2canvas: {
            scale: 0.45
        },
        callback: function (doc) {
            doc.save();
        }
    });

@potapovnikita
Copy link
Author

@HackbrettXXX the same with Polish signs :(
Is there any chance for a quick fix of this problem?

I'm tring to create pdf in this way:

window.jsPDF = window.jspdf.jsPDF
var doc = new jsPDF('p', 'px', 'a4');

var elementToPrint = document.getElementById('printPDFtest');
doc.html(elementToPrint, {
        html2canvas: {
            scale: 0.45
        },
        callback: function (doc) {
            doc.save();
        }
    });

It works?

@LucaCode92
Copy link

@potapovnikita as I mentioned - there is a problem. I just showed part of my code in case I made a mistake somewhere :)

@Jigisha-sublime
Copy link

@potapovnikita

I'm opening this issue again.

I need to convert html to pdf with jsPDF. It contains UTF-8 symbols (cyrillic). I used fontconverter to generate js-file for my custom font as written here: https://github.com/MrRio/jsPDF

So now example with text works like a charm (from https://github.com/MrRio/jsPDF/blob/master/examples/js/russian.js)

var pdf = new jsPDF('p', 'pt', 'letter');
doc.setFont('PTSans');
doc.setFontSize(10);
doc.text("А ну чики брики и в дамки!", 10, 10);

And example with html ignores my custom font and exports incorrect symbols.

var pdf = new jsPDF('p', 'pt', 'letter');
doc.setFont('PTSans');
doc.setFontSize(10);
pdf.html( "<html>А ну чики брики и в дамки!</html>", { callback: function (pdf) {
    var iframe = document.createElement('iframe');
    iframe.setAttribute('style', 'position:absolute;right:0; top:0; bottom:0; height:100%; width:500px');
    document.body.appendChild(iframe);
    iframe.src = pdf.output('datauristring');
    }
});

What I need to do to export html to pdf with unicode symbols?

I would like to mention two things here.

  1. setting font as doc.setFont('PTSans') won't work for the HTML. for accessing fonts in the HTML you have to pass it as an inline style with font-family.

  2. I have observed that the .html API of jsPdf does not support directly, takes the main element of the body, and renders it. ( Correct me if I'm wrong but I have observed it many times.)

so, after spending almost my entire day on it, I have figure out the below solution which helps me to get those bullets on my pdf.

after adding custom fonts just like explained below article you have to import your font files into your component and just style your HTML like this.
https://www.devlinpeck.com/tutorials/jspdf-custom-font#:~:text=Adding%20Custom%20Fonts%20to%20jsPDF,of%20your%20desired%20font%20file.&text=Once%20you%20have%20your%20.,to%20this%20jsPDF%20Font%20Converter.

`import '../../../Lato-Regular-normal';

const htmlToConvert =

doc.html(htmlToConvert,{
callback:function{
doc.save()
}
})`

@Jigisha-sublime
Copy link

Hope that it will help some one.

@Jigisha-sublime
Copy link

Then I guess it's a bug...

So, I guess it's not a bug but a lack of clarity for the use case.

@Rui-Jesus
Copy link
Contributor

Rui-Jesus commented Nov 16, 2020

In my case, using the version 2.1, setting the font style on the html element like so: <html style="font-family: PTSans;">А ну чики брики и в дамки!</html> and importing the fonts according to https://www.devlinpeck.com/tutorials/jspdf-custom-font#:~:text=Adding%20Custom%20Fonts%20to%20jsPDF,of%20your%20desired%20font%20file.&text=Once%20you%20have%20your%20.,to%20this%20jsPDF%20Font%20Converter. worked for me when using an html element reference instead of using a raw html string.

@HackbrettXXX
Copy link
Collaborator

@potapovnikita which jsPDF version do you use? If it's not the current one please update.

@Rui-Jesus If this only works if the markup is passed as element, this might be an encoding issue of the file that contains the html markup?

@cakesforfree
Copy link

In my case, using the version 2.1, setting the font style on the html element like so: <html style="font-family: PTSans;">А ну чики брики и в дамки!</html> and importing the fonts according to https://www.devlinpeck.com/tutorials/jspdf-custom-font#:~:text=Adding%20Custom%20Fonts%20to%20jsPDF,of%20your%20desired%20font%20file.&text=Once%20you%20have%20your%20.,to%20this%20jsPDF%20Font%20Converter. worked for me when using an html element reference instead of using a raw html string.

It works, and it works wonderfully, thank you <3

@Rui-Jesus
Copy link
Contributor

Rui-Jesus commented Dec 15, 2020

@HackbrettXXX I did not test passing a file with the html markup, I had it stored in memory, the html markup. To be honest I didn't look too much into the issue since the solution I provided works perfectly for me.

@CurryPaste
Copy link

In my case, using the version 2.1, setting the font style on the html element like so: <html style="font-family: PTSans;">А ну чики брики и в дамки!</html> and importing the fonts according to https://www.devlinpeck.com/tutorials/jspdf-custom-font#:~:text=Adding%20Custom%20Fonts%20to%20jsPDF,of%20your%20desired%20font%20file.&text=Once%20you%20have%20your%20.,to%20this%20jsPDF%20Font%20Converter. worked for me when using an html element reference instead of using a raw html string.

Thank you. He inspired me.
I use html method, but the tag on the page does not show the Chinese I want, but after reading your reply, I added font family to the tag on the page, and it can be used.

This is the end result:
QQ截图20210120095315
This is code:

const htmlStr: HTMLElement = document.querySelector('.main') || document.body;
doc.html(htmlStr, {
        callback(isPdf) {
          // add the font to jsPDF
          doc.addFileToVFS('fzjt.ttf', MyFont); // addfont
          doc.addFont('fzjt.ttf', 'MyFont', 'normal');
          doc.setFont('MyFont');
          isPdf.text('又是中文', 10, 10);
          isPdf.save();
        },
      });
.main
  background #ffffff
  width 90%
  font-family 'MyFont'

It's amazing 🎉

@jedaix
Copy link

jedaix commented Feb 17, 2021

I have a same problem. utf-8 characters not working with html method.
window.jsPDF = window.jspdf.jsPDF; $("#downPDF").on("click", function() { var doc = new jsPDF({ orientation: "landscape" }); var source = document.getElementById("pdfCard"); doc.setFont("Roboto-Regular"); doc.html(source, { callback: function(doc) { doc.save(); }, x: 2, y: 2, html2canvas: { scale: 0.25, }, }); })

if I try only generate:
doc.text("ľščťžžýáíúô", 10, 10); doc.save();
it's working

@LazZiya
Copy link

LazZiya commented Mar 9, 2021

I am building a web app with three cultures "en", "tr", "ar". I followed the process as mentioned by @Rui-Jesus, but it didn't work!

In my case, using the version 2.1, setting the font style on the html element like so: <html style="font-family: PTSans;">А ну чики брики и в дамки!</html> and importing the fonts according to https://www.devlinpeck.com/tutorials/jspdf-custom-font#:~:text=Adding%20Custom%20Fonts%20to%20jsPDF,of%20your%20desired%20font%20file.&text=Once%20you%20have%20your%20.,to%20this%20jsPDF%20Font%20Converter. worked for me when using an html element reference instead of using a raw html string.

Then I did few modifications to make it work with specific font (the same process didn't work with all fonts)

  • Download font from google fonts, in my case I used Cairo (Regular 400) because it supports all my cultures.
  • Put the font link inside <header> :
<!-- GoogleFonts: Cairo -->
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Cairo&display=swap" rel="stylesheet">
  • Use CSS rules in CSS file:
body {
    font-family: 'Cairo', sans-serif !important;
}
  • Convert the font as mentioned in the tutorial. But I changed the module format to UMD.
  • The downloaded file uses the font name as Cairo-Regular, and that was the problem. I changed it to Cairo since the CSS font name is Cairo.
// this.addFont('Cairo-Regular-normal.ttf', 'Cairo-Regular', 'normal');
this.addFont('Cairo-Regular-normal.ttf', 'Cairo', 'normal');
  • Adding the style to html didn't work, but it worked when added style to the body tag:
<body style="font-family: 'Cairo', sans-serif !important;">
  • Below is the rest of the code:
<!-- jsPDF -->
<script src="~/lib/jspdf/dist/jspdf.umd.min.js"></script>
<script src="~/js/html2canvas.min.js"></script>
<script src="~/lib/dompurify/dist/purify.min.js"></script>
<script src="~/js/Cairo-Regular-normal.js"></script>
<script>
    $(function () {
        setTimeout(function () {
            window.jsPDF = window.jspdf.jsPDF;
            // Default export is a4 paper, portrait, using millimeters for units
            const doc = new jsPDF('p', 'pt', 'a4');
            doc.html(document.body, {
                html2canvas: {
                    scale: 0.5,
                    scrollY:0
                },
                x: 0,
                y: 0,
                callback: function (doc) {
                    window.open(doc.output('bloburl'));
                }
            });
        }, 1000);
    });
</script>

Now I have a working solution with English and Turkish :
image

But it is not fully supporting Arabic. Some letters are missing, and if I have multiple languages the latin letters are rendred over each other as seen in the below image:
image

The correct html page looks like below:
image

I also tried with adding doc.addLanguage("ar") but it didn't help.

@ghost
Copy link

ghost commented Mar 11, 2021

my solution to this problem:

  1. create custom font ( use this : https://www.devlinpeck.com/tutorials/jspdf-custom-font#:~:text=Adding%20Custom%20Fonts%20to%20jsPDF,of%20your%20desired%20font%20file.&text=Once%20you%20have%20your%20.,to%20this%20jsPDF%20Font%20Converter )
  2. add font to project :
    image
  3. import this font:
    image
  4. add font to pdf doc.:
    image

@bemulima
Copy link

bemulima commented Apr 21, 2021

I have the same problem.
I'm surprised there is no good solution. How this library got so many likes? Everything is so hard to solve in there.

so it is my code but not supporting fornAwesome and cyrylic.

import './RobotoBlackNormal';
...
var doc = new jsPDF('p', 'pt', 'a4');
        // doc.addFont("test/reference/PTSans.ttf", "PTSans", "normal");
        doc.addFont('https://use.fontawesome.com/releases/v5.3.1/webfonts/fa-regular-400.ttf', 'FontAwesome', 'normal');
        doc.addFont('Roboto-Regular.ttf', 'Roboto-Regular', 'normal');
        doc.addFont('Roboto-Black.ttf', 'Roboto-Black', 'normal');
        doc.addFont('Roboto-Bold.ttf', 'Roboto-Bold', 'normal');
        doc.addFont('Roboto-Medium.ttf', 'Roboto-Medium', 'normal');
        doc.setFont('Font Awesome 5 Free');
        doc.setFont('Roboto-Regular');
        doc.setFont('Roboto-Black');
        doc.setFont('Roboto-Bold');
        doc.setFont('Roboto-Medium');

        doc.html(ref.current.querySelector('#response-list'), {
            callback: function (doc) {
                doc.save();
            }});

image

@bemulima
Copy link

just cyrylic text correct displaying but by document element not supported

var doc = new jsPDF('p', 'pt', 'a4');
        // doc.addFont("test/reference/PTSans.ttf", "PTSans", "normal");
        doc.addFont('https://use.fontawesome.com/releases/v5.3.1/webfonts/fa-regular-400.ttf', 'FontAwesome', 'normal');
        // doc.addFont('Roboto-Regular.ttf', 'Roboto-Regular', 'normal');
        // doc.addFont('Roboto-Black.ttf', 'Roboto-Black', 'normal');
        // doc.addFont('Roboto-Bold.ttf', 'Roboto-Bold', 'normal');
        // doc.addFont('Roboto-Medium.ttf', 'Roboto-Medium', 'normal');
        doc.setFont('Font Awesome 5 Free');
        doc.setFont('Roboto-Regular');
        // doc.setFont('Roboto-Black');
        // doc.setFont('Roboto-Bold');
        // doc.setFont('Roboto-Medium');
        doc.text("А ну чики брики и в дамки!", 10, 10);
        // doc.html('<html style="font-family: Roboto;">' + ref.current.querySelector('#response-list').innerHTML + '</html>>',
        //     {
        //     callback: function (doc) {
        //         doc.save();
        //     }});
        doc.save('ho-ho-ho.pdf');

image

@bemulima
Copy link

also I can't set HTML as just string to doc.html():

 console.log('doc', ref.current.querySelector('#response-list'))
        var doc = new jsPDF('p', 'pt', 'a4');
        // doc.addFont("test/reference/PTSans.ttf", "PTSans", "normal");
        doc.addFont('https://use.fontawesome.com/releases/v5.3.1/webfonts/fa-regular-400.ttf', 'FontAwesome', 'normal');
        // doc.addFont('Roboto-Regular.ttf', 'Roboto-Regular', 'normal');
        // doc.addFont('Roboto-Black.ttf', 'Roboto-Black', 'normal');
        // doc.addFont('Roboto-Bold.ttf', 'Roboto-Bold', 'normal');
        // doc.addFont('Roboto-Medium.ttf', 'Roboto-Medium', 'normal');
        doc.setFont('Font Awesome 5 Free');

        // doc.setFont('Roboto-Black');
        // doc.setFont('Roboto-Bold');
        // doc.setFont('Roboto-Medium');
        // doc.text("А ну чики брики и в дамки!", 10, 10);
        // doc.html(ref.current.querySelector('#response-list'),
        doc.html("<html style='font-family: Roboto;'>А ну чики брики и в дамки!</html>",
            {
            callback: function (doc) {
                doc.setFont('Roboto-Regular');
                doc.setFont('Roboto-Bold');
                doc.save();
            }});

image

@jedaix
Copy link

jedaix commented Sep 7, 2021

any progress on this issue?

@NeonDB
Copy link

NeonDB commented Oct 5, 2021

Well, dear friends, perhaps I have found the Main Evil. To display .html with a specific font as of October 05, 2021, it is enough to specify the font as a style for the html element, and it will be applied to all the text inside it. It is important to use the correct fonts, which have the layout of your alphabet, Cyrillic, Polish, etc. This is my experience of 2 days searching for an answer to my problem. Hope this helps someone not to waste time. Alternatively, write the same set of fonts that is used on your site using the .addFont & .setFont method. That is, the text in your html has exactly the same font set as you specify with the .addFont & .setFont methods. Otherwise, the font will be displayed incorrectly. All the best, be attentive and quick

@jedaix
Copy link

jedaix commented Oct 5, 2021

@NeonDB not working for me. I'm using Roboto font on page. And this initialization is not working:
var doc = new jsPDF({ orientation: "landscape" }); var source = document.getElementById("pdfCard"); doc.addFont("src/Roboto-Regular.ttf", "Roboto-Regular", "normal"); doc.setFont("Roboto-Regular"); doc.html(source, { callback: function (doc) { doc.save(); }, x: 2, y: 2, html2canvas: { scale: 0.25, }, });

@NeonDB
Copy link

NeonDB commented Oct 5, 2021

@NeonDB не работает на меня. Я использую шрифт Roboto на странице. И эта инициализация не работает: var doc = new jsPDF({ orientation: "landscape" }); var source = document.getElementById("pdfCard"); doc.addFont("src/Roboto-Regular.ttf", "Roboto-Regular", "normal"); doc.setFont("Roboto-Regular"); doc.html(source, { callback: function (doc) { doc.save(); }, x: 2, y: 2, html2canvas: { scale: 0.25, }, });

This cannot work, since the html markup source is passed as the first property to the .html method. You are not explicitly specifying which part of the html code you are going to use, be it body, div.container_kek, etc. Fix that and this piece of code should work correctly. I also recommend getting rid of "var" by replacing it with "let", it's prettier :) If you are using the same font on the page, you may not need to use the .addFont & .setFont methods. Importantly, different styles, such as Bold, Italic are also a type of font, and they also need to be specified. I forgot an important point, this is adding a font to the jsPDF API, for this use this link, https://rawgit.com/MrRio/jsPDF/master/fontconverter/fontconverter.html load your font in the .ttf format into it and paste the resulting code into yours.

@jedaix
Copy link

jedaix commented Oct 6, 2021

@NeonDB what do you mean by "not explicitly specifying"
there is a variable "source" which is specifying "div" in html code. Here is part of it:
<div class="modal-body" id="pdfCard" style="font-family: Roboto, sans-serif !important;"> <!-- first row --> <div class="row"> <div class="col-lg-12 d-flex align-items-center justify-content-center"> <span class="h4" style="font-family: Roboto, sans-serif !important;">ľščťžýáéúäô</span> </div> </div>

this is what i see on webpage:
image

and this is how i see it on generated PDF:
image

jsPDF can't generate characters: ľ č ť

i have converted Robot font and attach to code
`<script type="text/javascript" src="js/Roboto-Regular-normal.js"></script>

<script type="text/javascript" src="js/Roboto-Bold-normal.js"></script> <script type="text/javascript" src="js/Roboto-Light-normal.js"></script> <script type="text/javascript" src="js/Roboto-Medium-normal.js"></script> <script type="text/javascript" src="js/Roboto-Thin-normal.js"></script>`

@a-givertzman
Copy link

a-givertzman commented Mar 1, 2022

#2968 (comment)

my solution to this problem:

  1. create custom font ( use this : https://www.devlinpeck.com/tutorials/jspdf-custom-font#:~:text=Adding%20Custom%20Fonts%20to%20jsPDF,of%20your%20desired%20font%20file.&text=Once%20you%20have%20your%20.,to%20this%20jsPDF%20Font%20Converter )
  2. add font to project :
    image
  3. import this font:
    image
  4. add font to pdf doc.:
    image

thank you so much
this solution works wry well!

@robinhuy
Copy link

My solution is:

  1. Convert file font .ttf to base64 string.
  2. Add font to doc:
  const doc = new jsPDF({
      orientation: "portrait",
      format: "a4",
      unit: "px",
      hotfixes: ["px_scaling"],
  });

   doc.addFileToVFS("Roboto.ttf", RobotoStringBase64);
   doc.addFont("Roboto.ttf", "Roboto", "normal");
   doc.setFont("Roboto");
  1. Render HTML string PDF:
  await doc.html(
     `<html>
        <body >
          <div style="width: 210mm;">${element.innerHTML}</div>
        </body>
     </html>`,
     {
        callback(doc) {
          window.open(URL.createObjectURL(doc.output("blob")));
        },
        margin: [30, 15, 30, 15],
     },
  )

@stm-seek
Copy link

In my case, using the version 2.1, setting the font style on the html element like so: <html style="font-family: PTSans;">А ну чики брики и в дамки!</html> and importing the fonts according to https://www.devlinpeck.com/tutorials/jspdf-custom-font#:~:text=Adding%20Custom%20Fonts%20to%20jsPDF,of%20your%20desired%20font%20file.&text=Once%20you%20have%20your%20.,to%20this%20jsPDF%20Font%20Converter. worked for me when using an html element reference instead of using a raw html string.

Thanks it work for me!

@chetvertkoff
Copy link

It works for me, if use div tag instead html
<div style="font-family: PTSans;">А ну чики брики и в дамки!</div>

@sogrbilja
Copy link

I've tried this and it worked, except the text rendered was a bit overlapped.

@tpurg
Copy link

tpurg commented Feb 2, 2023

Same problem as @jedaix. I got and HTML object that cannot be converted to string. I try setting the style of the HTML object, but it still doesn't want to output characters čđć. I get my HTML object from ReactQuill.

@mexvod
Copy link

mexvod commented Feb 23, 2023

Hi guys. I figured out the reason. It's about html2canvas. The fact is that if your styles explicitly specify the font, and it is not imported into the jspdf fonts, then you will not display correctly. When the html2canvas library reads the css properties from your html, it takes into account the css font-family as well.

Example of non-working code:
<style> h1 { font-family: "Roboto", sans-serif; } </style>

`<div id="get">
	<h1 class="align-center">А ну чики брики и в дамки!</h1>
</div>

<script src="https://html2canvas.hertzen.com/dist/html2canvas.js"></script>
<script src='../../dist/jspdf.umd.js'></script>

<script>
	 
	const { jsPDF } = window.jspdf;

	const pdf = new jsPDF({
		orientation: "p",
		unit: "pt",
		format: "a4"
	});

	pdf.addFileToVFS('RobotoCondensedLight', RobotoCondensed.Light);
	pdf.addFileToVFS('RobotoCondensedBold', RobotoCondensed.Bold);
	pdf.addFileToVFS('RobotoCondensedLightItalic', RobotoCondensed.LightItalic);
	pdf.addFileToVFS('RobotoCondensedBoldItalic', RobotoCondensed.BoldItalic);
	pdf.addFont('RobotoCondensedLight', 'RobotoCondensed', 'normal');
	pdf.addFont('RobotoCondensedBold', 'RobotoCondensed', 'bold');
	pdf.addFont('RobotoCondensedLightItalic', 'RobotoCondensed', 'italic');
	pdf.addFont('RobotoCondensedBoldItalic', 'RobotoCondensed', 'bolditalic');
	pdf.setFont('RobotoCondensed');

	const div = document.createElement('div');
	div.style.fontFamily = "RobotoCondensed";

	const cop = document.getElementById('get');
	 
	div.innerHTML = cop.outerHTML;
	document.body.appendChild(div);

	pdf.html(div, {
		callback: function (isPdf) {
			isPdf.save('test.pdf');
		}
	});
</script>`

Now remove the css property:
<style> h1 { } </style>

`<div id="get">
	<h1 class="align-center">А ну чики брики и в дамки!</h1>
</div>

<script src="https://html2canvas.hertzen.com/dist/html2canvas.js"></script>
<script src='../../dist/jspdf.umd.js'></script>

<script>
	 
	const { jsPDF } = window.jspdf;

	const pdf = new jsPDF({
		orientation: "p",
		unit: "pt",
		format: "a4"
	});

	pdf.addFileToVFS('RobotoCondensedLight', RobotoCondensed.Light);
	pdf.addFileToVFS('RobotoCondensedBold', RobotoCondensed.Bold);
	pdf.addFileToVFS('RobotoCondensedLightItalic', RobotoCondensed.LightItalic);
	pdf.addFileToVFS('RobotoCondensedBoldItalic', RobotoCondensed.BoldItalic);
	pdf.addFont('RobotoCondensedLight', 'RobotoCondensed', 'normal');
	pdf.addFont('RobotoCondensedBold', 'RobotoCondensed', 'bold');
	pdf.addFont('RobotoCondensedLightItalic', 'RobotoCondensed', 'italic');
	pdf.addFont('RobotoCondensedBoldItalic', 'RobotoCondensed', 'bolditalic');
	pdf.setFont('RobotoCondensed');

	const div = document.createElement('div');
	div.style.fontFamily = "RobotoCondensed";

	const cop = document.getElementById('get');
	 
	div.innerHTML = cop.outerHTML;
	document.body.appendChild(div);

	pdf.html(div, {
		callback: function (isPdf) {
			isPdf.save('test.pdf');
		}
	});
</script>`

And now everything works!!!

@mexvod
Copy link

mexvod commented Feb 23, 2023

My solution is:

1. Convert file font **.ttf** to base64 string.

2. Add font to doc:
  const doc = new jsPDF({
      orientation: "portrait",
      format: "a4",
      unit: "px",
      hotfixes: ["px_scaling"],
  });

   doc.addFileToVFS("Roboto.ttf", RobotoStringBase64);
   doc.addFont("Roboto.ttf", "Roboto", "normal");
   doc.setFont("Roboto");
3. Render HTML string PDF:
  await doc.html(
     `<html>
        <body >
          <div style="width: 210mm;">${element.innerHTML}</div>
        </body>
     </html>`,
     {
        callback(doc) {
          window.open(URL.createObjectURL(doc.output("blob")));
        },
        margin: [30, 15, 30, 15],
     },
  )

You need to remove fonts from css or import them into jspdf. See my comment above

@mexvod
Copy link

mexvod commented Feb 23, 2023

@NeonDB what do you mean by "not explicitly specifying" there is a variable "source" which is specifying "div" in html code. Here is part of it: <div class="modal-body" id="pdfCard" style="font-family: Roboto, sans-serif !important;"> <!-- first row --> <div class="row"> <div class="col-lg-12 d-flex align-items-center justify-content-center"> <span class="h4" style="font-family: Roboto, sans-serif !important;">ľščťžýáéúäô</span> </div> </div>

this is what i see on webpage: image

and this is how i see it on generated PDF: image

jsPDF can't generate characters: ľ č ť

i have converted Robot font and attach to code `<script type="text/javascript" src="js/Roboto-Regular-normal.js"></script>

<script type="text/javascript" src="js/Roboto-Bold-normal.js"></script> <script type="text/javascript" src="js/Roboto-Light-normal.js"></script> <script type="text/javascript" src="js/Roboto-Medium-normal.js"></script> <script type="text/javascript" src="js/Roboto-Thin-normal.js"></script>`

You need to remove fonts from css or import them into jspdf. See my comment above

@mexvod
Copy link

mexvod commented Feb 23, 2023

I have the same problem. I'm surprised there is no good solution. How this library got so many likes? Everything is so hard to solve in there.

so it is my code but not supporting fornAwesome and cyrylic.

import './RobotoBlackNormal';
...
var doc = new jsPDF('p', 'pt', 'a4');
        // doc.addFont("test/reference/PTSans.ttf", "PTSans", "normal");
        doc.addFont('https://use.fontawesome.com/releases/v5.3.1/webfonts/fa-regular-400.ttf', 'FontAwesome', 'normal');
        doc.addFont('Roboto-Regular.ttf', 'Roboto-Regular', 'normal');
        doc.addFont('Roboto-Black.ttf', 'Roboto-Black', 'normal');
        doc.addFont('Roboto-Bold.ttf', 'Roboto-Bold', 'normal');
        doc.addFont('Roboto-Medium.ttf', 'Roboto-Medium', 'normal');
        doc.setFont('Font Awesome 5 Free');
        doc.setFont('Roboto-Regular');
        doc.setFont('Roboto-Black');
        doc.setFont('Roboto-Bold');
        doc.setFont('Roboto-Medium');

        doc.html(ref.current.querySelector('#response-list'), {
            callback: function (doc) {
                doc.save();
            }});

image

You need to remove fonts from css or import them into jspdf. See my comment above

@MatijaWezeo
Copy link

After 4 hours of intense debugging this worked for me:

jsPDF version 2.5.1

tested for symbols: ľ š č ť ž ý á í é ú ä ň ô ď

  1. download Roboto-Regular.ttf
  2. add it do the root of your project
  3. add following lines to your script:
...
let doc = new jsPDF();

//add this:
doc.addFont('Roboto-Regular.ttf', 'Roboto-Regular', 'normal');
doc.setFont('Roboto-Regular');

  1. last step is to add the font-family to the HTML you are trying to convert:
wrapper.style.fontFamily = "Roboto-Regular";

Hope this helps some of yall 🙏

@alexal
Copy link

alexal commented Mar 8, 2023

None of the examples on this page worked for me, neither for Chinese nor for Cyrillic symbols. I'm using jsPDF version 2.5.1 and Arial Unicode MS font. Are there any plans to fix this problem?

@kamil-kielczewski
Copy link

kamil-kielczewski commented Mar 13, 2023

POLISH LETTERS

Here is my working js fiddle (multipage) - I left it here for future readers

@sogrbilja
Copy link

POLISH LETTERS

Here is my working js fiddle - I left it here for future readers

It works with some fonts, but not with all - that is the first problem one will have if trying to work with this (for example, it doesn't work with Roboto). Next, I was able to create a regular font (like you did) but when I start adding italic, bold, and bold italic everything was messed up again. Simply said it can't give you the full thing anyway. So what I did I dismiss everything and just replace ČĆĐ (čćđ) to c i dj (what in Serbian Latin script we can read without any problems). Of course, that may not work for more complex scripts, but my client is happy!

@alexal
Copy link

alexal commented Mar 14, 2023

None of the examples on this page worked for me, neither for Chinese nor for Cyrillic symbols.

I've finally got it working. Here is my piece of code:

`
report.addFileToVFS('arialunicode.ttf', arialunicode);
report.addFont('arialunicode.ttf', fontFamily, 'normal');
report.setFont(fontFamily);

      pdfContent.querySelectorAll('pre').forEach((element) => {
        element.style.fontFamily = fontFamily;
      });

      report.html(pdfContent, {
        margin: 10,
        callback: (doc) => {
          doc.save('compare-code-report.pdf');
          pdfContent.remove();
        },
      });

`

A few important things are:

  • Load the font and add it to the PDF before using html method
  • In my case pdfContent contains a table, and the very last element in each cell that actually displaying the text is <pre>, I have to find all of them and adjust font-family style.

@antonsadovskiy
Copy link

my solution to this problem:

  1. create custom font ( use this : https://www.devlinpeck.com/tutorials/jspdf-custom-font#:~:text=Adding%20Custom%20Fonts%20to%20jsPDF,of%20your%20desired%20font%20file.&text=Once%20you%20have%20your%20.,to%20this%20jsPDF%20Font%20Converter )
  2. add font to project :
    image
  3. import this font:
    image
  4. add font to pdf doc.:
    image

thank you so much, i downloaded custom font, and I had to add style="font-family: ..." to wrapper div

@sungbin-hub
Copy link

image
this is how i solve this problem.

@Erlinddd
Copy link

Erlinddd commented Dec 5, 2023

Steps to Follow for Exporting HTML Content with Cyrillic Fonts:

1.Download Roboto Font:
Start by downloading the Roboto font family from Google Fonts. Afterward, use a font converter, like https://peckconsulting.s3.amazonaws.com/fontconverter/fontconverter.html, to convert the font for integration into your project.

2.Add Roboto-Regular Font:
Once you have the converted Roboto-Regular font files, incorporate them into your project. The roboto regular font converted by this converter should look like this :
Screenshot 2023-12-05 113009

3.Import Font in Code:
In the component or file where you plan to export content as a PDF, import the Roboto-Regular font. For instance:
import '../../assets/fonts/Roboto-Regular-normal.css';

  1. Generate Report Method:
    Implement a method for generating the PDF report. Ensure to set the font family to 'Roboto-Regular' for content that includes Cyrillic characters. A sample method might look like this:
    image
  const generatePDF = () => {
    let doc = new jsPDF();
    let elementHTML = document.getElementById('print-content-report');
    if (elementHTML) {
      elementHTML.style.fontFamily = 'Roboto-Regular';

      doc.html(elementHTML, {
        callback: function (doc) {
          doc.save('sample-document.pdf', { returnPromise: true }).then(() => {
            console.log('content is exported successfully');
          });
        },
        x: 15,
        y: 15,
        width: 170,
        windowWidth: 650
      });
    } else {
      console.error('Element with id "print-content-report" not found');
    }
  };

@AyanAcharya
Copy link

AyanAcharya commented Dec 18, 2023

I have the same problem. I'm surprised there is no good solution. How this library got so many likes? Everything is so hard to solve in there.

so it is my code but not supporting fornAwesome and cyrylic.

import './RobotoBlackNormal';
...
var doc = new jsPDF('p', 'pt', 'a4');
        // doc.addFont("test/reference/PTSans.ttf", "PTSans", "normal");
        doc.addFont('https://use.fontawesome.com/releases/v5.3.1/webfonts/fa-regular-400.ttf', 'FontAwesome', 'normal');
        doc.addFont('Roboto-Regular.ttf', 'Roboto-Regular', 'normal');
        doc.addFont('Roboto-Black.ttf', 'Roboto-Black', 'normal');
        doc.addFont('Roboto-Bold.ttf', 'Roboto-Bold', 'normal');
        doc.addFont('Roboto-Medium.ttf', 'Roboto-Medium', 'normal');
        doc.setFont('Font Awesome 5 Free');
        doc.setFont('Roboto-Regular');
        doc.setFont('Roboto-Black');
        doc.setFont('Roboto-Bold');
        doc.setFont('Roboto-Medium');

        doc.html(ref.current.querySelector('#response-list'), {
            callback: function (doc) {
                doc.save();
            }});

image

use it like this

var callAddFont = function () {
    /* add all types or that font to jspdf fontlist below all is ttf file just in  alias */
    this.addFont(interfontNormal, "inter", "normal");
    this.addFont(interfontBold, "inter", "bold");
    this.addFont(interfontLight, "inter", "lighter");
    this.addFont(interfontThin, "inter", "thin");
  };

  jsPDF.API.events.push(["addFonts", callAddFont]);
}

@Johongirmirzo
Copy link

Johongirmirzo commented Dec 28, 2023

Setting PTSans-Bold on body worked for me

import { jsPDF } from 'jspdf'
import '@/assets/font/PTSans-Bold-normal'
export const useDownloadCompPdf = () => {
  const savePDF = (htmlElement: HTMLElement) => {
    const body = document.querySelector('body')
    body.style = 'font-family: PTSans-Bold'
    const doc = new jsPDF({
      orientation: 'l',
      unit: 'mm',
      format: 'b0',
      putOnlyUsedFonts: true,
      floatPrecision: 'smart',
    })
    doc.addFont('PTSans-Bold-normal.ttf', 'PTSans-Bold', 'normal')
    doc.setFont('PTSans-Bold')

    doc.html(htmlElement, {
      callback(pdf) {
        pdf.addFont('PTSans-Bold-normal.ttf', 'PTSans-Bold', 'normal')
        pdf.setFont('PTSans-Bold')
        pdf.save('invoice.pdf')
      },
    })
    setTimeout(() => {
      body.style = 'font-family: Inter, sans-serif'
    }, 1000)
  }
  return { savePDF }
}

@MartinJHammer
Copy link

I managed to get multiple different fonts working for me. I'll try to map out my steps (a lot of it is based on above advice).

Result
image

  1. Get the Arial Unicode MS font. It can be downloaded here, but feel free to find your own source for the font. Why this font? Because it supports the most languages in one font, which is critical for a mixed language setup like I have. If you go with a Noto font from Google or similar, you will be limited in the languages you can show in the pdf ( more on this in a sec).

  2. Upload the Arial Unicode Font.ttf file to https://peckconsulting.s3.amazonaws.com/fontconverter/fontconverter.html and download the resulting js file.

  3. Modify the JS file so it simply exports the font string. It should just contain export const font = "AAEAAAAUAQAABABARFNJR21e.... part.
    image

  4. Add the file in your project (note I renamed mine to .ts for my setup in angular)
    image

  5. Add the font _when generating the pdf. I lazy load the font only when the user starts to generate the pdf, so not all users have to download the quite large Arial font. IF YOU USE THE .html() THE NEXT PART IS CRITICAL. So, if you use pdf.html() method, you have to create a css class that sets the font family you added, and place it on every single html element rendering your characters. If you don't set the font, it won't render correctly. See below screenshots of how it i can work/not work. Note that since we have to set one font family, we can't cover multiple languages with multiple noto fonts, since the first font match is the only one that will be used. If you want to use multiple noto fonts, you will have to find a way to combine them first. This is why I opted for the Arial one.
    image

image

image

  1. ???

  2. Profit! Your pdf should now be able to print with a multitude of languages. I won't say it's elegant, but at least it's working. Good luck!

@mrazvanalex
Copy link

I managed to get multiple different fonts working for me. I'll try to map out my steps (a lot of it is based on above advice).

Result image

  1. Get the Arial Unicode MS font. It can be downloaded here, but feel free to find your own source for the font. Why this font? Because it supports the most languages in one font, which is critical for a mixed language setup like I have. If you go with a Noto font from Google or similar, you will be limited in the languages you can show in the pdf ( more on this in a sec).
  2. Upload the Arial Unicode Font.ttf file to https://peckconsulting.s3.amazonaws.com/fontconverter/fontconverter.html and download the resulting js file.
  3. Modify the JS file so it simply exports the font string. It should just contain export const font = "AAEAAAAUAQAABABARFNJR21e.... part.
    image
  4. Add the file in your project (note I renamed mine to .ts for my setup in angular)
    image
  5. Add the font _when generating the pdf. I lazy load the font only when the user starts to generate the pdf, so not all users have to download the quite large Arial font. IF YOU USE THE .html() THE NEXT PART IS CRITICAL. So, if you use pdf.html() method, you have to create a css class that sets the font family you added, and place it on every single html element rendering your characters. If you don't set the font, it won't render correctly. See below screenshots of how it i can work/not work. Note that since we have to set one font family, we can't cover multiple languages with multiple noto fonts, since the first font match is the only one that will be used. If you want to use multiple noto fonts, you will have to find a way to combine them first. This is why I opted for the Arial one.
    image

image

image

  1. ???
  2. Profit! Your pdf should now be able to print with a multitude of languages. I won't say it's elegant, but at least it's working. Good luck!

Works like a charm! THANKS. I was so close but was really messing up the matching names and classes in my less files. Kept getting me frustrated but going step by step as you said worked perfectly.

@stif4
Copy link

stif4 commented May 16, 2024

  1. Download a font that supports utf-8. Example (https://fonts.google.com/specimen/Roboto?query=Roboto).
  2. Convert the font to a binary string. https://products.aspose.app/font/base64/ttf
  3. Copy the result and put it in a js file.
copy past 4) Set the font. set

@DanyAtanov
Copy link

DanyAtanov commented May 16, 2024

@stif4 thank you so much! Your answer was the last, but its finally works for me! 🙌🏻

@Esmaelasid
Copy link

file-pcQwQmY3Cz2a0LmAy5nQ2TiK
I created a function to create a pdf file from an html table and when opening the pdf file the data appears in symbols. There is a problem with the text encoding in the jsPDF library. I am bored. How do I solve the problem?

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

No branches or pull requests