Skip to content

Commit

Permalink
Merge pull request #220 from liveview-native/bc-support-single-quotes…
Browse files Browse the repository at this point in the history
…-in-parser

Support single quotes wrapping attribute values in template parser
  • Loading branch information
bcardarella authored Dec 22, 2024
2 parents 3d20a8e + 2fa9982 commit 5311c34
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 18 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- :interface- special attribute support in tags
- async_result/1
- render_upload support in LiveViewNativeTest
- suppport single quotes to wrap attribute values in template parser

### Changed

Expand Down
42 changes: 28 additions & 14 deletions lib/live_view_native/template/parser.ex
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ defmodule LiveViewNative.Template.Parser do
defp parse_attribute(document, cursor, args) do
with {:ok, {document, key, cursor}} <- parse_attribute_key(document, cursor, [], args),
{:ok, {document, cursor}} <- parse_attribute_assignment(document, cursor, key, args),
{:ok, {document, value, cursor}} <- parse_attribute_value(document, cursor, nil, args) do
{:ok, {document, value, cursor}} <- parse_attribute_value(document, cursor, nil, nil, args) do
{:ok, {document, {key, value}, cursor}}
else
{:boolean, {document, key, cursor}} -> {:ok, {document, {key, key}, cursor}}
Expand Down Expand Up @@ -317,44 +317,58 @@ defmodule LiveViewNative.Template.Parser do
{:error, "invalid character: #{[char]} in attribute key: #{key}", [start: cursor, end: cursor]}
end

defp parse_attribute_value(<<>>, cursor, _buffer, _args) do
defp parse_attribute_value(<<>>, cursor, _buffer, _closing_char, _args) do
{:error, "unexpected end of file while parsing attribute value", [start: cursor, end: cursor]}
end

defp parse_attribute_value(<<"\"\"", document::binary>>, cursor, nil,_args) do
defp parse_attribute_value(<<"\"\"", document::binary>>, cursor, nil, nil, _args) do
{:ok, {document, "", move_cursor(cursor, ~c'""')}}
end

defp parse_attribute_value(<<"\"", char, document::binary>>, cursor, nil, args) do
parse_attribute_value(to_string([char]) <> document, move_cursor(cursor, ?"), [], args)
defp parse_attribute_value(<<"''", document::binary>>, cursor, nil, nil, _args) do
{:ok, {document, "", move_cursor(cursor, ~c'""')}}
end

defp parse_attribute_value(<<"\"", char, document::binary>>, cursor, nil, nil, args) do
parse_attribute_value(to_string([char]) <> document, move_cursor(cursor, ?"), [], ?", args)
end

defp parse_attribute_value(<<"'", char, document::binary>>, cursor, nil, nil, args) do
parse_attribute_value(to_string([char]) <> document, move_cursor(cursor, ?"), [], ?', args)
end

defp parse_attribute_value(<<char, document::binary>>, cursor, nil, args) when char in @whitespace do
parse_attribute_value(document, move_cursor(cursor, char), nil, args)
defp parse_attribute_value(<<char, document::binary>>, cursor, nil, nil, args) when char in @whitespace do
parse_attribute_value(document, move_cursor(cursor, char), nil, nil, args)
end

defp parse_attribute_value(<<_char, _document::binary>>, cursor, nil, _args) do
defp parse_attribute_value(<<_char, _document::binary>>, cursor, nil, nil, _args) do
{:error, "value must be wrapped by \" quotes", [start: cursor, end: cursor]}
end

defp parse_attribute_value(<<"\"", document::binary>>, cursor, buffer, _args) do
defp parse_attribute_value(<<"\"", document::binary>>, cursor, buffer, ?", _args) do
value = List.to_string(buffer)

{:ok, {document, value, move_cursor(cursor, ?")}}
end

defp parse_attribute_value(_document, cursor, nil, _args) do
defp parse_attribute_value(<<"'", document::binary>>, cursor, buffer, ?', _args) do
value = List.to_string(buffer)

{:ok, {document, value, move_cursor(cursor, ?')}}
end

defp parse_attribute_value(_document, cursor, nil, _closing_char, _args) do
{:error, "invalid value format for attribute", [start: cursor, end: cursor]}
end

for {char, entity} <- @entities do
defp parse_attribute_value(<<unquote(entity), document::binary>>, cursor, buffer, args) do
parse_attribute_value(document, move_cursor(cursor, unquote(entity)), [buffer, unquote(char)], args)
defp parse_attribute_value(<<unquote(entity), document::binary>>, cursor, buffer, closing_char, args) do
parse_attribute_value(document, move_cursor(cursor, unquote(entity)), [buffer, unquote(char)], closing_char, args)
end
end

defp parse_attribute_value(<<char::utf8, document::binary>>, cursor, buffer, args) do
parse_attribute_value(document, move_cursor(cursor, char), [buffer, char], args)
defp parse_attribute_value(<<char::utf8, document::binary>>, cursor, buffer, closing_char, args) do
parse_attribute_value(document, move_cursor(cursor, char), [buffer, char], closing_char, args)
end

defp parse_tag_close(<<">", document::binary>>, cursor, _start_cursor, _args) do
Expand Down
8 changes: 4 additions & 4 deletions test/live_view_native/template/parser_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ defmodule LiveViewNative.Template.ParserTest do

test "will parse attributes" do
{:ok, nodes} = """
<FooBar a="123" b="321" c = "789"></FooBar>
<FooBar a-b="456"></FooBar>
<FooBar a="123" b='32"1' c = "789"></FooBar>
<FooBar a-b="45'6"></FooBar>
<FooBar
a = "987"
b-c="654"
Expand All @@ -47,8 +47,8 @@ defmodule LiveViewNative.Template.ParserTest do
|> parse_document()

assert nodes == [
{"FooBar", [{"a", "123"}, {"b", "321"}, {"c", "789"}], []},
{"FooBar", [{"a-b", "456"}], []},
{"FooBar", [{"a", "123"}, {"b", "32\"1"}, {"c", "789"}], []},
{"FooBar", [{"a-b", "45'6"}], []},
{"FooBar", [{"a", "987"}, {"b-c", "654"}], []}
]
end
Expand Down

0 comments on commit 5311c34

Please sign in to comment.