/* eslint-disable react-refresh/only-export-components */ /** * render.jsx - Markdown-naar-React renderer * * Rendert de block-array uit directives.js naar React elementen. * Elke block-type mapped naar bestaande Tailwind classes uit het project. * Afbeeldingpaden worden automatisch geprefixed met BASE_URL. */ import { useState, useCallback } from 'react'; import { marked } from 'marked'; const BASE_URL = import.meta.env.BASE_URL; // Map van directive keys naar context property namen const CONTEXT_KEY_MAP = { os: 'activeOS' }; /** * Haalt de context-waarde op voor een directive key (bijv. "os" -> context.activeOS). */ function getContextValue(key, context) { const contextKey = CONTEXT_KEY_MAP[key]; return contextKey ? context[contextKey] : context[key]; } /** * Rendert een array van blocks naar React elementen. * * @param {Array} blocks - Geparsde block-array uit parseDocument() * @param {object} context - Gedeelde state: { activeOS, setActiveOS } * @returns {JSX.Element[]} */ export function renderBlocks(blocks, context) { return blocks.map((block, index) => ( )); } function RenderBlock({ block, context }) { switch (block.type) { case 'markdown': return ; case 'tabs': return ; case 'accordion': return ; case 'warning': return ; case 'info': return ; case 'tip': return ; case 'steps': return ; case 'checklist': return ; case 'checklist-verify': return ; case 'command': return ; case 'conditional': return ; case 'conditional-image': return ; case 'troubleshoot': return ; default: return null; } } /** * Zet Markdown om naar HTML met marked, fixt afbeeldingpaden. */ function renderMarkdown(content) { let html = marked.parse(content, { breaks: false }); // Prefix afbeeldingpaden met BASE_URL html = html.replace( /src="(?!https?:\/\/|data:)([^"]+)"/g, `src="${BASE_URL}$1"` ); return html; } /** * Gewone Markdown paragrafen, headings, links, etc. */ function MarkdownBlock({ content }) { return (
); } /** * OS-tabbladen (Mac/Windows). * Hergebruikt de coral button styling uit de originele pagina. */ function TabsBlock({ block, context }) { const { activeOS, setActiveOS } = context; const tabMap = { Mac: 'mac', Windows: 'windows' }; return (
{block.tabs.map((tab) => { const osKey = tabMap[tab.label] || tab.label.toLowerCase(); const isActive = activeOS === osKey; return ( ); })}
{block.tabs.map((tab) => { const osKey = tabMap[tab.label] || tab.label.toLowerCase(); if (activeOS !== osKey) return null; return (
{renderBlocks(tab.blocks, context)}
); })}
); } /** * Uitklapbare accordion sectie. */ function AccordionBlock({ block, context }) { const [open, setOpen] = useState(false); return (
{open && (
{renderBlocks(block.blocks, context)}
)}
); } /** * Waarschuwingsblok (teal achtergrond). */ function WarningBlock({ content }) { return (
); } /** * Informatieblok (warm achtergrond). */ function InfoBlock({ content }) { return (
); } /** * Tipblok (gele achtergrond met lampje). */ function TipBlock({ content }) { return (
💡
); } /** * Genummerde stappen met coral cirkel-iconen. * Gebruikt pre-parsed steps uit de directive parser. * Elke stap heeft: number, text (eerste regel), blocks (geneste directives). */ function StepsBlock({ block, context }) { return (
    {block.steps.map((step) => (
  1. {step.number}
    {step.blocks.length > 0 && renderBlocks(step.blocks, context)}
  2. ))}
); } /** * Checklijst met coral vink-iconen. */ function ChecklistBlock({ content }) { const items = content .split('\n') .filter(line => line.match(/^-\s/)) .map(line => line.replace(/^-\s+/, '')); return (
    {items.map((item, i) => (
  • ))}
); } /** * Verificatie checklijst met teal vinkjes. */ function ChecklistVerifyBlock({ content }) { const items = content .split('\n') .filter(line => line.match(/^-\s/)) .map(line => line.replace(/^-\s+/, '')); return (
    {items.map((item, i) => (
  • ))}
); } /** * Terminal commando blok (donkere achtergrond) met kopieerknop. */ function CommandBlock({ command, content }) { const [copied, setCopied] = useState(false); const handleCopy = useCallback(() => { navigator.clipboard.writeText(content).then(() => { setCopied(true); setTimeout(() => setCopied(false), 2000); }); }, [content]); return (
{command}
{content}
); } /** * Conditioneel blok - toont alleen als de context-waarde matcht. */ function ConditionalBlock({ block, context }) { const contextValue = getContextValue(block.key, context); if (contextValue !== block.value) return null; return <>{renderBlocks(block.blocks, context)}; } /** * Conditionele afbeelding - toont alleen als OS matcht. */ function ConditionalImageBlock({ block, context }) { const contextValue = getContextValue(block.key, context); if (contextValue !== block.value) return null; return (
); } /** * Probleemoplossing kaart. */ function TroubleshootBlock({ title, content }) { return (

{title}

); }