Description
Not sure if the title makes sense. Essentially, the behavior of this plugin differs from the behavior of raw highlight.js.
To reproduce the issue, I have the following relevant pieces of code in my Vue app setup:
import { createApp } from "vue";
import App from "./App.vue";
import "highlight.js/styles/stackoverflow-light.css";
import javascript from "highlight.js/lib/languages/javascript";
import hljs from "highlight.js/lib/core";
import hljsVuePlugin from "@highlightjs/vue-plugin";
hljs.registerLanguage("javascript", javascript);
createApp(App).use(hljsVuePlugin).mount("#app");
My test template:
const doHighlight = () => {
hljs.highlightElement(document.getElementById("scripted-highlight"));
const result = hljs.highlight("els 'something", { language: "javascript" });
document.getElementById("manual-highlight").innerHTML = result.value;
};
</script>
<template>
<input type="button" @click="doHighlight()" value="Do highlight!" style="border: 1px solid red;"/>
<pre><code class="language-javascript" id="scripted-highlight">els 'something</code></pre>
<pre><code id="manual-highlight"></code></pre>
<highlightjs language="javascript" code="els 'something"></highlightjs>
Here's what I see after clicking the button:
Ignore the background, pay attention to the color of something
. It is highlighted only inside the HTML elements that use the raw hljs API, but not in the Vue highlightjs
element.
Now I change els
to else
so that the quoted string has a keyword before it:
const doHighlight = () => {
hljs.highlightElement(document.getElementById("scripted-highlight"));
const result = hljs.highlight("else 'something", { language: "javascript" });
document.getElementById("manual-highlight").innerHTML = result.value;
};
</script>
<template>
<input type="button" @click="doHighlight()" value="Do highlight!" style="border: 1px solid red;"/>
<pre><code class="language-javascript" id="scripted-highlight">else 'something</code></pre>
<pre><code id="manual-highlight"></code></pre>
<highlightjs language="javascript" code="else 'something"></highlightjs>
Now the highlightjs
also got something
colored, as expected!
This leads to the situation when the user gets colored output only if they do not start typing with something that does not have a start token (such as a quote).
When I check the generated code for the broken case with els 'something
, it shows that hljs class had been assigned to the code
element, but there is no span
element:
I'm puzzled, what's going on there? The Vue plugin should not affect the parsing of the tokens; it's just a wrapper around hljs , isn't it?
I guess, I'll have to use the raw hljs API instead of the Vue plugin unless somebody has a clue how to fix this easily.
The long story. I have built a real-time editor with highlighting for my project to have custom token parsing and noticed that when I type an opening token, the token and the following text are not highlighted until I add the closing token. For example, I start typing 'something
and it is not colored until I type the closing quote, e.g. 'something'
. But then I discovered that if I type a keyword, such as else
in front of the opening quote, then suddenly the coloring works from the start. I was pulling my hair, trying to understand what was wrong with my custom language setup.
Then I switched to Javascript highlighting, and it had the same issue. Then I went to the highlight.js demo website and checked it there - no problems! Then I added raw HTML and hljs API calls to my code - and it also worked fine. So I concluded that there is some kind of black magic happening with that vue plugin and I'm missing something or it's a bug.