mirror of
https://github.com/h44z/wg-portal.git
synced 2026-07-13 20:18:22 +00:00
fix: resolve Prism syntax highlighting error in peer config modal
The PeerViewModal and InterfaceViewModal components displayed: Error: The language "undefined" has no grammar. Root cause: vue-prism-component bundles its own instance of prismjs (separate from the one imported elsewhere), so registering the ini grammar on a different Prism instance had no effect on the one actually performing the highlighting. Fix: bypass vue-prism-component entirely. Import a single Prism instance via a new helper (frontend/src/helpers/prism-setup.js) that also registers the ini grammar, then render highlighted HTML directly with <pre><code v-html="highlightedConfig">. This ensures the same Prism object that owns the ini grammar is the one calling highlight(). Affected files: - frontend/src/helpers/prism-setup.js (new): imports prismjs, defines the ini grammar on the Prism instance, re-exports it - frontend/src/components/PeerViewModal.vue: replaces <Prism> with v-html using the shared Prism instance - frontend/src/components/InterfaceViewModal.vue: same replacement - frontend/src/main.js: removes the now-unused prism-setup import Fixes #726
This commit is contained in:
@@ -3,8 +3,7 @@ import Modal from "./Modal.vue";
|
||||
import {computed, ref, watch} from "vue";
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import {interfaceStore} from "@/stores/interfaces";
|
||||
import Prism from 'vue-prism-component'
|
||||
import 'prismjs/components/prism-ini'
|
||||
import Prism from '@/helpers/prism-setup';
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
@@ -17,6 +16,14 @@ const props = defineProps({
|
||||
|
||||
const configString = ref("")
|
||||
|
||||
const highlightedConfig = computed(() => {
|
||||
const grammar = Prism.languages.ini
|
||||
if (grammar) {
|
||||
return Prism.highlight(configString.value, grammar, 'ini')
|
||||
}
|
||||
return configString.value
|
||||
})
|
||||
|
||||
const emit = defineEmits(['close'])
|
||||
|
||||
const selectedInterface = computed(() => {
|
||||
@@ -51,7 +58,7 @@ function close() {
|
||||
<template>
|
||||
<Modal :title="title" :visible="visible" @close="close">
|
||||
<template #default>
|
||||
<Prism language="ini" :code="configString"></Prism>
|
||||
<pre class="language-ini"><code class="language-ini" v-html="highlightedConfig"></code></pre>
|
||||
</template>
|
||||
<template #footer>
|
||||
<button class="btn btn-primary" type="button" @click.prevent="close">{{ $t('general.close') }}</button>
|
||||
|
||||
@@ -5,7 +5,7 @@ import { interfaceStore } from "@/stores/interfaces";
|
||||
import { computed, ref, watch } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { freshInterface, freshPeer, freshStats } from '@/helpers/models';
|
||||
import Prism from "vue-prism-component";
|
||||
import Prism from '@/helpers/prism-setup';
|
||||
import { notify } from "@kyvg/vue3-notification";
|
||||
import { settingsStore } from "@/stores/settings";
|
||||
import { profileStore } from "@/stores/profile";
|
||||
@@ -81,6 +81,14 @@ const title = computed(() => {
|
||||
|
||||
const configStyle = ref("wgquick")
|
||||
|
||||
const highlightedConfig = computed(() => {
|
||||
const grammar = Prism.languages.ini
|
||||
if (grammar) {
|
||||
return Prism.highlight(configString.value, grammar, 'ini')
|
||||
}
|
||||
return configString.value
|
||||
})
|
||||
|
||||
watch(() => props.visible, async (newValue, oldValue) => {
|
||||
if (oldValue === false && newValue === true) { // if modal is shown
|
||||
await peers.LoadPeerConfig(selectedPeer.value.Identifier, configStyle.value)
|
||||
@@ -217,7 +225,7 @@ function ConfigQrUrl() {
|
||||
<div id="collapseConfig" class="accordion-collapse collapse" aria-labelledby="headingConfig"
|
||||
data-bs-parent="#peerInformation" style="">
|
||||
<div class="accordion-body">
|
||||
<Prism language="ini" :code="configString"></Prism>
|
||||
<pre class="language-ini"><code class="language-ini" v-html="highlightedConfig"></code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
39
frontend/src/helpers/prism-setup.js
Normal file
39
frontend/src/helpers/prism-setup.js
Normal file
@@ -0,0 +1,39 @@
|
||||
import Prism from 'prismjs'
|
||||
|
||||
Prism.languages.ini = {
|
||||
comment: {
|
||||
pattern: /(^[ \f\t\v]*)[#;][^\n\r]*/m,
|
||||
lookbehind: true
|
||||
},
|
||||
section: {
|
||||
pattern: /(^[ \f\t\v]*)\[[^\n\r\]]*\]?/m,
|
||||
lookbehind: true,
|
||||
inside: {
|
||||
'section-name': {
|
||||
pattern: /(^\[[ \f\t\v]*)[^ \f\t\v\]]+(?:[ \f\t\v]+[^ \f\t\v\]]+)*/,
|
||||
lookbehind: true,
|
||||
alias: 'selector'
|
||||
},
|
||||
punctuation: /\[|\]/
|
||||
}
|
||||
},
|
||||
key: {
|
||||
pattern: /(^[ \f\t\v]*)[^ \f\n\r\t\v=]+(?:[ \f\t\v]+[^ \f\n\r\t\v=]+)*(?=[ \f\t\v]*=)/m,
|
||||
lookbehind: true,
|
||||
alias: 'attr-name'
|
||||
},
|
||||
value: {
|
||||
pattern: /(=[ \f\t\v]*)[^ \f\n\r\t\v]+(?:[ \f\t\v]+[^ \f\n\r\t\v]+)*/,
|
||||
lookbehind: true,
|
||||
alias: 'attr-value',
|
||||
inside: {
|
||||
'inner-value': {
|
||||
pattern: /^("|').+(?=\1$)/,
|
||||
lookbehind: true
|
||||
}
|
||||
}
|
||||
},
|
||||
punctuation: /=/
|
||||
}
|
||||
|
||||
export default Prism
|
||||
@@ -22,7 +22,6 @@ import "@fontsource/nunito-sans/600.css";
|
||||
import "flag-icons/css/flag-icons.min.css"
|
||||
|
||||
// Syntax Highlighting
|
||||
import 'prismjs'
|
||||
import 'prismjs/themes/prism-okaidia.css'
|
||||
|
||||
const app = createApp(App);
|
||||
|
||||
Reference in New Issue
Block a user