<p align="center">
  <img alt="Marked Extensions Logo" src="https://raw.githubusercontent.com/fsegurai/marked-extensions/main/public/marked-extensions.svg">
</p>

<p align="center">
  <a href="https://github.com/fsegurai/marked-extensions">
      <img src="https://img.shields.io/azure-devops/build/fsegurai/93779823-473d-4fb3-a5b1-27aaa1a88ea2/18/main?label=Build%20Status&"
          alt="Build Main Status">
  </a>
  <a href="https://www.npmjs.org/package/@fsegurai/marked-extended-accordion">
      <img src="https://img.shields.io/npm/v/@fsegurai/marked-extended-accordion.svg"
          alt="Latest Release">
  </a>
  <br>
  <img alt="GitHub contributors" src="https://img.shields.io/github/contributors/fsegurai/marked-extensions">
  <img alt="Dependency status for repo" src="https://img.shields.io/librariesio/github/fsegurai/marked-extensions">
  <a href="https://opensource.org/licenses/MIT">
    <img alt="GitHub License" src="https://img.shields.io/github/license/fsegurai/marked-extensions">
  </a>
  <br>
  <img alt="Stars" src="https://img.shields.io/github/stars/fsegurai/marked-extensions?style=square&labelColor=343b41"/> 
  <img alt="Forks" src="https://img.shields.io/github/forks/fsegurai/marked-extensions?style=square&labelColor=343b41"/>
</p>

