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

v17.0.0

Published

Extension for Marked.js that adds support for extended tabs, allowing the creation of tabbed content sections within Markdown documents. It supports any Markdown rendering and can be customized to fit your needs.

Readme

An extension library for Marked.js to enhance Markdown rendering.

@fsegurai/marked-extended-tabs Extension for Marked.js that adds support for extended tabs, allowing the creation of tabbed content sections within Markdown documents. It supports any Markdown rendering and can be customized to fit your needs.

🎯 Overview

The marked-extended-tabs extension transforms your Markdown into interactive tabbed content sections with support for custom icons, smooth animations, and nested Markdown content. With a CSS-only implementation for excellent performance and accessibility, it's perfect for code examples, documentation, API references, tutorials, and organizing complex content.

✨ Key Features

  • 📑 Interactive Tabs: Create multi-tab content sections with easy navigation
  • 🎨 Custom Icons: Add emojis or Unicode icons to tab headers
  • 3 Animation Types: Fade, slide, or no animation between tabs
  • 🚀 CSS-Only: Pure CSS implementation for optimal performance
  • 📝 Rich Content: Full Markdown support including code, tables, lists
  • Fully Accessible: ARIA labels, keyboard navigation, semantic HTML
  • ⌨️ Keyboard Navigation: Arrow keys, Home/End keys for tab switching
  • 💾 Persist Selection: Remember tab choice across sessions (localStorage)
  • 🎯 Auto-Activation: Automatically activate first tab
  • 🎪 Custom Events: tab-switched events for external script integration
  • 🔄 Callback Hooks: onBeforeSwitch and onAfterSwitch callbacks
  • 🎨 Customizable Styles: Multiple variants (compact, vertical, pills)
  • 🌈 Dark Mode Ready: Theme support included
  • 📱 Responsive: Mobile-friendly with scrollable tabs
  • 🔧 Highly Configurable: Extensive customization options

🎪 Live Demo

Experience all tab styles and animations: View Demo


Table of contents

Installation

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

bun install @fsegurai/marked-extended-tabs marked@^17 --save

Usage

Basic Usage

Import @fsegurai/marked-extended-tabs and apply it to your Marked instance as shown below.

Quick Start

Basic Concept

tabs is the identifier for the tabbed container, and tab for individual tab items. Each tab can have a label, icon, and active state.

import { marked } from 'marked';
import markedExtendedTabs from '@fsegurai/marked-extended-tabs';

// 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-tabs/lib/index.umd.js"></script>

marked.use(markedExtendedTabs());

### Installation

Install the package using your preferred package manager:

```bash
# Using Bun (recommended)
bun add @fsegurai/marked-extended-tabs

# Using npm
npm install @fsegurai/marked-extended-tabs

# Using yarn
yarn add @fsegurai/marked-extended-tabs

# Using pnpm
pnpm add @fsegurai/marked-extended-tabs

Basic Implementation

import {marked} from 'marked';
import markedExtendedTabs from '@fsegurai/marked-extended-tabs';

// Import styles (required for functionality)
import '@fsegurai/marked-extended-tabs/styles/tabs.css';
// Optional: Import theme for enhanced visuals
import '@fsegurai/marked-extended-tabs/styles/tabs-theme.css';

// Register the extension
marked.use(markedExtendedTabs({
    animation: 'fade',
    autoActivate: true,
    persistSelection: false
}));

// Your markdown content with tabs
const markdown = `
# API Documentation

## Quick Start Guide

::::tabs
:::tab{label="JavaScript" icon="📜" active="true"}
## Installation

\`\`\`bash
npm install @myapi/client
\`\`\`

## Basic Usage

\`\`\`javascript
import { APIClient } from '@myapi/client';

const client = new APIClient({
  apiKey: 'your-api-key',
  baseURL: 'https://api.example.com'
});

// Fetch data
const users = await client.users.list();
console.log(users);

// Create a resource
const newUser = await client.users.create({
  name: 'John Doe',
  email: '[email protected]'
});
\`\`\`

**Key Features:**
- ✅ TypeScript support
- ✅ Promise-based API
- ✅ Automatic retries
- ✅ Request/response interceptors
:::tabend

:::tab{label="Python" icon="🐍"}
## Installation

\`\`\`bash
pip install myapi-client
\`\`\`

## Basic Usage

\`\`\`python
from myapi import APIClient

# Initialize client
client = APIClient(
    api_key='your-api-key',
    base_url='https://api.example.com'
)

# Fetch data
users = client.users.list()
print(users)

# Create a resource
new_user = client.users.create(
    name='John Doe',
    email='[email protected]'
)
\`\`\`

**Key Features:**
- ✅ Type hints included
- ✅ Async/await support
- ✅ Automatic pagination
- ✅ Built-in error handling
:::tabend

:::tab{label="cURL" icon="🔧"}
## Authentication

Add your API key to the request headers:

\`\`\`bash
curl -H "Authorization: Bearer YOUR_API_KEY" \\
     https://api.example.com/users
\`\`\`

## List Users

\`\`\`bash
curl -X GET https://api.example.com/users \\
     -H "Authorization: Bearer YOUR_API_KEY" \\
     -H "Content-Type: application/json"
\`\`\`

## Create User

\`\`\`bash
curl -X POST https://api.example.com/users \\
     -H "Authorization: Bearer YOUR_API_KEY" \\
     -H "Content-Type: application/json" \\
     -d '{
       "name": "John Doe",
       "email": "[email protected]"
     }'
\`\`\`

**Response:**
\`\`\`json
{
  "id": "usr_123",
  "name": "John Doe",
  "email": "[email protected]",
  "created_at": "2026-02-17T10:00:00Z"
}
\`\`\`
:::tabend

:::tab{label="Ruby" icon="💎"}
## Installation

\`\`\`bash
gem install myapi-client
\`\`\`

## Basic Usage

\`\`\`ruby
require 'myapi'

# Initialize client
client = MyAPI::Client.new(
  api_key: 'your-api-key',
  base_url: 'https://api.example.com'
)

# Fetch data
users = client.users.list
puts users

# Create a resource
new_user = client.users.create(
  name: 'John Doe',
  email: '[email protected]'
)
\`\`\`

**Key Features:**
- ✅ Ruby 3.0+ compatible
- ✅ ActiveRecord-style interface
- ✅ Comprehensive test suite
- ✅ Webhook support
:::tabend
::::tabsend

## Response Format

All API responses follow this structure:

\`\`\`json
{
  "data": { /* Your resource */ },
  "meta": {
    "timestamp": "2026-02-17T10:00:00Z",
    "version": "v2.0"
  }
}
\`\`\`
`;

