2022-07-28 00:09:28 +00:00
|
|
|
import { lowlight } from 'lowlight/lib/core';
|
2021-04-29 00:09:48 +00:00
|
|
|
import { CodeBlockLowlight } from '@tiptap/extension-code-block-lowlight';
|
2022-03-23 12:07:27 +00:00
|
|
|
import { textblockTypeInputRule } from '@tiptap/core';
|
2022-05-05 18:08:40 +00:00
|
|
|
import { VueNodeViewRenderer } from '@tiptap/vue-2';
|
|
|
|
import languageLoader from '../services/code_block_language_loader';
|
|
|
|
import CodeBlockWrapper from '../components/wrappers/code_block.vue';
|
2021-04-13 12:11:32 +00:00
|
|
|
|
2022-06-15 21:10:04 +00:00
|
|
|
const extractLanguage = (element) => element.dataset.canonicalLang ?? element.getAttribute('lang');
|
|
|
|
|
2022-04-19 21:09:48 +00:00
|
|
|
export const backtickInputRegex = /^```([a-z]+)?[\s\n]$/;
|
|
|
|
export const tildeInputRegex = /^~~~([a-z]+)?[\s\n]$/;
|
2021-04-13 12:11:32 +00:00
|
|
|
|
2021-07-27 21:09:42 +00:00
|
|
|
export default CodeBlockLowlight.extend({
|
2021-12-16 15:10:28 +00:00
|
|
|
isolating: true,
|
2022-04-19 21:09:48 +00:00
|
|
|
exitOnArrowDown: false,
|
2021-04-29 00:09:48 +00:00
|
|
|
addAttributes() {
|
2021-04-13 12:11:32 +00:00
|
|
|
return {
|
2021-06-08 18:10:23 +00:00
|
|
|
language: {
|
|
|
|
default: null,
|
2021-09-16 15:12:47 +00:00
|
|
|
parseHTML: (element) => extractLanguage(element),
|
2021-06-08 18:10:23 +00:00
|
|
|
},
|
|
|
|
class: {
|
2021-09-23 22:34:10 +00:00
|
|
|
// eslint-disable-next-line @gitlab/require-i18n-strings
|
|
|
|
default: 'code highlight',
|
2021-06-08 18:10:23 +00:00
|
|
|
},
|
2021-04-13 12:11:32 +00:00
|
|
|
};
|
2021-04-29 00:09:48 +00:00
|
|
|
},
|
2022-03-23 12:07:27 +00:00
|
|
|
addInputRules() {
|
2022-04-19 21:09:48 +00:00
|
|
|
const getAttributes = (match) => languageLoader?.loadLanguageFromInputRule(match) || {};
|
2022-03-23 12:07:27 +00:00
|
|
|
|
|
|
|
return [
|
|
|
|
textblockTypeInputRule({
|
|
|
|
find: backtickInputRegex,
|
|
|
|
type: this.type,
|
2022-04-19 21:09:48 +00:00
|
|
|
getAttributes,
|
2022-03-23 12:07:27 +00:00
|
|
|
}),
|
|
|
|
textblockTypeInputRule({
|
|
|
|
find: tildeInputRegex,
|
|
|
|
type: this.type,
|
2022-04-19 21:09:48 +00:00
|
|
|
getAttributes,
|
2022-03-23 12:07:27 +00:00
|
|
|
}),
|
|
|
|
];
|
|
|
|
},
|
2022-04-19 21:09:48 +00:00
|
|
|
parseHTML() {
|
|
|
|
return [
|
|
|
|
{
|
|
|
|
tag: 'div.markdown-code-block',
|
|
|
|
skip: true,
|
|
|
|
},
|
2022-07-01 21:08:27 +00:00
|
|
|
{
|
|
|
|
tag: 'pre.js-syntax-highlight',
|
|
|
|
preserveWhitespace: 'full',
|
|
|
|
},
|
2022-04-19 21:09:48 +00:00
|
|
|
];
|
|
|
|
},
|
2021-06-08 18:10:23 +00:00
|
|
|
renderHTML({ HTMLAttributes }) {
|
2022-01-11 18:16:38 +00:00
|
|
|
return [
|
|
|
|
'pre',
|
|
|
|
{
|
|
|
|
...HTMLAttributes,
|
2022-04-19 21:09:48 +00:00
|
|
|
class: `content-editor-code-block ${gon.user_color_scheme} ${HTMLAttributes.class}`,
|
2022-01-11 18:16:38 +00:00
|
|
|
},
|
|
|
|
['code', {}, 0],
|
|
|
|
];
|
2021-06-08 18:10:23 +00:00
|
|
|
},
|
2022-05-05 18:08:40 +00:00
|
|
|
|
|
|
|
addNodeView() {
|
|
|
|
return new VueNodeViewRenderer(CodeBlockWrapper);
|
|
|
|
},
|
2022-07-28 00:09:28 +00:00
|
|
|
}).configure({ lowlight });
|