This commit is contained in:
Ondrej Vlach 2023-11-29 14:04:36 +01:00
parent 5115265592
commit 0e0754fa10
9 changed files with 659 additions and 30 deletions

370
Cargo.lock generated
View File

@ -217,6 +217,16 @@ dependencies = [
"generic-array", "generic-array",
] ]
[[package]]
name = "bstr"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "542f33a8835a0884b006a0c3df3dadd99c0c3f296ed26c2fdc8028e01ad6230c"
dependencies = [
"memchr",
"serde",
]
[[package]] [[package]]
name = "bumpalo" name = "bumpalo"
version = "3.14.0" version = "3.14.0"
@ -270,6 +280,28 @@ dependencies = [
"windows-targets", "windows-targets",
] ]
[[package]]
name = "chrono-tz"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e23185c0e21df6ed832a12e2bda87c7d1def6842881fb634a8511ced741b0d76"
dependencies = [
"chrono",
"chrono-tz-build",
"phf",
]
[[package]]
name = "chrono-tz-build"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "433e39f13c9a060046954e0592a8d0a4bcb1040125cbf91cb8ee58964cfb350f"
dependencies = [
"parse-zoneinfo",
"phf",
"phf_codegen",
]
[[package]] [[package]]
name = "convert_case" name = "convert_case"
version = "0.4.0" version = "0.4.0"
@ -321,6 +353,30 @@ dependencies = [
"crossbeam-utils", "crossbeam-utils",
] ]
[[package]]
name = "crossbeam-deque"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef"
dependencies = [
"cfg-if",
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7"
dependencies = [
"autocfg",
"cfg-if",
"crossbeam-utils",
"memoffset",
"scopeguard",
]
[[package]] [[package]]
name = "crossbeam-utils" name = "crossbeam-utils"
version = "0.8.16" version = "0.8.16"
@ -421,6 +477,12 @@ dependencies = [
"syn 1.0.109", "syn 1.0.109",
] ]
[[package]]
name = "deunicode"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a1abaf4d861455be59f64fd2b55606cb151fce304ede7165f410243ce96bde6"
[[package]] [[package]]
name = "devise" name = "devise"
version = "0.4.1" version = "0.4.1"
@ -699,6 +761,30 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
[[package]]
name = "globset"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1"
dependencies = [
"aho-corasick",
"bstr",
"log",
"regex-automata 0.4.3",
"regex-syntax 0.8.2",
]
[[package]]
name = "globwalk"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93e3af942408868f6934a7b85134a3230832b9977cf66125df2f9edcfce4ddcc"
dependencies = [
"bitflags 1.3.2",
"ignore",
"walkdir",
]
[[package]] [[package]]
name = "h2" name = "h2"
version = "0.3.22" version = "0.3.22"
@ -802,6 +888,15 @@ version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
[[package]]
name = "humansize"
version = "2.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6cb51c9a029ddc91b07a787f1d86b53ccfa49b0e86688c946ebe8d3555685dd7"
dependencies = [
"libm",
]
[[package]] [[package]]
name = "hyper" name = "hyper"
version = "0.14.27" version = "0.14.27"
@ -877,6 +972,22 @@ dependencies = [
"unicode-normalization", "unicode-normalization",
] ]
[[package]]
name = "ignore"
version = "0.4.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "747ad1b4ae841a78e8aba0d63adbfbeaea26b517b63705d47856b73015d27060"
dependencies = [
"crossbeam-deque",
"globset",
"log",
"memchr",
"regex-automata 0.4.3",
"same-file",
"walkdir",
"winapi-util",
]
[[package]] [[package]]
name = "indexmap" name = "indexmap"
version = "1.9.3" version = "1.9.3"
@ -951,6 +1062,12 @@ version = "0.2.150"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c"
[[package]]
name = "libm"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058"
[[package]] [[package]]
name = "linux-raw-sys" name = "linux-raw-sys"
version = "0.4.11" version = "0.4.11"
@ -1009,6 +1126,15 @@ version = "2.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
[[package]]
name = "memoffset"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c"
dependencies = [
"autocfg",
]
[[package]] [[package]]
name = "mime" name = "mime"
version = "0.3.17" version = "0.3.17"
@ -1061,6 +1187,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"gethostname", "gethostname",
"opentelemetry", "opentelemetry",
"opentelemetry-appender-tracing",
"opentelemetry-otlp", "opentelemetry-otlp",
"opentelemetry-semantic-conventions", "opentelemetry-semantic-conventions",
"opentelemetry-stdout", "opentelemetry-stdout",
@ -1068,6 +1195,7 @@ dependencies = [
"rocket", "rocket",
"tracing", "tracing",
"tracing-appender", "tracing-appender",
"tracing-core",
"tracing-log", "tracing-log",
"tracing-opentelemetry", "tracing-opentelemetry",
"tracing-subscriber", "tracing-subscriber",
@ -1135,6 +1263,20 @@ dependencies = [
"urlencoding", "urlencoding",
] ]
[[package]]
name = "opentelemetry-appender-tracing"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12c4bd073648dae8ac45cfc81588d74b3dc5f334119ac08567ddcbfe16f2d809"
dependencies = [
"once_cell",
"opentelemetry",
"opentelemetry_sdk",
"tracing",
"tracing-core",
"tracing-subscriber",
]
[[package]] [[package]]
name = "opentelemetry-otlp" name = "opentelemetry-otlp"
version = "0.14.0" version = "0.14.0"
@ -1254,8 +1396,11 @@ dependencies = [
"rocket", "rocket",
"serde", "serde",
"serde_yaml", "serde_yaml",
"tempfile",
"tera",
"tokio", "tokio",
"tracing", "tracing",
"urlencoding",
"yansi 0.5.1", "yansi 0.5.1",
] ]
@ -1282,6 +1427,15 @@ dependencies = [
"windows-targets", "windows-targets",
] ]
[[package]]
name = "parse-zoneinfo"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c705f256449c60da65e11ff6626e0c16a0a0b96aaa348de61376b249bc340f41"
dependencies = [
"regex",
]
[[package]] [[package]]
name = "pear" name = "pear"
version = "0.2.7" version = "0.2.7"
@ -1311,6 +1465,89 @@ version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
[[package]]
name = "pest"
version = "2.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae9cee2a55a544be8b89dc6848072af97a20f2422603c10865be2a42b580fff5"
dependencies = [
"memchr",
"thiserror",
"ucd-trie",
]
[[package]]
name = "pest_derive"
version = "2.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81d78524685f5ef2a3b3bd1cafbc9fcabb036253d9b1463e726a91cd16e2dfc2"
dependencies = [
"pest",
"pest_generator",
]
[[package]]
name = "pest_generator"
version = "2.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68bd1206e71118b5356dae5ddc61c8b11e28b09ef6a31acbd15ea48a28e0c227"
dependencies = [
"pest",
"pest_meta",
"proc-macro2",
"quote",
"syn 2.0.39",
]
[[package]]
name = "pest_meta"
version = "2.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c747191d4ad9e4a4ab9c8798f1e82a39affe7ef9648390b7e5548d18e099de6"
dependencies = [
"once_cell",
"pest",
"sha2",
]
[[package]]
name = "phf"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc"
dependencies = [
"phf_shared",
]
[[package]]
name = "phf_codegen"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a"
dependencies = [
"phf_generator",
"phf_shared",
]
[[package]]
name = "phf_generator"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0"
dependencies = [
"phf_shared",
"rand",
]
[[package]]
name = "phf_shared"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b"
dependencies = [
"siphasher",
]
[[package]] [[package]]
name = "pin-project" name = "pin-project"
version = "1.1.3" version = "1.1.3"
@ -1661,6 +1898,15 @@ version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
[[package]]
name = "same-file"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
dependencies = [
"winapi-util",
]
[[package]] [[package]]
name = "scoped-tls" name = "scoped-tls"
version = "1.0.1" version = "1.0.1"
@ -1747,6 +1993,17 @@ dependencies = [
"digest", "digest",
] ]
[[package]]
name = "sha2"
version = "0.10.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
dependencies = [
"cfg-if",
"cpufeatures",
"digest",
]
[[package]] [[package]]
name = "sharded-slab" name = "sharded-slab"
version = "0.1.7" version = "0.1.7"
@ -1765,6 +2022,12 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "siphasher"
version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
[[package]] [[package]]
name = "slab" name = "slab"
version = "0.4.9" version = "0.4.9"
@ -1774,6 +2037,16 @@ dependencies = [
"autocfg", "autocfg",
] ]
[[package]]
name = "slug"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3bd94acec9c8da640005f8e135a39fc0372e74535e6b368b7a04b875f784c8c4"
dependencies = [
"deunicode",
"wasm-bindgen",
]
[[package]] [[package]]
name = "smallvec" name = "smallvec"
version = "1.11.2" version = "1.11.2"
@ -1882,6 +2155,28 @@ dependencies = [
"windows-sys", "windows-sys",
] ]
[[package]]
name = "tera"
version = "1.19.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "970dff17c11e884a4a09bc76e3a17ef71e01bb13447a11e85226e254fe6d10b8"
dependencies = [
"chrono",
"chrono-tz",
"globwalk",
"humansize",
"lazy_static",
"percent-encoding",
"pest",
"pest_derive",
"rand",
"regex",
"serde",
"serde_json",
"slug",
"unic-segment",
]
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.50" version = "1.0.50"
@ -2258,6 +2553,12 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "ucd-trie"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9"
[[package]] [[package]]
name = "uncased" name = "uncased"
version = "0.9.9" version = "0.9.9"
@ -2268,6 +2569,56 @@ dependencies = [
"version_check", "version_check",
] ]
[[package]]
name = "unic-char-property"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8c57a407d9b6fa02b4795eb81c5b6652060a15a7903ea981f3d723e6c0be221"
dependencies = [
"unic-char-range",
]
[[package]]
name = "unic-char-range"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0398022d5f700414f6b899e10b8348231abf9173fa93144cbc1a43b9793c1fbc"
[[package]]
name = "unic-common"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80d7ff825a6a654ee85a63e80f92f054f904f21e7d12da4e22f9834a4aaa35bc"
[[package]]
name = "unic-segment"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4ed5d26be57f84f176157270c112ef57b86debac9cd21daaabbe56db0f88f23"
dependencies = [
"unic-ucd-segment",
]
[[package]]
name = "unic-ucd-segment"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2079c122a62205b421f499da10f3ee0f7697f012f55b675e002483c73ea34700"
dependencies = [
"unic-char-property",
"unic-char-range",
"unic-ucd-version",
]
[[package]]
name = "unic-ucd-version"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96bd2f2237fe450fcd0a1d2f5f4e91711124f7857ba2e964247776ebeeb7b0c4"
dependencies = [
"unic-common",
]
[[package]] [[package]]
name = "unicode-bidi" name = "unicode-bidi"
version = "0.3.13" version = "0.3.13"
@ -2368,6 +2719,16 @@ version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "walkdir"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee"
dependencies = [
"same-file",
"winapi-util",
]
[[package]] [[package]]
name = "want" name = "want"
version = "0.3.1" version = "0.3.1"
@ -2482,6 +2843,15 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596"
dependencies = [
"winapi",
]
[[package]] [[package]]
name = "winapi-x86_64-pc-windows-gnu" name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0" version = "0.4.0"

