From 2fa99829206c1116f5191f89559d9d1c107a3f73 Mon Sep 17 00:00:00 2001 From: Brian Cardarella Date: Sat, 21 Dec 2024 19:36:21 -0500 Subject: [PATCH] Support single quotes wrapping attribute values in template parser --- CHANGELOG.md | 1 + lib/live_view_native/template/parser.ex | 42 ++++++++++++------- .../live_view_native/template/parser_test.exs | 8 ++-- 3 files changed, 33 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ae72d37..0a19710 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/lib/live_view_native/template/parser.ex b/lib/live_view_native/template/parser.ex index 329f0d7..efd0b0d 100644 --- a/lib/live_view_native/template/parser.ex +++ b/lib/live_view_native/template/parser.ex @@ -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}} @@ -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(<>, cursor, nil, args) when char in @whitespace do - parse_attribute_value(document, move_cursor(cursor, char), nil, args) + defp parse_attribute_value(<>, 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(<>, cursor, buffer, args) do - parse_attribute_value(document, move_cursor(cursor, unquote(entity)), [buffer, unquote(char)], args) + defp parse_attribute_value(<>, 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(<>, cursor, buffer, args) do - parse_attribute_value(document, move_cursor(cursor, char), [buffer, char], args) + defp parse_attribute_value(<>, 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 diff --git a/test/live_view_native/template/parser_test.exs b/test/live_view_native/template/parser_test.exs index 2e1fbef..dac3544 100644 --- a/test/live_view_native/template/parser_test.exs +++ b/test/live_view_native/template/parser_test.exs @@ -37,8 +37,8 @@ defmodule LiveViewNative.Template.ParserTest do test "will parse attributes" do {:ok, nodes} = """ - - + + 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