| #!/bin/sh -eu |
| in=$1 |
| |
| # Optional second argument: explicit output file. Made absolute here because we |
| # may cd into the input's directory below. Further arguments are ignored. |
| out_arg="" |
| if [ $# -ge 2 ]; then |
| out_arg=", output='$(realpath -m "$2")'" |
| fi |
| |
| doc=$in |
| backup_file="" |
| poster_lang=en |
| |
| # For local files (not URLs): temporarily inject CSS that forces exact A0 |
| # dimensions and prevents Chrome's print shrinking, and work from the file's |
| # directory so relative links (e.g. skeleton_files/) resolve. |
| if [ -f "$in" ]; then |
| abs_in=$(realpath "$in") |
| work_dir=$(dirname "$abs_in") |
| |
| # Language the poster is written in, from <html lang="…"> (posterdown copies |
| # it from the Rmd `lang:` field). Used for the hyphenation check below. |
| poster_lang=$(sed -n 's/.*<html[^>]*[[:space:]]lang="\([A-Za-z-]*\)".*/\1/p' "$in" | head -n1) |
| poster_lang=${poster_lang:-en} |
| |
| backup_file="${abs_in}.backup" |
| cp "$abs_in" "$backup_file" |
| # Restore the original file when we exit, also on failure. |
| trap '[ -n "$backup_file" ] && mv "$backup_file" "$abs_in"' EXIT |
| |
| sed -i '/<\/head>/i\ |
| <style>\ |
| @page { size: 841mm 1189mm !important; margin: 0mm 0mm 20mm 0mm !important; }\ |
| html { width: 841mm !important; height: 1189mm !important; transform-origin: 0 0; }\ |
| body { width: 841mm !important; height: 1189mm !important; margin: 0 !important; padding: 0 !important; overflow: hidden !important; line-height: 1.2 !important; }\ |
| .poster { width: 841mm !important; height: 1189mm !important; }\ |
| * { line-height: 1.2 !important; }\ |
| p, div, span, li, ul, ol, td, th, a, strong, em, blockquote, caption, h1, h2, h3, h4, h5, h6 { line-height: 1.2 !important; }\ |
| </style>' "$abs_in" |
| |
| cd "$work_dir" |
| doc=$(basename "$abs_in") |
| fi |
| |
| # --- Automatic hyphenation --------------------------------------------------- |
| # The template HTML carries `hyphens: auto` plus an <html lang="…"> attribute. |
| # Whether Chrome actually hyphenates depends on where it finds its hyphenation |
| # dictionaries: |
| # |
| # * chrome-headless-shell (used in CI) BUNDLES the dictionaries in a |
| # `hyphen-data` folder next to the binary and loads them automatically, so |
| # hyphenation already works there without any help from us. |
| # * full google-chrome (typical locally) ships the dictionaries as a |
| # *component* living in the normal browser profile |
| # (~/.config/google-chrome/hyphen-data). pagedown::chrome_print() launches |
| # Chrome with a throwaway --user-data-dir that has no such component, so |
| # hyphenation silently does nothing. |
| # |
| # For the local case we seed a persistent profile with that component and point |
| # Chrome at it: extra_args are appended after pagedown's own --user-data-dir and |
| # Chrome honours the last value of a repeated switch. We symlink the whole |
| # hyphen-data tree (all languages), so whatever `lang:` the poster declares is |
| # respected -- nothing here is English-specific. |
| lang_base=${poster_lang%%-*} |
| |
| chrome_profile="${CHROME_PROFILE_DIR:-$HOME/.cache/pagedown-chrome-profile}" |
| user_data_dir_arg="" |
| for hyphen_src in \ |
| "$HOME/.config/google-chrome/hyphen-data" \ |
| "$HOME/.config/google-chrome-beta/hyphen-data" \ |
| "$HOME/.config/chromium/hyphen-data"; do |
| [ -d "$hyphen_src" ] || continue |
| mkdir -p "$chrome_profile" |
| ln -sfn "$hyphen_src" "$chrome_profile/hyphen-data" |
| # Only override the profile when we have something to seed; otherwise leave |
| # pagedown's default (throwaway) profile so CI's bundled dictionaries load. |
| user_data_dir_arg=",'--user-data-dir=$chrome_profile'" |
| break |
| done |
| |
| # Warn at build time if no dictionary for the poster's language is reachable, |
| # either from the seeded profile or bundled next to the Chrome binary pagedown |
| # will launch. Better a clear warning than a silently un-hyphenated poster. |
| chrome_bin=$(R --slave -e 'cat(pagedown::find_chrome())' 2>/dev/null || true) |
| bundled_dir="/nonexistent" |
| [ -n "$chrome_bin" ] && bundled_dir="$(dirname "$(readlink -f "$chrome_bin")")/hyphen-data" |
| have_dict=false |
| for dict in "$chrome_profile"/hyphen-data/*/hyph-"$lang_base"*.hyb \ |
| "$bundled_dir"/hyph-"$lang_base"*.hyb; do |
| # Unmatched globs stay literal, so the file test simply fails for them. |
| [ -e "$dict" ] && { have_dict=true; break; } |
| done |
| if $have_dict; then |
| echo "html2pdf: hyphenation enabled for lang='$poster_lang'." >&2 |
| else |
| echo "html2pdf: WARNING - no hyphenation dictionary for lang='$poster_lang'; the PDF will not be hyphenated." >&2 |
| fi |
| |
| R -e "pagedown::chrome_print('$doc'$out_arg, |
| options=list( |
| pageRanges='1', |
| paperWidth=33.11, |
| paperHeight=46.81, |
| marginTop=0, |
| marginBottom=0, |
| marginLeft=0, |
| marginRight=0, |
| printBackground=TRUE, |
| scale=0.98, # Compensate for ~2% print scaling |
| displayHeaderFooter=FALSE, |
| preferCSSPageSize=TRUE |
| ), |
| extra_args = c( |
| '--disable-gpu', |
| '--no-sandbox', |
| '--disable-dev-shm-usage', |
| '--force-device-scale-factor=1', |
| '--disable-print-preview', |
| '--disable-background-timer-throttling', |
| '--allow-file-access-from-files', |
| '--force-color-profile=srgb', |
| '--disable-lcd-text', |
| '--disable-font-subpixel-positioning', |
| '--run-all-compositor-stages-before-draw'$user_data_dir_arg |
| ) |
| )" |