From 039c9be049fdc014faa225532c00dde807d12976 Mon Sep 17 00:00:00 2001 From: Antonio Date: Fri, 29 Apr 2022 17:04:28 +0300 Subject: [PATCH 1/7] docs: update contribution guide --- docs/contribution-guide.md | 49 ++++++++++++++++++++++++++++++++++++++ mkdocs.yml | 1 + 2 files changed, 50 insertions(+) create mode 100644 docs/contribution-guide.md diff --git a/docs/contribution-guide.md b/docs/contribution-guide.md new file mode 100644 index 0000000..bb8f828 --- /dev/null +++ b/docs/contribution-guide.md @@ -0,0 +1,49 @@ +If you wish to contribute, this is your starting point. + +This document contains guidelines to help you make your contribution clear and consistent. +These guidelines also help us to review your PR faster and, as a result, will give you +appropriate credit in your GitHub profile. + +If you have time to contribute to this project, we are happy to give you credit for it. + +We thank you in advance for your contribution! + +### Features + +You can request a new feature by submitting an issue. If you would like to implement a new feature, +feel free to issue a Pull Request. + +### Pull requests + +Pull Requests (PRs) are awesome. Get familiar with the following guidelines before you begin: + +1. Search the project for a Pull Request related to your submission. You don't want to duplicate effort. +1. A PR that contains code changes should be created from a git branch based on **develop**: + + ```bash + git checkout -b my-fix-branch develop + ``` + +1. Follow our [coding style rules][coding-rules]. +1. Run full test suite and ensure all tests pass. + 1. If some tests fail, ensure that you follow [coding style rules][coding-rules]. +1. One PR - one issue. Refrain from fixing multiple issues in the same pull request. Several small PRs are preferable instead of a big one. +1. If the PR introduces a new feature or fixes an issue, **please add the appropriate test case(s)**. +1. Follow [conventional commit guidelines][conventional-commits] for your commit message(s) when saving changes in your branch and PR. +1. Add your name to the [Credits](credits.md) file. We like to give credit where it's due. + +1. If we suggest changes: + 1. Make the required updates. + 1. Re-run test suite to ensure tests are still green. + 1. Rebase your branch and force push to your GitHub repository (this will update your Pull Request): + + ```bash + git rebase develop -i + git push origin my-fix-branch -f + ``` + +1. After your pull request is merged, you can safely delete your branch. + + +[coding-rules]: https://github.com/showdownjs/code-style/blob/master/README.md +[conventional-commits]: https://www.conventionalcommits.org/ \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index 3544dd5..e516162 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -30,6 +30,7 @@ site_dir: public nav: - Home: - Introduction: index.md + - Contribution guide: contribution-guide.md - Donations: donations.md - Credits: credits.md - Quickstart: From b64f0bea9d3f00f6598869333e3b1781007ceb5f Mon Sep 17 00:00:00 2001 From: Antonio Date: Fri, 13 May 2022 22:59:38 +0300 Subject: [PATCH 2/7] docs: fully revised event system (listener extensions) doc --- docs/assets/extra.css | 4 + docs/event-system.md | 238 ++++++++++++++++++++++++++++++++++++++++++ docs/event_system.md | 228 ---------------------------------------- mkdocs.yml | 1 + 4 files changed, 243 insertions(+), 228 deletions(-) create mode 100644 docs/event-system.md delete mode 100644 docs/event_system.md diff --git a/docs/assets/extra.css b/docs/assets/extra.css index de7a641..4a42324 100644 --- a/docs/assets/extra.css +++ b/docs/assets/extra.css @@ -1,4 +1,8 @@ :root { --md-primary-fg-color: rgb(196, 54, 39); --md-accent-fg-color: rgb(62, 139, 138); +} + +table { + box-sizing: initial; } \ No newline at end of file diff --git a/docs/event-system.md b/docs/event-system.md new file mode 100644 index 0000000..81b85b1 --- /dev/null +++ b/docs/event-system.md @@ -0,0 +1,238 @@ +## Introduction + +The Event System is the basis of the new Listener extensions, replacing the ["old" extension system](extensions.md) altogether. + +In short, the Event System lifecycle looks as follows: + +1. A sub-parser emits an event. + + !!! note "" + Each sub-parser can emit a batch of events (see the list below) + +1. Extension A (which is a _Listener Extension_) registers and listens to a specific event. + + !!! note "" + An extension can only register for a specific event + +1. Extension A receives an event object and modifies it. + + !!! note "" + Certain properties of the event object can be changed, which will change the behavior or output of the sub-parser + +1. Extension A returns the event object to the converter. +1. The converter passes the received event object to the next extension in the chain. + +## Event Object + +### Properties + +#### matches + +**matches** is an object that holds the text captured by the sub-parser. The properties of this object are different for each sub-parser. +Some properties can be read-only: their names start with `_` (underscore). + +!!! example "blockquote `onCapture` event" + + ```js + { + _wholeMatch: "> some awesome quote", + blockquote: "some awesome quote" + } + ``` + + + +## Event types + +Events are emitted when a sub-parser runs (or about to be run). +In the sub-parser, the events follow strict order sequence: [`onStart`](#onstart) -> [`onCapture`](#oncapture) -> [`onHash`](#onhash) -> [`onEnd`](#onend) + +It means that `.before` events always run before `.captureStart`. + +### onStart + +**`..onStart`**: **always runs** except if the sub-parser is disabled. + +Emitted when the sub-parser has started, but no capturing or modifications to the text were done. + +**Always runs** except if the sub-parser is disabled via options. + +!!! hint "When to use `onStart` event" + Use this event when you want to change the input passed to the sub-parser. + +!!! warning "" + Please note that the input is the **full text** that was passed to the converter. + +**Properties** + +| property | type | access | description | +|--------------|----------|---------|----------------------------------------------------------------| +| `input` | `string` | `read` | Full text that was passed to the subparser | +| `output` | `string` | `write` | Full text with modification that will be passed along the chain | +| `regexp` | `null` | | | +| `matches` | `null` | | | +| `attributes` | `null` | | | + +### onCapture + +**`..onCapture`**: *might not be run*. + +Emitted when a regex match is found and capture was successful. +Further normalization and modification of the regex captured groups might be performed. + +Might not be run if no regex match found. + +!!! hint "When to use `onCapture` event" + Use this event if you want to: + + * modify the sub-parser behavior, text; + * modify the HTML output of the sub-parser. + +**Properties** + +| property | type | access | description | +|--------------|----------|--------------|-------------------------------------------------------------------| +| `input` | `string` | `readonly` | The captured text | +| `output` | `string` | `write` | `null` or well-formed HTML (see the Important Note below) | +| `regexp` | `RegExp` | `readonly` | Regular Expression to capture groups | +| `matches` | `object` | `read/write` | Match groups. Changes to this object are reflected in the output. | +| `attributes` | `object` | `read/write` | Attributes to add to the HTML output | + +!!! warning "IMPORTANT NOTE" + Extensions listening to the `onCapture` event **should avoid** changing the output property. + Instead, they should modify the values of the matches and attribute objects. + + The reason is that the **output property takes precedence over the matches objects** and + **prevents showdown from calling other sub-parsers** inside the captured fragment. + + The above means the following: + + 1. If something is passed as the output property, any changes to the matches and attributes objects will be ignored. + 1. Any changes made by other extensions to the matches or attributes objects will be ignored. + 1. Showdown will not call other sub-parsers, such as encode code or span gamut in the text fragment, which may lead to unexpected results. + + **Example** + + !!! example "" + + ```js hl_lines="4" + // Showdown extension 1 that is listening to makehtml.blockquote.onCapture + function extension_1 (showdownEvent) { + // Let's imagine you're a bad person who writes to output + showdownEvent.output = '
foo
'; // must be a well-formed HTML + showdownEvent.matches.blockquote = 'some nice quote'; + } + + // Showdown extension 2 that is also listening to makehtml.blockquote.onCapture + function extension_2 (showdownEvent) { + // I make blockquotes bold + let quote = showdownEvent.matches.blockquote; + showdownEvent.matches.blockquote = '' + quote + ''; + } + ``` + + In the example above, the result will always be `
foo
`, regardless of the order of extension loading and call. + +!!! danger "Infinite loop" + Do not pass the input as output to the `onCapture` event, or you might trigger an infinite loop. + +### onHash + +**`..onHash`**: *always runs*. + +Raised before the output is hashed. + +**Always runs** (except if the sub-parser is disabled via options), even if no hashing is performed. + +!!! hint "When to use `onHash` event" + Use this event when you want to change the sub-parser's raw output before it is hashed. + +**Properties** + +| property | type | access | description | +|--------------|----------|---------|----------------------------------------------| +| `input` | `string` | `read` | The captured text | +| `output` | `string` | `write` | The text that will be passed along the chain | +| `regexp` | `null` | | | +| `matches` | `null` | | | +| `attributes` | `null` | | | + +### onEnd + +**`..onEnd`**: **always runs**; + +Emitted when the sub-parser has finished its work and is about to exit. + +**Always runs** (except if the sub-parser is disabled via options). + +!!! hint "When to use `onEnd` event" + Use this event when you want to run code or perform changes to the text after the subparser has run and its output was hashed. + +!!! warning "" + Please note that the input is the **full text** and might contain hashed elements. + +**Properties** + +| property | type | access | description | +|-----------|----------|---------|-------------------------------------------------------------| +| `input` | `string` | `read` | Full text with the subparser modifications (contains hashes) | +| `output` | `string` | `write` | The text that will be passed to other subparsers | +| `regexp` | `null` | | | +| `matches` | `null` | | | + +## Special Events + +There are special events useful for *"positioning"* a listener extension in the main chain of events. +Usually, these extensions introduce new syntax that, due to precedence + +In contrary, the special events will always be called, regardless of options or circumstances. + +### .before.{subparserName} + +**`.before.{subparserName}`**: **always runs** + +Emitted just before the **`{subparserName}` is about to be entered**. + +**Properties** + +| property | type | access | description | +|-----------|----------|---------|----------------------------------------------------------------| +| `input` | `string` | `read` | Full text that was passed to the subparser | +| `output` | `string` | `write` | Full text with modification that will be passed along the chain | +| `regexp` | `null` | | | +| `matches` | `null` | | | + +!!! note "Difference between `before.{subparserName}` and `{subparserName}.start`" + + 1. **`before.{subparserName}`** is always guaranteed to be called, **even if the subparser is disabled**, + while **{subparserName}.start** isn't. + + For example, `makehtml.before.strikethrough` is always called even if the option `strikethrough` is `false`. + + 1. **`before.{subparserName}`** is only emitted **once** in a span context while **`{subparserName}.start`** is emitted + everytime **`{subparserName}`** is called. + + + +### .after.{subparserName} + +**`.after.{subparserName}`**: **always runs**; + +Emitted when the **`{subparserName}` has exited** and before the next one is called. + +**Properties** + +| property | type | access | description | +|-----------|----------|---------|---------------------------------------------------| +| `input` | `string` | `read` | Partial/full text with the subparser modifications | +| `output` | `string` | `write` | The text that will be passed to other subparsers | +| `regexp` | `null` | | | +| `matches` | `null` | | | + + diff --git a/docs/event_system.md b/docs/event_system.md deleted file mode 100644 index d5002aa..0000000 --- a/docs/event_system.md +++ /dev/null @@ -1,228 +0,0 @@ -# Event System ) - -## Introduction - -The Event System is the basis of the new Listener extensions, replacing the old extension system altogether. - -The life cycle can be summarized as this: - - - A subparsers emmits an event - - Each subparser can emmit a bunch of events (see list below) - - Extension A, which is a _Listener Extension_ registers and listens to a specific event - - An extension can only register to a specific event - - Extension A receives an event object and modifies it - - Certain properties of the event object can be changed, ehich will change the behavior or output of the subparser - - The extension then returns the event object - - The converter passes this event object to the next extension in the chain - - -Note: - -## The Event Object - -### Properties - -#### matches (type: **object**) - -This object holds the text captured by the subparser. The properties of this object -are different for each subparser. - -**Properties whose name starts with `_` are readonly**. - -Example: - -```js -// blockquote onCapture event -{ - _wholeMatch: "> some awesome quote", - blockquote: "some awesome quote" -} -``` - - -## Basic Event - - -## Event Types - -Events are raised when a subparser is run (or about to be run). -Within a subparser, the events always follow a certain order (sequence). For instance, **.before** events always run before **.captureStart**. -Each subparser raises several events sequentially: - -### onStart - -**`..onStart`**: **always runs** except if the subparser is disabled - -Raised when the **subparser has started**, but no capturing or any modification to the text was done. -**Always runs** (except if the subparser is deactivated through options). - -***Properties***: - -| property | type | access | description | -|------------|-----------|------------|--------------------------------------------------------------------| -| input | string | read | The full text that was passed to the subparser | -| output | string | write | The full text with modification that will be passed along the chain| -| regexp | null | | | -| matches | null | | | -| attributes | null | | | - - -Usually you would want to use this event if you wish to change the input to the subparser. Please note, -however, that the input text is the **complete text** that was fed to the converter. - -### onCapture - -**`..onCapture`**: *might not be run*; - -Raised when a regex match is found and a capture was successful. Some normalization and modification -of the regex captured groups might be performed. - -Might not be run if no regex match is found. - -***Properties***: - -| property | type | access | description | -|------------|----------|------------|--------------------------------------------------------------------| -| input | string | readonly | The captured text | -| output | string | write | null or well formed HTML (see note) | -| regexp | RegExp | readonly | Regular Expression used to capture groups | -| matches | object | read/write | Matches groups. Changes to this object are reflected in the output | -| attributes | object | read/write | Attributes to add to the HTML output | - -Usually you would want to use this event if you wish to modify the subparser behavior, text or modify the HTML output -of the subparser. - -**IMPORTANT NOTE**: Extensions listening to onCapture event should try to AVOID changing the output property. -Instead, they should modify the values of the matches and attributes objects. This is because -the **output property takes precedence over the matches objects** and **prevents showdown to call other subparsers** -inside the captured fragment.This means 3 very important things: - - 1. If something is passed as the output property, any changes to the matches and attributes objects will be ignored. - 2. Changes made by other extensions to the matches or attributes objects will also be ignored - 3. Showdown will not call other subparsers, such as encode code or span gamut in the text fragment, which may lead to - weird results. - -```javascript -// showdown extension 1 that is listening to makehtml.blockquote.onCapture -function extension_1 (showdownEvent) { - // i'm bad and write to output - showdownEvent.output = '
foo
'; // must be an well formed html string - showdownEvent.matches.blockquote = 'some nice quote'; -} - -// showdown extension 1 that is also listening to makehtml.blockquote.onCapture -function extension_2 (showdownEvent) { - // I make blockquotes become bold - let quote = showdownEvent.matches.blockquote; - showdownEvent.matches.blockquote = '' + quote + ''; -} - -// the result will always be
foo
, regardless of the order of extension loading and call -``` - - -### onHash - -**`..onHash`**: *always runs*; - -Raised before the output is hashed. **Always runs** (except if the subparser was deactivated through options), -even if no hashing is performed. - -***Properties***: - -| property | type | access | description | -|------------|------------|------------|--------------------------------------------------------------------| -| input | string | read | The captured text | -| output | string | write | The text that will be passed to the subparser/other listeners | -| regexp | null | | | -| matches | null | | | -| attributes | null | | | - -Usually you would want to use this event if you wish change the subparser's raw output before it is hashed. - -### onEnd - -**`..onEnd`**: *always runs*; - -Raised when the subparser has finished its work and is about to exit. - -Always runs (except if the subparser is deactivated through options). - -***Properties***: - -| property | type | access | description | -|----------|-----------|------------|--------------------------------------------------------------------| -| input | string | read | The full text with the subparser modifications (contains hashes) | -| output | string | write | The text that will be passed to other subparsers | -| regexp | null | | | -| matches | null | | | - -Usually you would want to use this event if you want to run code or perform changes to the text after the subparser was -run and it's output was hashed. Keep in mind that the input is the full text and might contain hashed elements. - - -### Special Events - -There are some special events that are useful for *"positioning"* a listener extension in the main chain of events. -Usually these extensions introduce new syntax that, due to precedence -These events are always guaranteed to be called, regardless of options or circumstances. - - 1. **.before_{subparserName}**: *always runs* - - Raised just before the **{subparserName} is about to be entered**. - - ***Properties***: - - | property | type | access | description | - |----------|-----------|------------|--------------------------------------------------------------------| - | input | string | read | The full text that was passed to the subparser | - | output | string | write | The full text with modification that will be passed along the chain| - | regexp | null | | | - | matches | null | | | - - 2. **.after**.{subparserName}: *always runs*; - - Raised when the **{subparserName} has exited** and before the next one is called. - - ***Properties***: - - | property | type | access | description | - |----------|-----------|------------|--------------------------------------------------------------------| - | input | string | read | The partial/full text with the subparser modifications | - | output | string | write | The text that will be passed to other subparsers | - | regexp | null | | | - | matches | null | | | - - -### Notes - - - There are 2 main differences between **before.{subparserName}** and **{subparserName}.start**. - - 1. **before.{subparserName}** is always guaranteed to be called, even if the subparser is disabled, - while **{subparserName}.start** doesn't. - - ex: `makehtml.before.strikethrough` is always called even if the option `strikethrough` is false - - 2. **before.{subparserName}** is only raised once in a span context while **{subparserName}.start** is raised - everytime **{subparserName}** is called. - - As a rule of thumb, - -## Events List - - -### blockquote - -#### - - -### metadata - - - -## Common pitfalls - -### Infinite loop - -If you pass the input as output in a `onCapture` event, you might trigger an infinite loop. - diff --git a/mkdocs.yml b/mkdocs.yml index e516162..1f75413 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -43,6 +43,7 @@ nav: - Flavors: flavors.md - CLI: cli.md - Integrations: integrations.md + - Event system: event-system.md - Extensions: - Overview: extensions.md - Create an extension: create-extension.md From da09ee8565b95ca80249542921a78fb1933a598d Mon Sep 17 00:00:00 2001 From: Antonio Date: Sat, 14 May 2022 01:02:26 +0300 Subject: [PATCH 3/7] docs: update README to get rid of overlapping info from main docs --- CREDITS.md | 53 ------ README.md | 546 ++++------------------------------------------------- 2 files changed, 41 insertions(+), 558 deletions(-) delete mode 100644 CREDITS.md diff --git a/CREDITS.md b/CREDITS.md deleted file mode 100644 index 2aba05c..0000000 --- a/CREDITS.md +++ /dev/null @@ -1,53 +0,0 @@ -Credits -======= - - - Showdown v2 - * [Estevão Santos](https://github.com/tivie) - * [SyntaxRules](https://github.com/SyntaxRules) - - - Showdown v1 - * [Estevão Santos](https://github.com/tivie) - * [Pascal Deschênes](https://github.com/pdeschen) - - - Showdown v0 - * [Corey Innis](http://github.com/coreyti):
- Original GitHub project maintainer - * [Remy Sharp](https://github.com/remy/):
- CommonJS-compatibility and more - * [Konstantin Käfer](https://github.com/kkaefer/):
- CommonJS packaging - * [Roger Braun](https://github.com/rogerbraun):
- Github-style code blocks - * [Dominic Tarr](https://github.com/dominictarr):
- Documentation - * [Cat Chen](https://github.com/CatChen):
- Export fix - * [Titus Stone](https://github.com/tstone):
- Mocha tests, extension mechanism, and bug fixes - * [Rob Sutherland](https://github.com/roberocity):
- The idea that lead to extensions - * [Pavel Lang](https://github.com/langpavel):
- Code cleanup - * [Ben Combee](https://github.com/unwiredben):
- Regex optimization - * [Adam Backstrom](https://github.com/abackstrom):
- WebKit bugfix - * [Pascal Deschênes](https://github.com/pdeschen):
- Grunt support, extension fixes + additions, packaging improvements, documentation - * [Estevão Santos](https://github.com/tivie)
- Bug fixing and late maintainer - * [Hannah Wolfe](https://github.com/ErisDS)
- Bug fixes - * [Alexandre Courtiol](https://github.com/acourtiol)
- Bug fixes and build optimization - * [Karthik Balakrishnan](https://github.com/torcellite)
- Support for table alignment - * [rheber](https://github.com/rheber)
- Cli - - - - Original Project - * [John Gruber](http://daringfireball.net/projects/markdown/)
- Author of Markdown - * [John Fraser](http://attacklab.net/)
- Author of Showdown diff --git a/README.md b/README.md index c27e7de..b7cef74 100644 --- a/README.md +++ b/README.md @@ -2,541 +2,77 @@ ![Build Status: Linux](https://github.com/showdownjs/showdown/actions/workflows/node.linux.yml/badge.svg) ![Build Status: Windows](https://github.com/showdownjs/showdown/actions/workflows/node.win.yml/badge.svg) -[![Browserstack Tests](https://automate.browserstack.com/badge.svg?badge_key=VTIvTDNqWVdaTHljbS9RNmYrcTBiL0Uxc3dkRDhaN1dPaXpPb2VOc1B2VT0tLU1Ib09kVjVzMjhFcHExbWFSWlJEV3c9PQ==--1fb92e1730e4a00630d17d533822de6403ca65ec)](https://automate.browserstack.com/public-build/VTIvTDNqWVdaTHljbS9RNmYrcTBiL0Uxc3dkRDhaN1dPaXpPb2VOc1B2VT0tLU1Ib09kVjVzMjhFcHExbWFSWlJEV3c9PQ==--1fb92e1730e4a00630d17d533822de6403ca65ec) [![npm version](https://badge.fury.io/js/showdown.svg)](http://badge.fury.io/js/showdown) [![Bower version](https://badge.fury.io/bo/showdown.svg)](http://badge.fury.io/bo/showdown) +[![Join the chat at https://gitter.im/showdownjs/showdown](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/showdownjs/showdown?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.me/tiviesantos) ------- - Showdown is a JavaScript Markdown to HTML converter, based on the original works by John Gruber. -Showdown can be used client side (in the browser) or server side (with Node.js). -## Live DEMO +Showdown can be used on the client-side (in the browser) or server-side (with Node.js). -Check out a live demo here: http://demo.showdownjs.com/ +---- -As you know, ShowdownJS is a free library and it will remain free forever. However, maintaining and improving the library costs time and money. +## Live demo -If you like our work and find our library useful, please donate through [PayPal](https://www.paypal.me/tiviesantos)! Your contribution will be greatly appreciated and help me continue to develop this awesome library. - -## License - -ShowdownJS v 2.0 is released under the MIT license. -Previous versions are released under BSD. + ## Who uses Showdown (or a fork) - - [GoogleCloudPlatform](https://github.com/GoogleCloudPlatform) - - [Meteor](https://www.meteor.com/) - - [Stackexchange](http://stackexchange.com/) - forked as [PageDown](https://code.google.com/p/pagedown/) - - [docular](https://github.com/Vertafore/docular) - - [md-page](https://github.com/oscarmorrison/md-page) - - [QCObjects](https://qcobjects.dev) - - [and some others...](https://www.npmjs.com/browse/depended/showdown) +* [Antmarky](https://github.com/bandantonio/antmarky) +* [GoogleCloudPlatform](https://github.com/GoogleCloudPlatform) +* [Meteor](https://www.meteor.com/) +* [StackExchange](http://stackexchange.com/) - forked as [PageDown](https://code.google.com/p/pagedown/) +* [docular](https://github.com/Vertafore/docular) +* [md-page](https://github.com/oscarmorrison/md-page) +* [QCObjects](https://qcobjects.dev) +* [and some others](https://www.npmjs.com/browse/depended/showdown) -## Installation +## Quickstart -### Download tarball +Check our documentation for the [quickstart guide][quickstart] +and possible [installation methods][installation-methods]. -You can download the latest release tarball directly from [releases][releases]. +## Showdown features -### Bower +### Platform-agnostic - bower install showdown +Showdown can easily be used on server-side and client-side. -### npm (server-side) +### Two-way conversion - npm install showdown +Showdown not only helps you to convert your Markdown documents into HTML but also can bring them back to Markdown from HTML. -### NuGet package +### Extensions - PM> Install-Package showdownjs +Expand Showdown's functionality using a powerful [extension system][extensions]. Extensions can also be used on server-side and client-side. -The NuGet Packages can be found [here](https://www.nuget.org/packages/showdownjs/). +### CLI -### CDN +Showdown comes bundled with a Command-line interface (CLI) tool that allows you to run Showdown converter from the command line. -You can also use one of several CDNs available: +Check the [CLI][cli] section in the documentation for more information. -* jsDelivr +## Contribution guide - https://cdn.jsdelivr.net/npm/showdown@/dist/showdown.min.js - -* cdnjs - - https://cdnjs.cloudflare.com/ajax/libs/showdown//showdown.min.js - -* unpkg - - https://unpkg.com/showdown/dist/showdown.min.js - -*Note*: replace `` with an actual full length version you're interested in e.g. `1.9.0` -## Browser Compatibility - -Showdown has been tested successfully with: - - * Firefox 1.5 and 2.0 - * Chrome 12.0 - * Internet Explorer 6 and 7 - * Safari 2.0.4 - * Opera 8.54 and 9.10 - * Netscape 8.1.2 - * Konqueror 3.5.4 - -In theory, Showdown will work in any browser that supports ECMA 262 3rd Edition (JavaScript 1.5). -The converter itself might even work in things that aren't web browsers, like Acrobat. No promises. - - -## Node compatibility - -Showdown is intended to work on any supported Node.js version (see the [Node.js releases schedule](https://nodejs.org/en/about/releases/). The code may work with previous versions of Node.js, but no accomidations are made to ensure it does. - - -## Legacy version - -If you're looking for showdown v<1.0.0, you can find it in the [**legacy branch**][legacy-branch]. - -## Changelog - -You can check the full [changelog][changelog] - -## Extended documentation -Check our [wiki pages][wiki] for examples and a more in-depth documentation. - - -## Quick Example - -### Node - -```js -var showdown = require('showdown'), - converter = new showdown.Converter(), - text = '# hello, markdown!', - html = converter.makeHtml(text); -``` - -### Browser - -```js -var converter = new showdown.Converter(), - text = '# hello, markdown!', - html = converter.makeHtml(text); -``` - -### Output - -Both examples should output... - -```html -

