import type { EditorView as CodeMirror } from '@codemirror/view' import clsx from 'clsx' import DOMPurify from 'dompurify' import { defineComponent, ref, type Ref, h, Fragment, onMounted, watch, } from 'vue' import type { CodeBlockConfig } from '../../config' import type { LanguageInfo } from '../loader' import { Icon } from '../../../__internal__/components/icon' import { keepAlive } from '../../../__internal__/keep-alive' import { CopyButton } from './copy-button' import { LanguagePicker } from './language-picker' import { PreviewPanel } from './preview-panel' keepAlive(h, Fragment) export type CodeBlockProps = { text: Ref selected: Ref getReadOnly: () => boolean codemirror: CodeMirror language: Ref getAllLanguages: () => Array setLanguage: (language: string) => void config: Omit } export const CodeBlock = defineComponent({ props: { text: { type: Object, required: true, }, selected: { type: Object, required: true, }, getReadOnly: { type: Function, required: true, }, codemirror: { type: Object, required: true, }, language: { type: Object, required: true, }, getAllLanguages: { type: Function, required: true, }, setLanguage: { type: Function, required: true, }, config: { type: Object, required: true, }, }, setup(props) { const previewOnlyByDefault = props.config.previewOnlyByDefault ?? props.getReadOnly() const previewOnlyMode = ref(previewOnlyByDefault) const codemirrorHostRef = ref() const preview = ref(null) onMounted(() => { while (codemirrorHostRef.value?.firstChild) { codemirrorHostRef.value.removeChild(codemirrorHostRef.value.firstChild) } if (codemirrorHostRef.value) { codemirrorHostRef.value.appendChild(props.codemirror.dom) } }) watch( () => [props.text.value, props.language.value], () => { const result = props.config.renderPreview( props.language.value, props.text.value, (value) => (preview.value = value) ) if (result) { preview.value = result } // set default value for async renderPreview const isAsyncPreview = result === undefined if (isAsyncPreview && !preview.value) { preview.value = DOMPurify.sanitize(props.config.previewLoading) } if (result === null) { preview.value = null } }, { immediate: true } ) const empty = () => {} return () => { return ( <>
{preview.value ? ( ) : null}
) } }, })