Expose chromium pdf options to config

Signed-off-by: trivernis <trivernis@protonmail.com>
pull/4/head v0.30.2
trivernis 3 years ago
parent 169e062d29
commit f2b154b7c3
Signed by: Trivernis
GPG Key ID: DFFFCC2C7A02DB45

1778
Cargo.lock generated

File diff suppressed because it is too large Load Diff

@ -1,6 +1,6 @@
[package]
name = "snekdown"
version = "0.30.1"
version = "0.30.2"
authors = ["trivernis <trivernis@protonmail.com>"]
edition = "2018"
license-file = "LICENSE"

@ -191,6 +191,38 @@ smart-arrows = true
# Includes a MathJax script tag in the document to render MathML in chromium.
# (default: true)
include-math-jax = true
### PDF Options - needs the pdf feature enabled ###
# If the header and footer of the pdf should be displayed (default: true)
pdf-display-header-footer = true
# PDF header template of each page (default: empty)
pdf-header-template = "<div><span class='title'></span></div>"
# PDF footer template of each page (default: see chromium_pdf assets)
pdf-footer-template = "<div><span class='pageNumber'></span></div>"
# Top margin of the pdf. Should be between 0 and 1. (default: 1.0)
pdf-margin-top = 1
# Bottom margin of the pdf. Should be between 0 and 1. (default: 1.0)
pdf-margin-bottom = 1
# Left margin of the pdf. Should be between 0 and 1.
pdf-margin-left = 0
# Right margin of the pdf. Should be between 0 and 1.
pdf-margin-right = 0
# Page height of the pdf
pdf-page-height = 100
# Page width of the pdf
pdf-page-width = 80
# The scale at which the website is rendered into pdf.
pdf-page-scale = 1.0
```
The `[Section]` keys are not relevant as the structure gets flattened before the values are read.

@ -0,0 +1,3 @@
<div style="font-size: 10px; text-align: center; width: 100%;">
<span class="pageNumber"></span>/<span class="totalPages"></span>
</div>

@ -2,10 +2,16 @@ use crate::elements::Document;
use crate::format::chromium_pdf::result::{PdfRenderingError, PdfRenderingResult};
use crate::format::html::html_writer::HTMLWriter;
use crate::format::html::to_html::ToHtml;
use crate::references::configuration::keys::INCLUDE_MATHJAX;
use crate::references::configuration::keys::{
INCLUDE_MATHJAX, PDF_DISPLAY_HEADER_FOOTER, PDF_FOOTER_TEMPLATE, PDF_HEADER_TEMPLATE,
PDF_MARGIN_BOTTOM, PDF_MARGIN_LEFT, PDF_MARGIN_RIGHT, PDF_MARGIN_TOP, PDF_PAGE_HEIGHT,
PDF_PAGE_SCALE, PDF_PAGE_WIDTH,
};
use crate::references::configuration::Configuration;
use crate::utils::downloads::get_cached_path;
use headless_chrome::protocol::page::PrintToPdfOptions;
use headless_chrome::{Browser, LaunchOptionsBuilder, Tab};
use std::fs;
use std::fs::OpenOptions;
use std::io::BufWriter;
use std::path::PathBuf;
@ -16,7 +22,7 @@ pub mod result;
/// Renders the document to pdf and returns the resulting bytes
pub fn render_to_pdf(document: Document) -> PdfRenderingResult<Vec<u8>> {
let mut file_path = PathBuf::from("tmp-document.html");
let mut file_path = PathBuf::from(format!("tmp-document.html"));
file_path = get_cached_path(file_path).with_extension("html");
let mut mathjax = false;
@ -25,24 +31,26 @@ pub fn render_to_pdf(document: Document) -> PdfRenderingResult<Vec<u8>> {
mathjax = true;
}
}
let config = document.config.clone();
let handle = thread::spawn({
let file_path = file_path.clone();
move || {
log::debug!("Rendering html...");
log::info!("Rendering html...");
let writer = BufWriter::new(
OpenOptions::new()
.create(true)
.write(true)
.truncate(true)
.open(file_path)?,
);
let mut html_writer = HTMLWriter::new(Box::new(writer));
document.to_html(&mut html_writer)?;
log::debug!("Successfully rendered temporary html file!");
log::info!("Successfully rendered temporary html file!");
html_writer.flush()
}
});
log::debug!("Starting browser...");
let browser = Browser::new(LaunchOptionsBuilder::default().build().unwrap())?;
let tab = browser.wait_for_initial_tab()?;
handle.join().unwrap()?;
@ -52,7 +60,10 @@ pub fn render_to_pdf(document: Document) -> PdfRenderingResult<Vec<u8>> {
if mathjax {
wait_for_mathjax(&tab, Duration::from_secs(60))?;
}
let result = tab.print_to_pdf(Some(get_pdf_options()))?;
log::info!("Rendering pdf...");
let result = tab.print_to_pdf(Some(get_pdf_options(config)))?;
log::info!("Removing temporary html...");
fs::remove_file(file_path)?;
Ok(result)
}
@ -95,22 +106,49 @@ fn wait_for_mathjax(tab: &Tab, timeout: Duration) -> PdfRenderingResult<()> {
Ok(())
}
fn get_pdf_options() -> PrintToPdfOptions {
fn get_pdf_options(config: Configuration) -> PrintToPdfOptions {
PrintToPdfOptions {
landscape: None,
display_header_footer: Some(false),
display_header_footer: config
.get_entry(PDF_DISPLAY_HEADER_FOOTER)
.and_then(|value| value.get().as_bool()),
print_background: Some(true),
scale: None,
paper_width: None,
paper_height: None,
margin_top: None,
margin_bottom: None,
margin_left: None,
margin_right: None,
scale: config
.get_entry(PDF_PAGE_SCALE)
.and_then(|value| value.get().as_float())
.map(|value| value as f32),
paper_width: config
.get_entry(PDF_PAGE_WIDTH)
.and_then(|value| value.get().as_float())
.map(|value| value as f32),
paper_height: config
.get_entry(PDF_PAGE_HEIGHT)
.and_then(|value| value.get().as_float())
.map(|value| value as f32),
margin_top: config
.get_entry(PDF_MARGIN_TOP)
.and_then(|value| value.get().as_float())
.map(|f| f as f32),
margin_bottom: config
.get_entry(PDF_MARGIN_BOTTOM)
.and_then(|value| value.get().as_float())
.map(|f| f as f32),
margin_left: config
.get_entry(PDF_MARGIN_LEFT)
.and_then(|value| value.get().as_float())
.map(|f| f as f32),
margin_right: config
.get_entry(PDF_MARGIN_RIGHT)
.and_then(|value| value.get().as_float())
.map(|f| f as f32),
page_ranges: None,
ignore_invalid_page_ranges: None,
header_template: None,
footer_template: None,
header_template: config
.get_entry(PDF_HEADER_TEMPLATE)
.map(|value| value.get().as_string()),
footer_template: config
.get_entry(PDF_FOOTER_TEMPLATE)
.map(|value| value.get().as_string()),
prefer_css_page_size: None,
}
}

@ -1,6 +1,7 @@
pub const BIB_REF_DISPLAY: &str = "bib-ref-display";
pub const META_LANG: &str = "language";
// import and include options
pub const IMP_IGNORE: &str = "ignored-imports";
pub const IMP_STYLESHEETS: &str = "included-stylesheets";
pub const IMP_CONFIGS: &str = "included-configs";
@ -9,3 +10,15 @@ pub const IMP_GLOSSARY: &str = "included-glossary";
pub const EMBED_EXTERNAL: &str = "embed-external";
pub const SMART_ARROWS: &str = "smart-arrows";
pub const INCLUDE_MATHJAX: &str = "include-math-jax";
// PDF options
pub const PDF_DISPLAY_HEADER_FOOTER: &str = "pfd-display-header-footer";
pub const PDF_HEADER_TEMPLATE: &str = "pdf-header-template";
pub const PDF_FOOTER_TEMPLATE: &str = "pdf-footer-template";
pub const PDF_MARGIN_TOP: &str = "pdf-margin-top";
pub const PDF_MARGIN_BOTTOM: &str = "pdf-margin-bottom";
pub const PDF_MARGIN_LEFT: &str = "pdf-margin-left";
pub const PDF_MARGIN_RIGHT: &str = "pdf-margin-right";
pub const PDF_PAGE_HEIGHT: &str = "pdf-page-height";
pub const PDF_PAGE_WIDTH: &str = "pdf-page-width";
pub const PDF_PAGE_SCALE: &str = "pdf-page-scale";

@ -1,5 +1,8 @@
use crate::elements::MetadataValue;
use crate::references::configuration::keys::{BIB_REF_DISPLAY, META_LANG};
use crate::references::configuration::keys::{
BIB_REF_DISPLAY, META_LANG, PDF_FOOTER_TEMPLATE, PDF_HEADER_TEMPLATE, PDF_MARGIN_BOTTOM,
PDF_MARGIN_TOP,
};
use crate::references::templates::Template;
use serde::export::TryFrom;
use std::collections::HashMap;
@ -50,6 +53,13 @@ impl Value {
_ => None,
}
}
pub fn as_float(&self) -> Option<f64> {
match self {
Value::Float(v) => Some(*v),
_ => None,
}
}
}
impl ConfigEntry {
@ -71,6 +81,16 @@ impl Default for Configuration {
let mut self_config = Self::new();
self_config.set(BIB_REF_DISPLAY, Value::String("{{number}}".to_string()));
self_config.set(META_LANG, Value::String("en".to_string()));
self_config.set(PDF_MARGIN_BOTTOM, Value::Float(0.5));
self_config.set(PDF_MARGIN_TOP, Value::Float(0.5));
self_config.set(PDF_HEADER_TEMPLATE, Value::String("<div/>".to_string()));
self_config.set(
PDF_FOOTER_TEMPLATE,
Value::String(
include_str!("../../format/chromium_pdf/assets/default-footer-template.html")
.to_string(),
),
);
self_config
}

Loading…
Cancel
Save