#!/usr/bin/env clojure ;; Selmer Examples ;; NOTE: Selmer requires Clojure (JVM) and is NOT compatible with Babashka ;; Run with: clojure -M examples.clj ;; Or add deps.edn with selmer dependency (comment "To run these examples, create a deps.edn file:" {:deps {selmer/selmer {:mvn/version "1.12.65"}}} "Then run: clojure -M examples.clj") (require '[selmer.parser :as parser]) (require '[selmer.filters :as filters]) (println "=== Selmer Templating Examples ===\n") ;; ============================================================================ ;; Basic Rendering ;; ============================================================================ (println "1. Basic Variable Rendering") (println (parser/render "Hello {{name}}!" {:name "World"})) (println (parser/render "{{greeting}}, {{name}}!" {:greeting "Hi" :name "Alice"})) (println) (println "2. Nested Data Access") (println (parser/render "{{person.name}} is {{person.age}} years old" {:person {:name "Bob" :age 30}})) (println (parser/render "First item: {{items.0}}" {:items ["apple" "banana" "cherry"]})) (println) ;; ============================================================================ ;; Filters ;; ============================================================================ (println "3. String Filters") (println (parser/render "{{name|upper}}" {:name "alice"})) (println (parser/render "{{name|lower}}" {:name "ALICE"})) (println (parser/render "{{text|capitalize}}" {:text "hello world"})) (println (parser/render "{{text|title}}" {:text "hello world"})) (println) (println "4. Filter Chaining") (println (parser/render "{{text|upper|take:5}}" {:text "hello world"})) (println (parser/render "{{items|join:\", \"|upper}}" {:items ["a" "b" "c"]})) (println) (println "5. Collection Filters") (println (parser/render "Count: {{items|count}}" {:items [1 2 3 4 5]})) (println (parser/render "First: {{items|first}}, Last: {{items|last}}" {:items [10 20 30]})) (println (parser/render "Joined: {{items|join:\", \"}}" {:items ["red" "green" "blue"]})) (println (parser/render "Reversed: {{items|reverse|join:\"-\"}}" {:items [1 2 3]})) (println) (println "6. Utility Filters") (println (parser/render "Value: {{val|default:\"N/A\"}}" {:val nil})) (println (parser/render "Value: {{val|default:\"N/A\"}}" {:val "Present"})) (println (parser/render "Length: {{text|length}}" {:text "hello"})) (println) ;; ============================================================================ ;; Control Flow ;; ============================================================================ (println "7. If/Else Tags") (println (parser/render "{% if user %}Hello {{user}}!{% else %}Please log in{% endif %}" {:user "Alice"})) (println (parser/render "{% if user %}Hello {{user}}!{% else %}Please log in{% endif %}" {})) (println) (println "8. If with Comparisons") (println (parser/render "{% if count > 10 %}Many{% elif count > 0 %}Few{% else %}None{% endif %}" {:count 15})) (println (parser/render "{% if count > 10 %}Many{% elif count > 0 %}Few{% else %}None{% endif %}" {:count 5})) (println (parser/render "{% if count > 10 %}Many{% elif count > 0 %}Few{% else %}None{% endif %}" {:count 0})) (println) (println "9. Ifequal/Ifunequal") (println (parser/render "{% ifequal role \"admin\" %}Admin panel{% endifequal %}" {:role "admin"})) (println (parser/render "{% ifunequal status \"active\" %}Inactive{% endifunequal %}" {:status "pending"})) (println) ;; ============================================================================ ;; Loops ;; ============================================================================ (println "10. For Loops") (def for-template "{% for item in items %}{{forloop.counter}}. {{item}}\n{% endfor %}") (println (parser/render for-template {:items ["apple" "banana" "cherry"]})) (println "11. For Loop Variables") (def loop-vars-template "{% for item in items %}{{item}}{% if not forloop.last %}, {% endif %}{% endfor %}") (println (parser/render loop-vars-template {:items [1 2 3 4 5]})) (println) (println "12. For with Empty") (def for-empty-template "{% for item in items %}{{item}}\n{% empty %}No items found{% endfor %}") (println (parser/render for-empty-template {:items []})) (println (parser/render for-empty-template {:items ["present"]})) (println) (println "13. Destructuring in For Loops") (def destructure-template "{% for [k v] in pairs %}{{k}}: {{v}}\n{% endfor %}") (println (parser/render destructure-template {:pairs [["name" "Alice"] ["age" "30"] ["city" "NYC"]]})) ;; ============================================================================ ;; Template Includes (Inline) ;; ============================================================================ (println "14. Template Composition with Render") (def header-template "=== {{title}} ===") (def content-template "{{header}}\n{{body}}") (let [header (parser/render header-template {:title "Welcome"}) result (parser/render content-template {:header header :body "This is the content"})] (println result)) (println) ;; ============================================================================ ;; Custom Filters ;; ============================================================================ (println "15. Custom Filters") (filters/add-filter! :shout (fn [s] (str (clojure.string/upper-case s) "!!!"))) (println (parser/render "{{msg|shout}}" {:msg "hello"})) (filters/add-filter! :repeat (fn [s n] (apply str (repeat (Integer/parseInt n) s)))) (println (parser/render "{{x|repeat:3}}" {:x "ha"})) (println) ;; ============================================================================ ;; Custom Tags ;; ============================================================================ (println "16. Custom Tags") (parser/add-tag! :uppercase (fn [args context-map] (clojure.string/upper-case (first args)))) (println (parser/render "{% uppercase \"hello world\" %}" {})) (println) ;; ============================================================================ ;; Escaping ;; ============================================================================ (println "17. HTML Escaping (Default)") (println (parser/render "{{html}}" {:html "Bold"})) (println "\n18. Safe Filter (No Escaping)") (println (parser/render "{{html|safe}}" {:html "Bold"})) (println) ;; ============================================================================ ;; Variable Introspection ;; ============================================================================ (println "19. Known Variables") (println "Variables in template '{{x}} {{y.z}}':") (println (parser/known-variables "{{x}} {{y.z}}")) (println) ;; ============================================================================ ;; Practical Examples ;; ============================================================================ (println "20. Email Template Example") (def email-template "Dear {{name}}, Thank you for registering! Your account details: Username: {{username}} Email: {{email}} Registered: {% now \"yyyy-MM-dd HH:mm\" %} {% if premium %} Premium features are now available! {% else %} Upgrade to premium for additional features. {% endif %} Best regards, The Team") (println (parser/render email-template {:name "Alice Johnson" :username "alice" :email "alice@example.com" :premium true})) (println) (println "21. HTML List Example") (def list-template "") (println (parser/render list-template {:items [{:name "Widget" :price 19.99} {:name "Gadget" :price 29.50} {:name "Doohickey" :price 9.99}]})) (println) (println "22. Conditional Navigation") (def nav-template "") (println "Admin user:") (println (parser/render nav-template {:user {:name "Admin" :role "admin"}})) (println "\nRegular user:") (println (parser/render nav-template {:user {:name "Bob" :role "user"}})) (println "\nNot logged in:") (println (parser/render nav-template {})) (println) (println "23. Data Table Example") (def table-template " {% for user in users %} {% empty %} {% endfor %}
#NameStatus
{{forloop.counter}} {{user.name|title}} {% if user.active %}Active{% else %}Inactive{% endif %}
No users found
") (println (parser/render table-template {:users [{:name "alice" :active true} {:name "bob" :active false} {:name "charlie" :active true}]})) (println "\n=== Examples Complete ===")