PDF documents
Simple PDFs: receipts, letters, tickets and reports as headings and paragraphs, wrapped and flowed onto A4 or Letter pages.
Version 1.0.0 · 1 function · 1 crate
Functions
What use pdf.qwer gives a program, with the types Quillo sees. To take only some, or under other names: use pdf_write from pdf (Quillo 0.6).
pdf_write(path: str, title: str, size: str, blocks: list) → intor an errorWrites a PDF to path: title (the document's), page size "A4" or "Letter", and blocks, each { text, size?, bold? } (size in points, 11 by default), wrapped and flowed onto new pages. The standard fonts cover Latin-1 text. The number of pages.
Get it
$ quillo install pdf # pdf.qwer into this folder$ quillo install pdf --example # and its example, pdf.qweOr with curl:
$ curl -O https://quillolang.org/plugins/files/pdf.qwer$ curl -O https://quillolang.org/plugins/files/pdf.qweThen, in your program, all of it or only what you call:
use pdf.qweruse pdf_write from pdf // Quillo 0.6: only theseIt uses this crate, which cargo fetches the first time the plugin is built:
printpdf = "0.7"Example
// A receipt as a PDF download.//// quillo run pdf.qwe then open http://localhost:8080/receipt.pdfuse "pdf.qwer"route GET /receipt.pdf { pdf_write("receipt.pdf", "Receipt 4521", "A4", [ { text: "Quillo Café", size: 22, bold: true }, { text: "Receipt 4521 · 20 November 2026" }, { text: "2 × Flat white € 7.00\n1 × Croissant € 3.20" }, { text: "Total € 10.20", bold: true }, { text: "Thank you, and see you soon.", size: 9 }, ])? file("receipt.pdf")}route GET /pages = { pages: pdf_write("long.pdf", "Long", "Letter", for i in range(120) => { text: `Line ${i + 1} of a long report.` })? }$ quillo run pdf.qwe$ curl 'localhost:8080/receipt.pdf'$ curl 'localhost:8080/pages'Source
//! Simple PDF documents: receipts, letters, tickets and reports, as headings and paragraphs on A4 or Letter pages, in the standard fonts.//! version: 1.0.0//!//! [dependencies]//! printpdf = "0.7"use printpdf::{BuiltinFont, IndirectFontRef, Mm, PdfDocument};use serde_json::Value;use std::io::BufWriter;/// Points to millimetres, and how wide a line of `size`-point Helvetica may be, in characters, across `width` mm.fn chars_per_line(size: f64, width: f64) -> usize { ((width / (size * 0.3528 * 0.5)).floor() as usize).max(10)}fn wrap(text: &str, max: usize) -> Vec<String> { let mut lines = Vec::new(); for para in text.split('\n') { let mut line = String::new(); for word in para.split_whitespace() { if !line.is_empty() && line.chars().count() + 1 + word.chars().count() > max { lines.push(std::mem::take(&mut line)); } if !line.is_empty() { line.push(' '); } line.push_str(word); } lines.push(line); } lines}/// Writes a PDF to `path`: `title` (the document's), page `size` "A4" or "Letter", and `blocks`, each `{ text, size?, bold? }` (size in points, 11 by default), wrapped and flowed onto new pages. The standard fonts cover Latin-1 text. The number of pages.pub fn pdf_write(path: &str, title: &str, size: &str, blocks: Vec<serde_json::Value>) -> Result<i64, String> { let (w, h): (f32, f32) = if size.eq_ignore_ascii_case("letter") { (215.9, 279.4) } else { (210.0, 297.0) }; let margin: f32 = 20.0; let (doc, p1, l1) = PdfDocument::new(title, Mm(w), Mm(h), "text"); let regular: IndirectFontRef = doc.add_builtin_font(BuiltinFont::Helvetica).map_err(|e| e.to_string())?; let bold: IndirectFontRef = doc.add_builtin_font(BuiltinFont::HelveticaBold).map_err(|e| e.to_string())?; let mut layer = doc.get_page(p1).get_layer(l1); let (mut y, mut pages) = (h - margin, 1); for b in &blocks { let text = b.get("text").and_then(Value::as_str).unwrap_or(""); let pt = b.get("size").and_then(Value::as_f64).unwrap_or(11.0).clamp(4.0, 72.0); let font = if b.get("bold").and_then(Value::as_bool).unwrap_or(false) { &bold } else { ®ular }; let leading = (pt * 0.3528 * 1.35) as f32; for line in wrap(text, chars_per_line(pt, (w - 2.0 * margin) as f64)) { if y - leading < margin { let (p, l) = doc.add_page(Mm(w), Mm(h), "text"); layer = doc.get_page(p).get_layer(l); y = h - margin; pages += 1; } y -= leading; layer.use_text(line, pt as f32, Mm(margin), Mm(y), font); } y -= leading * 0.5; } let file = std::fs::File::create(path).map_err(|e| format!("{}: {}", path, e))?; doc.save(&mut BufWriter::new(file)).map_err(|e| e.to_string())?; Ok(pages)}Related
images_pdf.qwer · 1.0.0Pictures put into a PDF, one per page, fitted and centred, with captions if you like: photo reports, scans and receipts.7 views · 7 downloadsPDF tools pdf_tools.qwer · 1.0.0Merge PDFs, pick and split their pages, count them, and read or set the title and author.8 views · 6 downloadsExcel files spreadsheet.qwer · 1.0.0Read the sheets of .xlsx, .xls and .ods files, and write .xlsx reports with a bold header and fitted columns.7 views · 7 downloadsFont subsets font_subset.qwer · 1.0.0TrueType fonts cut down to the characters a page or a PDF uses, as .ttf, as .woff for the web, or as a data URL for CSS, with the characters the font lacks.6 views · 7 downloadsPDF forms pdf_forms.qwer · 1.0.0PDF forms: the fields listed with their types, values and choices, filled from a map with their appearances drawn, and flattened so they cannot be changed.8 views · 6 downloadsPDF text pdf_text.qwer · 1.0.0The text of a PDF, whole or by page, and the lines holding a word: for search, imports and reading invoices.7 views · 6 downloadsThread 0 posts
On PDF documents: questions, tips, corrections, and code that uses it.
No posts yet. The first one opens the thread.