From 647990c43abb3593b913f41f023a82f5296205f4 Mon Sep 17 00:00:00 2001 From: gered Date: Thu, 5 Jul 2018 11:10:38 -0400 Subject: [PATCH] replace broken method of getting base-uri with a custom uri resolver apparently didn't test that get-base-resource-path-url function nearly enough... oops. this new ability to specify a custom uri resolver is much better anyway. the default resolver (using the resolve-uri function) is geared towards the common case (or what i assume will be the common case) where you want to refer to css/image/etc resources located on the classpath (e.g. under your project's "resources" directory somewhere). --- src/clj_htmltopdf/core.clj | 1 + src/clj_htmltopdf/options.clj | 55 ++++++++++++++++++++++++++++------- 2 files changed, 46 insertions(+), 10 deletions(-) diff --git a/src/clj_htmltopdf/core.clj b/src/clj_htmltopdf/core.clj index 7dbe405..9eda54d 100644 --- a/src/clj_htmltopdf/core.clj +++ b/src/clj_htmltopdf/core.clj @@ -86,6 +86,7 @@ (let [builder (PdfRendererBuilder.) base-uri (opt/->base-uri options) w3c-doc (jsoup->w3c html-doc)] + (opt/set-uri-resolver! builder options) (obj/set-object-drawer-factory builder options) (.useSVGDrawer builder (BatikSVGDrawer.)) (.withW3cDocument builder w3c-doc base-uri) diff --git a/src/clj_htmltopdf/options.clj b/src/clj_htmltopdf/options.clj index 4dab1a9..eab6f4d 100644 --- a/src/clj_htmltopdf/options.clj +++ b/src/clj_htmltopdf/options.clj @@ -5,16 +5,51 @@ [clj-htmltopdf.css :as css] [clj-htmltopdf.utils :as utils]) (:import - [org.jsoup.nodes Document Element] - [org.jsoup.parser Tag])) + [java.net URI URL] + [com.openhtmltopdf.extend FSUriResolver] + [com.openhtmltopdf.pdfboxout PdfRendererBuilder] + [org.jsoup.nodes Document Element])) -(defn- get-base-resource-path-url - [] - (if-let [css-resource (io/resource "htmltopdf-base.css")] - (-> (io/file css-resource) - (.getParentFile) - (.toURL)) - "")) +(defn ->uri-resolver + ^FSUriResolver [f] + (reify FSUriResolver + (^String resolveURI [_ ^String base-uri ^String uri] + (f base-uri uri)))) + +(defn resolve-uri + "default URI resolver. if the combination of base-uri + uri is found to be an absolute URI, then that + absolute URI is returned. if the uri itself is an absolute URI, then base-uri is not used at all. + otherwise, the relative URI (again, the combination of base-uri and uri) is resolved as a resource + URL via clojure.java.io/resource. + + because java.net.URI defines an 'absolute URI' as a URI that includes a scheme (e.g. http:// or file://), + if you want to use an absolute path to a file on disk, you MUST prefix your uri with 'file:' else it will + be treated as a relative URI and resolved via clojure.java.io/resource (likely resulting in a nil return)" + ^String [^String base-uri ^String uri] + (if-not (string/blank? uri) + (let [possibly-relative-uri (URI. uri) + possibly-relative-base-uri (if-not (string/blank? base-uri) + (URI. base-uri))] + (cond + (.isAbsolute possibly-relative-uri) + (str possibly-relative-uri) + + (and possibly-relative-base-uri + (.isAbsolute possibly-relative-base-uri)) + (str (URL. base-uri) uri) + + :else + (let [relative-uri (if possibly-relative-base-uri + (.resolve possibly-relative-base-uri possibly-relative-uri) + possibly-relative-uri) + url (io/resource (str relative-uri))] + (if url (str url))))))) + +(defn set-uri-resolver! + [^PdfRendererBuilder builder options] + (let [f (or (:uri-resolver options) + resolve-uri)] + (.useUriResolver builder (->uri-resolver f)))) (defn append-style-tag! ^Element [^Element parent css-styles] @@ -40,7 +75,7 @@ (def default-options {:logging? false - :base-uri (get-base-resource-path-url) + :base-uri "" :styles true :page {:size :letter :orientation :portrait