Skip to content

Commit cb585f7

Browse files
committed
feat(vue): add code highlighting
1 parent c14530c commit cb585f7

File tree

2 files changed

+93
-0
lines changed

2 files changed

+93
-0
lines changed
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/**
2+
* Prism is used to syntax highlight code blocks in markdown files.
3+
*
4+
* Original source:
5+
* @link https://github.com/facebook/docusaurus/blob/main/packages/docusaurus-theme-classic/src/theme/prism-include-languages.ts
6+
*
7+
* Reason for overriding:
8+
* - Add Vue language support since it's not included in Prism
9+
*/
10+
11+
import siteConfig from '@generated/docusaurus.config';
12+
import type * as PrismNamespace from 'prismjs';
13+
import type { Optional } from 'utility-types';
14+
15+
export default function prismIncludeLanguages(PrismObject: typeof PrismNamespace): void {
16+
const {
17+
themeConfig: { prism },
18+
} = siteConfig;
19+
const { additionalLanguages } = prism as { additionalLanguages: string[] };
20+
21+
// Prism components work on the Prism instance on the window, while prism-
22+
// react-renderer uses its own Prism instance. We temporarily mount the
23+
// instance onto window, import components to enhance it, then remove it to
24+
// avoid polluting global namespace.
25+
// You can mutate PrismObject: registering plugins, deleting languages... As
26+
// long as you don't re-assign it
27+
28+
const PrismBefore = globalThis.Prism;
29+
globalThis.Prism = PrismObject;
30+
31+
additionalLanguages.forEach((lang) => {
32+
if (lang === 'php') {
33+
// eslint-disable-next-line global-require
34+
require('prismjs/components/prism-markup-templating.js');
35+
}
36+
// eslint-disable-next-line global-require, import/no-dynamic-require
37+
require(`prismjs/components/prism-${lang}`);
38+
});
39+
40+
// CUSTOM CODE
41+
require('../theme/prism-languages/prism-vue');
42+
// CUSTOM CODE END
43+
44+
// Clean up and eventually restore former globalThis.Prism object (if any)
45+
delete (globalThis as Optional<typeof globalThis, 'Prism'>).Prism;
46+
if (typeof PrismBefore !== 'undefined') {
47+
globalThis.Prism = PrismObject;
48+
}
49+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
(function (Prism) {
2+
Prism.languages.vue = Prism.languages.extend('markup', {
3+
// Add Vue template interpolation (e.g., {{ expression }})
4+
interpolation: {
5+
pattern: /\{\{[^}]+\}\}/,
6+
inside: {
7+
punctuation: /\{\{|\}\}/,
8+
expression: {
9+
pattern: /[\s\S]+/,
10+
inside: Prism.languages.javascript,
11+
},
12+
},
13+
},
14+
15+
// Add Vue-specific attributes (v-bind, @click, :prop)
16+
attribute: {
17+
pattern: /(^|["'\s])(?:v-|:|\@|#)[\w-]+(?:\.[\w-]+)*(?=[^\w-])(?=[^=>]*=)/,
18+
lookbehind: true,
19+
alias: 'keyword',
20+
},
21+
});
22+
23+
Prism.languages.insertBefore('vue', 'comment', {
24+
script: {
25+
pattern: /<script[\s\S]*?>[\s\S]*?<\/script>/i,
26+
inside: {
27+
rest: Prism.languages.javascript,
28+
},
29+
alias: 'language-javascript',
30+
},
31+
style: {
32+
pattern: /<style[\s\S]*?>[\s\S]*?<\/style>/i,
33+
inside: {
34+
rest: Prism.languages.css,
35+
},
36+
alias: 'language-css',
37+
},
38+
});
39+
40+
Prism.languages.html = Prism.languages.vue;
41+
Prism.languages.markup = Prism.languages.vue;
42+
43+
Prism.languages.v = Prism.languages.vue;
44+
})(Prism);

0 commit comments

Comments
 (0)