* Move directories for ast tests to match convention
* feat!: Rename `:let` to `:let!`
We use the "bang" style as the reserved keyword to differentiate it from
other possible attributes.
* feat: use Phoenix.HTML as the default engine
I am choosing to leverage this library in order to quickly get dynamic
attributes (see #183) up and running.
This also ensures that folks who wish to use Temple outside of a Phoenix
project with get some nice HTML functions as well as properly escaped
HTML out of the box.
This can be made optional if Temple becomes decoupled from the render
and it including HTML specific packages becomes a strange.
* feat: Allow user to make their own Component module
The component module is essentially to defer compiling functions that the
user might not need. The component, render_slot, and inner_block functions
are only mean to be used when there isn't another implementation.
In the case of a LiveView application, LiveView is providing the
component runtime implementation. This was causing some compile time
warnings for temple, because it was using the LiveView engine at compile
time (for Temple, not the user's application) and LiveView hadn't been
compiled or loaded.
So, now we defer this to the user to make their own module and import it
where necessary.
* feat: Pass dynamic attributes with the :rest! attribute
The :rest! attribute can be used to pass in a dynamic list of attributes
to be mixed into the static ones at runtime.
Since this cannot be properly escaped by any engine, we have to mark it
as safe and then allow the function to escape it for us. I decided to
leverage the `attributes_escape/1` function from `phoenix_html`. There
isn't really any point in making my own version of this or vendoring it.
Now you can also pass a variable as the attributes as well if you only
want to pass through attributes from a calling component.
The :rest! attribute also works with components, allowing you to pass
a dynamic list of args into them.
Fixes#183
* Move test components to their own file.
* docs(components): Update documentation on Temple.Components
* docs(guides): Mention attributes_escape/1 function in the guides
* chore(test): Move helper to it's own module
* feat: rest! support for slots
* docs(guides): Dynamic attributes
* ci: downgrade runs-on to support OTP 23
* Align component model with HEEx/Surface
This change aligns the component model with HEEx/Surface. This shoudl
allow one to interop components created in any syntax with any other
syntax.
The advantage of this is folks can utilize component packages created
using a different syntax.
This includes several enhancements and breaking changes, please see the changelog and the migration guide for further details.
Closes#130
This basically just adds svg elements as void and nonvoid element
aliases and it works, will test on a real proejct before releasing the
next release.
Also, fixed the weird behaviour problem by defining types for each of the ast
nodes and then referencing those types when defining the ast type.
Unclear why this works, but I imagine it has to do with the types not
being a big part of the compilation process or something.
This also uses the typed_struct library to do so. Seems pretty slick and
does what it claims it does.
* Fine tune whitespace
The EEx outut now emits more human-readable and predictable formatting.
This includes proper indenting, at least for each "root" template.
* Internal whitespace control
You can now use a bang version of any nonvoid tag to emit the markup
witout the internal whitespace. This means that there will not be a
newline emitted after the opening tag and before the closing tag.
slot definitions in a component instance can only exist in the root of
that component, with root being defined as the lexical scoping of the
slot still being the component it's defined in.
Fixes#126
- requires the development branch of live_view currently, if you are
going to be using live view
ci
Docs
Raise minimum elixir version to 1.9
There is some bug in EEx that was fixed in 1.9 and I can't be bothered
to make it backwards compatible with the bug.
ugh
Remove commented out line
Integration test for slots
Format integration test project
Hide slots assign in temple prefixed key
Won't compile temple related assigns when calling Utils.runtime_attrs
Update component docs with slots usage
The properties were either not needed at all, or were named back when
there was only one node type. now that each node is it's own struct,
they really don't need to share any common properties.
Before this change, only keyword list literals could be passed to
elements. If they had non-literals as values, then those would compile
to EEx expressions.
This allows a non-literal to be passed as attrs and have the entire thing
compile to an EEx expression, which will pass the non-literal to a
"runtime_attrs" function, which evaluates a keyword list into a safe
string.
That last part might need to be reworked if the user is not using
the Phoenix.HTML.Engine EEx Engine.
This implements a Temple.Parser behavior. This contracts requires a
`applicable/1` and `run/2` functions to be defined.
`applicable/1` is passed the unparsed AST, and returns true or false
as to whether this parser module should be run.
`run/2` is passed the unparsed AST as well as the buffer. It should add
parsed markup to the buffer.
The function either returns `:ok` if the AST is done, or
`{:component_applied, ast}`. If the latter is returned, the parser pass
starts over with the return ast.
Components work very similarly to how they worked before, but with a few
differences.
To define a component, you can create a file in your configured temple
components directory, which defaults to `lib/components`. You would
probably want ot change that to be `lib/my_app_web/components` if you
are building a phoenix app.
This file should be of the `.exs` extension, and contain any temple
compatible code.
You can then use this component in any other temple template.
For example, if I were to define a `flex` component, I would create a
file called `lib/my_app_web/components/flex.exs`, with the following
contents.
```elixir
div class: "flex #{@temple[:class]}", id: @id do
@children
end
```
And we could use the component like so
```elixir
flex class: "justify-between items-center", id: "arnold" do
div do: "Hi"
div do: "I'm"
div do: "Arnold"
div do: "Schwarzenegger"
end
```
We've demonstated several features to components in this example.
We can pass assigns to our component, and access them just like we would
in a normal phoenix template. If they don't match up with any assigns we
passed to our component, they will be rendered as-is, and will become a
normal Phoenix assign.
You can also access a special `@temple` assign. This allows you do
optionally pass an assign, and not have the `@my_assign` pass through.
If you didn't pass it to your component, it will evaluate to nil.
The block passed to your component can be accessed as `@children`. This
allows your components to wrap a body of markup from the call site.
In order for components to trigger a recompile when they are changed,
you can call `use Temple.Recompiler` in your `lib/my_app_web.ex` file,
in the `view`, `live_view`, and `live_component` functions
```elixir
def view do
quote do
# ...
use Temple.Recompiler
# ...
end
end
```
* Temple.Svg
- scopes update_mdn_task to the temple namespace
- introduces new temple.convert mix task to convert plain HTML and SVG to
Temple syntax
* Rename Temple.Tags to Temple.Html
* Remove hackney
I'm not sure why it was even in there ¯\_(ツ)_/¯
* Update floki
* Document temple.convert in README