// Parse and render
const html = marked.parse(markdown);
document.getElementById('content').innerHTML = html;

Syntax & Usage

Basic Tabs

Create simple tabs with labels:

::::tabs
:::tab{label="Tab 1" active="true"}
Content for tab 1
:::tabend

:::tab{label="Tab 2"}
Content for tab 2
:::tabend

:::tab{label="Tab 3"}
Content for tab 3
:::tabend
::::tabsend

Tabs with Icons

Add emojis or Unicode icons:

::::tabs
:::tab{label="JavaScript" icon="📜" active="true"}
JavaScript code here
:::tabend

:::tab{label="Python" icon="🐍"}
Python code here
:::tabend

:::tab{label="Ruby" icon="💎"}
Ruby code here
:::tabend
::::tabsend

Auto-Active First Tab

When no tab has active="true", the first tab activates automatically (if autoActivate: true):

::::tabs
:::tab{label="Overview"}
First tab (auto-active)
:::tabend

:::tab{label="Details"}
Second tab
:::tabend
::::tabsend

Rich Content in Tabs

Tabs support full Markdown:

::::tabs
:::tab{label="Documentation" icon="📖" active="true"}

# Getting Started

Follow these steps:

1. Install the package
2. Import the library
3. Initialize the client

## Code Example

\`\`\`javascript
import { Client } from 'mylib';
const client = new Client();
\`\`\`

**Important**: Don't forget to set your API key!

[Read more →](https://docs.example.com)
:::tabend

:::tab{label="FAQ" icon="❓"}

## Frequently Asked Questions

### How do I authenticate?

Use your API key in the Authorization header.

### What's the rate limit?

- Free tier: 100 requests/hour
- Pro tier: 10,000 requests/hour
- Enterprise: Custom limits
  :::tabend
  ::::tabsend

Short Aliases

Use shorter syntax:

:tabs
:tab{label="Tab 1"}
Content here
:tabend

:tab{label="Tab 2"}
More content
:tabend
:tabsend

The extension supports **nested Markdown content** within tabs, including code blocks, tables, lists, and even other
marked extensions. Tabs use a CSS-only implementation for optimal performance and can be styled to match your design
system.

### Styling Your Tabs

This extension provides optional CSS/SCSS files located in the `styles/` directory. Import them into your project to
style the tabs.

Usage examples:

```javascript
// JS/TS
import '@fsegurai/marked-extended-tabs/styles/tabs.css';
import '@fsegurai/marked-extended-tabs/styles/tabs-theme.css';
<!-- Plain HTML -->
<link rel="stylesheet" href="node_modules/@fsegurai/marked-extended-tabs/styles/tabs.css">
<link rel="stylesheet" href="node_modules/@fsegurai/marked-extended-tabs/styles/tabs-theme.css">

Generated HTML Structure


<div class="marked-extended-tabs-container" id="tabs-{id}">
    <nav class="marked-extended-tabs-nav" role="tablist">
        <input type="radio" name="tabs-{id}" id="tab-{id}-0" class="marked-extended-tabs-input" checked>
        <label for="tab-{id}-0" class="marked-extended-tabs-label" role="tab">
            <span class="marked-extended-tabs-icon">🔧</span>
            <span class="marked-extended-tabs-label-text">JavaScript</span>
        </label>
        <!-- More tabs... -->
    </nav>
    <div class="marked-extended-tabs-content">
        <div class="marked-extended-tabs-content-pane" role="tabpanel">
            <!-- Tab 1 content -->
        </div>
        <div class="marked-extended-tabs-content-pane" role="tabpanel">
            <!-- Tab 2 content -->
        </div>
    </div>
</div>

CSS Classes Reference

| Class | Purpose | Element | |-----------------------------------------------------|----------------------|----------------| | .marked-extended-tabs-container | Main wrapper | Container | | .marked-extended-tabs-nav | Tab navigation bar | Nav | | .marked-extended-tabs-input | Hidden radio input | Input (hidden) | | .marked-extended-tabs-label | Tab button/label | Label | | .marked-extended-tabs-label[aria-selected="true"] | Active tab | Active Label | | .marked-extended-tabs-icon | Tab icon | Span | | .marked-extended-tabs-label-text | Tab text | Span | | .marked-extended-tabs-content | Content area wrapper | Div | | .marked-extended-tabs-content-pane | Individual tab pane | Div |

Complete Styling Example

/* Container */
.marked-extended-tabs-container {
    border: 1px solid #ddd;
    border-radius: 8px;
    background: #fff;
    overflow: hidden;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
}

/* Navigation Bar */
.marked-extended-tabs-nav {
    display: flex;
    background: #f5f5f5;
    border-bottom: 1px solid #ddd;
    overflow-x: auto;
    scrollbar-width: thin;
}

/* Hide radio inputs */
.marked-extended-tabs-input {
    position: absolute;
    opacity: 0;
    pointer-events: none;
}

/* Tab Labels (Buttons) */
.marked-extended-tabs-label {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.75rem 1.5rem;
    cursor: pointer;
    border-bottom: 2px solid transparent;
    background: transparent;
    transition: all 0.2s ease;
    font-weight: 500;
    color: #666;
    white-space: nowrap;
}

.marked-extended-tabs-label:hover {
    background: #e8e8e8;
    color: #333;
}

/* Active Tab */
.marked-extended-tabs-label[aria-selected="true"] {
    background: #fff;
    border-bottom-color: #0066cc;
    color: #0066cc;
    font-weight: 600;
}

