jsPDF: Convert html to pdf: utf-8 works only with text, but not html (unicode/cyrillic not working)
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?
About this issue
- Original URL
- State: open
- Created 4 years ago
- Reactions: 18
- Comments: 47 (2 by maintainers)
Please try setting the font name also in the html markup. E.g.
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 Custom Fonts to jsPDF,of your desired font file.&text=Once you have your .,to this jsPDF Font Converter. worked for me when using an html element reference instead of using a raw html string.After 4 hours of intense debugging this worked for me:
jsPDF version 2.5.1
tested for symbols:
ľ š č ť ž ý á í é ú ä ň ô ď
Hope this helps some of yall 🙏
my solution to this problem:
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
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).
Upload the Arial Unicode Font.ttf file to https://peckconsulting.s3.amazonaws.com/fontconverter/fontconverter.html and download the resulting js file.
Modify the JS file so it simply exports the font string. It should just contain
export const font = "AAEAAAAUAQAABABARFNJR21e....
part.Add the file in your project (note I renamed mine to .ts for my setup in angular)
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.???
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!
thank you so much, i downloaded custom font, and I had to add style=“font-family: …” to wrapper div
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);
`
A few important things are:
<pre>
, I have to find all of them and adjust font-family style.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>
Now remove the css property:
<style> h1 { } </style>
And now everything works!!!
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!Then I did few modifications to make it work with specific font (the same process didn’t work with all fonts)
<header>
:UMD
.Cairo-Regular
, and that was the problem. I changed it toCairo
since the CSS font name isCairo
.html
didn’t work, but it worked when added style to thebody
tag:Now I have a working solution with English and Turkish :
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:
The correct html page looks like below:
I also tried with adding
doc.addLanguage("ar")
but it didn’t help.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.
Setting PTSans-Bold on body worked for me
use it like this
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 :
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’;
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!
https://github.com/parallax/jsPDF/issues/2968#issuecomment-796507870
thank you so much this solution works wry well!
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 quickThank 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:
This is code:
It’s amazing 🎉
@potapovnikita
I would like to mention two things here.
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.
I have observed that the .html API of jsPdf does not support <html> 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 Custom Fonts to jsPDF,of your desired font file.&text=Once you have your .,to this jsPDF Font Converter.
`import ‘…/…/…/Lato-Regular-normal’;
const htmlToConvert = <div style="font-size:16px;font-family:Lato ">
doc.html(htmlToConvert,{ callback:function{ doc.save() } })`
@potapovnikita as I mentioned - there is a problem. I just showed part of my code in case I made a mistake somewhere 😃
@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: