add extensions/middleware for web app usage

This commit is contained in:
Gered 2014-11-15 12:33:42 -05:00
parent 72f44a278c
commit 7161e66381
4 changed files with 118 additions and 1 deletions

View file

@ -8,6 +8,7 @@
(:require [clojure.walk :refer [stringify-keys]] (:require [clojure.walk :refer [stringify-keys]]
[clj-pebble.extensions :as ext] [clj-pebble.extensions :as ext]
[clj-pebble.standard-extensions :as std] [clj-pebble.standard-extensions :as std]
[clj-pebble.web.extensions :as web]
[clj-pebble.options :refer [options]])) [clj-pebble.options :refer [options]]))
(defonce classpath-loader (ClasspathLoader.)) (defonce classpath-loader (ClasspathLoader.))
@ -29,7 +30,8 @@
(defn- make-pebble-engine [] (defn- make-pebble-engine []
(let [engine (-> (PebbleEngine. classpath-loader) (let [engine (-> (PebbleEngine. classpath-loader)
(ext/add-extensions-library! std/extensions))] (ext/add-extensions-library! std/extensions)
(ext/add-extensions-library! web/extensions))]
(apply-options! engine) (apply-options! engine)
engine)) engine))

27
src/clj_pebble/utils.clj Normal file
View file

@ -0,0 +1,27 @@
(ns clj-pebble.utils
(:import (java.net URL)
(java.io File)))
(defn inside-jar? [^File file]
(-> file
(.getPath)
; the path of a file inside a jar looks something like "jar:file:/path/to/file.jar!/path/inside/jar/to/file"
(.contains "jar!")))
(defn get-file-last-modified [^File file]
(if (inside-jar? file)
0
(.lastModified file)))
(defn get-resource-path
(^URL [^String filename]
(-> (Thread/currentThread)
(.getContextClassLoader)
(.getResource filename))))
(defn get-resource-modification-date [^String filename]
(when-let [resource-filename (get-resource-path filename)]
(->> resource-filename
(.getPath)
(new File)
(get-file-last-modified))))

View file

@ -0,0 +1,80 @@
(ns clj-pebble.web.extensions
(:import (java.net URI))
(:require [clojure.string :as str]
[clj-pebble.web.middleware :refer [*servlet-context-path*]]
[clj-pebble.options :refer [options]])
(:use [clj-pebble.utils]))
;; TODO: while 'public' is the default with Compojure, applications can override with something else ...
;; should make this customizable (some option added to clj-pebble.options likely ...)
(def root-resource-path "public")
(defn- get-context-url [url]
(str *servlet-context-path* url))
(defn- relative-url? [url]
(if-not (str/blank? url)
(let [uri (new URI url)]
(str/blank? (.getScheme uri)))))
(defn- get-resource-modification-timestamp [^String resource-url]
(if (relative-url? resource-url)
(->> (str root-resource-path resource-url)
(get-context-url)
(get-resource-modification-date))))
(defn- get-url-string [url]
(if-let [modification-timestamp (get-resource-modification-timestamp url)]
; because it looks kind of dumb to have '?0' at the end of URLs when running from a jar ...
(if (= modification-timestamp 0)
url
(str url "?" modification-timestamp))
url))
(defn- minified-url? [url]
(re-matches #"^(.+\.)min\.(css|js)$" url))
(defn- make-minified-url [^String url]
(let [pos (.lastIndexOf url (int \.))]
(if (> pos -1)
(let [name (subs url 0 pos)
extension (subs url (inc pos))]
(str name ".min." extension))
url)))
(defn- get-minified-resource-url [url]
(if (or (not (:check-for-minified-web-resources @options))
(minified-url? url))
url
(let [minified-url (make-minified-url url)]
(if (get-resource-path (str root-resource-path minified-url))
minified-url
url))))
; defined using the same type of map structure as in clj-pebble.standard-extensions
(defonce extensions
{:functions
{"path"
{:fn (fn [url]
(get-context-url url))}
"stylesheet"
{:fn (fn [url & [media]]
(let [fmt (if media
"<link href=\"%s\" rel=\"stylesheet\" type=\"text/css\" media=\"%s\" />"
"<link href=\"%s\" rel=\"stylesheet\" type=\"text/css\" />")
resource-path (get-minified-resource-url url)]
(format fmt (get-url-string resource-path) media)))}
"javascript"
{:fn (fn [url]
(let [fmt "<script type=\"text/javascript\" src=\"%s\"></script>"
resource-path (get-minified-resource-url url)]
(format fmt (get-url-string resource-path))))}}
:filters
{}
:tests
{}})

View file

@ -0,0 +1,8 @@
(ns clj-pebble.web.middleware)
(declare ^:dynamic *servlet-context-path*)
(defn wrap-servlet-context-path [handler]
(fn [req]
(binding [*servlet-context-path* (:context req)]
(handler req))))