import { parse } from 'node-html-parser'; import { v4 as uuid } from 'uuid'; /** * Eleventy plugin to turn `` blocks into live examples. */ export function codeExamplesPlugin(options = {}) { options = { container: 'body', ...options }; return function (eleventyConfig) { eleventyConfig.addTransform('code-examples', content => { const doc = parse(content, { blockTextElements: { code: true } }); const container = doc.querySelector(options.container); if (!container) { return content; } // Look for external links container.querySelectorAll('code.example').forEach(code => { const pre = code.closest('pre'); const adjacentPre = pre.nextElementSibling?.localName === 'pre' ? pre.nextElementSibling : null; const adjacentPreForReact = adjacentPre?.querySelector('code.react') ? adjacentPre.querySelector('code') : null; const hasButtons = !code.classList.contains('no-buttons'); const isOpen = code.classList.contains('open') || !hasButtons; const noEdit = code.classList.contains('no-edit'); const id = `code-example-${uuid().slice(-12)}`; let preview = pre.textContent; // Run preview scripts as modules to prevent collisions const root = parse(preview, { blockTextElements: { script: true } }); root.querySelectorAll('script').forEach(script => script.setAttribute('type', 'module')); preview = root.toString(); const codeExample = parse(`
${preview}
HTML ${pre.outerHTML} ${ adjacentPreForReact ? ` React ${adjacentPre.outerHTML} ` : '' }
${ hasButtons ? `
${ noEdit ? '' : ` ` } ` : '' }
`); pre.replaceWith(codeExample); adjacentPre?.remove(); }); return doc.toString(); }); }; }