[#821] Include Selmer

This commit is contained in:
Michiel Borkent 2021-05-06 12:53:59 +02:00 committed by GitHub
parent 29483d6740
commit cbd8a2d07d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
60 changed files with 1591 additions and 29 deletions

View file

@ -8,6 +8,7 @@
"feature-test-check"
"feature-spec-alpha"
"feature-rewrite-clj"
"feature-selmer"
"pods/src"
"babashka.nrepl/src"
"depstar/src" "process/src"
@ -35,7 +36,8 @@
babashka/clojure-lanterna {:mvn/version "0.9.8-SNAPSHOT"}
org.clojure/core.match {:mvn/version "1.0.0"}
hiccup/hiccup {:mvn/version "2.0.0-alpha2"}
rewrite-clj/rewrite-clj {:mvn/version "1.0.605-alpha"}}
rewrite-clj/rewrite-clj {:mvn/version "1.0.605-alpha"}
org.clojars.borkdude/selmer {:mvn/version "1.12.35-pre1"}}
:aliases {:babashka/dev
{:main-opts ["-m" "babashka.main"]}
:profile

View file

@ -0,0 +1,58 @@
(ns babashka.impl.selmer
{:no-doc true}
(:require [babashka.impl.classpath :refer [resource]]
[sci.core :as sci]
[selmer.filters :as filters]
[selmer.parser]
[selmer.tags :as tags]
[selmer.util :refer [*resource-fn*]]))
(def spns (sci/create-ns 'selmer.parser nil))
(defn make-ns [ns sci-ns]
(reduce (fn [ns-map [var-name var]]
(let [m (meta var)
no-doc (:no-doc m)
doc (:doc m)
arglists (:arglists m)]
(if no-doc ns-map
(assoc ns-map var-name
(sci/new-var (symbol var-name) @var
(cond-> {:ns sci-ns
:name (:name m)}
(:macro m) (assoc :macro true)
doc (assoc :doc doc)
arglists (assoc :arglists arglists)))))))
{}
(ns-publics ns)))
(def selmer-parser-ns (make-ns 'selmer.parser spns))
(defn render-file
"Parses files if there isn't a memoized post-parse vector ready to go,
renders post-parse vector with passed context-map regardless. Double-checks
last-modified on files. Uses classpath for filename-or-url path "
[& args]
(binding [*resource-fn* resource]
(apply selmer.parser/render-file args)))
(def selmer-parser-namespace
(assoc selmer-parser-ns 'render-file (sci/copy-var render-file spns)))
(def stns (sci/create-ns 'selmer.tags nil))
(def selmer-tags-ns (sci/create-ns 'selmer.tags stns))
(def selmer-tags-namespace
{;; needed by selmer.parser/add-tag!
'expr-tags (sci/copy-var tags/expr-tags stns)
;; needed by selmer.parser/add-tag!
'tag-handler (sci/copy-var tags/tag-handler stns)})
(def sfns (sci/create-ns 'selmer.filters nil))
(def selmer-filters-ns (sci/create-ns 'selmer.filters sfns))
(def selmer-filters-namespace
{'add-filter! (sci/copy-var filters/add-filter! sfns)
'remove-filter! (sci/copy-var filters/remove-filter! sfns)})

View file

@ -54,6 +54,8 @@
:feature/spec-alpha {:source-paths ["feature-spec-alpha"]}
:feature/rewrite-clj {:source-paths ["feature-rewrite-clj"]
:dependencies [[rewrite-clj/rewrite-clj "1.0.605-alpha"]]}
:feature/selmer {:source-paths ["feature-selmer"]
:dependencies [[org.clojars.borkdude/selmer "1.12.35-pre1"]]}
:test [:feature/xml
:feature/lanterna
:feature/yaml
@ -70,6 +72,7 @@
:feature/test-check
:feature/spec-alpha
:feature/rewrite-clj
:feature/selmer
{:dependencies [[com.clojure-goes-fast/clj-async-profiler "0.4.1"]
[com.opentable.components/otj-pg-embedded "0.13.3"]]}]
:uberjar {:global-vars {*assert* false}

View file

@ -85,6 +85,12 @@ if [ "$BABASHKA_FEATURE_HSQLDB" = "true" ]; then
args+=("-H:IncludeResources=org/hsqldb/.*\.properties" "-H:IncludeResources=org/hsqldb/.*\.sql")
fi
BABASHKA_FEATURE_SELMER=${BABASHKA_FEATURE_SELMER:-}
if [ "$BABASHKA_FEATURE_SELMER" = "true" ]; then
args+=("-H:IncludeResources=json.human.css")
fi
BABASHKA_LEAN=${BABASHKA_LEAN:-}
if [ "$BABASHKA_LEAN" = "true" ]
@ -104,6 +110,7 @@ then
export BABASHKA_FEATURE_TEST_CHECK="${BABASHKA_FEATURE_TEST_CHECK:-false}"
export BABASHKA_FEATURE_SPEC_ALPHA="${BABASHKA_FEATURE_SPEC_ALPHA:-false}"
export BABASHKA_FEATURE_REWRITE_CLJ="${BABASHKA_FEATURE_REWRITE_CLJ:-false}"
export BABASHKA_FEATURE_SELMER="${BABASHKA_FEATURE_SELMER:-false}"
fi
"$GRAALVM_HOME/bin/native-image" "${args[@]}"

View file

@ -153,6 +153,14 @@ else
BABASHKA_LEIN_PROFILES+=",-feature/rewrite-clj"
fi
if [ "$BABASHKA_FEATURE_SELMER" != "false" ]
then
BABASHKA_LEIN_PROFILES+=",+feature/selmer"
else
BABASHKA_LEIN_PROFILES+=",-feature/selmer"
fi
if [ -z "$BABASHKA_JAR" ]; then
lein with-profiles "$BABASHKA_LEIN_PROFILES,+reflection,-uberjar" do run
lein with-profiles "$BABASHKA_LEIN_PROFILES" do clean, uberjar

View file

@ -118,6 +118,11 @@ set BABASHKA_LEIN_PROFILES=%BABASHKA_LEIN_PROFILES%,+feature/rewrite-clj
set BABASHKA_LEIN_PROFILES=%BABASHKA_LEIN_PROFILES%,-feature/rewrite-clj
)
if not "%BABASHKA_FEATURE_REWRITE_SELMER%"=="false" (
set BABASHKA_LEIN_PROFILES=%BABASHKA_LEIN_PROFILES%,+feature/selmer
) else (
set BABASHKA_LEIN_PROFILES=%BABASHKA_LEIN_PROFILES%,-feature/selmer
)
call lein with-profiles %BABASHKA_LEIN_PROFILES% bb "(+ 1 2 3)"

View file

@ -15,7 +15,7 @@
(deftype DirectoryResolver [path]
IResourceResolver
(getResource [_ resource-paths {:keys [:url?]}]
(getResource [_ resource-paths url?]
(some
(fn [resource-path]
(let [f (io/file path resource-path)]
@ -28,23 +28,22 @@
resource-paths)))
(defn path-from-jar
[^java.io.File jar-file resource-paths opts]
(let [url? (:url? opts)]
(with-open [jar (JarFile. jar-file)]
(some (fn [path]
(when-let [entry (.getEntry jar path)]
(if url?
;; manual conversion, faster than going through .toURI
(java.net.URL. "jar" nil
(str "file:" (.getAbsolutePath jar-file) "!/" path))
{:file path
:source (slurp (.getInputStream jar entry))})))
resource-paths))))
[^java.io.File jar-file resource-paths url?]
(with-open [jar (JarFile. jar-file)]
(some (fn [path]
(when-let [entry (.getEntry jar path)]
(if url?
;; manual conversion, faster than going through .toURI
(java.net.URL. "jar" nil
(str "file:" (.getAbsolutePath jar-file) "!/" path))
{:file path
:source (slurp (.getInputStream jar entry))})))
resource-paths)))
(deftype JarFileResolver [jar-file]
IResourceResolver
(getResource [_ resource-paths opts]
(path-from-jar jar-file resource-paths opts)))
(getResource [_ resource-paths url?]
(path-from-jar jar-file resource-paths url?)))
(defn part->entry [part]
(when-not (str/blank? part)
@ -107,6 +106,12 @@
[]
(:cp @cp-state))
(defn resource [path]
(when-let [st @cp-state]
(let [loader (:loader st)]
(if (str/starts-with? path "/") nil ;; non-relative paths always return nil
(getResource loader [path] true)))))
(def cns (sci/create-ns 'babashka.classpath nil))
(def classpath-namespace

View file

@ -1,6 +1,7 @@
(ns babashka.impl.clojure.java.io
{:no-doc true}
(:require [clojure.java.io :as io]
(:require [babashka.impl.classpath :as cp]
[clojure.java.io :as io]
[sci.core :as sci :refer [copy-var]]
[sci.impl.types :as types])
(:import [java.io File ]))
@ -64,4 +65,5 @@
'make-parents (copy-var io/make-parents io-ns)
'output-stream (copy-var io/output-stream io-ns)
'reader (copy-var io/reader io-ns)
'writer (copy-var io/writer io-ns)})
'writer (copy-var io/writer io-ns)
'resource (sci/copy-var cp/resource io-ns)})

View file

@ -15,6 +15,7 @@
(def hiccup? (not= "false" (System/getenv "BABASHKA_FEATURE_HICCUP")))
(def test-check? (not= "false" (System/getenv "BABASHKA_FEATURE_TEST_CHECK")))
(def rewrite-clj? (not= "false" (System/getenv "BABASHKA_FEATURE_REWRITE_CLJ")))
(def selmer? (not= "false" (System/getenv "BABASHKA_FEATURE_SELMER")))
;; excluded by default
(def jdbc? (= "true" (System/getenv "BABASHKA_FEATURE_JDBC")))
@ -70,3 +71,6 @@
(when rewrite-clj?
(require '[babashka.impl.rewrite-clj]))
(when selmer?
(require '[babashka.impl.selmer]))

View file

@ -165,9 +165,9 @@ When no eval opts or subcommand is provided, the implicit subcommand is repl.")
(let [arg (first command-line-args)
tasks (:tasks @common/bb-edn)]
(if (or (when-let [s (tasks/doc-from-task
ctx
tasks
(get tasks (symbol arg)))]
ctx
tasks
(get tasks (symbol arg)))]
[(do (println "-------------------------")
(println arg)
(println "Task")
@ -207,7 +207,8 @@ When no eval opts or subcommand is provided, the implicit subcommand is repl.")
:feature/hiccup %s
:feature/test-check %s
:feature/spec-alpha %s
:feature/rewrite-clj %s}")
:feature/rewrite-clj %s
:feature/selmer %s}")
version
features/core-async?
features/csv?
@ -225,7 +226,8 @@ When no eval opts or subcommand is provided, the implicit subcommand is repl.")
features/hiccup?
features/test-check?
features/spec-alpha?
features/rewrite-clj?)))
features/rewrite-clj?
features/selmer?)))
(defn read-file [file]
(let [f (io/file file)]
@ -365,7 +367,13 @@ When no eval opts or subcommand is provided, the implicit subcommand is repl.")
'rewrite-clj.zip
@(resolve 'babashka.impl.rewrite-clj/zip-namespace)
'rewrite-clj.zip.subedit
@(resolve 'babashka.impl.rewrite-clj/subedit-namespace))))
@(resolve 'babashka.impl.rewrite-clj/subedit-namespace))
features/selmer? (assoc 'selmer.parser
@(resolve 'babashka.impl.selmer/selmer-parser-namespace)
'selmer.tags
@(resolve 'babashka.impl.selmer/selmer-tags-namespace)
'selmer.filters
@(resolve 'babashka.impl.selmer/selmer-filters-namespace))))
(def imports
'{ArithmeticException java.lang.ArithmeticException
@ -683,11 +691,6 @@ When no eval opts or subcommand is provided, the implicit subcommand is repl.")
(assoc 'clojure.core
(assoc core-extras
'load-file load-file*))
(assoc-in ['clojure.java.io 'resource]
(fn [path]
(when-let [{:keys [:loader]} @cp/cp-state]
(if (str/starts-with? path "/") nil ;; non-relative paths always return nil
(cp/getResource loader [path] {:url? true})))))
(assoc-in ['user (with-meta '*input*
(when-not stream?
{:sci.impl/deref! true}))] input-var))

View file

@ -198,6 +198,8 @@
(test-namespaces 'helins.binf.test)
(test-namespaces 'selmer.core-test)
;;;; final exit code
(let [{:keys [:test :fail :error] :as m} @status]

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,3 @@
{% for p in products %}
{% if any p.a p.b p.c p.d p.e p.f p.g %}{% endif %}
{% endfor %}

View file

@ -0,0 +1,4 @@
Base template.
[# block body #]
[# block content #][# endblock #]
[# endblock #]

View file

@ -0,0 +1,4 @@
Base template.
{% block body %}
{% block content %}{% endblock %}
{% endblock %}

View file

@ -0,0 +1,5 @@
[# extends "templates/base-custom.html" #]
[# block content #]
<p>[(content)]</p>
[# endblock content #]

View file

@ -0,0 +1,5 @@
{% extends "templates/base.html" %}
{% block content %}
<p>{{content}}</p>
{% endblock content %}

View file

@ -0,0 +1,5 @@
{% if foo %} foo!
{% elif bar %} bar!
{% elif baz %} baz!
{% else %} else!
{% endif %}

View file

@ -0,0 +1,22 @@
{% if foo %}
<h1>FOO!</h1>
{% endif %}
{% if bar %}
<h1>BAR!</h1>
{% else %}
<h1>NOT BAR!</h1>
{% endif %}
{% if user-id %}
"foo"
{% else %}
"bar"
{% endif %}
{% if nested %}
{% if inner %}
inner
{% endif %}
{% endif %}

View file

@ -0,0 +1,13 @@
{% ifequal foo "bar" %}
<h1>equal!</h1>
{% endifequal %}
{% ifequal foo bar %}
<h1>equal!</h1>
{% endifequal %}
{% ifequal baz "test" %}
<h1>equal!</h1>
{% else %}
<p>not equal</p>
{% endifequal %}

View file

@ -0,0 +1 @@
{% include "templates/snippet.html" with url="/page?name=foo" gridid="abc" %}

View file

@ -0,0 +1 @@
<div>{% block content %}{% endblock %}</div>

View file

@ -0,0 +1,10 @@
<html>
<body>{% block header %}
original header
{% endblock %}
<div>{% block content %}{% endblock %}</div>
{% block footer %}
{% endblock %}</body>
</html>

View file

@ -0,0 +1,2 @@
{% block foo %}Here's the default text of foo {{foo}}{% endblock %}
{% block bar %}Here's the default text of bar {{bar}}{% endblock %}

View file

@ -0,0 +1,9 @@
{% extends "templates/inheritance/base.html" %}
{% block header %}
<h1>child-a header</h1>
<<{{block.super}}>>
{% endblock %}
{% block footer %}
<p>footer</p>
{% endblock %}

View file

@ -0,0 +1,9 @@
{% extends "templates/inheritance/child-a.html" %}
{% block header %}
B header
{{block.super}}
{% endblock %}
{% block content %}
Some content
{% endblock %}

View file

@ -0,0 +1,2 @@
{% extends "templates/inheritance/include-head.html" %}
{% block my-script %}<script src="my/C/script" />{% endblock %}

View file

@ -0,0 +1,2 @@
{% extends "templates/inheritance/include-head.html" %}
{% block my-script %}<script src="my/D/script" />{% endblock %}

View file

@ -0,0 +1 @@
{%ifequal greeting name%} {{greeting}} {{name}} {%endifequal%}

View file

@ -0,0 +1 @@
Hello, {{name}}!

View file

@ -0,0 +1,3 @@
{% block home %}
<h1>Hello {{user}}</h1>
{% endblock %}

View file

@ -0,0 +1,2 @@
{% include "templates/inheritance/include/head.html" %}
<body>my-body</body>

View file

@ -0,0 +1,5 @@
{% extends "templates/inheritance/another-parent.html" %}
{% block content %}
{% include "templates/inheritance/include/snippet.html" %}
{% endblock %}

View file

@ -0,0 +1 @@
base tempate {% include "templates/inheritance/include/snippet.html" %}

View file

@ -0,0 +1 @@
foo {% include "templates/inheritance/include/parent.html" with my-variable="default-value" my-other-variable="other-default-value" %}

View file

@ -0,0 +1 @@
foo {% include "templates/inheritance/include/child.html" with my-variable="default-value" my-other-variable="another-default-value"%}

View file

@ -0,0 +1 @@
baz {{ my-variable }} {{ my-other-variable }}

View file

@ -0,0 +1 @@
foo {% with my-variable="some-value" my-other-variable="some-other-value"%}{% include "templates/inheritance/include/parent.html" %}{% endwith %}

View file

@ -0,0 +1 @@
<head>{% block my-script %}{% endblock %}</head>

View file

@ -0,0 +1 @@
bar {% include "templates/inheritance/include/child.html" %}

View file

@ -0,0 +1 @@
hello

View file

@ -0,0 +1,7 @@
start a
{% block a %}{% endblock %}
stop a
{% block content %}{% endblock %}
{% include "templates/inheritance/foo.html" %}

View file

@ -0,0 +1,8 @@
{% extends "templates/inheritance/inherit-a.html" %}
{% block a %}
start b
{% block b %}{% endblock %}
stop b
{% endblock %}
{% block content %}content{% endblock %}

View file

@ -0,0 +1,6 @@
{% extends "templates/inheritance/inherit-b.html" %}
{% block b %}
start c
stop c
{% endblock %}

View file

@ -0,0 +1 @@
{% include "templates/inheritance/child.html" with name = "Jane Doe" greeting="Hello!" %}

View file

@ -0,0 +1,8 @@
{% block register %}
<form action="/register" method="POST">
<label for="id">user id</label>
<input id="id" name="id" type="text"></input>
<input pass="pass" name="pass" type="text"></input>
<input type="submit" value="register">
</form>
{% endblock %}

View file

@ -0,0 +1,8 @@
<html>
<head></head>
<body>
{% block hello %}
Hello
{% endblock %}
</body>
</html>

View file

@ -0,0 +1,4 @@
{% extends "templates/inheritance/super-a.html" %}
{% block hello %}
{{ block.super }} World
{% endblock %}

View file

@ -0,0 +1,4 @@
{% extends "templates/inheritance/super-b.html" %}
{% block hello %}
{{ block.super }}Cruel World
{% endblock %}

View file

@ -0,0 +1 @@
{{ foo }}{{ bar }}

View file

@ -0,0 +1 @@
main template {% include "templates/my-include-child.html" %} body

View file

@ -0,0 +1,13 @@
<html>
<body>
<ul>
{% for user in users %}
<li>
{% for i in user %}
{{i.name}}
{% endfor %}
</li>
{% endfor %}
</ul>
</body>
</html>

View file

@ -0,0 +1 @@
{

View file

@ -0,0 +1,4 @@
{% for p in ps %}
{% if p.a > p.b %}
{% endif %}
{% endfor %}

View file

@ -0,0 +1 @@
{% safe %}{% block foo %}{% if bar %}{{unsafe}}{% endif %}{% endblock %}{% endsafe %}

View file

@ -0,0 +1 @@
{{url}} - {{gridid}}

View file

@ -0,0 +1 @@
{% with total=business.employees|count %}{{ total }}{% endwith %}

View file

@ -0,0 +1,14 @@
{% extends "app/views/templates/base.html" %}
{% block body %}
<div class="container-fluid">
<div class="centered-form">
<form action="{{context}}/login" class="form-signin" method="POST">
<h3 class="form-signin-heading">{{title|upper}}</h3>
{% if formid|str|date %}<input type="hidden" id="formid" name="formid" value="{{formid}}" />{% endif %}
<input class="input-block-level" id="userid" name="userid" placeholder="T-id" type="text">
<input class="input-block-level" id="pass" name="pass" placeholder="Password" type="password">
<input class="btn btn-primary" type="submit" value="Sign in">
</form>
</div>
</div>
{% endblock %}

View file

@ -0,0 +1,3 @@
{% verbatim %}
<p class="name">{%=file.name%}</p>
{% endverbatim %}