mikepqr / resume.md

Write your resume in Markdown, style it with CSS, output to HTML and PDF
MIT License
565 stars 228 forks source link

Font awesome support for PDF #36

Open jessecambon opened 2 years ago

jessecambon commented 2 years ago

First of all, thanks for this repo! I really like this workflow. I did run into one issue when I inserted Font Awesome icons via a Font Awesome kit. The icons show up fine on the HTML version of the resume, but they do not show up in the PDF.

However, if I manually use my Chrome browser to print the HTML resume to PDF then the icons do show up in the saved PDF. This makes me think the base64 HTML encoding step might be causing an issue with the Font Awesome icons. Do you know if there is a different way I can encode the HTML content so that the Font Awesome icons will be preserved?

For reference below is the HTML content for a Font Awesome icon (you can set the kit to use either the web font or the SVG version).

Web font (default):

<i class="fa fa-envelope" aria-hidden="true"></i>

SVG:

<svg class="svg-inline--fa fa-envelope" aria-hidden="true" focusable="false" data-prefix="fas" data-icon="envelope" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" data-fa-i2svg=""><path fill="currentColor" d="M464 64C490.5 64 512 85.49 512 112C512 127.1 504.9 141.3 492.8 150.4L275.2 313.6C263.8 322.1 248.2 322.1 236.8 313.6L19.2 150.4C7.113 141.3 0 127.1 0 112C0 85.49 21.49 64 48 64H464zM217.6 339.2C240.4 356.3 271.6 356.3 294.4 339.2L512 176V384C512 419.3 483.3 448 448 448H64C28.65 448 0 419.3 0 384V176L217.6 339.2z"></path></svg>
mikepqr commented 2 years ago

I write via a base64 encoded stream to avoid writing a temporary file when supporting people who just want PDF output (which is probably most users).

If doing this causes problems I would consider writing a temporary file. But I would like to reproduce this bug first, and see if there's an alternative.

I tried just dumping

<svg class="svg-inline--fa fa-envelope" aria-hidden="true" focusable="false" data-prefix="fas" data-icon="envelope" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" data-fa-i2svg=""><path fill="currentColor" d="M464 64C490.5 64 512 85.49 512 112C512 127.1 504.9 141.3 492.8 150.4L275.2 313.6C263.8 322.1 248.2 322.1 236.8 313.6L19.2 150.4C7.113 141.3 0 127.1 0 112C0 85.49 21.49 64 48 64H464zM217.6 339.2C240.4 356.3 271.6 356.3 294.4 339.2L512 176V384C512 419.3 483.3 448 448 448H64C28.65 448 0 419.3 0 384V176L217.6 339.2z"></path></svg>

into resume.md and running python resume.py and was unable to reproduce the bug, i.e. the envelope icon appears in both the html and pdf output for me.

So, could you please share exact steps to reproduce, i.e. a minimal resume.md file and, if necessary, a resume.css file, and the version of Chrome and OS you are using?

jessecambon commented 2 years ago

@mikepqr I just tried this and I get the same result when I put the raw SVG content into the .md file (the icon shows up in both HTML and PDF). If nothing else that should be a workaround for now, but I'll do some more digging and see if I can figure out what's going on.

If you want to reproduce the issue:

  1. Sign up for a (free) Font Awesome kit
  2. Insert the script reference for your kit into your HTML <head> section (should be in the format <script src="https://kit.fontawesome.com/YOURKITCODE.js" crossorigin="anonymous"></script>)
  3. Insert an HTML reference to an icon such as <i class="fa fa-envelope"></i> into the md file. The font awesome library is here: https://fontawesome.com/search?m=free
  4. run python resume.py
mikepqr commented 2 years ago

Ah. I assume Chrome's headless print rendering refuses to execute remote js on security grounds (probably quite rightly).

If that's the case then your original idea (writing out the HTML to a file, rather than passing it as encoded input) will not help.

If you can figure out a way around this (e.g. a command line switch) then I'll happily take a look, but given the use case of resume.py (render a boring resume) it's going to be a hard sell.

Your best bet is either the workaround you suggested (i.e. inline the SVG) or use FA without the js. You can do the latter by adding e.g. <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"> to the html header and then doing as usual .

jessecambon commented 2 years ago

Unfortunately, using the CSS approach instead of JS resulted in the same issue for me (no icons in the PDF). The (quite hacky) workaround I've found for now is this:

  1. Follow these steps to produce the SVG content for the icons (make sure you have set your font awesome kit to SVG). This will produce icons that display in the HTML, but not the PDF. Or more directly you could just place the Font Awesome HTML icon content (ie. <i class="fa fa-envelope" aria-hidden="true"></i>) and the Font Awesome kit into an HTML file.
  2. Use Chrome's "inspect" feature to extract the SVG content for each icon (ie. open the HTML file in chrome, right click on the icon, and select "inspect").
  3. Also using inspect, extract the CSS content for the svg-inline--fa class. You should see this when inspecting any one of the icons:
.svg-inline--fa {
    display: var(--fa-display,inline-block);
    height: 1em;
    overflow: visible;
    vertical-align: -.125em;
}
  1. Insert the SVG content into resume.md
  2. Insert the svg-inline--fa CSS content into resume.css
  3. Run python resume.py

The CSS content is necessary to properly size and position the icons in the PDF file (otherwise they take up the entire page). It appears the Font Awesome JavaScript produces SVG and CSS content, but does not place them in the HTML file itself so we have to get the content using Chrome's inspect function.

Again, quite a hacky solution, but maybe there is a more automated way to extract this SVG and CSS content?

mikepqr commented 2 years ago

I confirm that embedding the font via CSS doesn't work, i.e. the icons appear in the HTML output, but do not appear in the PDF output.

I suspect this is a limitation of Chrome rather than font-awesome (or resume.py, which essentially just calls chrome --print-to-pdf). But this should work, so I'm happy to call this a bug in resume.py, and I'll leave this open.

tclancy commented 1 year ago

Does embedding the content of the font awesome JavaScript file solve the problem?