highlight.js icon indicating copy to clipboard operation
highlight.js copied to clipboard

Highlight.js strips whitespace in pre tag

Open Martmists-GH opened this issue 2 years ago • 4 comments

Describe the issue/behavior that seems buggy

When calling hljs.highlightElement, it strips all whitespace.

Sample Code or Instructions to Reproduce

fun `editor$transformer`() {  // called on page load
    document.querySelector<HTMLDivElement>(".md-editor")?.let { editor ->
        val input = editor.querySelector<HTMLTextAreaElement>(".md-editor-input")!!
        val code = editor.querySelector<HTMLElement>(".md-editor-code")!!

        input.addEventListener<InputEvent>("input") {
            var text = input.value
            if (text.isNotEmpty() && text.last() == '\n') {
                text += " "
            }
            println(text)
            code.innerText = text
            hljs.highlightElement(code)  // Removing this keeps whitespace as intended
            Unit
        }
    }
}
            <div class="row md-editor">
                <div class="col-7">
                    <div class="content md-editor-out">
                    </div>
                </div>
                <div class="col-5">
                    <div class="content md-editor-wrapper">
                        <textarea class="md-editor-input" spellcheck="false"></textarea>
                        <pre class="md-editor-highlight" aria-hidden="true"><code class="md-editor-code language-markdown"></code></pre>
                    </div>
                </div>
            </div>

Expected behavior Highlight.js correctly keeps spaces.

Additional context Disabling highlighting preserves spaces.

Martmists-GH avatar Aug 06 '22 04:08 Martmists-GH

It's the APIs you are using. Use textContent instead of innerText.

joshgoebel avatar Aug 06 '22 11:08 joshgoebel

using textContent preserves spaces but still strips newlines. I also tried using innerHTML and replacing spaces with &nbsp; and newlines with <br />, both of which are stripped by highlight.js

Martmists-GH avatar Aug 06 '22 12:08 Martmists-GH

using textContent preserves spaces but still strips newlines.

Please provide a jsfiddle demonstrating this and I will review. If your taking HTML out of another element you'll be responsible for doing any work necessary for preserving breaks, etc - such as possibly converting BR tags into new lines.

Highlight.js merely requests the textContent property, which does not render HTML to white space. It silently drops HTML.

joshgoebel avatar Aug 06 '22 17:08 joshgoebel

Unfortunately JSFiddle does not support Kotlin/JS, so that's impossible...

Martmists-GH avatar Aug 06 '22 17:08 Martmists-GH

using textContent preserves spaces but still strips newlines.

It does not - IF they are textual (\n), or no one would be able to use the library... as I stated earlier <br> is not supported or will need to be handled by you manually if you need to support <br>, first replace them in the content with \n before doing the highlighting, etc...

joshgoebel avatar Sep 12 '22 01:09 joshgoebel

JSFiddle does not support Kotlin/JS, so that's impossible...

We are a pure JS library, if there is a bug with the library itself then it should be possible to reproduce it with just JS (and JSFiddle) - no need for Kotlin. But as mentioned, I think you're seeing the expected behavior here...

joshgoebel avatar Sep 12 '22 01:09 joshgoebel

Closing until a test JSFiddle case can be provided. Right now this sounds like expected behavior that can be resolved by using clean text (no HTML) inside the block and using the textContent API exclusively.

If you truly need BR, consider the use of a plugin or manually replacing the <br> with real line breaks BEFORE highlighting. Ref: https://github.com/highlightjs/highlight.js/issues/2559

joshgoebel avatar Sep 14 '22 07:09 joshgoebel