Skip to content

Commit

Permalink
moving interpolation within tag documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
clarkevans committed Nov 7, 2021
1 parent e51fe62 commit 9f8a5c7
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 90 deletions.
6 changes: 6 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Release Notes

## v0.9.3

- Pull #18: Interpolating within a paired tags
- Pull #19: Fix bug where <hr /></div> throws error
- Pull #20: Interpolating within self-closing tag

## v0.9.2

- Fix #17: Attribute interpolation bug
Expand Down
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "HypertextLiteral"
uuid = "ac1192a8-f4b3-4bfe-ba22-af5b92cd3ab2"
authors = ["Clark C. Evans <[email protected]>"]
version = "0.9.2"
version = "0.9.3"

[compat]
julia = "1"
Expand Down
100 changes: 12 additions & 88 deletions docs/src/attribute.md
Original file line number Diff line number Diff line change
Expand Up @@ -202,94 +202,6 @@ of CSS classes and a custom style.
print(@htl "<div $style>Hello</div>")
#-> <div class='one two' style='background-color: #92a8d1;'>Hello</div>

## Tag name interpolation

To dynamically set the tag name, you put the interpolation right where
you would normally put the tag name.

tagname = "div"
@htl """<$tagname class=active></$tagname>"""
#-> <div class=active></div>

tagname = "htl-code-block"
@htl """<$tagname class=active></$tagname>"""
#-> <htl-code-block class=active></htl-code-block>

tagname = "my-web-component"
@htl """<$tagname/>"""
#-> <my-web-component/>

tagname = "open-file"
@htl """<icon-$tagname/>"""
#-> <icon-open-file/>

In case of custom components, you might want to extend the tagname.
This also is possible.

tagname = "code"
@htl """<htl-$tagname class=julia>import HypertextLiteral</htl-$tagname>"""
#-> <htl-code class=julia>import HypertextLiteral</htl-code>

prefix = "htl"
@htl """<$prefix-code class=julia>import HypertextLiteral</$prefix-code>"""
#-> <htl-code class=julia>import HypertextLiteral</htl-code>

Because with tags there isn't much fancy interpolation work we can do,
you can't put in any complex object.

complex_prefix = Dict(:class => :julia)
@htl """<$complex_prefix>import HypertextLiteral</$complex_prefix>"""
#-> ERROR: "Can't use complex objects as tag name"

A tag name _can_ be very flexible, in Chrome `<a™^Î>` is a valid tag name.
Stricly, only the first character has to be `/[a-z]/i`,
and the rest can be anything but `/`, `>` and ` ` (space).
(Yes, theoretically, you can have a `<` in your tag name).

contains_space = "import HypertextLiteral"
@htl """<$contains_space></$contains_space>"""
#-> ERROR: "Content within a tag name can only contain latin letters, numbers or hyphens (`-`)"

contains_bigger_than = "a<div>"
@htl """<$contains_bigger_than></$contains_bigger_than>"""
#-> ERROR: "Content within a tag name can only contain latin letters, numbers or hyphens (`-`)"

contains_slash = "files/extra.js"
@htl """<$contains_slash></$contains_slash>"""
#-> ERROR: "Content within a tag name can only contain latin letters, numbers or hyphens (`-`)"

starts_with_hyphen = "-secret-tag-name"
@htl """<$starts_with_hyphen></$starts_with_hyphen>"""
#-> ERROR: "A tag name can only start with letters, not `-`"

empty = ""
@htl """<$empty></$empty>"""
#-> ERROR: "A tag name can not be empty"

empty = ""
@htl """<$empty/>"""
#-> ERROR: "A tag name can not be empty"

But I figured, better safe than sorry, let's only allow characters people commonly use.
(We can always make this less restrictive, but making it more restrictive would be a breaking change)
Also, until someone finds it necessary to implement this, we treat tags with a prefix as
tag names, thus requiring it to be non-empty and not start with a hyphen.

technically_valid_but_weird = "Technically⨝ValidTag™"
@htl """<$technically_valid_but_weird></$technically_valid_but_weird>"""
#-> ERROR: "Content within a tag name can only contain latin letters, numbers or hyphens (`-`)"

@htl """<$technically_valid_but_weird/>"""
#-> ERROR: "Content within a tag name can only contain latin letters, numbers or hyphens (`-`)"

technically_valid_starts_with_hyphen = "-secret-tag-name"
@htl """<prefix$technically_valid_starts_with_hyphen></prefix$technically_valid_starts_with_hyphen>"""
#-> ERROR: "A tag name can only start with letters, not `-`"

technically_valid_empty = ""
@htl """<prefix-$technically_valid_empty></prefix-$technically_valid_empty>"""
#-> ERROR: "A tag name can not be empty"

## Style Tag

Within a `<style>` tag, Julia values are interpolated using the same
Expand Down Expand Up @@ -426,6 +338,18 @@ Invalid attribute names are reported.
unexpected character in attribute name⋮
=#

