From 823c8f0e7cc4100ba98c7d08f100b95bea2107ca Mon Sep 17 00:00:00 2001 From: gered Date: Sun, 2 Apr 2017 15:16:48 -0400 Subject: [PATCH] improve base css style support / options. add custom font support --- resources/htmltopdf-base.css | 6 --- src/clj_htmltopdf/options.clj | 95 ++++++++++++++++++++++++++--------- src/clj_htmltopdf/utils.clj | 11 ++++ 3 files changed, 82 insertions(+), 30 deletions(-) create mode 100644 src/clj_htmltopdf/utils.clj diff --git a/resources/htmltopdf-base.css b/resources/htmltopdf-base.css index 1a806a0..77f0419 100644 --- a/resources/htmltopdf-base.css +++ b/resources/htmltopdf-base.css @@ -1,9 +1,3 @@ -body { - font: 12pt sans-serif; - line-height: 1.2; - background: #fff; - color: #000; -} a { page-break-inside: avoid; } diff --git a/src/clj_htmltopdf/options.clj b/src/clj_htmltopdf/options.clj index 498a8bc..2d3221f 100644 --- a/src/clj_htmltopdf/options.clj +++ b/src/clj_htmltopdf/options.clj @@ -2,18 +2,35 @@ (:require [clojure.java.io :as io] [clojure.string :as string] - [clj-htmltopdf.css :as css]) + [clj-htmltopdf.css :as css] + [clj-htmltopdf.utils :as utils]) (:import [org.jsoup.nodes Document Element] [org.jsoup.parser Tag])) +(defn append-style-tag! + ^Element [^Element parent css-styles] + (let [element (.appendElement parent "style")] + (.attr element "type" "text/css") + (.text element + (if (string? css-styles) + css-styles + (css/css->str css-styles))))) + +(defn append-css-link-tag! + ^Element [^Element parent href] + (let [element (.appendElement parent "link")] + (.attr element "type" "text/css") + (.attr element "rel" "stylesheet") + (.attr element "href" (str href)))) + (def default-options - {:logging? false - :base-uri "" - :include-base-css? true - :page {:size :letter - :orientation :portrait - :margin "1.0in"}}) + {:logging? false + :base-uri "" + :styles true + :page {:size :letter + :orientation :portrait + :margin "1.0in"}}) (defn get-final-options [options] @@ -48,25 +65,55 @@ (reduce #(assoc %1 (first %2) (second %2)) {}))] [["@page" styles]])) -(defn append-page-options-style-tag! - ^Element [^Element parent options] - (let [styles (-> (:page options) - (page-options->css) - (css/css->str)) - element (.appendElement parent "style")] - (.attr element "type" "text/css") - (.text element styles))) +(defn append-stylesheet-link-tags! + [^Element parent stylesheets] + (doseq [stylesheet stylesheets] + (append-css-link-tag! parent stylesheet))) -(defn append-base-css-link-tag! - ^Element [^Element parent] - (let [element (.appendElement parent "link")] - (.attr element "type" "text/css") - (.attr element "rel" "stylesheet") - (.attr element "href" (str (io/resource "htmltopdf-base.css"))))) +(defn build-body-css-style + [styles] + [[:body + (merge + {:font-family "sans-serif" + :font-size "12pt" + :line-height "1.3" + :background-color "#fff" + :color "#000"} + (if (map? styles) + (dissoc styles :styles :fonts)))]]) + +(defn build-font-face-styles + [styles] + (if-let [fonts (seq (:fonts styles))] + (mapv + (fn [{:keys [font-family src]}] + ["@font-face" + {:font-family font-family + :src (str "url(\"" (utils/string->url-or-file src) "\")")}]) + fonts))) + +(defn build-base-css-styles + [styles] + (vec + (concat + (build-body-css-style styles) + (build-font-face-styles styles)))) + +(defn build-and-append-base-css-styles! + [^Element parent styles] + (append-style-tag! parent (build-base-css-styles styles)) + (if-let [additional-styles (:styles styles)] + (cond + (sequential? additional-styles) (append-stylesheet-link-tags! parent additional-styles) + (string? additional-styles) (append-stylesheet-link-tags! parent [additional-styles])))) (defn inject-options-into-html! [^Document doc options] - (let [head-tag (-> doc (.select "head") (.first))] - (if (:page options) (append-page-options-style-tag! head-tag options)) - (if (:include-base-css? options) (append-base-css-link-tag! head-tag)) + (let [head-tag (-> doc (.select "head") (.first)) + styles (:styles options)] + (if (:page options) (append-style-tag! head-tag (page-options->css (:page options)))) + (cond + (sequential? styles) (append-stylesheet-link-tags! head-tag styles) + (string? styles) (append-stylesheet-link-tags! head-tag [styles]) + (or (true? styles) (map? styles)) (build-and-append-base-css-styles! head-tag styles)) doc)) diff --git a/src/clj_htmltopdf/utils.clj b/src/clj_htmltopdf/utils.clj new file mode 100644 index 0000000..b5f54f3 --- /dev/null +++ b/src/clj_htmltopdf/utils.clj @@ -0,0 +1,11 @@ +(ns clj-htmltopdf.utils + (:import + [java.io File] + [java.net URL MalformedURLException])) + +(defn string->url-or-file + [^String s] + (try + (URL. s) + (catch MalformedURLException _ + (File. (str "file:" s)))))