hello, markdown!

-``` - -## Options - -You can change some of showdown's default behavior through options. - -### Setting options - -Options can be set: - -#### Globally - -Setting a "global" option affects all instances of showdown - -```js -showdown.setOption('optionKey', 'value'); -``` - -#### Locally -Setting a "local" option only affects the specified Converter object. -Local options can be set: - - * **through the constructor** - ```js - var converter = new showdown.Converter({optionKey: 'value'}); - ``` - - * **through the setOption() method** - ```js - var converter = new showdown.Converter(); - converter.setOption('optionKey', 'value'); - ``` - -### Getting an option - -Showdown provides 2 methods (both local and global) to retrieve previous set options. - -#### getOption() - -```js -// Global -var myOption = showdown.getOption('optionKey'); - -//Local -var myOption = converter.getOption('optionKey'); -``` - -#### getOptions() - -```js -// Global -var showdownGlobalOptions = showdown.getOptions(); - -//Local -var thisConverterSpecificOptions = converter.getOptions(); -``` - -### Retrieve the default options - -You can get showdown's default options with: -```js -var defaultOptions = showdown.getDefaultOptions(); -``` - -### Valid Options - - * **omitExtraWLInCodeBlocks**: (boolean) [default false] Omit the trailing newline in a code block. Ex: - - This: - ```html -
var foo = 'bar';
-    
- ``` - Becomes this: - ```html -
var foo = 'bar';
- ``` - - * **noHeaderId**: (boolean) [default false] Disable the automatic generation of header ids. - Setting to true overrides **prefixHeaderId** - - * **customizedHeaderId**: (boolean) [default false] Use text in curly braces as header id. **(since v1.7.0)** - Example: - ``` - ## Sample header {real-id} will use real-id as id - ``` - - * **ghCompatibleHeaderId**: (boolean) [default false] Generate header ids compatible with github style - (spaces are replaced with dashes and a bunch of non alphanumeric chars are removed) **(since v1.5.5)** - - * **prefixHeaderId**: (string/boolean) [default false] Add a prefix to the generated header ids. - Passing a string will prefix that string to the header id. Setting to `true` will add a generic 'section' prefix. - - * **rawPrefixHeaderId**: (boolean) [default false] Setting this option to true will prevent showdown from modifying the prefix. - This might result in malformed IDs (if, for instance, the " char is used in the prefix). - Has no effect if prefixHeaderId is set to false. **(since v 1.7.3)** - - * **rawHeaderId**: (boolean) [default false] Remove only spaces, ' and " from generated header ids (including prefixes), - replacing them with dashes (-). WARNING: This might result in malformed ids **(since v1.7.3)** - - * **headerLevelStart**: (integer) [default 1] Set the header starting level. For instance, setting this to 3 means that - - ```md - # foo - ``` - will be parsed as - - ```html -