View File

@ -17,10 +17,9 @@ ovlach_data = { git = "ssh://git@gitlab.nanobyte.cz/ondrej/ov-site-api-data.git"
async-trait = "0.1.74" async-trait = "0.1.74"
async-mutex = "1.4.0" async-mutex = "1.4.0"
tokio = { version = "1.34.0", features = ["macros"] } tokio = { version = "1.34.0", features = ["macros"] }
tracing = { version = "0.1.40", features = ["attributes", "std"] } tracing = { version = "0.1.40", features = ["attributes", "std"] }
yansi = "0.5.1" yansi = "0.5.1"
tera = "1.19.1"
nanobyte_opentelemetry = { path = "../nanobyte_opentelemetry" } nanobyte_opentelemetry = { path = "../nanobyte_opentelemetry" }
tempfile = "3.8.1"
urlencoding = "2.1.3"

View File

@ -12,5 +12,6 @@ pub fn rocket_builder() -> Rocket<Build> {
.attach(Chromium::ignite()) .attach(Chromium::ignite())
.mount("/", routes![ .mount("/", routes![
routes::pdf::render_pdf_cv, routes::pdf::render_pdf_cv,
routes::pdf::render_html_cv
]) ])
} }

View File

@ -1,13 +1,18 @@
use nanobyte_opentelemetry::{default_filter_layer, LogLevel}; use std::{panic, fs::File, io::Write};
use log::error;
use nanobyte_opentelemetry::{default_filter_layer, LogLevel, install_panic_handler};
use ovlach_pdf::rocket_builder; use ovlach_pdf::rocket_builder;
use tracing::Level; use tracing::Level;
#[rocket::main] #[rocket::main]
async fn main() { async fn main() {
install_panic_handler();
let _opentelemetry = nanobyte_opentelemetry::init_telemetry( let _opentelemetry = nanobyte_opentelemetry::init_telemetry(
env!("CARGO_PKG_NAME"), env!("CARGO_PKG_NAME"),
env!("CARGO_PKG_VERSION"), env!("CARGO_PKG_VERSION"),
Some(default_filter_layer(LogLevel::Normal)) Some(default_filter_layer(LogLevel::DebugWithoutRs))
); );
let _ = rocket_builder().launch().await; let _ = rocket_builder().launch().await;
} }

