White space stripped from Django Template tags in PrismJS code blocks

44 views Asked by At

When I render Django template code in a prismjs block, it strips white space {{}} and {%%}.

For example, pre-render, the code might be

{% image self.search_image thumbnail-400x200 as img %}
<img src="{{ img.url }}" alt="{{ img.title }}">

But the rendered code block will be

{%image self.search_image thumbnail-400x200 as img%}
<img src="{{img.url}}" alt="{{img.title}}">

It's not a case of css, the space is missing from the html. I can set the language to HTML, or even python etc, the same issue remains.

Does anyone know of a way to prevent this?

2

There are 2 answers

0
Rich - enzedonline On BEST ANSWER

Not so much of an answer as a workaround. I've tacked on the following function to put those whitespaces back in:

const processDjangoCodeBlock = (element) => {
    const content = element.innerHTML;

    // Step 1: Insert whitespace after "{%" and "{{" 
    //         if the next character is not whitespace
    const step1Content = content.replace(/({%)(?!\s)/g, "$1 ")
        .replace(/({{)(?!\s)/g, "$1 ");

    // Step 2: Insert whitespace before "%}" and "}}" 
    //         if the previous character is not whitespace
    const step2Content = step1Content.replace(/(?<!\s)(%})/g, " $1")
        .replace(/(?<!\s)(}})/g, " $1");

    // Update the inner HTML of the element with the processed content
    element.innerHTML = step2Content;
};

Not very satisfactory as I would prefer to just stop PrismJS stripping these in the first place. That issue is going to be lurking in the core code somewhere, another century when I have more time.

The calling template is a Wagtail block, which goes like:

<pre><code class="prism-block language-{{ self.language }}" 
      id="code-block-{{ block.id }}">{{ self.code }}</code></pre>

{% if self.language == "django" %}
    <script>
    document.addEventListener("DOMContentLoaded", () => {
        processDjangoCodeBlock(
            document.getElementById("code-block-{{ block.id }}")
        );
    });
    </script>
{% endif %}
1
Saxtheowl On

PrismJS is trying to handle your Django template tags as the chosen language, we could just tells PrismJS to ignore the content inside the block, for example:

<pre><code class="language-none">{% image self.search_image thumbnail-400x200 as img %}
<img src="{{ img.url }}" alt="{{ img.title }}"></code></pre>

Now if we want to find a workaround for your case we could replace the spaces in your Django tags with &nbsp; before you display them in PrismJS.

{%&nbsp;image self.search_image thumbnail-400x200 as img&nbsp;%}
<img src="{{&nbsp;img.url&nbsp;}}" alt="{{&nbsp;img.title&nbsp;}}">