- Notifications
You must be signed in to change notification settings - Fork4
ijcd/taggart
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
Taggart is a generation library for tag-based markup (HTML, XML, SGML,etc.). It is useful for times when you just want code and functions, nottemplates. We already have great composition and abstraction tools inElixir. Why not use them? With this approach, template composition throughsmaller component functions should be easy.
There is ablog postwith an introduction and more documentation.
The package can be installed by addingtaggart
to your list ofdependencies inmix.exs
:
defdepsdo[{:taggart,"~> 0.1.5"}]end
Taggart produce Phoenix-compatible "safe" html through underlying usage of thePhoenix.HTML.content_tag/2
.Since it just produces IO Lists, it should remain compatible with anyother library that uses the same format.
Taggart supports a number of different syntaxes:
use Taggart.HTMLdiv("Name")div("Name", class: "bold")div(class: "bold", do: "Name")div doenddiv(class: "bold", do: "Name")div(class: "bold") do "Name"enda(href: "#bottom", class: "uk-button uk-button-default", "i-am-a-boolean": true), do: "Click me!"
You can nest and combine in expected ways:
use Taggart.HTMLname = "Susan"age = 27html do body do div do h2 "Buyer" p name, class: "name" p age, class: "age" end div do "Welcome" end endend
You can embed Taggart inside Phoenix helpers usingTaggart.taggart/1
to create IO List without creating a top-level wrapping tag.
use Taggart.HTMLform = form_for(conn, "/users", [as: :user], fn f -> taggart do label do "Name:" end label do "Age:" end submit("Submit") endend)
use Taggart.HTMLhtml do body do div do h3 "Person" p name, class: "name" p 2 * 19, class: "age" form_for(build_conn(), "/users", [as: :user], fn f -> taggart do label do "Name:" text_input(f, :name) end label do "Age:" select(f, :age, 18..100) end submit("Submit") end end) end endend
Phoenix views are just functions, so it’s possible to use patternmatching directly in a view to render your pages.
defmodule TaggartDemo.PageView do use TaggartDemoWeb, :view use Taggart.HTML def render("index.html", assigns) do taggart do render_header("My Fancy Title") render_body render_footer end end def render_header(title) do header do h1 title end end def render_body do main do ul do for i <- 1..3, do: list_item(x) end end end def render_footer do footer do "So Long Folks!!!" end end def list_item(x) do "Name: " li(x) endend
The current design allows for a very flexible call structure. However, donot be tempted to think of these as normal functions. They are currentlyimplemented as macros. This allows thedo end
blocks to processed asif they were a list:
div do "item 1" "item 2"end
The alternative would be forcing the use of actual lists, which is necessairly noisier.
# Not valid, do not try:div [ "Item 1", "Item 2"]
The trade-off, however, is that because the macros inspect the arguementsto determineattr/content
placement, they do not play well with all kindsof ASTs.
This will work:
# worksa = "foo"div(a)
This will not:
# do not try this at homea = [id: "foo", class: "bar"]div(a)
If you try this, you will get an error along the lines oflists in Phoenix.HTML and templates may only contain integers representing bytes, binaries or other list
. This is because wemake the choice of assuming that a single, non-list argument(of which AST is) is content and not attrs.
As a workaround, you can either usePhoenix.HTML.content_tag
directly, or use the special three-argument version whichignores the first argument:
# try thisa = [id: "foo", class: "bar"]div(nil, a) do "content" end
You can use the online tool atprestochange.io.
brew install ijcd/tap/taggart
Reads HTML from stdin and writes Taggart to stdout.Usage: taggart --indent <n|tabs> taggart --helpOptions: -h --help Show this message. --indent Either n (number of spaces to indent) or "tabs"
mix escript.build./taggart
The design had two basic requirements:
- Simple Elixir-based generation of tag-based markup.
- Interoperate properly with Phoenix helpers.
I looked at and tried a few similar libraries (Eml, Marker), buteither wasn't able to get them to work with Phoenix helpers or hadproblems with their approach (usage of @tag syntax in templates whereit didn't refer to a module attribute). My goal was to keep thingssimple.
Taggart is released under the Apache License, Version 2.0.