**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](https://marked.js.org/) 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](https://fsegurai.github.io/marked-extensions)

---

### Table of contents

- [Installation](#installation)
- [Usage](#usage)
	- [Basic Usage](#basic-usage)
- [Quick Start](#quick-start)
	- [Syntax & Usage](#syntax--usage)
	- [Aliases](#aliases)
	- [Configuration Options](#configuration-options)
	- [Styling Guide](#styling-your-accordions)
	- [Advanced Examples](#advanced-examples)
	- [Framework Integration](#integration-examples)
- [More Resources](#more-resources)
	- [Available Extensions](#available-extensions)
	- [Demo Application](#demo-application)
- [License](#license)

## Installation

To add `@fsegurai/marked-extended-accordion` along with Marked.js to your `package.json` use the following commands.

```bash
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:

```markdown
::::accordion{title="Your Title"}
Your content goes here...
::::accordionend
```

```javascript
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

```javascript
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:

```markdown
::::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:**

```markdown
<!-- 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):

```html

<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):

```html
<!-- 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/marked-extended-accordion@17.0.0/styles/accordion.css">
<link rel="stylesheet"
      href="https://cdn.jsdelivr.net/npm/@fsegurai/marked-extended-accordion@17.0.0/styles/accordion-theme.css">
```

#### Option 2: Using SCSS (For customization)

```scss
// 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`:

```typescript
// 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:

```html
<!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:

```html

<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](https://github.com/fsegurai/marked-extensions/blob/main/packages/accordion/styles/accordion-theme.css)

- Includes base styles + light/dark theme support
- Copy to your project:

   ```html

<link rel="stylesheet" href="path/to/accordion-theme.css">
   ```

**Method 2: Custom CSS** (Full Control)

Create your own styles targeting the classes:

```css
/* 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:

```css
: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:

```css
/* 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:

```css
/* 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

```css
.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](https://fsegurai.github.io/marked-extensions) 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

```markdown
<!-- 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:

```javascript
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](#custom-html-template)) |
| `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:**

```javascript
marked.use(markedExtendedAccordion({
    className: 'custom-accordion'
}));
```

**Custom ID Prefix:**

```javascript
marked.use(markedExtendedAccordion({
    prefixId: 'faq-'
}));
// Generates IDs like: faq-abc123, faq-def456, etc.
```

**Global Animation Duration:**

```javascript
marked.use(markedExtendedAccordion({
    animationDuration: '0.5s'
}));
```

**Advanced Token Customization:**

```javascript
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](#importing-styles) section).

### Advanced Examples

#### Multi-Level Nested Accordions

```markdown
::::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

```markdown
::::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

```markdown
::::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

```markdown
::::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

```javascript
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:

```javascript
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**

```javascript
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:

```css
.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;
}
```

3. **Limit Nesting Depth**: For optimal performance, limit nested accordions to 2-3 levels deep.

4. **Content Loading**: For very large content blocks, consider using `content-visibility`:

```css
.marked-extended-accordion-content {
    content-visibility: auto;
    contain-intrinsic-size: 0 500px; /* Estimated height */
}
```

5. **Reduce Reflows**: Batch DOM updates when manipulating multiple accordions programmatically.

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

```markdown
::::accordion{title="Main Section" level="2"}
Content
::::accordionend

::::accordion{title="Subsection" level="3"}
Content
::::accordionend
```

2. **Provide Descriptive Titles**: Make accordion titles clear and descriptive

```markdown
<!-- Good -->
::::accordion{title="How to install the extension"}
Installation instructions...
::::accordionend

<!-- Avoid -->
::::accordion{title="Click here"}
Content...
::::accordionend
```

3. **Add Focus Styles**: Ensure keyboard users can see focus (
   see [Accessibility Considerations](#accessibility-considerations))

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

5. **Test with Assistive Technologies**: Regularly test with screen readers and keyboard-only navigation

#### Programmatic Control

You can control accordions programmatically while maintaining accessibility:

```javascript
// 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:
   ```javascript
   import '@fsegurai/marked-extended-accordion/styles/accordion.css'
   ```
2. Check for conflicting CSS that might disable pointer events:
   ```css
   /* 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:
   ```javascript
   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:

```css
.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**:

```css
.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:

```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;
}
```

2. Use `will-change` sparingly for better performance:

```css
.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:**

```markdown
::::accordion{title="Outer"}
Content here

::::accordion{title="Inner"}
Nested content
::::accordionend

More outer content
::::accordionend
```

### Integration Examples

#### Next.js Integration

```tsx
// 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

```vue
<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

```svelte
<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:

```markdown
<!-- 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:

```markdown
::::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:

```markdown
<!-- 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:

```markdown
<!-- 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):

```css
.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:

```markdown
<!-- 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):

```javascript
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:

```markdown
<!-- 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:

```markdown
<!-- 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

```javascript
// 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](./MIGRATION.md) for complete migration guide.

### API Reference

#### Extension Options

```typescript
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

```markdown
::::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:

```markdown
::::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:

```markdown
::::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:

```markdown
::::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:

```markdown
::::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:

```markdown
::::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:

```markdown
::::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:

```markdown
::::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:

```markdown
::::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](https://github.com/fsegurai/marked-extensions/issues).

### Related Resources

- [Marked.js Documentation](https://marked.js.org/)
- [Extension Demo](https://fsegurai.github.io/marked-extensions)
- [Source Code](https://github.com/fsegurai/marked-extensions)
- [npm Package](https://www.npmjs.com/package/@fsegurai/marked-extended-accordion)

### Available Extensions

| Extension   | Package                                                                                                      | Version                                                                    | Description                                                          |
|-------------|--------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------|----------------------------------------------------------------------|
| All - Bundle       | [@fsegurai/marked-extended-bundle](https://www.npmjs.com/package/@fsegurai/marked-extended-bundle)             | ![npm](https://img.shields.io/npm/v/@fsegurai/marked-extended-bundle)       | Includes all extensions in a single package for easy integration                  |
| Accordion   | [@fsegurai/marked-extended-accordion](https://www.npmjs.com/package/@fsegurai/marked-extended-accordion)     | ![npm](https://img.shields.io/npm/v/@fsegurai/marked-extended-accordion)   | Add collapsible accordion sections to your markdown                  |
| Alert       | [@fsegurai/marked-extended-alert](https://www.npmjs.com/package/@fsegurai/marked-extended-alert)             | ![npm](https://img.shields.io/npm/v/@fsegurai/marked-extended-alert)       | Create styled alert boxes for important information                  |
| Comments    | [@fsegurai/marked-extended-comments](https://www.npmjs.com/package/@fsegurai/marked-extended-comments)       | ![npm](https://img.shields.io/npm/v/@fsegurai/marked-extended-comments)    | Add comment sections with author and timestamp metadata              |
| Embeds      | [@fsegurai/marked-extended-embeds](https://www.npmjs.com/package/@fsegurai/marked-extended-embeds)           | ![npm](https://img.shields.io/npm/v/@fsegurai/marked-extended-embeds)      | Easily embed content from various platforms (YouTube, Twitter, etc.) |
| Footnote    | [@fsegurai/marked-extended-footnote](https://www.npmjs.com/package/@fsegurai/marked-extended-footnote)       | ![npm](https://img.shields.io/npm/v/@fsegurai/marked-extended-footnote)    | Add footnotes with automatic numbering                               |
| Kanban      | [@fsegurai/marked-extended-kanban](https://www.npmjs.com/package/@fsegurai/marked-extended-kanban)           | ![npm](https://img.shields.io/npm/v/@fsegurai/marked-extended-kanban)      | Create kanban boards with customizable columns and cards             |
| Lists       | [@fsegurai/marked-extended-lists](https://www.npmjs.com/package/@fsegurai/marked-extended-lists)             | ![npm](https://img.shields.io/npm/v/@fsegurai/marked-extended-lists)       | Enhanced list formatting options                                     |
| Slide       | [@fsegurai/marked-extended-slide](https://www.npmjs.com/package/@fsegurai/marked-extended-slide)             | ![npm](https://img.shields.io/npm/v/@fsegurai/marked-extended-slide)       | Create slide decks directly from markdown content                    |
| Spoiler     | [@fsegurai/marked-extended-spoiler](https://www.npmjs.com/package/@fsegurai/marked-extended-spoiler)         | ![npm](https://img.shields.io/npm/v/@fsegurai/marked-extended-spoiler)     | Hide content behind spoiler tags                                     |
| Tables      | [@fsegurai/marked-extended-tables](https://www.npmjs.com/package/@fsegurai/marked-extended-tables)           | ![npm](https://img.shields.io/npm/v/@fsegurai/marked-extended-tables)      | Advanced table formatting with cell spanning                         |
| Tabs        | [@fsegurai/marked-extended-tabs](https://www.npmjs.com/package/@fsegurai/marked-extended-tabs)               | ![npm](https://img.shields.io/npm/v/@fsegurai/marked-extended-tabs)        | Create tabbed content sections                                       |
| Timeline    | [@fsegurai/marked-extended-timeline](https://www.npmjs.com/package/@fsegurai/marked-extended-timeline)       | ![npm](https://img.shields.io/npm/v/@fsegurai/marked-extended-timeline)    | Display content in an interactive timeline format                    |
| Typographic | [@fsegurai/marked-extended-typographic](https://www.npmjs.com/package/@fsegurai/marked-extended-typographic) | ![npm](https://img.shields.io/npm/v/@fsegurai/marked-extended-typographic) | Improve typography with smart quotes, dashes, and more               |

### Demo Application

To see all extensions in action, check out the [[DEMO]](https://fsegurai.github.io/marked-extensions).

To set up the demo locally, follow the next steps:

```shell
git clone https://github.com/fsegurai/marked-extensions.git
bun install
bun start
```

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

## License

Licensed under [MIT](https://opensource.org/licenses/MIT).