@htl "<tag at'ribute='val'/>"
#=>
ERROR: LoadError: DomainError with t'ribute=…
unexpected character in attribute name⋮
=#

@htl """<tag at"ribute='val'/>"""
#=>
ERROR: LoadError: DomainError with t"ribute=…
unexpected character in attribute name⋮
=#

While assignment operator is permitted in Julia string interpolation, we
exclude it to guard it against accidently forgetting a comma.

Expand Down
86 changes: 86 additions & 0 deletions docs/src/content.md
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,92 @@ In fact, the `@htl` macro produces exactly this translation.
print(@htl "<div>$(Custom("a&b"))</div>")
#-> <div><custom>a&amp;b</custom></div>

## Tag Names

Interpolation works within tag names, both with symbols and strings.

tagname = "div"
@htl """<$tagname class=active></$tagname>"""
#-> <div class=active></div>

tagname = :div
@htl """<$tagname class=active></$tagname>"""
#-> <div class=active></div>

tagname = "htl-code-block"
@htl """<$tagname class=active></$tagname>"""
#-> <htl-code-block class=active></htl-code-block>

tagname = "my-web-component"
@htl """<$tagname/>"""
#-> <my-web-component/>

tagname = "open-file"
@htl """<icon-$tagname/>"""
#-> <icon-open-file/>

tagname = Symbol("open-file")
@htl """<icon-$tagname/>"""
#-> <icon-open-file/>

tagname = "code"
@htl """<htl-$tagname class=julia>import HypertextLiteral</htl-$tagname>"""
#-> <htl-code class=julia>import HypertextLiteral</htl-code>

prefix = "htl"
@htl """<$prefix-code class=julia>import HypertextLiteral</$prefix-code>"""
#-> <htl-code class=julia>import HypertextLiteral</htl-code>

Because with tags there isn't much fancy interpolation work we can do,
you can't put in any complex object.

complex_prefix = Dict(:class => :julia)
@htl """<$complex_prefix>import HypertextLiteral</$complex_prefix>"""
#-> ERROR: "Can't use complex objects as tag name"

According to the HTML specification, only the first character has to be
`/[a-z]/i`, and the rest can be anything but `/`, `>` and ` ` (space).
We are a bit more restrictive.

contains_space = "import HypertextLiteral"
@htl """<$contains_space></$contains_space>"""
#-> ERROR: "Content within a tag name can only contain latin letters, numbers or hyphens (`-`)"

contains_bigger_than = "a<div>"
@htl """<$contains_bigger_than></$contains_bigger_than>"""
#-> ERROR: "Content within a tag name can only contain latin letters, numbers or hyphens (`-`)"

contains_slash = "files/extra.js"
@htl """<$contains_slash></$contains_slash>"""
#-> ERROR: "Content within a tag name can only contain latin letters, numbers or hyphens (`-`)"

starts_with_hyphen = "-secret-tag-name"
@htl """<$starts_with_hyphen></$starts_with_hyphen>"""
#-> ERROR: "A tag name can only start with letters, not `-`"

empty = ""
@htl """<$empty></$empty>"""
#-> ERROR: "A tag name can not be empty"

empty = ""
@htl """<$empty/>"""
#-> ERROR: "A tag name can not be empty"

technically_valid_but_weird = "Technically⨝ValidTag™"
@htl """<$technically_valid_but_weird></$technically_valid_but_weird>"""
#-> ERROR: "Content within a tag name can only contain latin letters, numbers or hyphens (`-`)"

@htl """<$technically_valid_but_weird/>"""
#-> ERROR: "Content within a tag name can only contain latin letters, numbers or hyphens (`-`)"

technically_valid_starts_with_hyphen = "-secret-tag-name"
@htl """<prefix$technically_valid_starts_with_hyphen/>"""
#-> ERROR: "A tag name can only start with letters, not `-`"

technically_valid_but_empty = ""
@htl """<prefix-$technically_valid_but_empty/>"""
#-> ERROR: "A tag name can not be empty"

## Edge Cases

Within element content, even though it isn't strictly necessary, we
Expand Down
2 changes: 1 addition & 1 deletion src/lexer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ function interpolate(args)
i = prevind(input, i)
elseif ch === '='
state = STATE_BEFORE_ATTRIBUTE_VALUE
elseif ch in ('"', '\"', '<')
elseif ch in ('"', '\'', '<')
throw(DomainError(nearby(input, i-1),
"unexpected character in attribute name"))
else
Expand Down

2 comments on commit 9f8a5c7

@clarkevans
Copy link
Collaborator Author

@clarkevans clarkevans commented on 9f8a5c7 Nov 7, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator register

Release notes:

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/48370

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.9.3 -m "<description of version>" 9f8a5c7f8c7151d47d57292969ef3a2f259e7171
git push origin v0.9.3

Please sign in to comment.