UNPKG

aubade

Version:

filesystem-based content processor

47 lines (45 loc) 1.62 kB
import { createHighlighter, bundledLanguages } from 'shiki'; import { escape } from '../utils.js'; export const highlighter = await createHighlighter({ themes: ['github-dark'], langs: Object.keys(bundledLanguages), }); export function transform(source, dataset) { const { codeToTokensBase } = highlighter; const { file, ...rest } = dataset; let highlighted = ''; let line = +(rest['line-start'] || 1); for (const tokens of codeToTokensBase(source, { lang: rest.language, })) { let code = `<code data-line="${line++}">`; for (const { content, color } of tokens) { const style = color ? `style="color: ${color}"` : ''; code += `<span ${style}>${escape(content)}</span>`; } highlighted += `${code}</code>\n`; } const attrs = Object.entries(rest).map(([k, v]) => `data-${k.toLowerCase().replace(/[^a-z\-]/g, '')}="${escape(v || '')}"`); // needs to be /^<pre/ to prevent added wrapper from markdown-it return `<pre data-aubade="block"> <header data-aubade="header" ${attrs.join('\n\t\t')} class="aubade ${file ? '' : 'empty'}" >${file ? `<span>${file}</span>` : ''} <div data-aubade="toolbar"> ${icon('list', 'Toggle\nNumbering')} ${icon('clipboard', 'Copy')} </div> </header> <div data-aubade="pre" ${attrs.join('\n\t\t')} class="aubade language-${rest.language || 'none'}" >${highlighted.trim()}</div> </pre>`; } function icon(name, tooltip) { const span = `<span data-aubade="tooltip">${tooltip}</span>`; return `<button data-aubade-toolbar="${name}">${span}</button>`; }