foo

- ``` - - * **parseImgDimensions**: (boolean) [default false] Enable support for setting image dimensions from within markdown syntax. - Examples: - ``` - ![foo](foo.jpg =100x80) simple, assumes units are in px - ![bar](bar.jpg =100x*) sets the height to "auto" - ![baz](baz.jpg =80%x5em) Image with width of 80% and height of 5em - ``` - - * **simplifiedAutoLink**: (boolean) [default false] Turning this option on will enable automatic linking to urls. - This means that: - - ```md - some text www.google.com - ``` - will be parsed as - ```html -

some text www.google.com - ``` - - * ~~**excludeTrailingPunctuationFromURLs**: (boolean) [default false] This option excludes trailing punctuation from autolinking urls. - Punctuation excluded: `. ! ? ( )`. Only applies if **simplifiedAutoLink** option is set to `true`.~~ - - * **literalMidWordUnderscores**: (boolean) [default false] Turning this on will stop showdown from interpreting - underscores in the middle of words as `` and `` and instead treat them as literal underscores. - - Example: - - ```md - some text with__underscores__in middle - ``` - will be parsed as - ```html -

some text with__underscores__in middle

- ``` - - * ~~**literalMidWordAsterisks**: (boolean) [default false] Turning this on will stop showdown from interpreting asterisks - in the middle of words as `` and `` and instead treat them as literal asterisks.~~ - - * **strikethrough**: (boolean) [default false] Enable support for strikethrough syntax. - `~~strikethrough~~` as `strikethrough` - - * **tables**: (boolean) [default false] Enable support for tables syntax. Example: - - ```md - | h1 | h2 | h3 | - |:------|:-------:|--------:| - | 100 | [a][1] | ![b][2] | - | *foo* | **bar** | ~~baz~~ | - ``` - - See the wiki for more info - - * **tablesHeaderId**: (boolean) [default false] If enabled adds an id property to table headers tags. - - * **ghCodeBlocks**: (boolean) [default true] Enable support for GFM code block style. - - * **tasklists**: (boolean) [default false] Enable support for GFM tasklists. Example: - - ```md - - [x] This task is done - - [ ] This is still pending - ``` - * **smoothLivePreview**: (boolean) [default false] Prevents weird effects in live previews due to incomplete input - - * **smartIndentationFix**: (boolean) [default false] Tries to smartly fix indentation problems related to es6 template - strings in the midst of indented code. - - * **disableForced4SpacesIndentedSublists**: (boolean) [default false] Disables the requirement of indenting sublists - by 4 spaces for them to be nested, effectively reverting to the old behavior where 2 or 3 spaces were enough. - **(since v1.5.0)** - - * **simpleLineBreaks**: (boolean) [default false] Parses line breaks as `
`, without - needing 2 spaces at the end of the line **(since v1.5.1)** - - ```md - a line - wrapped in two - ``` - - turns into: - - ```html -

