npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@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

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 --save

Usage

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...
::::accordionend
import { 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-accordion

Basic 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...
::::accordionend

Available 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
:acdend

Note: 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
::::accordionend

FAQ 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.
::::accordionend

Documentation 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'
}
});
\`\`\`
::::accordionend

Interactive 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
\`\`\`
::::accordionend

Advanced 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

  1. Native Details Element: This extension uses the native <details> element, which has excellent performance as it's handled natively by the browser.

  2. 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;
}
  1. Limit Nesting Depth: For optimal performance, limit nested accordions to 2-3 levels deep.

  2. 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 */
}
  1. Reduce Reflows: Batch DOM updates when manipulating multiple accordions programmatically.

  2. 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

  1. Use Appropriate Heading Levels: Maintain proper document hierarchy
::::accordion{title="Main Section" level="2"}
Content
::::accordionend

::::accordion{title="Subsection" level="3"}
Content
::::accordionend
  1. 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...
::::accordionend
  1. Add Focus Styles: Ensure keyboard users can see focus ( see Accessibility Considerations)

  2. Respect User Preferences: Support reduced motion and high contrast modes (included in examples above)

  3. 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:

  1. Ensure you've imported the structural CSS:
    import '@fsegurai/marked-extended-accordion/styles/accordion.css'
  2. Check for conflicting CSS that might disable pointer events:
    /* Remove if present */
    .marked-extended-accordion-header {
      pointer-events: none; /* ❌ This breaks functionality */
    }
  3. Verify no JavaScript errors in browser console
  4. Make sure you're not preventing default on click events for the <summary> element

Styling Not Applied

Problem: Accordions appear unstyled or broken.

Solutions:

  1. Import both structural and theme CSS files:
    import '@fsegurai/marked-extended-accordion/styles/accordion.css';
    import '@fsegurai/marked-extended-accordion/styles/accordion-theme.css';
  2. Check CSS specificity - your styles might be overridden. Use browser DevTools to inspect.
  3. Verify the CSS files are being bundled correctly in your build process
  4. 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:

  1. 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;
}
  1. Use will-change sparingly 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:

  1. Ensure proper syntax with matching start/end tags
  2. Check nesting depth - avoid going beyond 3 levels
  3. 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
::::accordionend

Integration 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
::::accordionend

2. 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.
::::accordionend

3. 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...
::::accordionend

4. 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
::::accordionend

5. 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
::::accordionend

7. 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 -->
::::accordionend

9. 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
::::accordionend

10. 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:

  1. Styles no longer auto-inject - you must import CSS/SCSS manually
  2. Remove injectStyles option - 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
::::accordionend

Available properties:

  • title (string): Accordion header text
  • expanded ("true" | "false"): Initial state
  • level (1-6): Heading level
  • class (string): Additional CSS classes
  • duration (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.
::::accordionend

2. 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);
\`\`\`
::::accordionend

3. 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());
\`\`\`
::::accordionend

4. 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
  ::::accordionend

5. 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...
::::accordionend

6. 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
  ::::accordionend

7. 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

::::accordionend

8. 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...
::::accordionend

Contributing

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 | npm | Includes all extensions in a single package for easy integration | | Accordion | @fsegurai/marked-extended-accordion | npm | Add collapsible accordion sections to your markdown | | Alert | @fsegurai/marked-extended-alert | npm | Create styled alert boxes for important information | | Comments | @fsegurai/marked-extended-comments | npm | Add comment sections with author and timestamp metadata | | Embeds | @fsegurai/marked-extended-embeds | npm | Easily embed content from various platforms (YouTube, Twitter, etc.) | | Footnote | @fsegurai/marked-extended-footnote | npm | Add footnotes with automatic numbering | | Kanban | @fsegurai/marked-extended-kanban | npm | Create kanban boards with customizable columns and cards | | Lists | @fsegurai/marked-extended-lists | npm | Enhanced list formatting options | | Slide | @fsegurai/marked-extended-slide | npm | Create slide decks directly from markdown content | | Spoiler | @fsegurai/marked-extended-spoiler | npm | Hide content behind spoiler tags | | Tables | @fsegurai/marked-extended-tables | npm | Advanced table formatting with cell spanning | | Tabs | @fsegurai/marked-extended-tabs | npm | Create tabbed content sections | | Timeline | @fsegurai/marked-extended-timeline | npm | Display content in an interactive timeline format | | Typographic | @fsegurai/marked-extended-typographic | npm | 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 start

This will serve the application locally at http://[::1]:8000.

License

Licensed under MIT.