/* Tab Icon */
.marked-extended-tabs-icon {
    font-size: 1.2rem;
    opacity: 0.8;
}

/* Content Area */
.marked-extended-tabs-content {
    padding: 1.5rem;
    background: #fff;
}

.marked-extended-tabs-content-pane {
    display: none;
}

/* Show active pane (controlled by radio input) */
.marked-extended-tabs-input:checked + .marked-extended-tabs-label + * .marked-extended-tabs-content-pane:nth-of-type(1),
#tab-id-0:checked ~ .marked-extended-tabs-content .marked-extended-tabs-content-pane:nth-of-type(1) {
    display: block;
    animation: tab-fade-in 0.3s ease;
}

/* Fade animation */
@keyframes tab-fade-in {
    from {
        opacity: 0;
        transform: translateY(10px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

Variant: Compact Tabs

.marked-extended-tabs-container.tabs-compact .marked-extended-tabs-label {
    padding: 0.5rem 0.75rem;
    font-size: 0.875rem;
}

.marked-extended-tabs-container.tabs-compact .marked-extended-tabs-content {
    padding: 0.75rem;
}

Variant: Vertical Tabs

.marked-extended-tabs-container.tabs-vertical {
    display: flex;
}

.marked-extended-tabs-container.tabs-vertical .marked-extended-tabs-nav {
    flex-direction: column;
    min-width: 200px;
    border-right: 1px solid #ddd;
    border-bottom: none;
}

.marked-extended-tabs-container.tabs-vertical .marked-extended-tabs-label {
    border-bottom: none;
    border-right: 2px solid transparent;
    justify-content: flex-start;
}

.marked-extended-tabs-container.tabs-vertical .marked-extended-tabs-label[aria-selected="true"] {
    border-right-color: #0066cc;
    border-bottom: none;
}

.marked-extended-tabs-container.tabs-vertical .marked-extended-tabs-content {
    flex: 1;
}

Variant: Pills Style

.marked-extended-tabs-container.tabs-pills .marked-extended-tabs-nav {
    gap: 0.5rem;
    padding: 0.5rem;
    background: #f8f9fa;
    border-bottom: none;
}

.marked-extended-tabs-container.tabs-pills .marked-extended-tabs-label {
    border-radius: 20px;
    border: none;
    padding: 0.5rem 1rem;
}

.marked-extended-tabs-container.tabs-pills .marked-extended-tabs-label:hover {
    background: #e9ecef;
}

.marked-extended-tabs-container.tabs-pills .marked-extended-tabs-label[aria-selected="true"] {
    background: #0066cc;
    color: white;
    border: none;
}

Dark Mode Support

/* Light theme */
body.light .marked-extended-tabs-container {
    background: #ffffff;
    border-color: #ddd;
}

body.light .marked-extended-tabs-nav {
    background: #f5f5f5;
    border-bottom-color: #ddd;
}

body.light .marked-extended-tabs-label {
    color: #333;
}

body.light .marked-extended-tabs-label:hover {
    background: #e8e8e8;
}

body.light .marked-extended-tabs-content {
    background: #ffffff;
}

/* Dark theme */
body.dark .marked-extended-tabs-container {
    background: #22272e;
    border-color: #444c56;
}

body.dark .marked-extended-tabs-nav {
    background: #2d333b;
    border-bottom-color: #444c56;
}

body.dark .marked-extended-tabs-label {
    color: #d1d5da;
}

body.dark .marked-extended-tabs-label:hover {
    background: #444c56;
}

body.dark .marked-extended-tabs-label[aria-selected="true"] {
    background: #3b4551;
    color: #58a6ff;
}

body.dark .marked-extended-tabs-content {
    background: #22272e;
    color: #d1d5da;
}

Accessibility Enhancements

/* Focus styles for keyboard navigation */
.marked-extended-tabs-input:focus + .marked-extended-tabs-label {
    outline: 2px solid #0066cc;
    outline-offset: 2px;
}

/* Remove outline for mouse users */
.marked-extended-tabs-input:focus:not(:focus-visible) + .marked-extended-tabs-label {
    outline: none;
}

Copy Demo Theme

For complete styling with all variants: tabs-theme.css

Check the demo to see all tab variants in action.

Aliases

The tabs block can be rendered using alternative aliases for start and end blocks:

  • Start Aliases
    • :tbs
    • :tabs
  • End Aliases
    • :tbsend
    • :tabsend

Individual tabs can use these aliases:

  • Tab Start Aliases
    • :tab
  • Tab End Aliases
    • :tabend

Configuration Options

The marked-extended-tabs extension accepts the following configuration options:

  • className: The base CSS class name for tabs container. Defaults to 'marked-extended-tabs-container'.
  • persistSelection: Whether to remember tab selection across page reloads. Defaults to false.
  • animation: Animation type for tab transitions. Defaults to 'fade'. See Animation Types.
  • autoActivate: Automatically activate the first tab if none is explicitly active. Defaults to true.
  • template: A custom HTML template for the tabs structure. Defaults to the built-in template.
  • customizeToken: A function that allows you to customize the token object before rendering. Defaults to null.
  • enableKeyboardNavigation: Enable arrow key navigation between tabs. Defaults to true.
  • enableFocusManagement: Enable automatic focus management for accessibility. Defaults to true.
  • onBeforeSwitch: Callback function fired before switching tabs (can prevent switch). Defaults to null.
  • onAfterSwitch: Callback function fired after switching tabs. Defaults to null.

Tab syntax parameters:

  • label: The display text for the tab header. Defaults to 'Tab N' where N is the tab number.
  • active: Whether this tab is active by default ("true" or "false"). Defaults to "false".
  • icon: An optional icon (emoji or Unicode) to display in the tab header. No default.

Enhanced Tab Switching Features

The marked-extended-tabs extension now includes advanced interactivity features that enhance user experience and accessibility:

🎯 Keyboard Navigation

Users can navigate between tabs using keyboard shortcuts:

  • Arrow Right / Arrow Down - Move to the next tab
  • Arrow Left / Arrow Up - Move to the previous tab
  • Home - Jump to the first tab
  • End - Jump to the last tab
  • Space / Enter - Activate the focused tab

Keyboard navigation is enabled by default. Disable it with:

marked.use(markedExtendedTabs({
    enableKeyboardNavigation: false
}));

♿ Focus Management

Automatic focus management for keyboard accessibility:

  • Tabs are properly tabindexed for keyboard navigation
  • Active tab receives focus index 0
  • Other tabs have focus index -1
  • Focus automatically updates when switching tabs
  • Screen reader support with ARIA attributes

Enable/disable with:

marked.use(markedExtendedTabs({
    enableFocusManagement: true  // Default: true
}));

💾 State Persistence

Tab selection is automatically persisted to localStorage:

  • Each tab container has a unique storage key
  • When the page is reloaded, the previously selected tab is restored
  • Multiple tab groups maintain separate states
  • Works across browser sessions

Enable/disable with:

marked.use(markedExtendedTabs({
    persistSelection: true  // Default: false
}));

Storage key format: marked-extended-tabs-active-{containerId}

🎪 Custom Events

When a tab is switched, a custom tab-switched event is automatically dispatched:

document.addEventListener('tab-switched', (event) => {
    console.log('Tab switched:', event.detail.tabId);
    console.log('Timestamp:', event.detail.timestamp);
});

Event detail structure:

{
    tabId: string;        // ID of the newly active tab
    timestamp: number;    // Timestamp of the switch event (milliseconds)
}

🔄 Callback Hooks

Execute custom logic before and after tab switches using callback functions:

marked.use(markedExtendedTabs({
    onBeforeSwitch: (event) => {
        console.log('Switching from', event.previousTabId, 'to', event.newTabId);
        // Return false to prevent the switch
        return true;
    },
    onAfterSwitch: (event) => {
        console.log('Switched to tab:', event.newTabId);
    }
}));

onBeforeSwitch event detail:

{
    previousTabId: string | null;  // ID of the currently active tab (null on first)
    newTabId: string;               // ID of the tab being switched to
    tabIndex: number;               // Index of the new tab
    timestamp: number;              // Timestamp of the event
}

Return false from onBeforeSwitch to prevent the tab switch. Return true or any truthy value to allow it.

onAfterSwitch event detail:

{
    previousTabId: string | null;  // ID of the previously active tab (null on first)
    newTabId: string;               // ID of the newly active tab
    tabIndex: number;               // Index of the new tab
    timestamp: number;              // Timestamp of the event
}

📋 Complete Configuration Example

import {marked} from 'marked';
import markedExtendedTabs from '@fsegurai/marked-extended-tabs';
import '@fsegurai/marked-extended-tabs/styles/tabs.css';

marked.use(markedExtendedTabs({
    animation: 'fade',
    autoActivate: true,
    persistSelection: false,
    enableKeyboardNavigation: true,
    enableFocusManagement: true,

    onBeforeSwitch: (event) => {
        // Validate or prevent switches based on your logic
        if (someUnsavedChanges) {
            console.warn('Cannot switch - unsaved changes');
            return false;  // Prevent switch
        }
        return true;  // Allow switch
    },

    onAfterSwitch: (event) => {
        // Track analytics or update other UI elements
        analytics.trackEvent('tab_switched', {
            tab_id: event.newTabId,
            tab_index: event.tabIndex
        });
    }
}));

Animation Types

The extension supports three animation types:

  • 'fade': Smooth fade in/out transition between tabs (default)
  • 'slide': Horizontal sliding animation between tab contents
  • 'none': No animation, instant tab switching

Example with custom animation:

marked.use(markedExtendedTabs({
    animation: 'slide',
    autoActivate: true
}));

Advanced Examples

Tabs with Icons and Mixed Content

::::tabs
:::tab{label="Overview" icon="📋" active="true"}

## Project Overview

This project demonstrates the power of **nested Markdown** within tabs.

- ✅ Code highlighting
- ✅ Tables and lists
- ✅ Images and links
- ✅ Other extensions

[Learn more →](https://example.com)
:::tabend

:::tab{label="API Reference" icon="⚙️"}

### REST API Endpoints

| Method | Endpoint | Description |
|--------|----------|-------------|
| GET    | `/api/users` | List all users |
| POST   | `/api/users` | Create user |
| PUT    | `/api/users/{id}` | Update user |

> **Note**: All endpoints require authentication.
:::tabend

:::tab{label="Examples" icon="💻"}

### Code Examples

JavaScript implementation:
\`\`\`javascript
const api = new APIClient({
baseUrl: 'https://api.example.com',
apiKey: 'your-key-here'
});

const users = await api.get('/users');
console.log(users);
\`\`\`

Python implementation:
\`\`\`python
import requests

response = requests.get('https://api.example.com/users')
users = response.json()
print(users)
\`\`\`
:::tabend
::::tabsend

Configuration Example

import {marked} from "marked";
import markedExtendedTabs from "@fsegurai/marked-extended-tabs";

marked.use(markedExtendedTabs({
    className: 'my-custom-tabs',
    animation: 'slide',
    persistSelection: false,
    autoActivate: true,
    customizeToken: (token) => {
        // Add custom logic here
        console.log('Processing tabs token:', token);
    }
}));

Tab Features Summary

The extension provides comprehensive tab functionality:

| Feature | Description | Example | Default | |-----------------------|--------------------|--------------------------|-----------------------------| | Labels | Tab header text | label="Overview" | "Tab N" | | Icons | Emoji or Unicode | icon="📋" | None | | Active State | Default active tab | active="true" | First tab (if autoActivate) | | Animations | Transition effects | animation="fade" | "fade" | | Persist Selection | Remember choice | persistSelection: true | false | | Auto-Activate | First tab active | autoActivate: true | true | | Rich Content | Full Markdown | All Markdown syntax | Supported | | Nested Extensions | Other extensions | Accordions, tables, etc. | Supported |

Best Practices

1. Use Descriptive Labels

<!-- Good: Clear, descriptive labels -->
::::tabs
:::tab{label="Installation Guide"}
:::tab{label="Configuration Options"}
:::tab{label="API Reference"}
::::tabsend

<!-- Avoid: Vague labels -->
::::tabs
:::tab{label="Info"}
:::tab{label="More"}
:::tab{label="Other"}
::::tabsend

2. Appropriate Icon Usage

<!-- Good: Relevant icons -->
:::tab{label="JavaScript" icon="📜"}
:::tab{label="Python" icon="🐍"}
:::tab{label="Ruby" icon="💎"}

<!-- Avoid: Confusing or irrelevant -->
:::tab{label="JavaScript" icon="🌮"}  <!-- ❌ -->
:::tab{label="Python" icon="🚗"}      <!-- ❌ -->

3. Limit Number of Tabs

<!-- Good: 3-7 tabs for easy navigation -->
::::tabs
:::tab{label="Overview"}
:::tab{label="Installation"}
:::tab{label="Usage"}
:::tab{label="Examples"}
::::tabsend

<!-- Avoid: Too many tabs -->
::::tabs
<!-- 15+ tabs make navigation difficult -->
::::tabsend

4. Consistent Content Structure

<!-- Good: Similar structure across tabs -->
::::tabs
:::tab{label="JavaScript" icon="📜"}

## Installation

\`\`\`bash
npm install
\`\`\`

## Usage

\`\`\`javascript
// code
\`\`\`
:::tabend

:::tab{label="Python" icon="🐍"}

## Installation

\`\`\`bash
pip install
\`\`\`

## Usage

\`\`\`python

# code

\`\`\`
:::tabend
::::tabsend

<!-- Avoid: Inconsistent structure -->
::::tabs
:::tab{label="Tab 1"}

# Heading

Content
:::tabend

:::tab{label="Tab 2"}
Just some text without headings or structure
:::tabend
::::tabsend

5. Mark Appropriate Default Tab

<!-- Good: First tab or most relevant active -->
::::tabs
:::tab{label="Quick Start" icon="⚡" active="true"}
Most users start here
:::tabend

:::tab{label="Advanced"}
For experienced users
:::tabend
::::tabsend

<!-- Avoid: Marking wrong tab as active -->
::::tabs
:::tab{label="Quick Start"}
:::tabend

:::tab{label="Advanced Setup" active="true"}
<!-- ❌ New users shouldn't start here -->
:::tabend
::::tabsend

Use Cases

1. Multi-Language Code Examples

# Authentication API

## Making Your First Request

::::tabs
:::tab{label="JavaScript" icon="📜" active="true"}

### Using Fetch API

\`\`\`javascript
const response = await fetch('https://api.example.com/auth/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
username: '[email protected]',
password: 'secure_password'
})
});

const data = await response.json();
console.log('Token:', data.access_token);

// Use token in subsequent requests
const userData = await fetch('https://api.example.com/user/profile', {
headers: {
'Authorization': \`Bearer \${data.access_token}\`
}
});
\`\`\`

### Using Axios

\`\`\`javascript
import axios from 'axios';

const { data } = await axios.post('https://api.example.com/auth/login', {
username: '[email protected]',
password: 'secure_password'
});

console.log('Token:', data.access_token);

// Set default authorization header
axios.defaults.headers.common['Authorization'] = \`Bearer \${data.access_token}\`;
\`\`\`
:::tabend

:::tab{label="Python" icon="🐍"}

### Using Requests

\`\`\`python
import requests

# Login request

response = requests.post(
'https://api.example.com/auth/login',
json={
'username': '[email protected]',
'password': 'secure_password'
}
)

data = response.json()
access_token = data['access_token']
print(f'Token: {access_token}')

# Use token for authenticated requests

user_response = requests.get(
'https://api.example.com/user/profile',
headers={'Authorization': f'Bearer {access_token}'}
)

print(user_response.json())
\`\`\`

### Using HTTPX (Async)

\`\`\`python
import httpx
import asyncio

async def authenticate():
async with httpx.AsyncClient() as client:
# Login
response = await client.post(
'https://api.example.com/auth/login',
json={
'username': '[email protected]',
'password': 'secure_password'
}
)

        data = response.json()
        return data['access_token']

# Run async function

token = asyncio.run(authenticate())
\`\`\`
:::tabend

:::tab{label="Go" icon="🔷"}

### Using net/http

\`\`\`go
package main

import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)

type LoginRequest struct {
Username string \`json:"username"\`
Password string \`json:"password"\`
}

type LoginResponse struct {
AccessToken string \`json:"access_token"\`
}

func main() {
// Prepare login request
loginData := LoginRequest{
Username: "[email protected]",
Password: "secure_password",
}

    jsonData, _ := json.Marshal(loginData)
    
    // Make request
    resp, err := http.Post(
        "https://api.example.com/auth/login",
        "application/json",
        bytes.NewBuffer(jsonData),
    )
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()
    
    // Parse response
    body, _ := ioutil.ReadAll(resp.Body)
    var loginResp LoginResponse
    json.Unmarshal(body, &loginResp)
    
    fmt.Println("Token:", loginResp.AccessToken)

}
\`\`\`
:::tabend

:::tab{label="cURL" icon="🔧"}

### Basic Authentication Request

\`\`\`bash
curl -X POST https://api.example.com/auth/login \\
-H "Content-Type: application/json" \\
-d '{
"username": "[email protected]",
"password": "secure_password"
}'
\`\`\`

**Response:**
\`\`\`json
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 3600
}
\`\`\`

### Using the Token

\`\`\`bash

# Save token to variable

TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

# Make authenticated request

curl -X GET https://api.example.com/user/profile \\
-H "Authorization: Bearer \$TOKEN"
\`\`\`
:::tabend
::::tabsend

## Error Handling

All endpoints return standard error responses:

\`\`\`json
{
"error": {
"code": "INVALID_CREDENTIALS",
"message": "The username or password is incorrect",
"timestamp": "2026-02-17T10:30:00Z"
}
}
\`\`\`

2. Platform-Specific Installation

# Installation Guide

## Choose Your Platform

::::tabs
:::tab{label="Windows" icon="🪟" active="true"}

### Using Installer

1. **Download** the Windows installer:
    - [Download for Windows (64-bit)](https://example.com/download/windows-x64)
    - [Download for Windows (32-bit)](https://example.com/download/windows-x86)

2. **Run** the installer and follow the setup wizard

3. **Verify** installation:
   \`\`\`powershell
   myapp --version
   \`\`\`

### Using Package Manager (Chocolatey)

\`\`\`powershell
choco install myapp
\`\`\`

### Using Package Manager (Winget)

\`\`\`powershell
winget install MyCompany.MyApp
\`\`\`

### System Requirements

- Windows 10 or later
- 4GB RAM minimum (8GB recommended)
- 500MB free disk space
- .NET Runtime 6.0 or later

### Troubleshooting

**"Command not found" error:**
Add installation directory to PATH:

1. Open System Properties → Environment Variables
2. Edit PATH variable
3. Add: \`C:\\Program Files\\MyApp\\bin\`
   :::tabend

:::tab{label="macOS" icon="🍎"}

### Using Homebrew (Recommended)

\`\`\`bash
brew install myapp
\`\`\`

### Using DMG Installer

1. **Download** the macOS installer:
    - [Download for macOS (Apple Silicon)](https://example.com/download/macos-arm64)
    - [Download for macOS (Intel)](https://example.com/download/macos-x64)

2. **Open** the .dmg file

3. **Drag** MyApp to Applications folder

4. **Verify** installation:
   \`\`\`bash
   myapp --version
   \`\`\`

### System Requirements

- macOS 11 (Big Sur) or later
- 4GB RAM minimum
- 500MB free disk space

### Troubleshooting

**"App can't be opened" error:**
Right-click the app → Open → Confirm to bypass Gatekeeper
:::tabend

:::tab{label="Linux" icon="🐧"}

### Using Package Manager

**Ubuntu/Debian:**
\`\`\`bash
sudo apt update
sudo apt install myapp
\`\`\`

**Fedora/RHEL:**
\`\`\`bash
sudo dnf install myapp
\`\`\`

**Arch Linux:**
\`\`\`bash
sudo pacman -S myapp
\`\`\`

### Using Snap

\`\`\`bash
sudo snap install myapp
\`\`\`

### Building from Source

\`\`\`bash
git clone https://github.com/mycompany/myapp.git
cd myapp
./configure
make
sudo make install
\`\`\`

### System Requirements

- Linux kernel 5.0 or later
- 4GB RAM minimum
- 500MB free disk space
- glibc 2.31 or later

### Verify Installation

\`\`\`bash
myapp --version
which myapp
\`\`\`
:::tabend

:::tab{label="Docker" icon="🐳"}

### Using Docker

Pull the official image:
\`\`\`bash
docker pull mycompany/myapp:latest
\`\`\`

Run the container:
\`\`\`bash
docker run -d \\
--name myapp \\
-p 8080:8080 \\
-v \$(pwd)/data:/app/data \\
mycompany/myapp:latest
\`\`\`

### Using Docker Compose

Create \`docker-compose.yml\`:
\`\`\`yaml
version: '3.8'
services:
myapp:
image: mycompany/myapp:latest
ports:
- "8080:8080"
volumes:
- ./data:/app/data
environment:
- APP_ENV=production
- LOG_LEVEL=info
\`\`\`

Start services:
\`\`\`bash
docker-compose up -d
\`\`\`

### Available Tags

- \`latest\` - Latest stable release
- \`2.0.5\` - Specific version
- \`alpine\` - Lightweight Alpine-based image
- \`dev\` - Development build
  :::tabend
  ::::tabsend

## Post-Installation

After installation, configure your environment:

\`\`\`bash
myapp init
myapp config set api-key YOUR_KEY
\`\`\`

3. Framework Comparison

# Web Framework Comparison

## React vs Vue vs Angular

::::tabs
:::tab{label="React" icon="⚛️" active="true"}

### Overview

React is a JavaScript library for building user interfaces, focusing on component-based architecture.

**Pros:**

- ✅ Large ecosystem and community
- ✅ Virtual DOM for performance
- ✅ Flexible and unopinionated
- ✅ Excellent for SPAs
- ✅ Strong TypeScript support

**Cons:**

- ❌ Steep learning curve
- ❌ JSX syntax to learn
- ❌ Need additional libraries for routing, state

### Hello World Example

\`\`\`jsx
import React from 'react';

function App() {
const [count, setCount] = React.useState(0);

return (
<div>
<h1>Hello, React!</h1>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>
Increment
</button>
</div>
);
}

export default App;
\`\`\`

### When to Choose React

- Building complex SPAs
- Need flexibility in architecture
- Large team with React expertise
- Mobile app with React Native
  :::tabend

:::tab{label="Vue" icon="💚"}

### Overview

Vue is a progressive framework for building user interfaces with a gentle learning curve.

**Pros:**

- ✅ Easy to learn
- ✅ Great documentation
- ✅ Two-way data binding
- ✅ Smaller bundle size
- ✅ Template syntax familiar to HTML

**Cons:**

- ❌ Smaller ecosystem than React
- ❌ Less corporate backing
- ❌ Fewer job opportunities

### Hello World Example

\`\`\`vue
<template>
  <div>
    <h1>Hello, Vue!</h1>
    <p>Count: {{ count }}</p>
    <button @click="count++">
      Increment
    </button>
  </div>
</template>

<script setup>
import { ref } from 'vue';

const count = ref(0);
</script>
\`\`\`

### When to Choose Vue

- Quick prototyping
- Small to medium projects
- Team with HTML/CSS background
- Gradual migration from legacy code
  :::tabend

:::tab{label="Angular" icon="🅰️"}

### Overview

Angular is a full-featured framework with batteries included for enterprise applications.

**Pros:**

- ✅ Complete solution (routing, HTTP, forms)
- ✅ TypeScript by default
- ✅ Strong corporate backing (Google)
- ✅ Great for large applications
- ✅ CLI tooling

**Cons:**

- ❌ Steeper learning curve
- ❌ Larger bundle size
- ❌ More opinionated
- ❌ Verbose syntax

### Hello World Example

\`\`\`typescript
import { Component } from '@angular/core';

@Component({
selector: 'app-root',
template: \`
<div>
<h1>Hello, Angular!</h1>
<p>Count: {{ count }}</p>
<button (click)="increment()">
Increment
</button>
</div>
\`
})
export class AppComponent {
count = 0;

increment() {
this.count++;
}
}
\`\`\`

### When to Choose Angular

- Enterprise applications
- Large teams
- Need complete framework
- TypeScript-first development
  :::tabend

:::tab{label="Comparison" icon="📊"}

### Side-by-Side Comparison

| Feature | React | Vue | Angular |
|---------|-------|-----|---------|
| **Type** | Library | Framework | Framework |
| **Learning Curve** | Moderate | Easy | Steep |
| **Bundle Size** | Medium | Small | Large |
| **TypeScript** | Optional | Optional | Default |
| **Performance** | Excellent | Excellent | Good |
| **Ecosystem** | Huge | Growing | Large |
| **Best For** | SPAs, Complex UIs | All projects | Enterprise |
| **Mobile** | React Native | Weex, NativeScript | Ionic |
| **State Mgmt** | Redux, Context | Vuex, Pinia | Services, RxJS |
| **Community** | Very Large | Large | Large |

### Performance Benchmarks

| Metric | React | Vue | Angular |
|--------|-------|-----|---------|
| Initial Load | 45 KB | 38 KB | 95 KB |
| Time to Interactive | 1.2s | 0.9s | 1.8s |
| Memory Usage | 12 MB | 9 MB | 18 MB |
| DOM Operations | Fast | Fast | Good |

### Popularity (GitHub Stars)

- React: ⭐ 220K+
- Vue: ⭐ 205K+
- Angular: ⭐ 93K+

*As of February 2026*
:::tabend
::::tabsend

## Making Your Choice

Consider your:

- Team expertise
- Project requirements
- Timeline
- Long-term maintenance

4. Configuration Environments

# Environment Configuration

## Setup for Different Environments

::::tabs
:::tab{label="Development" icon="💻" active="true"}

### Development Environment Setup

\`\`\`bash

# Install dependencies

npm install

# Copy environment file

cp .env.example .env.development

# Start dev server

npm run dev
\`\`\`

### Configuration (\`.env.development\`)

\`\`\`env

# API Configuration

API_URL=http://localhost:3000
API_KEY=dev_key_1234567890

# Database

DB_HOST=localhost
DB_PORT=5432
DB_NAME=myapp_dev
DB_USER=dev_user
DB_PASSWORD=dev_password

# Features

ENABLE_DEBUG=true
ENABLE_HOT_RELOAD=true
ENABLE_SOURCE_MAPS=true

# Logging

LOG_LEVEL=debug
LOG_TO_FILE=false
\`\`\`

### Dev Tools

- ✅ Hot module replacement
- ✅ Source maps enabled
- ✅ Verbose logging
- ✅ Mock API responses
- ✅ Local database
  :::tabend

:::tab{label="Staging" icon="🧪"}

### Staging Environment Setup

\`\`\`bash

# Build for staging

npm run build:staging

# Deploy to staging

npm run deploy:staging
\`\`\`

### Configuration (\`.env.staging\`)

\`\`\`env

# API Configuration

API_URL=https://staging-api.example.com
API_KEY=staging_key_secure_token

# Database

DB_HOST=staging-db.example.com
DB_PORT=5432
DB_NAME=myapp_staging
DB_USER=staging_user
DB_PASSWORD=staging_secure_password

# Features

ENABLE_DEBUG=false
ENABLE_HOT_RELOAD=false
ENABLE_SOURCE_MAPS=true

# Logging

LOG_LEVEL=info
LOG_TO_FILE=true
LOG_PATH=/var/log/myapp

# Monitoring

SENTRY_DSN=https://[email protected]/staging
ANALYTICS_ID=staging-analytics-id
\`\`\`

### Staging Features

- ✅ Production-like environment
- ✅ Real database (non-production)
- ✅ Error tracking enabled
- ✅ Performance monitoring
- ✅ QA testing environment
  :::tabend

:::tab{label="Production" icon="🚀"}

### Production Environment Setup

\`\`\`bash

# Build for production

npm run build:production

# Deploy to production

npm run deploy:production
\`\`\`

### Configuration (\`.env.production\`)

\`\`\`env

# API Configuration

API_URL=https://api.example.com
API_KEY=prod_key_super_secure_token

# Database

DB_HOST=prod-db.example.com
DB_PORT=5432
DB_NAME=myapp_prod
DB_USER=prod_user
DB_PASSWORD=prod_ultra_secure_password

# Features

ENABLE_DEBUG=false
ENABLE_HOT_RELOAD=false
ENABLE_SOURCE_MAPS=false

# Logging

LOG_LEVEL=error
LOG_TO_FILE=true
LOG_PATH=/var/log/myapp
LOG_ROTATION=daily

# Monitoring

SENTRY_DSN=https://[email protected]/production
ANALYTICS_ID=prod-analytics-id

# Performance

ENABLE_CACHING=true
CACHE_TTL=3600
CDN_URL=https://cdn.example.com

# Security

RATE_LIMIT=100
CORS_ORIGIN=https://example.com
SSL_CERT=/path/to/cert.pem
\`\`\`

### Production Requirements

- ✅ SSL/TLS enabled
- ✅ CDN configured
- ✅ Caching enabled
- ✅ Rate limiting active
- ✅ Monitoring and alerts
- ✅ Automated backups
- ✅ Load balancing
  :::tabend

:::tab{label="Docker" icon="🐳"}

### Docker Configuration

Create \`docker-compose.yml\` per environment:

**Development:**
\`\`\`yaml
version: '3.8'
services:
app:
build:
context: .
target: development
ports:
- "3000:3000"
volumes:
- .:/app
- /app/node_modules
environment:
- NODE_ENV=development
command: npm run dev
\`\`\`

**Production:**
\`\`\`yaml
version: '3.8'
services:
app:
build:
context: .
target: production
ports:
- "3000:3000"
environment:
- NODE_ENV=production
restart: always
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 30s
timeout: 10s
retries: 3
\`\`\`

### Multi-stage Dockerfile

\`\`\`dockerfile

# Development stage

FROM node:18-alpine AS development
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
CMD ["npm", "run", "dev"]

# Production stage

FROM node:18-alpine AS production
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
CMD ["npm", "start"]
\`\`\`
:::tabend
::::tabsend

## Environment Variables Best Practices

1. ✅ Never commit secrets to version control
2. ✅ Use different keys for each environment
3. ✅ Rotate credentials regularly
4. ✅ Use secret management tools (Vault, AWS Secrets Manager)
5. ✅ Document all environment variables

Troubleshooting

Tabs Not Switching

Problem: Clicking tabs doesn't change content.

Solutions:

  1. Import CSS:
import '@fsegurai/marked-extended-tabs/styles/tabs.css';
  1. Check for conflicting styles:
/* Make sure nothing is overriding tab display */
.marked-extended-tabs-content-pane {
    display: none; /* Should be hidden by default */
}
  1. Verify tab structure:
<!-- Ensure proper nesting -->
::::tabs
:::tab{label="Tab 1"}
Content
:::tabend
::::tabsend

Icons Not Showing

Problem: Tab icons don't display.

Solutions:

  1. Use valid Unicode/emoji:
<!-- Correct -->
:::tab{label="Code" icon="📜"}
:::tab{label="Python" icon="🐍"}

<!-- Wrong -->
:::tab{label="Code" icon="invalid"}  <!-- ❌ -->
  1. Check font support:
/* Ensure emoji font is loaded */
.marked-extended-tabs-icon {
    font-family: "Apple Color Emoji", "Segoe UI Emoji", sans-serif;
}

Animation Not Working

Problem: No animation between tabs.

Solutions:

  1. Set animation type:
marked.use(markedExtendedTabs({
    animation: 'fade'  // or 'slide'
}));
  1. Import theme CSS:
import '@fsegurai/marked-extended-tabs/styles/tabs-theme.css';

First Tab Not Active

Problem: No tab is active by default.

Solution:

// Enable auto-activation
marked.use(markedExtendedTabs({
    autoActivate: true  // Default is true
}));

Or mark a tab as active:

:::tab{label="Tab 1" active="true"}

Framework Integration

React Integration

// TabsContent.tsx
import {marked} from 'marked';
import markedExtendedTabs from '@fsegurai/marked-extended-tabs';
import '@fsegurai/marked-extended-tabs/styles/tabs.css';
import '@fsegurai/marked-extended-tabs/styles/tabs-theme.css';
import {useEffect, useState} from 'react';

marked.use(markedExtendedTabs({
    animation: 'fade',
    autoActivate: true
}));

interface Props {
    content: string;
    animation?: 'fade' | 'slide' | 'none';
}

export function TabsContent({content, animation = 'fade'}: Props) {
    const [html, setHtml] = useState('');

    useEffect(() => {
        marked.use(markedExtendedTabs({animation}));
        const parsed = marked.parse(content);
        setHtml(parsed);
    }, [content, animation]);

    return (
            <div
                    className="tabs-wrapper"
                    dangerouslySetInnerHTML={{__html: html}}
            />
    );
}

// Usage:
// <TabsContent content={markdownWithTabs} animation="fade" />

Vue 3 Integration

<script setup lang="ts">
import { marked } from 'marked';
import markedExtendedTabs from '@fsegurai/marked-extended-tabs';
import '@fsegurai/marked-extended-tabs/styles/tabs.css';
import '@fsegurai/marked-extended-tabs/styles/tabs-theme.css';
import { computed } from 'vue';

marked.use(markedExtendedTabs({
  animation: 'fade'
}));

interface Props {
  content: string;
  animation?: 'fade' | 'slide' | 'none';
}

const props = withDefaults(defineProps<Props>(), {
  animation: 'fade'
});

const html = computed(() => {
  marked.use(markedExtendedTabs({ animation: props.animation }));
  return marked.parse(props.content);
});
</script>

<template>
  <div class="tabs-container" v-html="html" />
</template>

Angular Integration

// tabs-content.component.ts
import {Component, Input, OnChanges, SimpleChanges} from '@angular/core';
import {DomSanitizer, SafeHtml} from '@angular/platform-browser';
import {marked} from 'marked';
import markedExtendedTabs from '@fsegurai/marked-extended-tabs';

marked.use(markedExtendedTabs({
    animation: 'fade'
}));

@Component({
    selector: 'app-tabs-content',
    template: \`<div [innerHTML]="parsedContent"></div>\`,
  styleUrls: [
    '../node_modules/@fsegurai/marked-extended-tabs/styles/tabs.css',
    '../node_modules/@fsegurai/marked-extended-tabs/styles/tabs-theme.css'
  ]
})
export class TabsContentComponent implements OnChanges {
  @Input() content: string = '';
  @Input() animation: 'fade' | 'slide' | 'none' = 'fade';
  parsedContent: SafeHtml = '';

  constructor(private sanitizer: DomSanitizer) {}

  ngOnChanges(changes: SimpleChanges): void {
    if (changes['content'] || changes['animation']) {
      marked.use(markedExtendedTabs({ animation: this.animation }));
      const html = marked.parse(this.content);
      this.parsedContent = this.sanitizer.bypassSecurityTrustHtml(html);
    }
  }
}

Performance Tips

  1. Limit number of tabs: Keep under 10 tabs for best UX
  2. Lazy load content: For heavy content, consider lazy loading
  3. Optimize animations: Use 'none' for instant switching if needed
// Disable animations for better performance
marked.use(markedExtendedTabs({
    animation: 'none'
}));

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.