markdown-it-collapsible

A markdown-it plugin, which adds collapsibles via the HTML <details> and <summary> elements

Downloads in past

Stats

StarsIssuesVersionUpdatedCreatedSize
markdown-it-collapsible
1612.0.2a month ago4 years agoMinified + gzip package size for markdown-it-collapsible in KB

Readme

markdown-it-collapsible
npm Node.js CI markdown-it
A markdown-it plugin, which adds collapsibles via the HTML <details> and <summary> elements

Preview

preview

Usage

Install

npm install markdown-it-collapsible

Enable

// ESM
import MarkdownIt from "markdown-it";
import MarkdownItCollapsible from "markdown-it-collapsible";
const md = new MarkdownIt().use(MarkdownItCollapsible, options);

// CommonJS
const MarkdownIt = require("markdown-it");
const MarkdownItCollapsible = require("markdown-it-collapsible");
const md = MarkdownIt().use(MarkdownItCollapsible, options);

Syntax

+++ <visible_text>
<hidden_text>
+++

e.g.
+++ Click me!
Hidden text
+++

is interpreted as
<details>
    <summary>
        <span class="details-marker"></span>
        Click me!
    </summary>
    <p>
        Hidden text
    </p>
</details>

Open state

To start in open state, use ++> instead:
++> Click me!
Hidden text
++>

Nesting

You can nest collapsibles by adding more + characters to the outer elements:
## Closed
++++ Click me!
Hidden text
+++ Nested
Inner hidden text
+++
++++

## Open
+++> Click me!
Hidden text
+++ Nested
Inner hidden text
+++
+++>

Example CSS

Modern browsers don't need additional styling. For better UX you can add a few lines of CSS:
summary {
  display: flex;
  align-items: start;
  outline: none;
  list-style: none;
  user-select: none;
  cursor: pointer;
}

summary > h1, summary > h2, summary > h3, summary > h4, summary > h5, summary > h6 {
  display: inline-block;
  margin: 0;
}

details > *:not(summary) {
  margin-top: 0;
  margin-bottom: 0.5rem;
  margin-left: 1.25rem;

To make the marker scale with headings, an empty span element is created in the parsed HTML. Style the CSS class details-marker in any way you like, for example:
.details-marker::before {
  content: "▶︎";
  display: inline-block;
  margin-right: 0.5ch;
  flex-shrink: 0;
  transition: 0.3s;
}

details[open] > summary .details-marker::before {
  transform: rotate(90deg);
  transform-origin: 40% 45% 0;
}