How do I do syntax highlighting in VueJS - vue.js

How do I display syntax-highlighted HTML code like this picture from the VueJS documentation?
I have tried using v-html but I just get a console error.

Upon inspecting the VueJS documentation code snips, you can see they contain the class hljs.
This class is used by HighlightJS, a simple framework for code syntax highlighting.
HighlightJS automatically detects the language based on the syntax and can be extended with custom themes and configurations.
To install it in your vue package simply run either npm install highlight.js --save or yarn add highlight.js.
Once installed, import it and register it as a Vue plugin Vue.use(hljs.vuePlugin);
You can then use the component within your Vue templates:
<div id="app">
<!-- bind to a data property named `code` -->
<highlightjs autodetect :code="code" />
<!-- or literal code works as well -->
<highlightjs language='javascript' code="var x = 5;" />
</div>
You can find the above Vue example here in the documentation.

You could just put out the sanitized string:
new Vue({
el: "#app",
data() {
return {
script: `<script src="https://unpkg.com/vue#next"></script>`,
}
},
template: `
<div>
Code:<br>
<code v-html="script"></code><br>
</div>
`,
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app"></div>

Related

Inject Vue component from diet js file

I have a very simple app vue3:
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
let currentApp = createApp(App);
(window as any).load(currentApp);
currentApp.mount('#app');
In the index.html file i import a dist lib:
<script src="http://localhost:5173/dist/assets/index.59eda240.js">
The content of dist JS is:
import HelloWorld from './components/HelloWorld.vue'
(window as any).load = (app: any) => {
app.component('hello-world', HelloWorld);
}
If i use a very simple HelloWorld.vue with just one line of text "Hello", all works fine, but if i put some css classes or more complicated component i obtain:
[Vue warn]: Invalid VNode type: Symbol() (symbol) at <HelloWorld>
at <App>
How can i solve this? Or is there another way to load component at runtime?
Thanks in advance.
P.s. I have no problem doing the same thing with Vue
--------- UPDATE MORE INFO ----------
Vue version
3.2.38
Link to minimal reproduction
https://stackblitz.com/edit/vitejs-vite-744fbh?file=src/main.js
Steps to reproduce
The base idea is to have a main app the create a Vue app, and another external lib the load component at runtime.
Open the sample project and show console log to see "Invalid VNode type: Symbol() (symbol)"
What is expected?
I expect to see the components rendered correctly
What is actually happening?
I don't see the component UI, but looking at the console I see the logic code works correctly but we have a warning: Invalid VNode type: Symbol() (symbol) Invalid VNode type: Symbol() (symbol)
System Info
No response
Any additional comments?
This warning appears only in some components, for example, fur a very simple component, it works fine, see here: https://stackblitz.com/edit/vitejs-vite-nueucw?file=src/App.vue.
You can see the source of helloworld component at the top of lib.js file, inside a comment block
The actual problem is that there are multiple Vue library copies per page that interact with each other. This should be avoided, preferably by bundling multiple parts of the application together, so multiple apps would reuse the same modules from vendors chunk. In case this isn't possible or practical, a simple workaround is to use Vue CDN for all applications, either by using window.Vue instead of vue import, or aliasing the import to global variable by means of a bundler.
The root cause is that Vue built-in element are specific to Vue copy in use - Fragment, Teleport, Comment, etc. They are defined with Symbol() to be distinguished from other elements and components and used in compiled component templates. Symbol is used in JavaScript to define unique tokens, Symbol('foo') !== Symbol('foo'). The symbols of built-in elements from one Vue copy mean nothing to another Vue copy, this is the meaning of this error message.
It can be seen in this analyzer that this component template:
<h1 style="background-color:Red; font-size: 44px;">{{ msg }}</h1>
<button #click="msg = 'click';">CLICK</button>
is compiled to this render function:
export function render(_ctx, _cache, $props, $setup, $data, $options) {
return (_openBlock(), _createElementBlock(_Fragment, null, [
_createElementVNode("h1", { style: {"background-color":"Red","font-size":"44px"} }, _toDisplayString(_ctx.msg), 1 /* TEXT */),
_createElementVNode("button", {
onClick: $event => {_ctx.msg = 'click';}
}, "CLICK", 8 /* PROPS */, ["onClick"])
], 64 /* STABLE_FRAGMENT */))
}
Notice that the use of multiple root elements results in wrapping them in Fragment, which won't be correctly processed by multiple Vue copies, etc.
Change hello world with another component:
<template>
<div class="relative flex items-top justify-center min-h-screen sm:items-center py-4 sm:pt-0">
<div class="max-w-6xl mx-auto sm:px-6 lg:px-8">
<div class="card rounded-lg shadow-lg" style="background-color: yellow;">
<div class="card-body p-0 m-0 pt-2" style="background-color: orange;">
<div class="row border-bottom p-0 m-0 pt-2" style="background-color: brown;">
<div class="bg-secondary">
<h5 class="bg-info">test</h5>
<p>
test
</p>
</div>
</div>
<div>
<div>
test2
</div>
</div>
</div>
</div>
</div>
</div>
</template>
Only one root element, I have the same issue.

use dynamic component in the nuxt layout get runtime compile error

in my nuxt application. in layout file use dynamic component for set the component in different pages like below
<template>
<div id="app">
<div id="app-body">
<div id="app-topbar">
<component v-bind:is="actionBar.component"></component>
</div>
<div id="app-content">
<nuxt />
</div>
</div>
</div>
</template>
but when I'm runing the application I got the error in below
You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.
I'll try to wrap my component in no-ssr tags but the error still exist
as DigitalDrifter already said, you need to use the compiler-included build.
To do that in nuxt try to add the following to your nuxt.config.js:
build: {
extend(config, ctx) {
config.resolve.alias['vue'] = 'vue/dist/vue.common'

Using components without npm inside existing web page

I'm new to Vue.js and also do most work in a conventional LAMP environment.
The vue components tried so far don't seem to work linked in. Can anyone please:
Provide a sample process to install vue components in a legacy LAMP environment
Provide a simple html template showing how to load a vue component
Thanks for any tips.
Since you are in a legacy context, you probably won't use npm/webpack/babel. In this case, you'll import every package you need via <script> tags.
Process:
Look for the component you need
Check their docs for the steps needed to import them.
Usually it is a <script> tag (and a CSS <link> style) followed by some steps to configure (but not always).
In some rare cases the lib doesn't provide instructions for usage via <script>, in this case you can try using <script src="https://unkpg.com/NODE-PACKAGE-NAME"> and then see if it is possible to use it directly.
Examples:
Declaring your own <custom-comp> component and registering it globally via Vue.component.
<script src="https://unpkg.com/vue"></script>
<div id="app">
<p>{{ message }}</p>
<custom-comp v-bind:myname="name"></custom-comp>
</div>
<template id="cc">
<p>I am the custom component. You handled me {{ myname }} via props. I already had {{ myown }}.</p>
</template>
<script>
Vue.component('custom-comp', {
template: '#cc',
props: ['myname'],
data() {
return {
myown: 'Eve'
}
}
});
new Vue({
el: '#app',
data: {
message: 'Hello, Vue.js',
name: 'Alice'
}
});
</script>
Using a third-party component that gives instructions on how to use without NPM. Example bootstrap-vue. How to use? Follow their instructions for each specific component. Demo of the Card Component below.
<script src="https://unpkg.com/vue"></script>
<!-- Add this to <head> -->
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap/dist/css/bootstrap.min.css"/>
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap-vue#latest/dist/bootstrap-vue.css"/>
<!-- Add this after vue.js -->
<script src="//unpkg.com/babel-polyfill#latest/dist/polyfill.min.js"></script>
<script src="//unpkg.com/bootstrap-vue#latest/dist/bootstrap-vue.js"></script>
<div id="app">
<div>
<b-card title="Card Title"
img-src="https://lorempixel.com/600/300/food/5/"
img-alt="Image"
img-top
tag="article"
style="max-width: 20rem;"
class="mb-2">
<p class="card-text">
Some quick example text to build on the card title.
</p>
<b-button href="#" variant="primary">Go somewhere</b-button>
</b-card>
</div>
</div>
<script>
new Vue({
el: '#app'
});
</script>
Finally, using a third-party component that doesn't show any specific instructon on how to use without NPM. In the demo below we see the vue2-datepicker. They don't give specific instructions on how to use via <script>, but by looking at their readme, we see their component typically exports a DatePicker variable. Use then use <script src="https://unpkg.com/vue2-datepicker"> to load the component and register it for use via Vue.component('date-picker', DatePicker.default);. The need for .default varies. For other components, Vue.component('comp-name', ComponentName); (instead of ComponentName.default) directly could work.
// After importing the <script> tag, you use this command to register the component
// so you can use. Sometimes the components auto-register and this is not needed
// (but generally when this happens, they tell in their docs). Sometimes you need
// to add `.default` as we do below. It's a matter of trying the possibilities out.
Vue.component('date-picker', DatePicker.default);
new Vue({
el: '#app',
data() {
return {
time1: '',
time2: '',
shortcuts: [
{
text: 'Today',
start: new Date(),
end: new Date()
}
]
}
}
})
<script src="https://unpkg.com/vue"></script>
<script src="https://unpkg.com/vue2-datepicker"></script>
<div id="app">
<div>
<date-picker v-model="time1" :first-day-of-week="1" lang="en"></date-picker>
<date-picker v-model="time2" range :shortcuts="shortcuts" lang="en"></date-picker>
</div>
</div>

Safari shows a component error while the other browsers do not

I have some very simple vue code as shown below:
Vue.component('tabs', {
template: `
<div class="">
<div class="tabs">
<ul>
<li><a>Music</a></li>
<li><a>Videos</a></li>
<li><a>Documents</a></li>
</ul>
</div>
<div class="tab-detail">
<slot></slot>
</div>
</div>
`
});
new Vue ({
el: '#root'
});
and HTML code
<div id="root" class="container">
<tabs>
</tabs>
</div>
the problem I have is that the safari throws a warning:
[Vue warn]: Unknown custom element: <tabs> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
(found in <Root>)
I am a Vue beginner so I was looking for the solution but the answer I got was that I should just declare the new Vue after the component. That I did but I am still getting this error.
This is because Safari does not support es6 template string syntax ``. In order to fix it you should use Webpack or just a Babel to add support for new es6 features.

How to register vue components

I have recently started using Vue and I was looking for getting to use Vue.Draggable on my project. Due to framework and current setup in use I haven't been able to implement single-page-component .vue-files, and have instead simply written app & components with string-templates to .js -files.
I'm unable to figure out how to include draggable to my application.
Basic structure looks like follow:
#HTML
<div id="app">
<mycomponent></mycomponent>
</div>
<script src="vuedraggable.js"></script>
<script src="component.js"></script>
<script src="app.js"></script>
--
#app.js (simply a wrapper)
var vm = new Vue({
el: '#app',
});
--
#component.js
Vue.component('mycomponent',{
template: `
<form>
<h2>{{ form.label }}</h2>
<draggable v-model="form.fields" class="dragArea">
<div v-for="field in form.fields">
<field :field="field"></field>
</div>
</draggable>
</form>
`,
data: function() {
return {
form: { ... form-structure-to-be ...}
};
},
});
With this structure I'm getting error "vue.js:440 [Vue warn]: Unknown custom lement: - did you register the component correctly?"
I haven't been able to figure out either "require" nor "import" method and assume that both require bootstrapping. Due to environment I'm working with I'm having hard time installing libraries with NPM & strapping, and I would prefer to register components manually - is this possible and how?
Could someone please give me directions ?