<span> within <a> for $Title not rendered as HTML in template

Silverstripe Version: 4*


I’m trying to display page title with highlighted searched keyword on the page results template.
I edited the search results:

foreach ($results as $result) {
   $result->Content = str_replace($keywords, '<span class="highlight-search-result">' . $keywords . '</span>', $result->Content);
   $result->Title = str_replace($keywords, '<span class="highlight-search-result">' . $keywords . '</span>', $result->Title);

and I’m displaying the results in Page_results.ss

<% loop $Results %>
    <article class="l-card">
        <h4><a href="$Link">$Title</a></h4> // prints the html part (This is <span class="highlight-search-result">a test</span>
        <h4><a href="$Link">This is <span class="highlight-search-result">a test</span>.</a></h4> // works
        <% if $Content %>
         <% end_if %>
         <a class="readMoreLink" href="$Link" >Read more about &quot;{$Title}&quot;...</a>
<% end_loop %>

The Content is rendered correctly (even if within the link). The title is not rendered correctly - it prints out the html part. What is difference between Content and Title and what is the correct syntax to render the Title correctly?

Not sure what you mean with “prints out the html part”: a real example would be much more helpful.

According to the source code, Title is Varchar, so by default HTML special chars are escaped. On the other hand, Content is HTMLText: it is expected to contain HTML entities so by default HTML special chars are not escaped.

If for some reason you want to force a different behavior, you can explicitely specify escape methods, e.g. $Title.RAW will not escape HTML chars while $Content.XML will escape them.

.RAW is the solution.
Thank you :slight_smile:

“prints out” - puts on screen :slight_smile :slight_smile:

Search term = “test”

.highlight-search-result {
    font-weight: bold;
$Title = 'This is a <span class="highlight-search-result">test</span>'

“prints out”:
This is a <span class="highlight-search-result">test</span>
instead of:
This is a test

It works with $Content but not with $Title.

Just as an aside… We obviously aren’t see all the code, so this may not be relevant, but be really careful how you deal with the data going back and forth. If you’re not sanitising that user input, just outputting it back onto the screen (with escaping disabled) is an age-old way to open yourself up to injection attacks.

@Tim thank you for reminders. I do the sanitising - as used in default SearchForm. I’m making changes on the result. I published only the code that seemed relevant.

1 Like

Well, to me “prints out” sounds more like what is sent by the server, i.e. the HTML. And the difference between HTML and what is rendered is the core of this issue, hence my preamble.