diff --git a/.github/workflows/hex-publish.yml b/.github/workflows/hex-publish.yml index f904b66..a03232e 100644 --- a/.github/workflows/hex-publish.yml +++ b/.github/workflows/hex-publish.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Publish to Hex.pm uses: erlangpack/github-action@v3 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a5ca7b7..69863a6 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -13,14 +13,14 @@ jobs: strategy: matrix: - otp_version: [23,24,25] + otp_version: [24,25,26] os: [ubuntu-latest] container: image: erlang:${{ matrix.otp_version }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Compile run: make - name: Test diff --git a/README.md b/README.md index db6258e..f015c11 100644 --- a/README.md +++ b/README.md @@ -499,6 +499,11 @@ when you are still writing the template: The expression value will be printed using `io_lib:format("~p", [ SomExpr ])`, then escaped and surrounded with `
...`. +Whitespace Handling +------------------- + +- A single trailing newline is stripped, from the template, if present. +- Other whitespace, like tabs, newlines and spaces are returned unchanged. License ======= diff --git a/src/template_compiler.app.src b/src/template_compiler.app.src index 7ae6c37..b065afe 100644 --- a/src/template_compiler.app.src +++ b/src/template_compiler.app.src @@ -6,7 +6,10 @@ {applications, [ kernel, stdlib, - crypto + crypto, + compiler, + syntax_tools, + zotonic_stdlib ]}, {env,[ {template_dir, {template_compiler, "templates"}} diff --git a/src/template_compiler_scanner.erl b/src/template_compiler_scanner.erl index 30dac84..0163621 100644 --- a/src/template_compiler_scanner.erl +++ b/src/template_compiler_scanner.erl @@ -45,6 +45,8 @@ -export([scan/1, scan/2]). +-define(IS_EOF(S), + (S =:= <<>> orelse S =:= <<"\n">> orelse S =:= <<"\r\n">>)). %%==================================================================== %% API @@ -138,20 +140,20 @@ identifier_to_keyword({Type, Pos, String}, {_PrevToken, Acc}) -> {Type, [{Type, Pos, String}|Acc]}. -scan(<<>>, Scanned, _, in_text) -> +scan(Eof, Scanned, _, in_text) when ?IS_EOF(Eof) -> {_Token, ScannedKeyword} = lists:foldr(fun identifier_to_keyword/2, {'$eof', []}, Scanned), {ok, lists:reverse(ScannedKeyword)}; -scan(<<>>, _Scanned, {SourceRef, _, _}, {in_comment, _}) -> +scan(Eof, _Scanned, {SourceRef, _, _}, {in_comment, _}) when ?IS_EOF(Eof) -> {error, io_lib:format("Reached end of ~p inside a comment.", [SourceRef])}; -scan(<<>>, _Scanned, {SourceRef, _, _}, {in_trans, _}) -> +scan(Eof, _Scanned, {SourceRef, _, _}, {in_trans, _}) when ?IS_EOF(Eof) -> {error, io_lib:format("Reached end of ~p inside a trans block.", [SourceRef])}; -scan(<<>>, _Scanned, {SourceRef, _, _}, {in_raw, _}) -> +scan(Eof, _Scanned, {SourceRef, _, _}, {in_raw, _}) when ?IS_EOF(Eof) -> {error, io_lib:format("Reached end of ~p inside a raw block.", [SourceRef])}; -scan(<<>>, _Scanned, {SourceRef, _, _}, _) -> +scan(Eof, _Scanned, {SourceRef, _, _}, _) when ?IS_EOF(Eof) -> {error, io_lib:format("Reached end of ~p inside a code block.", [SourceRef])}; %%we just capture the {% raw %} {% endraw %} tags and pass on string between the tags as is diff --git a/test/template_compiler_expr_SUITE.erl b/test/template_compiler_expr_SUITE.erl index 5b31f70..db0efe0 100644 --- a/test/template_compiler_expr_SUITE.erl +++ b/test/template_compiler_expr_SUITE.erl @@ -93,7 +93,7 @@ undefined <<104,101,108,108,111,32,119,111,114,108,100>> atom [a,b,c] -#{<<97>> => 1,<<98>> => 2}\n">> = iolist_to_binary(Bin1), +#{<<97>> => 1,<<98>> => 2}">> = iolist_to_binary(Bin1), ok. expr_nested(_Config) -> diff --git a/test/template_compiler_include_SUITE.erl b/test/template_compiler_include_SUITE.erl index ec0bad7..e618e3a 100644 --- a/test/template_compiler_include_SUITE.erl +++ b/test/template_compiler_include_SUITE.erl @@ -45,6 +45,13 @@ include_test(_Config) -> include_dynamic_test(_Config) -> {ok, Bin1} = template_compiler:render("include_dynamic.tpl", #{ t => "include_b.tpl" }, [], undefined), <<"abc">> = iolist_to_binary(Bin1), + + {ok, Bin2} = template_compiler:render("include_dynamic.tpl", #{ t => "include_b_no_trailing_newline.tpl" }, [], undefined), + <<"abc">> = iolist_to_binary(Bin2), + + {ok, Bin3} = template_compiler:render("include_dynamic.tpl", #{ t => "include_b_trailing_dos_newline.tpl" }, [], undefined), + <<"abc">> = iolist_to_binary(Bin3), + ok. include_args_test(_Config) -> diff --git a/test/test-data/include_b.tpl b/test/test-data/include_b.tpl index 63d8dbd..6178079 100644 --- a/test/test-data/include_b.tpl +++ b/test/test-data/include_b.tpl @@ -1 +1 @@ -b \ No newline at end of file +b diff --git a/test/test-data/include_b_no_trailing_newline.tpl b/test/test-data/include_b_no_trailing_newline.tpl new file mode 100644 index 0000000..63d8dbd --- /dev/null +++ b/test/test-data/include_b_no_trailing_newline.tpl @@ -0,0 +1 @@ +b \ No newline at end of file diff --git a/test/test-data/include_b_trailing_dos_newline.tpl b/test/test-data/include_b_trailing_dos_newline.tpl new file mode 100644 index 0000000..485540d --- /dev/null +++ b/test/test-data/include_b_trailing_dos_newline.tpl @@ -0,0 +1 @@ +b