View File

@ -1,17 +1,20 @@
use core::panic;
use std::{fs, io::Write};
use headless_chrome::Browser; use headless_chrome::Browser;
use headless_chrome::types::PrintToPdfOptions; use headless_chrome::types::PrintToPdfOptions;
use nanobyte_opentelemetry::rocket::TracingSpan; use nanobyte_opentelemetry::rocket::TracingSpan;
use rocket::{get, fs::NamedFile}; use rocket::{get, response::stream::ByteStream, fairing::Fairing, fs::NamedFile, futures::TryFutureExt};
use tracing::{info_span, info}; use tempfile::NamedTempFile;
use crate::chromium::rocket::BrowserHolder; use tera::Context;
use tracing::{info_span, error, debug};
use crate::{chromium::rocket::BrowserHolder, tools::{tera::NanoTera, pdf::PdfStream}};
use urlencoding::encode;
fn generate_pdf(browser: Browser) { // TODO: request-id
fn generate_pdf(browser: Browser, file: &NamedTempFile) -> Vec<u8> {
let tab = browser.new_tab().unwrap(); let tab = browser.new_tab().unwrap();
let path = format!("file://{}", file.path().to_str().unwrap());
info_span!("open_pdf").in_scope(|| { info_span!("open_pdf").in_scope(|| {
tab.navigate_to("file:///home/6a6996c0-1609-48b6-8ca6-affbef1b4d1d/Devel/Nanobyte/ovlach/ovlach_pdf/template.html").unwrap().wait_until_navigated().unwrap(); debug!("Render pdf from {}", &path);
tab.navigate_to(&path).unwrap().wait_until_navigated().unwrap();
}); });
let options = PrintToPdfOptions{ let options = PrintToPdfOptions{
@ -31,25 +34,33 @@ fn generate_pdf(browser: Browser) {
tab.print_to_pdf(Some(options)).unwrap() tab.print_to_pdf(Some(options)).unwrap()
}); });
info_span!("write_temporary_file").in_scope(|| { return bytes;
let mut file = fs::OpenOptions::new()
// .create(true) // To create a new file
.write(true)
// either use the ? operator or unwrap since it returns a Result
.open("/tmp/foo.pdf").unwrap();
file.write_all(&bytes).unwrap();
});
} }
#[get("/cv/<username>/pdf")] #[tracing::instrument]
pub async fn render_pdf_cv(username: &str, browser: BrowserHolder, tracing: TracingSpan) -> Option<NamedFile> { fn render_template(template_name: &str, file: &NamedTempFile, tera: NanoTera) {
let entered_span = tracing.0.enter(); // TODO: handle errors
let span = info_span!("render_pdf", username = username); tera.0.render_to("two_column.html.tera", &Context::new(), file);
info!("generate PDF"); }
span.in_scope(||{
generate_pdf(browser.browser); #[get("/cv/<username>/output.pdf")]
}); pub async fn render_pdf_cv(username: &str, browser: BrowserHolder, tera: NanoTera, tracing: TracingSpan) -> PdfStream {
info!("done generating"); let entered_span = tracing.0.enter();
drop(entered_span); let file = tempfile::Builder::new().suffix(".html").tempfile().unwrap();
Some(NamedFile::open("/tmp/foo.pdf").await.expect("failed to open foo.pdf")) render_template("two_column", &file, tera);
let span = info_span!("render_pdf", username = username);
let pdf = span.in_scope(||{
generate_pdf(browser.browser, &file)
});
drop(entered_span);
PdfStream::new(pdf)
}
/// Route only for debuging
#[get("/cv/<username>/output.html")]
pub async fn render_html_cv(username: &str, tera: NanoTera, tracing: TracingSpan) -> NamedFile {
let entered_span = tracing.0.enter();
let file = tempfile::Builder::new().suffix(".html").tempfile().unwrap();
render_template("two_column", &file, tera);
NamedFile::open(file.path()).await.unwrap()
} }

