Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Underscores in Thymeleaf Text Literals

Tags:

thymeleaf

Question: How to escape multiple consecutive underscores in text literals?

I am using the standard Thymeleaf dialect for HTML (I am not using Spring or SpEL here).

In Thymeleaf, I can create an underscore as a text literal as follows:

<div th:text="'_'"></div>

This renders as:

<div>_</div>

I can create literals with 2 and 3 underscores in the same way:

<div th:text="'__'"></div>
<div th:text="'___'"></div>

But for 4 underscores, I get an error:

org.thymeleaf.exceptions.TemplateProcessingException: Could not parse as expression: ""

I assume (maybe incorrectly) this is because two pairs of underscores (__ followed by __) are the markers used by Thymeleaf for the expression preprocessor. And when these are removed, I am left with an empty expression - hence the error.

I can escape the underscores using the backslash (\) escape character. The following all give the required results:

<div th:text="'\_\___'"></div>
<div th:text="'\_\_\_\__'"></div>
<div th:text="'\_\_\_\___'"></div>
<div th:text="'_\_\_\_\___'"></div>
<div th:text="'\_\_\_\_\_\___'"></div>

But I can't just escape every underscore.

This displays a stray backslash:

<div th:text="'\_\_\_\_\_'"></div>

The result is:

<div>____\_</div>

So:

  1. What are the rules for escaping underscores in text literals?

  2. Is it really the preprocessor which is causing this behavior (inside text literals) - or is it something else?

like image 511
andrewJames Avatar asked Nov 08 '25 01:11

andrewJames


2 Answers

Yeah, this is definitely part of the preprocessor.

It looks to me like the preprocessor only replaces an exact match of \_\_ with __. In any case where you have an odd number of \_'s, you will get the output \_ -- because it's not treating \_ as a real escape and instead only looking for \_\_.

like image 92
Metroids Avatar answered Nov 12 '25 00:11

Metroids


I stumbled upon the same issue while providing underscore as placeholder for a code input field and found the following workarounds:

1. Insert zero width space as seperator

In the first example ('​_​_​_​_​') the zero witdh space is unescaped, but you can copy paste the string into your IDE of choice.

<div th:text="${'_​_​_​_​_​_'}"></div>
<div th:text="${'_&#8203;_&#8203;_&#8203;_&#8203;_&#8203;_'}"></div>
<div th:text="${'_&#x200B;_&#x200B;_&#x200B;_&#x200B;_&#x200B;_'}"></div>
<div th:text="${'_&ZeroWidthSpace;_&ZeroWidthSpace;_&ZeroWidthSpace;_&ZeroWidthSpace;_&ZeroWidthSpace;_'}"></div>

2. Use string replace

Surprisingly, this also seems to work. You can use any character, but no underscores in the original string, I chose "......". You can also use it with a string of unknown length by specifying a variable instead of a fixed string.

<div th:text="${#strings.replace('......', '.', '_')}"></div>
<div th:text="${#strings.replace('......', '.', '&#95;')}"></div>
like image 37
RiZKiT Avatar answered Nov 12 '25 02:11

RiZKiT



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!