$30 off During Our Annual Pro Sale. View Details »

Meta Template Engine

ayato
October 02, 2017

Meta Template Engine

ayato

October 02, 2017
Tweet

More Decks by ayato

Other Decks in Programming

Transcript

  1. メタテンプレートエンジンの話
    市ヶ谷Geek★Night#14 市ヶ谷java 〜JVM言語の玉手箱〜

    View Slide

  2. メタテンプレートエンジンの話
    市ヶ谷Geek★Night#14 市ヶ谷clojure 〜JVM言語の玉手箱〜

    View Slide

  3. あやぴー
    •ayato-p@github
    •Cybozu Startups, Inc.
    •Clojure書いてる
    •Webアプリ書いてる

    View Slide

  4. TL;DR

    View Slide

  5. というわけで…

    View Slide

  6. Clojureの話をします

    View Slide

  7. 事の発端

    View Slide

  8. HTMLフォーム面倒

    Email Address
    type="email" name="email"
    th:classappend=
    "${errors.containsKey('email')} ? 'is-invalid'"
    th:value="${values.email}"
    placeholder="Enter email" />



    We'll never share your email with anyone else.


    View Slide

  9. HTMLフォーム面倒
    [:div.form-group
    [:label {:for "input-email"} "Email address"]
    [:input#input-email.form-control
    {:type :email :name :email
    :class (when (contains? errors :email) "is-invalid")
    :value (:email values)
    :placeholder "Enter email"}]
    [:div.invalid-feedback (:email errors)]
    [:small.form-text.text-muted
    "We'll never share your email with anyone else."]]

    View Slide

  10. 面倒なこと
    •_methodみたいなやつ
    •formのmethod属性に直接putとかdelete書きたい
    •__csrf_tokenみたいなやつ
    •いちいち書くのは面倒
    •エラー表示のために書く条件分岐
    •前回表示していた値を表示するための式
    •たいていの場合name属性に依存している

    View Slide

  11. HTMLフォーム面倒
    [:div.form-group
    [:label {:for "input-email"} "Email address"]
    [:input#input-email.form-control
    {:type :email :name :email
    :class (when (contains? errors :email) "is-invalid")
    :value (:email values)
    :placeholder "Enter email"}]
    [:div.invalid-feedback (:email errors)]
    [:small.form-text.text-muted
    "We'll never share your email with anyone else."]]
    ここが決まれば…

    View Slide

  12. HTMLフォーム面倒
    [:div.form-group
    [:label {:for "input-email"} "Email address"]
    [:input#input-email.form-control
    {:type :email :name :email
    :class (when (contains? errors :email) "is-invalid")
    :value (:email values)
    :placeholder "Enter email"}]
    [:div.invalid-feedback (:email errors)]
    [:small.form-text.text-muted
    "We'll never share your email with anyone else."]]
    ここが決まるはず

    View Slide

  13. 考えた

    View Slide

  14. テンプレートエンジンが
    HTMLに変換する前に
    求める形に変換できれば
    いいんじゃない

    View Slide

  15. つまり…
    メタテンプレートエンジン…

    View Slide

  16. Kuuga
    https://github.com/ayato-p/kuuga

    View Slide

  17. “こんなやつらのために、
    これ以上誰かの涙は⾒たくない!
    皆に笑顔でいて欲しいんです!
    だから⾒ててください!俺の…変⾝!! ”

    View Slide

  18. “HTML Formのために、
    これ以上誰かの涙は⾒たくない!
    Hiccupユーザーに笑顔でいて欲しいんです!
    だから⾒ててください!俺の…変換!! ”

    View Slide

  19. 変換ルール(
    (defmethod growing/transform-by-tag :input
    [_ options tag-vector]
    (let [[tagkw tagopts contents] (tool/parse-tag-vector tag-vector)]
    `[~tagkw
    (update-input-opts ~options ~tagopts)
    ~@contents]))

    View Slide

  20. 変換ルール)
    (defmethod growing/transform-by-class :form-group
    [_ options tag-vector]
    (let [[tagkw tagopts contents] (tool/parse-tag-vector tag-vector)
    contents
    (reduce (fn [contents' tagvec']
    (let [[tk to _] (tool/parse-tag-vector tagvec')
    [_ t] (tool/parse-tag-keyword tk)]
    (cond-> (conj contents' tagvec')
    (= t "input") (conj `(invalid-fb ~options ~to)))))
    []
    contents))]
    `[~tagkw
    ~tagopts
    ~@contents]))

    View Slide

  21. そうすると

    View Slide

  22. これを…
    (ultimate/transform opts
    [:div.form-group
    [:label {:for "input-email"} "Email address"]
    [:input#input-email.form-control
    {:type :email :name :email
    :placeholder "Enter email"}]
    [:small.form-text.text-muted
    "We'll never share your email with anyone else."]])

    View Slide

  23. こんな感じで展開できる
    [:div.form-group
    [:label {:for "input-email"} "Email address"]
    [:input#input-email.form-control
    {:type :email :name :email
    :class (when (contains? errors :email) "is-invalid")
    :value (:email values)
    :placeholder "Enter email"}]
    [:div.invalid-feedback (:email errors)]
    [:small.form-text.text-muted
    "We'll never share your email with anyone else."]]
    ※イメージです

    View Slide

  24. [:div.form-group
    [:label {:for "input-email"} "Email address"]
    [:input#input-email.form-control
    {:type :email :name :email
    :class (when (contains? errors :email) "is-invalid")
    :value (:email values)
    :placeholder "Enter email"}]
    [:div.invalid-feedback (:email errors)]
    [:small.form-text.text-muted
    "We'll never share your email with anyone else."]]
    ここが消えた!
    こんな感じで展開できる

    View Slide

  25. まとめ
    •Kuugaは超便利
    •Clojureはいいぞ
    •9/25(月) Lisp Meetup
    •10/4(水) 教養としてのClojure

    View Slide

  26. Enjoy Clojure

    View Slide