@stackoverfloweth/prefect-design
Version:
A collection of low-level Vue components.
38 lines (30 loc) • 1.19 kB
text/typescript
import { marked } from 'marked'
import { MaybeRefOrGetter, onScopeDispose, Ref, ref, toValue, watchEffect } from 'vue'
import MarkdownTokenWorker from '@/components/MarkdownRenderer/worker?worker&inline'
import { ParseMessagePayload } from '@/types/markdownRenderer'
import { randomId } from '@/utilities'
export type Tokens = marked.TokensList | []
export type MarkdownRendererCallback = (tokens: Tokens) => void
export type UseMarkdownRenderer = {
tokens: Ref<Tokens>,
}
const callbacks = new Map<string, MarkdownRendererCallback>()
const worker = new MarkdownTokenWorker()
worker.onmessage = (message: MessageEvent<ParseMessagePayload>) => {
const { id, tokens } = message.data
const callback = callbacks.get(id)
if (callback) {
callback(tokens)
}
}
export function useMarkdownRenderer(text: MaybeRefOrGetter): UseMarkdownRenderer {
const id = randomId()
const tokensRef = ref<Tokens>([])
const rendererCallback = (tokens: Tokens): void => {
tokensRef.value = tokens
}
callbacks.set(id, rendererCallback)
watchEffect(() => worker.postMessage({ id, text: toValue(text) }))
onScopeDispose(() => callbacks.delete(id))
return { tokens: tokensRef }
}