Search code examples
pythondjangosyntax-highlightingprismjs

White space stripped from Django Template tags in PrismJS code blocks


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?


Solution

  • 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 %}