Skip to content

Commit d293c3d

Browse files
authored
feat: render like render-file (#315)
feat: update render behavior to match render-file
1 parent 932bc9d commit d293c3d

File tree

6 files changed

+151
-145
lines changed

6 files changed

+151
-145
lines changed

.dir-locals.el

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
((nil . ((cider-preferred-build-tool . clojure-cli)
2+
(cider-clojure-cli-aliases . ":dev:test"))))

README.md

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -814,9 +814,7 @@ and we want to be able to use variables, filters and tags for the string:
814814

815815
#### include
816816

817-
This tag is only available for `render-file` since `render` function only operates on a template consisting of a single string.
818-
819-
replaces itself with the contents of the referenced template
817+
Replaces itself with the contents of the referenced template
820818

821819
`{% include "path/to/comments.html" %}`
822820

@@ -1093,8 +1091,6 @@ injects the specified keys into the context map:
10931091

10941092
## Template Inheritance
10951093

1096-
**note**: tags using template inheritance can only be used with `render-file` since `render` will only consider the input string itself
1097-
10981094
### Extending Templates
10991095

11001096
Templates can inherit from other templates using the `extends` tag. When extending a template, any blocks in the parent

changes.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
* 1.12.62 - render's inheritance works like render-file
12
* 1.12.61 - improved `java.time.Instant` to the date filter support
23
* 1.12.60 - add support for passing `java.time.Instant` to the date filter
34
* 1.12.59 - [adds resolve-arg function in selmer.parser which lets you resolve args passed to the handler of custom tags](https://github.com/yogthos/Selmer/pull/304)

src/selmer/parser.clj

Lines changed: 42 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,21 @@
88
means the first time we see a template *at runtime*, not the
99
implementation's compile-time. "
1010
(:require
11-
[clojure.set :as set]
12-
[clojure.string :as string]
13-
[selmer.template-parser :refer [preprocess-template]]
14-
[selmer.filters :refer [filters]]
15-
[selmer.filter-parser :refer [compile-filter-body literal?
16-
split-value parse-literal]]
17-
[selmer.tags :refer :all]
18-
[selmer.util :refer :all]
19-
[selmer.validator :refer [validation-error]]
20-
selmer.node)
11+
[clojure.set :as set]
12+
[clojure.string :as string]
13+
[selmer.template-parser :refer [preprocess-template]]
14+
[selmer.filters :refer [filters]]
15+
[selmer.filter-parser :refer [compile-filter-body literal?
16+
split-value parse-literal]]
17+
[selmer.tags :refer :all]
18+
[selmer.util :refer :all]
19+
[selmer.validator :refer [validation-error]]
20+
selmer.node)
2121
(:import [selmer.node TextNode FunctionNode]))
2222

2323
;; Ahead decl because some fns call into each other.
2424

25-
(declare parse parse-input parse-file tag-content)
25+
(declare parse parse-input parse-str parse-file tag-content)
2626

2727
;; Memoization atom for templates. If you pass a filepath instead
2828
;; of a string, we'll use the last-modified timestamp to cache the
@@ -62,10 +62,10 @@
6262
(if (or (looks-like-absolute-file-path? path)
6363
(.startsWith ^java.lang.String path "file:/"))
6464
(append-slash
65-
(try
66-
(str (java.net.URL. path))
67-
(catch java.net.MalformedURLException err
68-
(str "file:///" path))))
65+
(try
66+
(str (java.net.URL. path))
67+
(catch java.net.MalformedURLException err
68+
(str "file:///" path))))
6969
(append-slash path))))
7070

7171
(defn set-resource-path!
@@ -117,8 +117,7 @@
117117
(defn render
118118
" render takes the string, the context-map and possibly also opts. "
119119
[s context-map & [opts]]
120-
(render-template (parse parse-input (java.io.StringReader. s) opts) context-map))
121-
120+
(render-template (parse parse-str s opts) context-map))
122121

123122
;; Primary fn you interact with as a user, you pass a path that
124123
;; exists somewhere in your class-path, typically something like
@@ -151,8 +150,8 @@
151150
:last-modified last-modified-time})
152151
(render-template template context-map))))
153152
(validation-error
154-
(str "resource-path for " filename-or-url " returned nil, typically means the file doesn't exist in your classpath.")
155-
nil nil nil))))
153+
(str "resource-path for " filename-or-url " returned nil, typically means the file doesn't exist in your classpath.")
154+
nil nil nil))))
156155

157156
;; For a given tag, get the fn handler for the tag type,
158157
;; pass it the arguments, tag-content, render-template fn,
@@ -161,8 +160,8 @@
161160
(defn expr-tag [{:keys [tag-name args]} rdr]
162161
(if-let [handler (tag-name @expr-tags)]
163162
(handler args tag-content render-template rdr)
164-
(throw (ex-info (str "unrecognized tag: " tag-name
165-
" - did you forget to close a tag?")
163+
(throw (ex-info (str "unrecognized tag: " tag-name
164+
" - did you forget to close a tag?")
166165
{}))))
167166

168167
;; Same as a vanilla data tag with a value, but composes
@@ -338,6 +337,11 @@
338337
(defn parse-file [file params]
339338
(-> file preprocess-template (java.io.StringReader.) (parse-input params)))
340339

340+
;; File-aware parse wrapper for string.
341+
342+
(defn parse-str [input params]
343+
(-> (char-array input) preprocess-template (java.io.StringReader.) (parse-input params)))
344+
341345
(defn parse [parse-fn input & [{:keys [tag-open tag-close filter-open filter-close tag-second short-comment-second]
342346
:or {tag-open *tag-open*
343347
tag-close *tag-close*
@@ -390,37 +394,37 @@
390394
updated-vars (cond-> vars
391395
should-add-var? (conj v))]
392396
(recur
393-
updated-vars
394-
nested-keys
395-
(rest tags)))
397+
updated-vars
398+
nested-keys
399+
(rest tags)))
396400
(= :for tag-name) (let [[ids [_ items]] (aggregate-args args)]
397401
(recur
398-
(conj vars (parse-variable-paths items))
399-
(conj (set (map keyword ids)) :forloop)
400-
(rest tags)))
402+
(conj vars (parse-variable-paths items))
403+
(conj (set (map keyword ids)) :forloop)
404+
(rest tags)))
401405

402406
(= :with tag-name) (let [[id value] (string/split (first args) #"=")]
403407
(recur
404-
(conj vars (parse-variable-paths value))
405-
#{(keyword id)}
406-
(rest tags)))
408+
(conj vars (parse-variable-paths value))
409+
#{(keyword id)}
410+
(rest tags)))
407411

408412
(contains? #{:endfor :endwith} tag-name) (recur vars #{} (rest tags))
409413

410414
:else
411415
(let [special-syms #{nil :not :all :any :< :> := :<= :>=}
412416
should-remove? (fn [[var-head :as var]]
413417
(or
414-
(special-syms var-head)
415-
(nested-keys var-head)))]
418+
(special-syms var-head)
419+
(nested-keys var-head)))]
416420

417421
(recur (set/union
418-
vars
419-
(->> args
420-
(filter (complement literal?))
421-
(map parse-variable-paths)
422-
(remove should-remove?)
423-
set))
422+
vars
423+
(->> args
424+
(filter (complement literal?))
425+
(map parse-variable-paths)
426+
(remove should-remove?)
427+
set))
424428
nested-keys
425429
(rest tags))))
426430
vars)))

0 commit comments

Comments
 (0)