import { computed, MaybeRefOrGetter, onScopeDispose, Ref, ref, toValue, watchEffect } from 'vue' import HighlightWorker from '@/components/CodeHighlight/worker?worker&inline' import { FormattedMessagePayload, UnformattedMessagePayload } from '@/types/codeHighlight' import { randomId } from '@/utilities' export type HighlightCallback = (payload: FormattedMessagePayload) => void export type UseCodeHighlight = { formatted: Ref, lines: Ref, illegal: Ref, relevance: Ref, } const callbacks = new Map() const worker = new HighlightWorker() worker.onmessage = (message: MessageEvent) => { const { id } = message.data const callback = callbacks.get(id) if (callback) { callback(message.data) } } export function useCodeHighlight(text: MaybeRefOrGetter, language: MaybeRefOrGetter): UseCodeHighlight { const id = randomId() const formatted = ref('') const illegal = ref(false) const relevance = ref(0) const lines = computed(() => toValue(text).split('\n').length) const highlightCallback = (payload: FormattedMessagePayload): void => { formatted.value = payload.formatted illegal.value = payload.illegal relevance.value = payload.relevance } callbacks.set(id, highlightCallback) watchEffect(() => { const message: UnformattedMessagePayload = { id, text: toValue(text), lang: toValue(language), } worker.postMessage(message) }) onScopeDispose(() => callbacks.delete(id)) return { formatted, illegal, relevance, lines } }