Showdown Markdown to HTML Converter
repository·master·Indexed 12 days ago
https://github.com/showdownjs/showdownA JavaScript library that converts Markdown text into HTML, compatible with both client-side (browser) and server-side (Node.js) environments. Version 3.0.0-rc2 supports multiple flavors including GFM, CommonMark, and original Markdown, and provides a CLI for file conversion. It features a flexible API for managing converter options, flavors, and custom extensions.
What's inside Showdown
- Showdown is a JavaScript library that converts Markdown to HTML. It is designed to be used in both client-side (browser) and server-side (Node.js) environments. It is based on the original Markdown specifications by John Gruber.
Enable Strikethrough syntax
masterStrikethrough is enabled by default in the vanilla flavor. Use two tildes (
~~) around text to produce a<s />element, similar to GitHub Flavored Markdown (GFM).a ~~strikethrough~~ elementHow the Showdown event system works
masterThe event system is the foundation for modern Showdown extensions (specifically
listenerextensions). As Showdown parses a document, sub-parsers emit events during the conversion process. A listener extension can subscribe to these events to inspect or modify the conversion in flight.The lifecycle of an event is as follows:
- A sub-parser emits an event (potentially a batch of events).
- A listener extension registers for a specific event type.
- The extension receives an event object and can modify certain properties to change the sub-parser's behavior or output.
- The extension returns the modified event object to the converter.
- The converter passes the event object to the next extension in the chain.
Override node rendering in makeMarkdown()
masterIn
makeMarkdown(), you can override how a specific HTML node is converted to Markdown by using theonStartevent of its corresponding sub-parser.If you set
evt.outputto a non-empty string within anonStartlistener, that string is used as the result and the default rendering of the node is skipped. The matchingonEndevent will still run, but the default logic is bypassed. This is themakeMarkdownequivalent of theonCapturebehavior inmakeHtml.// Render every <a> as bare text instead of a Markdown link converter.listen('makeMarkdown.links.onStart', function (evt) { evt.output = evt.matches.node.textContent; return evt; });Understand Showdown List Behavior
masterShowdown's list implementation has two specific behaviors to note:
- Loose vs Tight Lists: If any list item is separated from another by a blank line, Showdown wraps all items in
<p>tags. To avoid this, ensure items are adjacent. - Four-space Indentation: Nested lists require an indentation of four spaces (or one tab) per level. This is consistent with the original spec but differs from GFM/CommonMark. You can relax this using the
disableForced4SpacesIndentedSublistsoption.
* Item 1 * Item 2 (This will trigger <p> tags for all items in the list)- Loose vs Tight Lists: If any list item is separated from another by a blank line, Showdown wraps all items in
What GitHub Flavored Markdown (GFM) adds to CommonMark
masterThe
gfmflavor in Showdown is built on top of thecommonmarkbase and adds the following extensions:- Tables: Pipe tables with support for per-column alignment.
- Task lists: Checkboxes using
- [ ]and- [x]syntax. - Strikethrough: Text decoration using
~~text~~. - Autolink literals: Bare URLs are converted to links. Note: Showdown also links
<www.…>inside angle brackets, which is a deviation from the standard GFM spec. @-mentions and emoji: Support for mentions and emoji syntax (e.g.,:smile:).- Footnotes: Support for
[^id]references and definitions (also reversible viamakeMarkdown).
What the `cmSpec` option covers
masterSetting
cmSpectotrueswitches Showdown's block-level and inline parsing from legacy matching to the CommonMark spec. This affects:- Emphasis: Uses the CommonMark delimiter-run (flanking) algorithm.
- Autolinks: Recognizes
<scheme:uri>and<email>without entity-encoding, plus<www.…>(Showdown extension). - Links & images: Follows spec for balanced-paren,
<...>destinations, backslash escapes, and alt-text flattening. - Inline raw HTML: Uses strict CommonMark grammar; malformed tags are escaped.
- HTML blocks: Uses the 7 CommonMark block types.
- Block quotes: Parses as CommonMark container blocks (handles empty
>, splitting at blank lines, and lazy continuation). - Lists: Uses a container-block parser (marker/delimiter splitting, ordered start, loose/tight, and indentation-based nesting).
- Unified inline: Uses a single unified parser with one delimiter stack.
- Tabs: Expands tabs to 4-column tab stops in block-structure indentation.
- Containers: Parses leaf blocks (fenced code, HTML blocks, etc.) in the context of their containing block quote or list item.
Select a Markdown syntax flavor
masterShowdown supports four different Markdown syntax flavors. You can switch between them using
showdown.setFlavor(...)or by passing the corresponding flavor name in the converter options.Supported flavors:
original: The 2004 John Gruber reference implementation. Smallest feature set.vanilla: Showdown's default behavior. It includes the original spec plus opt-in extras like tables, task lists, and emoji (enabled via options).commonmark: A strict, unambiguous implementation of the CommonMark specification.gfm: GitHub Flavored Markdown. Includes CommonMark plus GitHub-specific extensions like task lists, tables, strikethrough, and@-mentions.
Note: The
vanillaflavor is the default behavior when no flavor is explicitly set.// Example of setting a flavor (conceptual usage) const converter = new showdown.Converter({ flavor: 'gfm' }); // OR converter.setFlavor('commonmark');Understand the Event Object and its properties
masterWhen an event is triggered, the listener receives an event object. A key property of this object is
matches, which contains the text captured by the sub-parser.Note that the structure of
matchesvaries depending on which sub-parser emitted the event. Additionally, some properties withinmatchesare read-only; these are identified by a leading underscore (e.g.,_wholeMatch).// Example of a blockquote `onCapture` event object { _wholeMatch: "> some awesome quote", blockquote: "some awesome quote" }How extension modes work in Showdown
masterShowdown extensions allow you to add custom functionality to the Markdown conversion process. There are two primary modes of operation:
- Listener extensions (Recommended): These use the Showdown event system to hook into sub-parsers. They can inspect or modify captures, matches, attributes, and output mid-conversion. This mode provides high precision for complex transformations.
- Legacy
lang/outputextensions (Deprecated): These are older modes that useregex/replaceor afiltercallback to rewrite text either before parsing (lang) or after parsing (output). While they still function, they are now thin wrappers over document-level events and will trigger a deprecation warning. Uselistenerextensions for all new development.
Use the `onStart` event to modify sub-parser input
masterThe
onStartevent is emitted when a sub-parser starts. It is always called unless the sub-parser is disabled via options.When to use: Use this event when you want to change the input passed to the sub-parser.
Warning: The
inputproperty contains the full text that was passed to the converter, not just the fragment relevant to the sub-parser. To pass modified text down the chain, write to theoutputproperty.// Example of the properties available in onStart // { // input: 'full text string', // output: 'modified text string', // regexp: null, // matches: null, // attributes: null // }Understand the Showdown sub-parser event lifecycle
masterWhen converting Markdown to HTML (
makehtml), sub-parsers emit events in a strict, sequential order. This lifecycle allows you to intercept, modify, or augment the parsing process at different stages:onStart: Emitted when the sub-parser begins. Use this to modify the full text passed to the sub-parser before any processing occurs.onCapture: Emitted when a regex match is successfully found. Use this to modify the sub-parser's behavior, the captured text, or the resulting HTML. Note: It is highly recommended to mutate thematchesorattributesobjects instead of writing to theoutputproperty to avoid breaking the parsing chain.onHash: Emitted after capture but before the output is hashed. Use this to change the sub-parser's raw output before hashing occurs.onEnd: Emitted when the sub-parser finishes. Use this to perform final changes to the text after it has been hashed.