View File

@ -0,0 +1,2 @@
pub mod tera;
pub mod pdf;

25
src/tools/pdf.rs Normal file
View File

@ -0,0 +1,25 @@
use rocket::{response::{Responder, self}, Request, Response, http::{Header, ContentType}};
use std::io::Cursor;
pub struct PdfStream {
data: Vec<u8>,
}
impl PdfStream {
pub fn new(data: Vec<u8>) -> PdfStream {
PdfStream { data }
}
}
#[rocket::async_trait]
impl<'r> Responder<'r, 'static> for PdfStream {
fn respond_to(self, _: &'r Request<'_>) -> response::Result<'static> {
Response::build()
.header(ContentType::PDF)
.sized_body(self.data.len(), Cursor::new(self.data))
.ok()
}
}

16
src/tools/tera.rs Normal file
View File

@ -0,0 +1,16 @@
use rocket::{request::{FromRequest, Outcome}, Request};
use tera::Tera;
#[derive(Debug)]
pub struct NanoTera(pub Tera);
// Allows a route to access the span
#[rocket::async_trait]
impl<'r> FromRequest<'r> for NanoTera {
type Error = ();
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, ()> {
rocket::outcome::Outcome::Success(NanoTera(Tera::new("templates/*").unwrap()))
}
}