a line
- wrapped in two

- ``` - - * **requireSpaceBeforeHeadingText**: (boolean) [default false] Makes adding a space between `#` and the header text mandatory **(since v1.5.3)** - - * **ghMentions**: (boolean) [default false] Enables github @mentions, which link to the username mentioned **(since v1.6.0)** - - * **ghMentionsLink**: (string) [default `https://github.com/{u}`] Changes the link generated by @mentions. - Showdown will replace `{u}` with the username. Only applies if ghMentions option is enabled. - Example: `@tivie` with ghMentionsOption set to `//mysite.com/{u}/profile` will result in `@tivie` - - * **encodeEmails**: (boolean) [default true] Enable e-mail addresses encoding through the use of Character Entities, transforming ASCII e-mail addresses into its equivalent decimal entities. (since v1.6.1) - - NOTE: Prior to version 1.6.1, emails would always be obfuscated through dec and hex encoding. - - * **openLinksInNewWindow**: (boolean) [default false] Open all links in new windows - (by adding the attribute `target="_blank"` to `` tags) **(since v1.7.0)** - - * **backslashEscapesHTMLTags**: (boolean) [default false] Support for HTML Tag escaping. ex: `\
foo\
` **(since v1.7.2)** - - * **emoji**: (boolean) [default false] Enable emoji support. Ex: `this is a :smile: emoji` - For more info on available emojis, see https://github.com/showdownjs/showdown/wiki/Emojis **(since v.1.8.0)** - - * **underline**: (boolean) [default false] ***EXPERIMENTAL FEATURE*** Enable support for underline. - Syntax is **double** or **triple** **underscores** ex: `__underlined word__`. With this option enabled, underscores are no longer parses into `` and ``. - - * **ellipsis**: (boolean) [default true] Replaces three dots with the ellipsis unicode character. - - * **completeHTMLDocument**: (boolean) [default false] Outputs a complete html document, - including ``, `` and `` tags' instead of an HTML fragment. (since v.1.8.5) - - * **metadata**: (boolean) [default false] Enable support for document metadata (defined at the top of the document - between `«««` and `»»»` or between `---` and `---`). (since v.1.8.5) - - ```js - var conv = new showdown.Converter({metadata: true}); - var html = conv.makeHtml(someMd); - var metadata = conv.getMetadata(); // returns an object with the document metadata - ``` - - * **splitAdjacentBlockquotes**: (boolean) [default false] Split adjacent blockquote blocks.(since v.1.8.6) - - * **moreStyling**: (boolean) [default false] Adds some useful classes for css styling. (since v2.0.1) - - - Tasklists: Adds the class `task-list-item-complete` to completed tasks items in GFM tasklists. - -**NOTE**: Please note that until **version 1.6.0**, all of these options are ***DISABLED*** by default in the cli tool. - - -## Flavors - -You can also use flavors or presets to set the correct options automatically, so that showdown behaves like popular markdown flavors. - -Currently, the following flavors are available: - - * original - original markdown flavor as in [John Gruber's spec](https://daringfireball.net/projects/markdown/) - * vanilla - showdown base flavor (as from v1.3.1) - * github - GFM (GitHub Flavored Markdown) - - -### Global -```javascript -showdown.setFlavor('github'); -``` - -### Instance -```javascript -converter.setFlavor('github'); -``` - - -## CLI Tool - -Showdown also comes bundled with a Command Line Interface tool. You can check the [CLI wiki page][cli-wiki] for more info - -## Integration with AngularJS - -ShowdownJS project also provides seamlessly integration with AngularJS via a "plugin". -Please visit https://github.com/showdownjs/ngShowdown for more information. - -## Integration with TypeScript - -If you're using TypeScript you maybe want to use the types from [DefinitelyTyped][definitely-typed] - -## Integration with SystemJS/JSPM - -Integration with SystemJS can be obtained via the third party ["system-md" plugin](https://github.com/guybedford/system-md). - -## Integration with VueJS - -To use ShowdownJS as a Vue component quickly, you can check [vue-showdown](https://vue-showdown.js.org/). - -## XSS vulnerability - -Showdown doesn't sanitize the input. This is by design since markdown relies on it to allow certain features to be correctly parsed into HTML. -This, however, means XSS injection is quite possible. - -Please refer to the wiki article [Markdown's XSS Vulnerability (and how to mitigate it)][xss-wiki] -for more information. - -## Extensions - -Showdown allows additional functionality to be loaded via extensions. (you can find a list of known showdown extensions [here][ext-wiki]) -You can also find a boilerplate, to create your own extensions in [this repository][boilerplate-repo] - -### Client-side Extension Usage - -```js -