@fsegurai/marked-extended-accordion
v17.0.0
Published
Extension for Marked.js that adds support for extended accordion blocks, allowing the creation of expandable panels with content. It supports any Markdown rendering and can be customized to fit your needs.
Downloads
106
Maintainers
Readme
An extension library for Marked.js to enhance Markdown rendering.
@fsegurai/marked-extended-accordion Extension for Marked.js that adds support for extended accordion blocks, allowing the creation of expandable panels with content. It supports any Markdown rendering and can be customized to fit your needs.
🎯 Overview
The marked-extended-accordion extension enables you to create interactive, collapsible accordion panels within your Markdown documents. Built for the powerful Marked.js parser, this extension transforms simple Markdown syntax into accessible, animated accordion components.
✨ Key Features
- 🎨 Customizable Styling: Full control over appearance with CSS/SCSS
- ♿ Accessibility First: Built-in ARIA attributes and keyboard navigation
- 🔄 Nested Support: Create multi-level accordion structures
- ⚡ Performance Optimized: Minimal overhead, smooth animations
- 🎛️ Flexible Configuration: Extensive options for customization
- 📱 Responsive: Works seamlessly across all device sizes
- 🌗 Theme Support: Light and dark mode out of the box
- 🔧 Framework Agnostic: Works with React, Vue, Angular, Svelte, and vanilla JS
🎪 Live Demo
Experience the accordion extension in action: View Demo
Table of contents
Installation
To add @fsegurai/marked-extended-accordion along with Marked.js to your package.json use the following commands.
bun install @fsegurai/marked-extended-accordion marked@^17 --saveUsage
Basic Usage
Import @fsegurai/marked-extended-accordion and apply it to your Marked instance as shown below.
Quick Start
Basic Syntax
accordion is the identifier for the extended accordion block. Use the following syntax to create an accordion:
::::accordion{title="Your Title"}
Your content goes here...
::::accordionendimport { marked } from 'marked';
import markedExtendedAccordion from '@fsegurai/marked-extended-accordion';
// or UMD script
// <script src="https://cdn.jsdelivr.net/npm/marked/lib/marked.umd.js"></script>
// <script src="https://cdn.jsdelivr.net/npm/@fsegurai/marked-extended-accordion/lib/index.umd.js"></script>
marked.use(markedExtendedAccordion());
### Installation
Install the package using your preferred package manager:
```bash
# Using Bun (recommended)
bun add @fsegurai/marked-extended-accordion
# Using npm
npm install @fsegurai/marked-extended-accordion
# Using yarn
yarn add @fsegurai/marked-extended-accordion
# Using pnpm
pnpm add @fsegurai/marked-extended-accordionBasic Implementation
import {marked} from 'marked';
import markedExtendedAccordion from '@fsegurai/marked-extended-accordion';
// Import styles (required for functionality)
import '@fsegurai/marked-extended-accordion/styles/accordion.css';
// Optional: Import theme for styled appearance
import '@fsegurai/marked-extended-accordion/styles/accordion-theme.css';
// Register the extension
marked.use(markedExtendedAccordion());
// Your markdown content
const markdown = `
::::accordion{title="Simple Accordion"}
This is the content of the accordion.
- Item 1
- Item 2
::::accordionend
::::accordion{title="Expanded Accordion" expanded="true"}
This accordion is expanded by default.
::::accordionend
::::accordion{title="Custom Heading Level" level="2"}
This accordion uses an H2 heading for better document structure.
::::accordionend
::::accordion{title="Custom Animation" duration="0.5s"}
This accordion has a custom animation duration.
::::accordionend
`;
// Parse and render
const html = marked.parse(markdown);
console.log(html);Syntax & Usage
The accordion syntax supports multiple properties to customize behavior and appearance:
::::accordion{title="Title" expanded="false" level="3" duration="0.3s"}
Your content here...
::::accordionendAvailable Properties:
| Property | Type | Default | Description |
|------------|-----------|----------|-------------------------------------------------|
| title | string | "" | The header text displayed on the accordion |
| expanded | boolean | false | Whether the accordion is open by default |
| level | number | 3 | Heading level (1-6) for semantic HTML structure |
| duration | string | "0.3s" | Animation duration (CSS time value) |
Examples:
<!-- Minimal accordion -->
::::accordion{title="Basic Example"}
Content here
::::accordionend
<!-- Expanded by default -->
::::accordion{title="Pre-opened" expanded="true"}
This content is visible on page load
::::accordionend
<!-- Custom heading level for better SEO -->
::::accordion{title="Section Heading" level="2"}
Using H2 for better document outline
::::accordionend
<!-- Slower animation -->
::::accordion{title="Smooth Animation" duration="0.5s"}
Content with slower transition
::::accordionend
### Importing Styles
Starting from version 17.0.0, this extension **does not automatically inject styles**. You must import the CSS or SCSS
files manually to ensure proper styling.
#### Option 1: Using CSS (Recommended for most projects)
```javascript
// Import minimal structural styles (required for functionality)
import '@fsegurai/marked-extended-accordion/styles/accordion.css';
// Optional: Import the basic theme
import '@fsegurai/marked-extended-accordion/styles/accordion-theme.css';Or in your HTML (Node.js projects):
<link rel="stylesheet" href="node_modules/@fsegurai/marked-extended-accordion/styles/accordion.css">
<link rel="stylesheet" href="node_modules/@fsegurai/marked-extended-accordion/styles/accordion-theme.css">Or using CDN (vanilla HTML/JavaScript projects):
<!-- Latest version -->
<link rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/@fsegurai/marked-extended-accordion@latest/styles/accordion.css">
<link rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/@fsegurai/marked-extended-accordion@latest/styles/accordion-theme.css">
<!-- Or lock to a specific version (recommended for production) -->
<link rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/@fsegurai/[email protected]/styles/accordion.css">
<link rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/@fsegurai/[email protected]/styles/accordion-theme.css">Option 2: Using SCSS (For customization)
// Import structural styles with customizable variables
@import '@fsegurai/marked-extended-accordion/styles/accordion.scss';
// Optional: Import theme with customizable variables
@import '@fsegurai/marked-extended-accordion/styles/accordion-theme.scss';
// Customize SCSS variables before importing (optional)
$accordion-animation-duration: 0.5s;
$accordion-border-color-light: #007bff;
@import '@fsegurai/marked-extended-accordion/styles/accordion-theme.scss';Available Style Files
| File | Purpose | Required |
|-------------------------------|------------------------------------------|-----------------------|
| styles/accordion.css | Minimal structural CSS for functionality | ✅ Yes |
| styles/accordion.scss | SCSS version with customizable variables | ✅ Yes (if using SCSS) |
| styles/accordion-theme.css | Example theme with light/dark mode | ❌ Optional |
| styles/accordion-theme.scss | SCSS theme with customizable variables | ❌ Optional |
Angular Integration
For Angular projects using ngx-markdown:
// In your angular.json, add the CSS file to styles array:
{
"styles"
:
[
"node_modules/@fsegurai/marked-extended-accordion/styles/accordion.css",
"node_modules/@fsegurai/marked-extended-accordion/styles/accordion-theme.css",
// ... other styles
]
}
// Or import in your global styles.scss:
@import '@fsegurai/marked-extended-accordion/styles/accordion.scss';
@import '@fsegurai/marked-extended-accordion/styles/accordion-theme.scss';Vanilla HTML/JavaScript Example
Complete example for projects without build tools:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Marked Extended Accordion Example</title>
<!-- Import Marked.js from CDN -->
<script src="https://cdn.jsdelivr.net/npm/marked@17/lib/marked.umd.js"></script>
<!-- Import Accordion Extension from CDN -->
<script src="https://cdn.jsdelivr.net/npm/@fsegurai/marked-extended-accordion@latest/dist/index.umd.js"></script>
<!-- Import Accordion Styles from CDN -->
<link rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/@fsegurai/marked-extended-accordion@latest/styles/accordion.css">
<link rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/@fsegurai/marked-extended-accordion@latest/styles/accordion-theme.css">
</head>
<body>
<div id="content"></div>
<script>
// Configure marked with the accordion extension
marked.use(markedExtendedAccordion());
// Your markdown content
const markdown = `
::::accordion{title="Simple Accordion"}
This is the content of the accordion.
- Item 1
- Item 2
::::accordionend
::::accordion{title="Expanded Accordion" expanded="true"}
This accordion is expanded by default.
::::accordionend
`;
// Render the markdown
document.getElementById('content').innerHTML = marked.parse(markdown);
</script>
</body>
</html>Styling Your Accordions
This extension follows a separation of concerns approach, injecting only minimal structural CSS required for accordion functionality (layout, positioning, display). Visual styling is completely separated, giving you maximum flexibility to match your design system.
Generated HTML Structure
The extension generates semantic HTML using native <details> and <summary> elements:
<details id="accordion-{unique-id}" class="marked-extended-accordion" open>
<summary class="marked-extended-accordion-header">
<h3 class="marked-extended-accordion-title">Your Title</h3>
</summary>
<div class="marked-extended-accordion-content">
<!-- Your markdown content rendered here -->
</div>
</details>Benefits of using <details>:
- ✅ Native browser support (no JavaScript required for basic functionality)
- ✅ Built-in accessibility features
- ✅ Better SEO as content is in the DOM
- ✅ Keyboard navigation works by default
CSS Classes Reference
| Class | Element | Purpose |
|--------------------------------------|-----------|----------------------------------|
| .marked-extended-accordion | details | Main container element |
| .marked-extended-accordion-header | summary | Clickable header/trigger element |
| .marked-extended-accordion-title | h1-h6 | Title text element |
| .marked-extended-accordion-content | div | Content wrapper |
Styling Targets:
- Container: Border, margin, border-radius, background
- Header: Background, padding, cursor, hover effects
- Title: Font size, weight, color, spacing
- Content: Padding, background, animations
Styling Methods
Method 1: Use the Provided Theme File (Quickest)
View: accordion-theme.css
Includes base styles + light/dark theme support
Copy to your project:
Method 2: Custom CSS (Full Control)
Create your own styles targeting the classes:
/* Base accordion styling */
.marked-extended-accordion {
border: 1px solid #e0e0e0;
border-radius: 8px;
margin: 1rem 0;
background: #fff;
overflow: hidden;
}
/* Header (summary) styling */
.marked-extended-accordion-header {
padding: 1rem;
background: #f5f5f5;
cursor: pointer;
list-style: none; /* Remove default marker */
transition: background-color 0.2s ease;
}
/* Remove default disclosure triangle in WebKit browsers */
.marked-extended-accordion-header::-webkit-details-marker {
display: none;
}
.marked-extended-accordion-header:hover {
background: #ebebeb;
}
/* Title styling */
.marked-extended-accordion-title {
margin: 0;
font-size: 1.1rem;
font-weight: 600;
color: #333;
display: inline;
}
/* Add custom icon using pseudo-element */
.marked-extended-accordion-header::before {
content: '▶';
display: inline-block;
margin-right: 0.5rem;
transition: transform 0.3s ease;
color: #666;
}
/* Rotate icon when expanded */
.marked-extended-accordion[open] .marked-extended-accordion-header::before {
transform: rotate(90deg);
}
/* Content styling */
.marked-extended-accordion-content {
padding: 1rem;
background: #fff;
}
/* Smooth opening animation */
@keyframes accordion-open {
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.marked-extended-accordion[open] .marked-extended-accordion-content {
animation: accordion-open 0.3s ease;
}Method 3: CSS Variables (Theme-Aware)
Use CSS variables for easy theming:
:root {
--accordion-border: #e0e0e0;
--accordion-bg: #ffffff;
--accordion-header-bg: #f5f5f5;
--accordion-header-hover: #ebebeb;
--accordion-text: #333;
--accordion-icon: #666;
}
/* Apply variables to classes */
.marked-extended-accordion {
border: 1px solid var(--accordion-border);
background: var(--accordion-bg);
}
.marked-extended-accordion-header {
background: var(--accordion-header-bg);
}
.marked-extended-accordion-header:hover {
background: var(--accordion-header-hover);
}
.marked-extended-accordion-title {
color: var(--accordion-text);
}
.marked-extended-accordion-icon {
color: var(--accordion-icon);
}Dark Mode Support
Add dark theme overrides:
/* Light theme (default) */
body.light .marked-extended-accordion {
border-color: #e0e0e0;
background: #ffffff;
}
body.light .marked-extended-accordion-header {
background: #f5f5f5;
color: #333;
}
/* Dark theme */
body.dark .marked-extended-accordion {
border-color: #444c56;
background: #22272e;
}
body.dark .marked-extended-accordion-header {
background: #2d333b;
color: #d1d5da;
}
body.dark .marked-extended-accordion-header:hover {
background: #343b45;
}
body.dark .marked-extended-accordion-content {
color: #d1d5da;
}Accessibility Considerations
The extension uses native <details> and <summary> elements which provide built-in accessibility:
✅ Native keyboard support: Space/Enter to toggle
✅ Screen reader compatible: Announces state changes automatically
✅ Semantic HTML: Better for SEO and assistive technologies
✅ No JavaScript required: Works even if JS is disabled
Enhance keyboard navigation styling:
/* Focus styles for keyboard navigation */
.marked-extended-accordion-header:focus {
outline: 2px solid #0066cc;
outline-offset: 2px;
}
.marked-extended-accordion-header:focus-visible {
outline: 2px solid #0066cc;
outline-offset: 2px;
}
/* Remove outline for mouse users (but keep for keyboard) */
.marked-extended-accordion-header:focus:not(:focus-visible) {
outline: none;
}
/* High contrast mode support */
@media (prefers-contrast: high) {
.marked-extended-accordion {
border-width: 2px;
}
.marked-extended-accordion-header {
border: 2px solid currentColor;
}
}
/* Reduced motion support */
@media (prefers-reduced-motion: reduce) {
.marked-extended-accordion-header::before,
.marked-extended-accordion-content {
transition: none;
animation: none;
}
}Example: Minimal Modern Style
.marked-extended-accordion {
border: none;
border-left: 3px solid #0066cc;
margin: 1.5rem 0;
background: transparent;
}
.marked-extended-accordion-header {
padding: 0.75rem 1rem;
background: rgba(0, 102, 204, 0.05);
border-radius: 4px;
list-style: none;
}
.marked-extended-accordion-header::-webkit-details-marker {
display: none;
}
.marked-extended-accordion[open] .marked-extended-accordion-header {
background: rgba(0, 102, 204, 0.1);
border-radius: 4px 4px 0 0;
}
.marked-extended-accordion-content {
padding: 1rem 1rem 1rem 1.5rem;
}Check the demo to see various styling examples in action.
Aliases
For convenience, the accordion block supports shorthand aliases. You can use these alternative syntaxes:
Available Aliases
Start Tags:
::::accordion{...}(full syntax):accordion{...}(short syntax):acd{...}(shortest syntax)
End Tags:
::::accordionend(full syntax):accordionend(short syntax):acdend(shortest syntax)
Examples Using Aliases
<!-- Full syntax -->
::::accordion{title="Full Syntax"}
Content here
::::accordionend
<!-- Short syntax -->
:accordion{title="Short Syntax"}
Content here
:accordionend
<!-- Shortest syntax -->
:acd{title="Shortest Syntax"}
Content here
:acdendNote: You can mix and match start/end aliases, but it's recommended to use consistent syntax throughout your document for readability.
Configuration Options
The accordion extension accepts several configuration options when initializing. Pass them as an object to the extension function:
marked.use(markedExtendedAccordion({
className: 'my-accordion',
prefixId: 'acc-',
animationDuration: '0.5s',
template: null,
customizeToken: null
}));Extension Options
| Option | Type | Default | Description |
|---------------------|------------|-------------------------------|------------------------------------------------------------------------------------|
| className | string | 'marked-extended-accordion' | Base CSS class name applied to all accordion containers |
| prefixId | string | 'accordion-' | Prefix for generating unique accordion IDs |
| animationDuration | string | '0.3s' | Default animation duration (can be overridden per accordion) |
| template | string | null | Custom HTML template for rendering (see Custom Templates) |
| customizeToken | function | null | Function to customize tokens before rendering |
Markdown Syntax Properties
These properties are specified in the accordion's opening tag:
| Property | Type | Default | Description |
|------------|----------|-----------|------------------------------------------------------------------|
| title | string | "" | The header text displayed on the accordion |
| expanded | string | "false" | Whether the accordion is open by default ("true" or "false") |
| level | string | "3" | Heading level (1-6) for semantic HTML structure |
| duration | string | "1s" | Animation duration override (CSS time value) |
Configuration Examples
Custom Class Names:
marked.use(markedExtendedAccordion({
className: 'custom-accordion'
}));Custom ID Prefix:
marked.use(markedExtendedAccordion({
prefixId: 'faq-'
}));
// Generates IDs like: faq-abc123, faq-def456, etc.Global Animation Duration:
marked.use(markedExtendedAccordion({
animationDuration: '0.5s'
}));Advanced Token Customization:
marked.use(markedExtendedAccordion({
customizeToken: (token) => {
// Auto-expand accordions with "Important" in the title
if (token.meta.title.includes('Important')) {
token.meta.expanded = true;
}
// Apply custom class based on content
if (token.meta.content.includes('warning')) {
token.meta.className += ' warning-accordion';
}
// Log for debugging
console.log('Processing accordion:', token.meta.title);
}
}));Note: For styling, you must manually import CSS/SCSS files (see Importing Styles section).
Advanced Examples
Multi-Level Nested Accordions
::::accordion{title="Level 1: Project Overview"}
This is the main project section.
::::accordion{title="Level 2: Phase 1 Details"}
Details about phase 1 of the project.
- Planning
- Design
- Development
::::accordionend
::::accordion{title="Level 2: Phase 2 Details"}
Details about phase 2 of the project.
::::accordionend
::::accordionendFAQ Section with Custom Styling
::::accordion{title="What is Marked.js?" class="faq-item"}
Marked.js is a markdown parser and compiler. Built for speed and extensibility.
::::accordionend
::::accordion{title="How do I install extensions?" class="faq-item"}
Use your preferred package manager:
\`\`\`bash
bun add @fsegurai/marked-extended-accordion
\`\`\`
::::accordionend
::::accordion{title="Is it free to use?" class="faq-item" expanded="true"}
Yes! This extension is MIT licensed and completely free to use in commercial and personal projects.
::::accordionendDocumentation Sections
::::accordion{title="API Reference" level="2"}
## Authentication
The API uses OAuth 2.0 for authentication.
### Endpoints
| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | /api/v1/users | List users |
| POST | /api/v1/users | Create user |
### Code Example
\`\`\`javascript
const response = await fetch('/api/v1/users', {
headers: {
'Authorization': 'Bearer YOUR_TOKEN'
}
});
\`\`\`
::::accordionendInteractive Tutorial Steps
::::accordion{title="Step 1: Installation" expanded="true" level="3"}
Install the required packages:
\`\`\`bash
bun add marked @fsegurai/marked-extended-accordion
\`\`\`
::::accordionend
::::accordion{title="Step 2: Configuration" level="3"}
Import and configure the extension:
\`\`\`javascript
import { marked } from 'marked';
import markedExtendedAccordion from '@fsegurai/marked-extended-accordion';
marked.use(markedExtendedAccordion({
animationDuration: '0.5s'
}));
\`\`\`
::::accordionend
::::accordion{title="Step 3: Usage" level="3"}
Write your markdown with accordion syntax:
\`\`\`markdown
::::accordion{title="My First Accordion"}
Content goes here
::::accordionend
\`\`\`
::::accordionendAdvanced Configuration
Custom Token Manipulation
import {marked} from 'marked';
import markedExtendedAccordion from '@fsegurai/marked-extended-accordion';
marked.use(markedExtendedAccordion({
customizeToken: (token) => {
// Add custom data attributes
if (token.props.title.includes('Important')) {
token.props.class = (token.props.class || '') + ' important-accordion';
}
// Auto-expand accordions with specific keywords
if (token.props.title.toLowerCase().includes('getting started')) {
token.props.expanded = 'true';
}
// Log for debugging
console.log('Processing accordion:', token.props.title);
}
}));Custom HTML Template
You can provide a custom HTML template for complete control over the structure:
marked.use(markedExtendedAccordion({
template: `
<details id="{accordionId}" class="{className}" {expandedAttr}>
<summary class="{className}-header">
<span class="icon">➤</span>
<{headingTag} class="{className}-title">{title}</{headingTag}>
</summary>
<div class="{className}-content" style="animation-duration: {animationDuration}">
{content}
</div>
</details>
`
}));Available Placeholders:
| Placeholder | Description | Example Value |
|-----------------------|-----------------------------------------------|-----------------------------|
| {accordionId} | Unique identifier for the accordion | accordion-abc123 |
| {className} | Base CSS class name | marked-extended-accordion |
| {expandedAttr} | open attribute if expanded, empty otherwise | open or `` |
| {headingTag} | HTML heading tag based on level | h2, h3, etc. |
| {title} | Accordion title text | My Accordion |
| {content} | Rendered markdown content | <p>Content...</p> |
| {animationDuration} | Animation duration value | 0.3s |
| {expanded} | Boolean string value | true or false |
Example: Card-Style Template
marked.use(markedExtendedAccordion({
template: `
<details id="{accordionId}" class="accordion-card" {expandedAttr}>
<summary class="accordion-card-header">
<div class="accordion-card-header-content">
<{headingTag} class="accordion-card-title">{title}</{headingTag}>
<span class="accordion-card-icon" aria-hidden="true">
<svg width="24" height="24" viewBox="0 0 24 24">
<path d="M7 10l5 5 5-5z"/>
</svg>
</span>
</div>
</summary>
<div class="accordion-card-body">
<div class="accordion-card-content">
{content}
</div>
</div>
</details>
`
}));Performance Tips
Native Details Element: This extension uses the native
<details>element, which has excellent performance as it's handled natively by the browser.CSS Animations: Use CSS transforms for better performance:
.marked-extended-accordion-content {
transform-origin: top;
transition: transform 0.3s ease, opacity 0.3s ease;
}
/* Use will-change sparingly, only when needed */
.marked-extended-accordion-header:hover ~ .marked-extended-accordion-content {
will-change: transform, opacity;
}Limit Nesting Depth: For optimal performance, limit nested accordions to 2-3 levels deep.
Content Loading: For very large content blocks, consider using
content-visibility:
.marked-extended-accordion-content {
content-visibility: auto;
contain-intrinsic-size: 0 500px; /* Estimated height */
}Reduce Reflows: Batch DOM updates when manipulating multiple accordions programmatically.
Animation Duration: Keep animation durations between 200-400ms for the best perceived performance.
Accessibility Features
This extension leverages native HTML <details> and <summary> elements for excellent built-in accessibility:
- ✅ Native Keyboard Navigation: Space/Enter keys toggle accordions automatically
- ✅ Screen Reader Support: State changes are announced automatically
- ✅ Semantic HTML Structure: Uses proper heading levels for document outline
- ✅ No JavaScript Required: Core functionality works without JavaScript
- ✅ Focus Management: Built-in focus handling by the browser
- ✅ WCAG 2.1 Compliant: Meets accessibility standards out of the box
Best Practices for Accessibility
- Use Appropriate Heading Levels: Maintain proper document hierarchy
::::accordion{title="Main Section" level="2"}
Content
::::accordionend
::::accordion{title="Subsection" level="3"}
Content
::::accordionend- Provide Descriptive Titles: Make accordion titles clear and descriptive
<!-- Good -->
::::accordion{title="How to install the extension"}
Installation instructions...
::::accordionend
<!-- Avoid -->
::::accordion{title="Click here"}
Content...
::::accordionendAdd Focus Styles: Ensure keyboard users can see focus ( see Accessibility Considerations)
Respect User Preferences: Support reduced motion and high contrast modes (included in examples above)
Test with Assistive Technologies: Regularly test with screen readers and keyboard-only navigation
Programmatic Control
You can control accordions programmatically while maintaining accessibility:
// Open an accordion
const accordion = document.getElementById('accordion-abc123');
accordion.open = true;
// Close an accordion
accordion.open = false;
// Toggle an accordion
accordion.open = !accordion.open;
// Listen for toggle events
accordion.addEventListener('toggle', (event) => {
console.log('Accordion is now:', accordion.open ? 'open' : 'closed');
});Troubleshooting
Accordion Not Expanding/Collapsing
Problem: Clicking the accordion header doesn't toggle the content.
Solutions:
- Ensure you've imported the structural CSS:
import '@fsegurai/marked-extended-accordion/styles/accordion.css' - Check for conflicting CSS that might disable pointer events:
/* Remove if present */ .marked-extended-accordion-header { pointer-events: none; /* ❌ This breaks functionality */ } - Verify no JavaScript errors in browser console
- Make sure you're not preventing default on click events for the
<summary>element
Styling Not Applied
Problem: Accordions appear unstyled or broken.
Solutions:
- Import both structural and theme CSS files:
import '@fsegurai/marked-extended-accordion/styles/accordion.css'; import '@fsegurai/marked-extended-accordion/styles/accordion-theme.css'; - Check CSS specificity - your styles might be overridden. Use browser DevTools to inspect.
- Verify the CSS files are being bundled correctly in your build process
- For CDN usage, ensure the URLs are correct and files are loading (check Network tab)
Default Disclosure Triangle Visible
Problem: Browser's default triangle/arrow appears alongside custom styling.
Solution: Hide the default marker:
.marked-extended-accordion-header::-webkit-details-marker {
display: none;
}
.marked-extended-accordion-header {
list-style: none; /* Firefox */
}Content Overflow Issues
Problem: Content overflows the accordion boundaries.
Solution:
.marked-extended-accordion-content {
overflow: hidden;
word-wrap: break-word;
overflow-wrap: break-word;
}
/* For code blocks */
.marked-extended-accordion-content pre {
overflow-x: auto;
max-width: 100%;
}Animation Issues
Problem: Accordion animations are jerky or don't work smoothly.
Solutions:
- The native
<details>element doesn't animate smoothly by default. For smooth animations, you may need custom JavaScript or CSS:
/* Smooth animation with max-height trick */
.marked-extended-accordion-content {
max-height: 0;
overflow: hidden;
transition: max-height 0.3s ease-out;
}
.marked-extended-accordion[open] .marked-extended-accordion-content {
max-height: 2000px; /* Large enough value */
transition: max-height 0.3s ease-in;
}- Use
will-changesparingly for better performance:
.marked-extended-accordion:hover .marked-extended-accordion-content {
will-change: max-height;
}Nested Accordions Not Working
Problem: Nested accordions don't render properly.
Solutions:
- Ensure proper syntax with matching start/end tags
- Check nesting depth - avoid going beyond 3 levels
- Verify there are no syntax errors in the markdown
Valid nesting:
::::accordion{title="Outer"}
Content here
::::accordion{title="Inner"}
Nested content
::::accordionend
More outer content
::::accordionendIntegration Examples
Next.js Integration
// app/layout.tsx
import '@fsegurai/marked-extended-accordion/styles/accordion.css';
import '@fsegurai/marked-extended-accordion/styles/accordion-theme.css';
// app/markdown-renderer.tsx
'use client';
import {marked} from 'marked';
import markedExtendedAccordion from '@fsegurai/marked-extended-accordion';
import {useEffect, useState} from 'react';
marked.use(markedExtendedAccordion());
export default function MarkdownRenderer({content}: { content: string }) {
const [html, setHtml] = useState('');
useEffect(() => {
setHtml(marked.parse(content));
}, [content]);
return <div dangerouslySetInnerHTML={{__html: html}}/>;
}Vue 3 Integration
<script setup lang="ts">
import { marked } from 'marked';
import markedExtendedAccordion from '@fsegurai/marked-extended-accordion';
import '@fsegurai/marked-extended-accordion/styles/accordion.css';
import '@fsegurai/marked-extended-accordion/styles/accordion-theme.css';
import { ref, computed } from 'vue';
marked.use(markedExtendedAccordion());
const markdown = ref(`
::::accordion{title="Example"}
Content here
::::accordionend
`);
const html = computed(() => marked.parse(markdown.value));
</script>
<template>
<div v-html="html" />
</template>Svelte Integration
<script lang="ts">
import { marked } from 'marked';
import markedExtendedAccordion from '@fsegurai/marked-extended-accordion';
import '@fsegurai/marked-extended-accordion/styles/accordion.css';
marked.use(markedExtendedAccordion());
let markdown = `::::accordion{title="Example"}
Content
::::accordionend`;
$: html = marked.parse(markdown);
</script>
<div>{@html html}</div>Best Practices
1. Semantic Structure
Use appropriate heading levels to maintain proper document hierarchy:
<!-- Good: Maintains logical hierarchy -->
::::accordion{title="Chapter 1: Introduction" level="2"}
Content for chapter 1
::::accordion{title="Section 1.1: Getting Started" level="3"}
Nested content
::::accordionend
::::accordionend
<!-- Avoid: Skipping heading levels -->
::::accordion{title="Main Topic" level="2"}
::::accordion{title="Subtopic" level="5"} <!-- ❌ Skips h3 and h4 -->
::::accordionend
::::accordionend2. Progressive Enhancement
Design content to be accessible even if JavaScript or CSS fails:
::::accordion{title="Important Information"}
Always write content that makes sense even when fully expanded.
Don't rely on the accordion state for critical information visibility.
::::accordionend3. Clear, Descriptive Titles
Use meaningful titles that describe the content:
<!-- Good: Descriptive -->
::::accordion{title="How to install the extension"}
Installation steps...
::::accordionend
<!-- Avoid: Vague -->
::::accordion{title="More info"}
Content...
::::accordionend4. Optimal Default States
Consider which accordions should be open by default:
<!-- Expand important or frequently accessed content -->
::::accordion{title="Quick Start Guide" expanded="true"}
Most users need this information first
::::accordionend
<!-- Keep optional details collapsed -->
::::accordion{title="Advanced Configuration"}
Optional advanced settings
::::accordionend5. Mobile Optimization
Ensure tap targets are large enough (minimum 44×44px):
.marked-extended-accordion-header {
min-height: 44px;
padding: 12px 16px;
}6. Limit Nesting Depth
Keep nesting to 2-3 levels maximum for optimal UX and performance:
<!-- Recommended: 2 levels -->
::::accordion{title="Level 1"}
::::accordion{title="Level 2"}
Content
::::accordionend
::::accordionend
<!-- Avoid: Too deep -->
::::accordion{title="Level 1"}
::::accordion{title="Level 2"}
::::accordion{title="Level 3"}
::::accordion{title="Level 4"} <!-- ❌ Too complex -->
::::accordionend
::::accordionend
::::accordionend
::::accordionend7. Animation Duration
Keep animations short and snappy (200-400ms):
marked.use(markedExtendedAccordion({
animationDuration: '0.3s' // ✅ Good balance
}));
// Avoid very slow animations
marked.use(markedExtendedAccordion({
animationDuration: '2s' // ❌ Too slow, feels sluggish
}));8. Content Length
Keep individual accordion content reasonable in length:
<!-- Good: Focused content -->
::::accordion{title="Installation"}
Run: `npm install package-name`
::::accordionend
<!-- Avoid: Overly long content -->
::::accordion{title="Everything About Our Product"}
<!-- ❌ Thousands of lines of content -->
::::accordionend9. Group Related Content
Use accordions to organize related information:
<!-- Good: Logical grouping -->
::::accordion{title="Getting Started"}
Installation, setup, and first steps
::::accordionend
::::accordion{title="Configuration"}
All configuration options
::::accordionend
::::accordion{title="API Reference"}
API documentation
::::accordionend10. Test Across Devices
Always test your accordions on:
- Desktop browsers (Chrome, Firefox, Safari, Edge)
- Mobile devices (iOS Safari, Android Chrome)
- With keyboard navigation only
- With screen readers
- In both light and dark modes
Migration from v16.x
If upgrading from v16.x, note these breaking changes:
- Styles no longer auto-inject - you must import CSS/SCSS manually
- Remove
injectStylesoption - this option has been removed
// Old (v16.x)
marked.use(markedExtendedAccordion({injectStyles: true}));
// New (v17.x)
import '@fsegurai/marked-extended-accordion/styles/accordion.css';
marked.use(markedExtendedAccordion());See MIGRATION.md for complete migration guide.
API Reference
Extension Options
interface AccordionOptions {
className?: string; // Base CSS class (default: 'marked-extended-accordion')
prefixId?: string; // ID prefix (default: 'accordion-')
animationDuration?: string; // Animation duration (default: '0.3s')
template?: string | null; // Custom HTML template (default: null)
customizeToken?: (token: AccordionToken) => void; // Token customization function
}Markdown Syntax
::::accordion{prop1="value1" prop2="value2"}
Content
::::accordionendAvailable properties:
title(string): Accordion header textexpanded("true" | "false"): Initial statelevel(1-6): Heading levelclass(string): Additional CSS classesduration(string): Custom animation duration
Real-World Use Cases
1. FAQ Pages
Create expandable frequently asked questions:
::::accordion{title="What is Marked.js?" expanded="true"}
Marked.js is a fast, lightweight markdown parser and compiler. It's built for speed and extensibility.
::::accordionend
::::accordion{title="How do I install extensions?"}
Use your preferred package manager:
\`\`\`bash
bun add @fsegurai/marked-extended-accordion
\`\`\`
::::accordionend
::::accordion{title="Is it free to use?"}
Yes! This extension is MIT licensed and completely free for commercial and personal use.
::::accordionend2. Documentation Sections
Organize API documentation or technical guides:
::::accordion{title="API Authentication" level="2"}
## Overview
The API uses OAuth 2.0 for authentication.
### Endpoints
| Method | Endpoint | Description |
|--------|----------|-------------|
| POST | /oauth/token | Get access token |
### Example
\`\`\`javascript
const token = await getAccessToken(clientId, clientSecret);
\`\`\`
::::accordionend3. Interactive Tutorials
Create step-by-step learning experiences:
::::accordion{title="Step 1: Installation" expanded="true" level="3"}
First, install the required packages:
\`\`\`bash
npm install marked @fsegurai/marked-extended-accordion
\`\`\`
::::accordionend
::::accordion{title="Step 2: Configuration" level="3"}
Configure the extension in your code:
\`\`\`javascript
import { marked } from 'marked';
import markedExtendedAccordion from '@fsegurai/marked-extended-accordion';
marked.use(markedExtendedAccordion());
\`\`\`
::::accordionend4. Product Features
Showcase product capabilities in an organized manner:
::::accordion{title="🚀 Performance Features"}
- Lightning-fast parsing
- Minimal bundle size
- Optimized rendering
::::accordionend
::::accordion{title="🎨 Customization Options"}
- Custom themes
- CSS variables
- Template overrides
::::accordionend
::::accordion{title="♿ Accessibility"}
- WCAG 2.1 compliant
- Screen reader support
- Keyboard navigation
::::accordionend5. Privacy Policies & Legal Documents
Make long documents more digestible:
::::accordion{title="1. Information We Collect" level="2"}
We collect information you provide directly to us...
::::accordionend
::::accordion{title="2. How We Use Your Information" level="2"}
We use the information we collect to...
::::accordionend
::::accordion{title="3. Information Sharing" level="2"}
We may share your information in the following circumstances...
::::accordionend6. Release Notes / Changelogs
Organize version history:
::::accordion{title="Version 2.0.0 - January 2024" expanded="true"}
### Breaking Changes
- Removed deprecated API methods
### New Features
- Added custom template support
- Improved accessibility
### Bug Fixes
- Fixed animation glitches
::::accordionend
::::accordion{title="Version 1.5.0 - December 2023"}
### New Features
- Added dark mode support
::::accordionend7. Course Curriculum
Structure educational content:
::::accordion{title="Week 1: Introduction to JavaScript" level="2"}
::::accordion{title="Lesson 1.1: Variables and Data Types" level="3"}
Learn about var, let, and const...
::::accordionend
::::accordion{title="Lesson 1.2: Functions" level="3"}
Understanding function declarations...
::::accordionend
::::accordionend8. Troubleshooting Guides
Organize problem-solution pairs:
::::accordion{title="Installation Issues"}
**Problem**: Package fails to install
**Solution**: Clear your package manager cache...
::::accordionend
::::accordion{title="Build Errors"}
**Problem**: Build fails with TypeScript errors
**Solution**: Update your tsconfig.json...
::::accordionendContributing
Found a bug or have a feature request? Please open an issue on GitHub.
Related Resources
Available Extensions
| Extension | Package | Version | Description |
|-------------|--------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------|----------------------------------------------------------------------|
| All - Bundle | @fsegurai/marked-extended-bundle | | Includes all extensions in a single package for easy integration |
| Accordion | @fsegurai/marked-extended-accordion |
| Add collapsible accordion sections to your markdown |
| Alert | @fsegurai/marked-extended-alert |
| Create styled alert boxes for important information |
| Comments | @fsegurai/marked-extended-comments |
| Add comment sections with author and timestamp metadata |
| Embeds | @fsegurai/marked-extended-embeds |
| Easily embed content from various platforms (YouTube, Twitter, etc.) |
| Footnote | @fsegurai/marked-extended-footnote |
| Add footnotes with automatic numbering |
| Kanban | @fsegurai/marked-extended-kanban |
| Create kanban boards with customizable columns and cards |
| Lists | @fsegurai/marked-extended-lists |
| Enhanced list formatting options |
| Slide | @fsegurai/marked-extended-slide |
| Create slide decks directly from markdown content |
| Spoiler | @fsegurai/marked-extended-spoiler |
| Hide content behind spoiler tags |
| Tables | @fsegurai/marked-extended-tables |
| Advanced table formatting with cell spanning |
| Tabs | @fsegurai/marked-extended-tabs |
| Create tabbed content sections |
| Timeline | @fsegurai/marked-extended-timeline |
| Display content in an interactive timeline format |
| Typographic | @fsegurai/marked-extended-typographic |
| Improve typography with smart quotes, dashes, and more |
Demo Application
To see all extensions in action, check out the [DEMO].
To set up the demo locally, follow the next steps:
git clone https://github.com/fsegurai/marked-extensions.git
bun install
bun startThis will serve the application locally at http://[::1]:8000.
License
Licensed under MIT.
