UNPKG

@rtdui/editor

Version:

React rich text editor based on tiptap

79 lines (76 loc) 2.68 kB
let _tiptap_core = require("@tiptap/core"); let shiki = require("shiki"); //#region packages/editor/src/RichTextEditor/tiptap_extensions/extension-code-block-shiki/shiki-highlighter.ts let highlighter; let highlighterPromise; const loadingLanguages = /* @__PURE__ */ new Set(); const loadingThemes = /* @__PURE__ */ new Set(); function getShiki() { return highlighter; } /** * Load the highlighter. Makes sure the highlighter is only loaded once. */ function loadHighlighter(opts) { if (!highlighter && !highlighterPromise) { highlighterPromise = (0, shiki.createHighlighter)({ themes: opts.themes.filter((theme) => !!theme && theme in shiki.bundledThemes), langs: opts.languages.filter((lang) => !!lang && lang in shiki.bundledLanguages) }).then((h) => { highlighter = h; }); return highlighterPromise; } if (highlighterPromise) return highlighterPromise; } /** * Loads a theme if it's valid and not yet loaded. * @returns true or false depending on if it got loaded. */ async function loadTheme(theme) { if (highlighter && !highlighter.getLoadedThemes().includes(theme) && !loadingThemes.has(theme) && theme in shiki.bundledThemes) { loadingThemes.add(theme); await highlighter.loadTheme(theme); loadingThemes.delete(theme); return true; } return false; } /** * Loads a language if it's valid and not yet loaded * @returns true or false depending on if it got loaded. */ async function loadLanguage(language) { if (highlighter && !highlighter.getLoadedLanguages().includes(language) && !loadingLanguages.has(language) && language in shiki.bundledLanguages) { loadingLanguages.add(language); await highlighter.loadLanguage(language); loadingLanguages.delete(language); return true; } return false; } /** * Initializes the highlighter based on the prosemirror document, * with the themes and languages in the document. */ async function initHighlighter({ doc, name, defaultTheme, defaultLanguage }) { const codeBlocks = (0, _tiptap_core.findChildren)(doc, (node) => node.type.name === name); const themes = [ ...codeBlocks.map((block) => block.node.attrs.theme), defaultTheme, "one-light", "one-dark-pro" ]; const languages = [...codeBlocks.map((block) => block.node.attrs.language), defaultLanguage]; if (!highlighter) await loadHighlighter({ languages, themes }); else await Promise.all([...themes.flatMap((theme) => loadTheme(theme)), ...languages.flatMap((language) => !!language && loadLanguage(language))]); } //#endregion exports.getShiki = getShiki; exports.initHighlighter = initHighlighter; exports.loadHighlighter = loadHighlighter; exports.loadLanguage = loadLanguage; exports.loadTheme = loadTheme;