// Helper function to find matching closing tag function findMatchingClosingTag(src: string, openTag: string, closeTag: string): number { let depth = 1; let index = openTag.length; while (depth > 0 && index < src.length) { if (src.startsWith(openTag, index)) { depth++; } else if (src.startsWith(closeTag, index)) { depth--; } if (depth > 0) { index++; } } return depth === 0 ? index + closeTag.length : -1; } // Function to parse attributes from tag function parseAttributes(tag: string): { [key: string]: string } { const attributes: { [key: string]: string } = {}; const attrRegex = /(\w+)="(.*?)"/g; let match; while ((match = attrRegex.exec(tag)) !== null) { attributes[match[1]] = match[2]; } return attributes; } function detailsTokenizer(src: string) { // Updated regex to capture attributes inside
const detailsRegex = /^]*)?>\n/; const summaryRegex = /^(.*?)<\/summary>\n/; const detailsMatch = detailsRegex.exec(src); if (detailsMatch) { const endIndex = findMatchingClosingTag(src, ''); if (endIndex === -1) return; const fullMatch = src.slice(0, endIndex); const detailsTag = detailsMatch[0]; const attributes = parseAttributes(detailsTag); // Parse attributes from
let content = fullMatch.slice(detailsTag.length, -10).trim(); // Remove
and
let summary = ''; const summaryMatch = summaryRegex.exec(content); if (summaryMatch) { summary = summaryMatch[1].trim(); content = content.slice(summaryMatch[0].length).trim(); } return { type: 'details', raw: fullMatch, summary: summary, text: content, attributes: attributes // Include extracted attributes from
}; } } function detailsStart(src: string) { return src.match(/^
/) ? 0 : -1; } function detailsRenderer(token: any) { const attributesString = token.attributes ? Object.entries(token.attributes) .map(([key, value]) => `${key}="${value}"`) .join(' ') : ''; return `
${token.summary ? `${token.summary}` : ''} ${token.text}
`; } // Extension wrapper function function detailsExtension() { return { name: 'details', level: 'block', start: detailsStart, tokenizer: detailsTokenizer, renderer: detailsRenderer }; } export default function (options = {}) { return { extensions: [detailsExtension(options)] }; }