View File

@ -0,0 +1,200 @@
<html>
<head>
<meta charset="UTF-8">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans:wght@400;800&family=Roboto&display=swap" rel="stylesheet">
<style>
h1 {
/*font-weight: 800;*/
font-size: 3em;
padding: 0;
margin: 0;
margin-left: -0.1em;
/* text upper */
text-transform: uppercase;
}
h2 {
font-size: 1.1em;
padding: 0;
margin: 0;
}
body { min-height: 100vh; }
body {
padding-left: 0.5em;
margin: 0;
font-family: 'Roboto' ;
min-height: 100%;
}
.about-me-small, .company {
color: #39c0ed;
}
.part-content > * {
padding-bottom: 0.2em;
}
.part {
padding-top: 1em;
font-size: 10pt;
}
.flex-container {
min-height: 100vh;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
align-items: normal;
align-content: normal;
width: 100%;
}
.flex-items:nth-child(1) {
display: block;
flex-grow: 1;
flex-shrink: 1;
flex-basis: auto;
align-self: auto;
order: 0;
}
.flex-items:nth-child(2) {
display: block;
flex-grow: 0;
flex-shrink: 1;
flex-basis: auto;
align-self: auto;
order: 0;
width: 30%;
background-color: gray;
}
.section-header {
border-bottom: 1px solid gray;
width: 99%;
margin-bottom: 1em;
}
.flex-container-experience {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: normal;
align-items: normal;
align-content: normal;
}
.flex-items-experience:nth-child(1) {
display: block;
flex-grow: 0;
flex-shrink: 1;
flex-basis: auto;
align-self: auto;
width: 70%;
order: 0;
}
.flex-items-experience:nth-child(2) {
display: block;
flex-grow: 0;
flex-shrink: 1;
flex-basis: auto;
text-align: right;
align-self: auto;
width: 30%;
margin-right: 1%;
order: 0;
}
</style>
</head>
<body>
<div class="flex-container">
<div class="flex-items">
<div class="header">
<h1>Ondřej Vlach</h1>
<div class="about-me-small">Software engineer</div>
</div>
<div class="part">
<div class="section-header">
<h2>Experience</h2>
</div>
<div class="job part-content">
<div class="flex-container-experience">
<div class="flex-items-experience">
<div class="title">Title</div>
<div class="company">Company</div>
<div class="languages">PHP HTML Aholamora Snake</div>
<p>
baklklbkalkblaklkb lakbl aklkbl akblka lkblakbla
</p>
</div>
<div class="flex-items-experience">
<div class="location">Location</div>
<div class="dates">Dates</div>
</div>
</div>
</div>
</div>
<div class="part">
<div class="section-header">
<h2>Experience</h2>
</div>
<div class="job part-content">
<div class="flex-container-experience">
<div class="flex-items-experience">
<div class="title">Title</div>
<div class="company">Company</div>
<div class="languages">PHP HTML Aholamora Snake</div>
<p>
baklklbkalkblaklkb lakbl aklkbl akblka lkblakbla
</p>
</div>
<div class="flex-items-experience">
<div class="location">Location</div>
<div class="dates">Dates</div>
</div>
</div>
</div>
</div>
<div class="part">
<div class="section-header">
<h2>Experience</h2>
</div>
<div class="job part-content">
<div class="flex-container-experience">
<div class="flex-items-experience">
<div class="title">Title</div>
<div class="company">Company</div>
<div class="languages">PHP HTML Aholamora Snake</div>
<p>
baklklbkalkblaklkb lakbl aklkbl akblka lkblakbla
</p>
</div>
<div class="flex-items-experience">
<div class="location">Location</div>
<div class="dates">Dates</div>
</div>
</div>
</div>
</div>
</div>
<div class="flex-items">
Photo2342342314213 423142342314213423
<div class="contact-bar">
<span class="phone">L</span>
<span class="email">L</span>
</div>
</div>
</div>
</body>
</html>