From efbd3731c986a8555869c184cda69ff9b910ce9f Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Sat, 23 Dec 2017 15:52:22 -0500 Subject: pdf support --- Makefile | 12 +++++++++-- README.org | 16 ++++++++++++++ lib/page_local.rb | 3 +++ lib/page_pdf.rb | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.scss | 26 +++++++++++++++++++++++ tmpl/pdf.md.erb | 5 +++++ 6 files changed, 122 insertions(+), 2 deletions(-) create mode 100644 lib/page_pdf.rb create mode 100644 tmpl/pdf.md.erb diff --git a/Makefile b/Makefile index 96e0fdf..f61c4c3 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,9 @@ MAKEFLAGS += -j1 +pdfjs = https://github.com/mozilla/pdf.js/releases/download/v1.9.426/pdfjs-1.9.426-dist.zip + # Default target -all: out/index.html out/main.css +all: out/index.html out/main.css out/pdfjs phony += all # Boilerplate @@ -25,7 +27,13 @@ out/%.css: src/%.scss @mkdir -p $(@D) scss --stdin < $< > $@ -targets = $(phony) %.css +out/$(notdir $(pdfjs)): + wget -c --no-use-server-timestamp -O $@ $(pdfjs) +out/pdfjs: out/$(notdir $(pdfjs)) + rm -rf -- $@ + mkdir -- $@ && bsdtar -xf $(abspath $<) -C $@ --exclude '*.pdf' || { rm -rf -- $@; false; } + +targets = $(phony) %.css out/pdfjs% $(sort $(filter-out $(targets),out/index.html $(MAKECMDGOALS))): FORCE ./bin/sitegen diff --git a/README.org b/README.org index e8a3542..e95aff5 100644 --- a/README.org +++ b/README.org @@ -63,6 +63,7 @@ Currently supported formats are: - Markdown (~.md~) : converted with Pandoc - Org-mode (~.org~) : converted with Pandoc + - PDF (~.pdf~) : embedded with PDF.js I don't need to tell you how to make these types of files. @@ -107,6 +108,21 @@ when converting to HTML. See the Org-mode and Pandoc documentation. AFAIK, unfortunately Org-mode only has values as strings, no structured data. +** Setting metadata: PDF + +PDF files natively support embedding certain bits of metadata. The +bits that we use are: + + - title + - author + - creation date + - modification date + +If you need to set any other metadata attributes, or want to override +the values in the PDF (since setting them can be difficult), create +YAML file with the same name as the PDF file, but with the ~.yaml~ +file extension instead of ~.pdf~. + ** Metadata attributes that are handles specially There are some metadata attributes that are used specially by the site diff --git a/lib/page_local.rb b/lib/page_local.rb index e956f6a..6c70ac3 100644 --- a/lib/page_local.rb +++ b/lib/page_local.rb @@ -16,6 +16,9 @@ class LocalPage < Page return IndexPage::new(inpath) when [".md", ".org"].include?(File::extname(inpath)) return LocalPage::new(inpath) + when ".pdf" == File::extname(inpath) + require 'page_pdf' + return PdfPage::new(inpath) else return nil end diff --git a/lib/page_pdf.rb b/lib/page_pdf.rb new file mode 100644 index 0000000..e70c887 --- /dev/null +++ b/lib/page_pdf.rb @@ -0,0 +1,62 @@ +# coding: utf-8 +require 'erb' +require 'open3' +require 'yaml' + +require 'page_local' + +class PdfPage < LocalPage + def initialize(filename) + super(filename) + end + + def pdf_metadata + if @metadata.nil? + stdout, stderr, status = Open3::capture3("pdfinfo", "--", local_infile) + unless stderr.empty? + raise stderr + end + unless status.success? + raise status + end + raw_metadata = stdout.split("\n").map{|l|l.split(":", 2).map{|c|c.strip}}.to_h + + # Transform the PDF property names to match our metadata names + key_map = { + "Title" => "title", + "Author" => "author", + "CreationDate" => "published", + "ModDate" => "updated", + # "Keywords" => "categories", + } + @metadata = raw_metadata.map{|k,v|[key_map[k]||k,v]}.to_h + + yamlfile = local_infile.sub(/\.pdf$/, '.yaml') + if File::exist?(yamlfile) + @metadata = @metadata.merge(YAML::load(File::read(yamlfile))) + end + end + @metadata + end + def pdf_js_url + @@pdjfs ||= Config::get.url + 'pdfjs/web/viewer.html' + end + def pdf_viewer_url + @viewer_url ||= pdf_js_url + ('?file=' + URI::encode_www_form_component(pdf_js_url.route_to(local_srcurl))) + end + + def local_intype + return 'markdown' + end + def local_depends + if @depends.nil? + yamlfile = local_infile.sub(/\.pdf$/, '.yaml') + metafile = File::exist?(yamlfile) ? yamlfile : File::dirname(yamlfile) + tmplfile = "tmpl/pdf.md.erb" + @depends = super.map{|k,v|[k,v.merge([metafile, tmplfile])]}.to_h + end + @depends + end +end + +ERB::new(File::read("tmpl/pdf.md.erb")).def_method(PdfPage, 'local_input()', "tmpl/pdf.md.erb") diff --git a/src/main.scss b/src/main.scss index be00d49..cdbc200 100644 --- a/src/main.scss +++ b/src/main.scss @@ -287,3 +287,29 @@ body.dnd { font-weight:bold; } } } + +/* D&D-style pages ************************************************************/ + +body.pdf { + position: absolute; + width: 100%; + height: 100%; + bottom: 0; + + display: flex; + flex-direction: column; + + article { + flex-grow: 2; + padding: 0; + + h1 { + text-align: center; + margin: 0.25em 0; + } + iframe { + width: 100%; + height: 100%; + } + } +} diff --git a/tmpl/pdf.md.erb b/tmpl/pdf.md.erb new file mode 100644 index 0000000..2ce7327 --- /dev/null +++ b/tmpl/pdf.md.erb @@ -0,0 +1,5 @@ +<%= pdf_metadata.to_yaml %> +class: pdf +--- + + -- cgit v1.1-4-g5e80