From 8a959a6ddd29a8008a3082239dd88f57e482e95c Mon Sep 17 00:00:00 2001 From: Antonio Date: Mon, 28 Mar 2022 01:59:41 +0300 Subject: [PATCH 01/10] docs: added showdown configuration document --- docs/configuration.md | 60 +++++++++++++++++++++++++++++++++++++++++++ mkdocs.yml | 4 ++- 2 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 docs/configuration.md diff --git a/docs/configuration.md b/docs/configuration.md new file mode 100644 index 0000000..760a97d --- /dev/null +++ b/docs/configuration.md @@ -0,0 +1,60 @@ +You can change Showdown's default behavior via options. + +## Set option + +### Globally + +Setting an option globally affects all Showdown instances. + +```js +showdown.setOption('optionKey', 'value'); +``` + +### Locally + +Setting an option locally affects the specified Converter object only. You can set local options via: + +=== "Constructor" + + ```js + var converter = new showdown.Converter({optionKey: 'value'}); + ``` + +=== "setOption() method" + + ```js + var converter = new showdown.Converter(); + converter.setOption('optionKey', 'value'); + ``` + +## Get option + +Showdown provides both local and global methods to retrieve previously 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(); + ``` + +### Get default options + +You can get Showdown's default options with: + +```js +var defaultOptions = showdown.getDefaultOptions(); +``` \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index 16401f6..9951def 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -32,4 +32,6 @@ nav: - Donations: donations.md - Quickstart: - Quickstart: quickstart.md - - Compatibility: compatibility.md \ No newline at end of file + - Compatibility: compatibility.md + - Configuration: + - Showdown options: configuration.md \ No newline at end of file From b3dac51d9e41d6f9cfdca83f08070c64aa31b62e Mon Sep 17 00:00:00 2001 From: Antonio Date: Mon, 28 Mar 2022 18:28:56 +0300 Subject: [PATCH 02/10] test: removed redundant path-ignore (#906) From 24016bfd0bd2a6f97cde944a516097d910b82a0e Mon Sep 17 00:00:00 2001 From: Antonio Date: Mon, 28 Mar 2022 21:54:41 +0300 Subject: [PATCH 03/10] docs: added page describing options supported by showdown --- docs/available-options.md | 773 ++++++++++++++++++++++++++++++++++++++ mkdocs.yml | 3 +- 2 files changed, 775 insertions(+), 1 deletion(-) create mode 100644 docs/available-options.md diff --git a/docs/available-options.md b/docs/available-options.md new file mode 100644 index 0000000..114244c --- /dev/null +++ b/docs/available-options.md @@ -0,0 +1,773 @@ +!!! warning "" + Starting from the version `1.6.0` and earlier, all the options are `disabled` by default in the cli tool. + +### omitExtraWLInCodeBlocks + +Omit trailing newline in code blocks (which is set by default before the closing tag). This option affects both indented and fenced (gfm style) code blocks. + +* type: `boolean` +* default value: `false` +* introduced in: `1.0.0` + +=== "input" + + ``` + var foo = 'bar'; + ``` + +=== "output (value is `false`)" + + ```html +
var foo = 'bar';
+    
+ ``` + +=== "output (value is `true`)" + + ```html +
var foo = 'bar';
+ ``` + +### noHeaderId + +Disable automatic generation of heading IDs. + +!!! warning "" + Setting the option to `true` overrides the following options: + + * [`prefixHeaderId`](#prefixheaderid) + * [`customizedHeaderId`](#customizedheaderid) + * [`ghCompatibleHeaderId`](#ghcompatibleheaderid) + +* type: `boolean` +* default value: `false` +* introduced in: `1.1.0` + +=== "input" + + ``` + # This is a heading + ``` + +=== "output (value is `false`)" + + ```html +

This is a heading

+ ``` + +=== "output (value is `true`)" + + ```html +

This is a heading

+ ``` + +### customizedHeaderId + +Set custom ID for a heading. + +!!! warning "" + This option can be overridden with the [`noHeaderId`](#noheaderid) option. + +* type: `boolean` +* default value: `false` +* introduced in: `1.7.0` + +=== "code" + + ```html + ## Sample heading {mycustomid} + ``` + +=== "output" + + ```html +

This is a heading

+ ``` + +!!! hint "" + For better readability and human-friendliness of the heading IDs, it is also recommended to set the [`ghCompatibleHeaderId`](#ghcompatibleheaderid) option to `true`. + +### ghCompatibleHeaderId + +Generate heading IDs compatible with GitHub style: spaces are replaced with dashes, and certain non-alphanumeric chars are removed. + +!!! warning "" + This option can be overridden with the [`noHeaderId`](#noheaderid) option. + +* type: `boolean` +* default value: `false` +* introduced in: `1.5.5` + +=== "input" + + ``` + # This is a heading with @#$% + ``` + +=== "output (value is `false`)" + + ```html +

This is a heading

+ ``` + +=== "output (value is `true`)" + + ```html +

This is a heading with @#$%

+ ``` + +### rawHeaderId + +Replace ` ` (space), `'` (single quote), and `"` (double quote) with `-` (dash) in the generated heading IDs, including prefixes. + +!!! danger "" + **Use with caution** as it might result in malformed IDs. + +* type: +* default value: +* introduced in: `1.7.3` + +### prefixHeaderId + +Add a prefix to the generated heading ID: + +* Passing a string will add that string to the heading ID. +* Passing `true` will add a generic `section` prefix. + +!!! warning "" + This option can be overridden with the [`noHeaderId`](#noheaderid) option. + +* type: `string / boolean` +* default value: `false` + +=== "input" + + ``` + # This is a heading + ``` + +=== "output (value is `false`)" + + ```html +

This is a heading

+ ``` + +=== "output (value is `true`)" + + ```html +

This is a heading

+ ``` + +=== "output (value is `showdown`)" + + ```html +

This is a heading

+ ``` + +### rawPrefixHeaderId + +Prevent Showndown from modifying the prefix. Works only when [`prefixHeaderId`](#prefixheaderid) is set to a string value. + +!!! danger "" + **Use with caution** as it might result in malformed IDs. For example, when the prefix contains special characters like `"` `\` `/` or others. + +* type: `boolean` +* default value: `false` +* introduced in: `1.7.3` + +### headerLevelStart + +Set starting level for the heading tags. + +* type: `integer` +* default value: `1` +* introduced in: `1.1.0` + +=== "input" + + ``` + # This is a heading + ``` + +=== "output (value is `1`)" + + ```html +

This is a heading

+ ``` + +=== "output (value is `3`)" + + ```html +

This is a heading

+ ``` + +### parseImgDimensions + +Set image dimensions from within Markdown syntax. + +* type: `boolean` +* default value: `false` +* introduced in: `1.1.0` + +=== "example" + + ``` + ![foo](foo.jpg =100x80) set width to 100px and height to 80px + ![bar](bar.jpg =100x*) set width to 100px and height to "auto" + ![baz](baz.jpg =80%x5em) set width to 80% and height to 5em + ``` + +### simplifiedAutoLink + +Enable automatic linking for plain text URLs. + +* type: `boolean` +* default value: `false` +* introduced in: `1.2.0` + +=== "input" + + ``` + Lorem ipsum www.google.com + ``` + +=== "output (value is `false`)" + + ```html +

Lorem ipsum www.google.com

+ ``` + +=== "output (value is `true`)" + + ```html +

Lorem ipsum www.google.com

+ ``` + +### excludeTrailingPunctuationFromURLs + +Exclude trailing punctuation from autolinked URLs: `.` `!` `?` `(` `)` + +This option applies only to links generated by [`simplifiedAutoLink`](#simplifiedautolink). + +* type: `boolean` +* default value: `false` +* introduced in: `1.5.1` + +=== "input" + + ``` + check this link www.google.com. + ``` + +=== "output (value is `false`)" + + ```html +

check this link www.google.com.

+ ``` + +=== "output (value is `true`)" + + ```html +

check this link www.google.com.

+ ``` + +### literalMidWordUnderscores + +Treat underscores in the middle of words as literal characters. + +Underscores allow you to specify the words that should be emphasized. However, in some cases, this may be unwanted behavior. With this option enabled, underscores in the middle of words will no longer be interpreted as `` and ``, but as literal underscores. + +* type: `boolean` +* default value: `false` +* introduced in: `1.2.0` + +=== "input" + + ``` + some text with__underscores__in the middle + ``` + +=== "output (value is `false`)" + + ```html +

some text withunderscoresin the middle

+ ``` + +=== "output (value is `true`)" + + ```html +

some text with__underscores__in the middle

+ ``` + +### strikethrough + +Enable support for strikethrough (``). + +* type: `boolean` +* default value: `false` +* introduced in: `1.2.0` + +=== "input" + + ``` + ~~strikethrough~~ + ``` + +=== "output (value is `true`)" + + ```html + strikethrough + ``` + +### tables + +Enable support for tables syntax. + +* type: `boolean` +* default value: `false` +* introduced in: `1.2.0` + +=== "example" + + ``` + | h1 | h2 | h3 | + |:------|:-------:|--------:| + | 100 | [a][1] | ![b][2] | + | *foo* | **bar** | ~~baz~~ | + ``` + +### tablesHeaderId + +Generate automatic IDs for table headings. Works only when [`tables: true`](#tables). + +* type: `boolean` +* default value: `false` +* introduced in: `1.2.0` + +### ghCodeBlocks + +Enable support for GFM code block style syntax (fenced codeblocks). + +* type: `boolean` +* default value: `true` +* introduced in: `0.3.1` + +=== "example" + + ``` + ``` + some code here + ``` + ``` + +### tasklists + +Enable support for GitHub style tasklists. + +* type: `boolean` +* default value: `false` +* introduced in: `1.2.0` + +=== "example" + + ``` + - [x] This task is done + - [ ] This task is still pending + ``` + +### ghMentions + +Enables support for GitHub `@mentions` that allows you to link to the GitHub profile page of the mentioned username. + +* type: `boolean` +* default value: `false` +* introduced in: `1.6.0` + +=== "input" + + ``` + hello there @tivie + ``` + +=== "output (value is `false`)" + + ```html +

hello there @tivie

+ ``` + +=== "output (value is `true`)" + + ```html +

hello there @tivie

+ ``` + +### ghMentionsLink + +Specify where the link generated by `@mentions` should point to. Works only when [`ghMentions: true`](#ghmentions). + +* type: `boolean` +* default value: `https://github.com/{u}` +* introduced in: `1.6.2` + +=== "input" + + ``` + hello there @tivie + ``` + +=== "output (value is `https://github.com/{u}`)" + + ```html +

hello there @tivie

+ ``` + +=== "output (value is `http://mysite.com/{u}/profile`)" + + ```html +

hello there @tivie

+ ``` + +### smoothLivePreview + +Resolve an awkward effect when a paragraph is followed by a list. This effect appears on some circumstances, in live preview editors. + +* type: `boolean` +* default value: `false` +* introduced in: `1.2.1` + +!!! example "awkward effect" + + ![](http://i.imgur.com/YQ9iHTL.gif​) + +### smartIndentationFix + +Resolve indentation problems related to ES6 template strings in the midst of indented code. + +* type: `boolean` +* default value: `false` +* introduced in: `1.4.2` + +### disableForced4SpacesIndentedSublists + +Disable the rule of 4 spaces to indent sub-lists. If enabled, this option effectively reverts to the old behavior where you can indent sub-lists with 2 or 3 spaces. + +* type: `boolean` +* default value: `false` +* introduced in: `1.5.0` + +=== "input" + + ``` + - one + - two + + ... + + - one + - two + ``` + +=== "output (value is `false`)" + + ```html +
    +
  • one
  • +
  • two
  • +
+

...

+
    +
  • one +
      +
    • two
    • +
    +
  • +
+ ``` + +=== "output (value is `true`)" + + ```html +
    +
  • one +
      +
    • two
    • +
    +
  • +
+

...

+
    +
  • one +
      +
    • two
    • +
    +
  • +
+ ``` + +### simpleLineBreaks + +Parse line breaks as `
` in paragraphs (GitHub-style behavior). + +* type: `boolean` +* default value: `false` +* introduced in: `1.5.1` + +=== "input" + + ``` + a line + wrapped in two + ``` + +=== "output (value is `false`)" + + ```html +

a line + wrapped in two

+ ``` + +=== "output (value is `true`)" + + ```html +

a line
+ wrapped in two

+ ``` + +### requireSpaceBeforeHeadingText + +Require a space between a heading `#` and the heading text. + +* type: `boolean` +* default value: `false` +* introduced in: `1.5.3` + +=== "input" + + ``` + #heading + ``` + +=== "output (value is `false`)" + + ```html +

heading

+ ``` + +=== "output (value is `true`)" + + ```html +

#heading

+ ``` + +### encodeEmails + +Enable automatic obfuscation of email addresses. During this process, email addresses are encoded via Character Entities, transforming ASCII email addresses into their equivalent decimal entities. + +* type: `boolean` +* default value: `false` +* introduced in: `1.6.1` + +=== "input" + + ``` + + ``` + +=== "output (value is `false`)" + + ```html + myself@example.com + ``` + +=== "output (value is `true`)" + + ```html + myself@example.com + ``` + +### openLinksInNewWindow + +Open links in new windows. + +* type: `boolean` +* default value: `false` +* introduced in: `1.7.0` + +=== "input" + + ``` + [link](https://google.com) + ``` + +=== "output (value is `false`)" + + ```html + link + ``` + +=== "output (value is `true`)" + + ```html + link + ``` + +### backslashEscapesHTMLTags + +Support escaping of HTML tags. + +* type: `boolean` +* default value: `false` +* introduced in: `1.7.2` + +=== "input" + + ```html + \
foo\
+ ``` + +=== "output (value is `true`)" + + ```html +

<div>foo</div>

+ ``` + +### emoji + +Enable emoji support. For more info on available emojis, see https://github.com/showdownjs/showdown/wiki/Emojis (since v.1.8.0) + +* type: `boolean` +* default value: `false` +* introduced in: `1.8.0` + +=== "input" + + ``` + this is a :smile: emoji + ``` + +=== "output (value is `false`)" + + ```html +

this is a :smile: emoji

+ ``` + +=== "output (value is `true`)" + + ```html +

this is a 😄 emoji

+ ``` + +!!! hint "Full list of supported emojies" + + Check the [Showdown Wiki](https://github.com/showdownjs/showdown/wiki/Emojis#emoji-list) for a full list of supported emojies. + +### underline + +Enable support for underline. If enabled, underscores will no longer be parsed as `` and ``. + +* type: `boolean` +* default value: `false` +* status: `Experimental` + +=== "example" + + ``` + __underlined word__ // double underscores + + ___underlined word___ // triple underscores + ``` + +### completeHTMLDocument + +Output a complete HTML document, including ``, ``, and `` tags instead of an HTML fragment. + +* type: `boolean` +* default value: `false` +* introduced in: `1.8.5` + +### metadata + +Enable support for document metadata (front-matter). You can define metadata at the top of a document between `««« »»»` or `--- ---` symbols. + +* type: `boolean` +* default value: `false` +* introduced in: `1.8.5` + +=== "input" + + ```js + let ref = `referenced value`; + + var markdown = ` + --- + first: Lorem + second: Ipsum + ref_variable: ${ref} + --- + ` + + var conv = new showdown.Converter({metadata: true}); + var html = conv.makeHtml(markdown); + var metadata = conv.getMetadata(); + ``` + +=== "output (value is `true`)" + + ```js + // console.log(metadata) + { + first: 'Lorem', + second: 'Ipsum', + ref_variable: 'referenced value' + } + ``` + +### splitAdjacentBlockquotes + +Split adjacent blockquote blocks. + +* type: `boolean` +* default value: `false` +* introduced in: `1.8.6` + +=== "input" + + ``` + > Quote #1 + >> Sub-quote 1 + + > Quote #2 + >> Sub-quote 2 + ``` + +=== "output (value is `false`)" + + ```html +
+

Quote #1

+
+

Sub-quote 1

+
+

Quote #2

+
+

Sub-quote 2

+
+
+ ``` + +=== "output (value is `true`)" + + ```html +
+

Quote #1

+
+

Sub-quote 1

+
+
+
+

Quote #2

+
+

Sub-quote 2

+
+
+ ``` diff --git a/mkdocs.yml b/mkdocs.yml index 9951def..727eb4a 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -34,4 +34,5 @@ nav: - Quickstart: quickstart.md - Compatibility: compatibility.md - Configuration: - - Showdown options: configuration.md \ No newline at end of file + - Showdown options: configuration.md + - Available options: available-options.md \ No newline at end of file From a1bb3e0a9bd388416409d22ecd9c779519a93685 Mon Sep 17 00:00:00 2001 From: Antonio Date: Mon, 28 Mar 2022 22:18:38 +0300 Subject: [PATCH 04/10] docs: sort showdown options alphabetically --- docs/available-options.md | 1074 ++++++++++++++++++------------------- 1 file changed, 537 insertions(+), 537 deletions(-) diff --git a/docs/available-options.md b/docs/available-options.md index 114244c..9cbc3c0 100644 --- a/docs/available-options.md +++ b/docs/available-options.md @@ -1,65 +1,33 @@ !!! warning "" Starting from the version `1.6.0` and earlier, all the options are `disabled` by default in the cli tool. -### omitExtraWLInCodeBlocks +### backslashEscapesHTMLTags -Omit trailing newline in code blocks (which is set by default before the closing tag). This option affects both indented and fenced (gfm style) code blocks. +Support escaping of HTML tags. * type: `boolean` * default value: `false` -* introduced in: `1.0.0` +* introduced in: `1.7.2` === "input" - ``` - var foo = 'bar'; - ``` - -=== "output (value is `false`)" - ```html -
var foo = 'bar';
-    
+ \
foo\
``` === "output (value is `true`)" ```html -
var foo = 'bar';
+

<div>foo</div>

``` -### noHeaderId +### completeHTMLDocument -Disable automatic generation of heading IDs. - -!!! warning "" - Setting the option to `true` overrides the following options: - - * [`prefixHeaderId`](#prefixheaderid) - * [`customizedHeaderId`](#customizedheaderid) - * [`ghCompatibleHeaderId`](#ghcompatibleheaderid) +Output a complete HTML document, including ``, ``, and `` tags instead of an HTML fragment. * type: `boolean` * default value: `false` -* introduced in: `1.1.0` - -=== "input" - - ``` - # This is a heading - ``` - -=== "output (value is `false`)" - - ```html -

This is a heading

- ``` - -=== "output (value is `true`)" - - ```html -

This is a heading

- ``` +* introduced in: `1.8.5` ### customizedHeaderId @@ -87,366 +55,6 @@ Set custom ID for a heading. !!! hint "" For better readability and human-friendliness of the heading IDs, it is also recommended to set the [`ghCompatibleHeaderId`](#ghcompatibleheaderid) option to `true`. -### ghCompatibleHeaderId - -Generate heading IDs compatible with GitHub style: spaces are replaced with dashes, and certain non-alphanumeric chars are removed. - -!!! warning "" - This option can be overridden with the [`noHeaderId`](#noheaderid) option. - -* type: `boolean` -* default value: `false` -* introduced in: `1.5.5` - -=== "input" - - ``` - # This is a heading with @#$% - ``` - -=== "output (value is `false`)" - - ```html -

This is a heading

- ``` - -=== "output (value is `true`)" - - ```html -

This is a heading with @#$%

- ``` - -### rawHeaderId - -Replace ` ` (space), `'` (single quote), and `"` (double quote) with `-` (dash) in the generated heading IDs, including prefixes. - -!!! danger "" - **Use with caution** as it might result in malformed IDs. - -* type: -* default value: -* introduced in: `1.7.3` - -### prefixHeaderId - -Add a prefix to the generated heading ID: - -* Passing a string will add that string to the heading ID. -* Passing `true` will add a generic `section` prefix. - -!!! warning "" - This option can be overridden with the [`noHeaderId`](#noheaderid) option. - -* type: `string / boolean` -* default value: `false` - -=== "input" - - ``` - # This is a heading - ``` - -=== "output (value is `false`)" - - ```html -

This is a heading

- ``` - -=== "output (value is `true`)" - - ```html -

This is a heading

- ``` - -=== "output (value is `showdown`)" - - ```html -

This is a heading

- ``` - -### rawPrefixHeaderId - -Prevent Showndown from modifying the prefix. Works only when [`prefixHeaderId`](#prefixheaderid) is set to a string value. - -!!! danger "" - **Use with caution** as it might result in malformed IDs. For example, when the prefix contains special characters like `"` `\` `/` or others. - -* type: `boolean` -* default value: `false` -* introduced in: `1.7.3` - -### headerLevelStart - -Set starting level for the heading tags. - -* type: `integer` -* default value: `1` -* introduced in: `1.1.0` - -=== "input" - - ``` - # This is a heading - ``` - -=== "output (value is `1`)" - - ```html -

This is a heading

- ``` - -=== "output (value is `3`)" - - ```html -

This is a heading

- ``` - -### parseImgDimensions - -Set image dimensions from within Markdown syntax. - -* type: `boolean` -* default value: `false` -* introduced in: `1.1.0` - -=== "example" - - ``` - ![foo](foo.jpg =100x80) set width to 100px and height to 80px - ![bar](bar.jpg =100x*) set width to 100px and height to "auto" - ![baz](baz.jpg =80%x5em) set width to 80% and height to 5em - ``` - -### simplifiedAutoLink - -Enable automatic linking for plain text URLs. - -* type: `boolean` -* default value: `false` -* introduced in: `1.2.0` - -=== "input" - - ``` - Lorem ipsum www.google.com - ``` - -=== "output (value is `false`)" - - ```html -

Lorem ipsum www.google.com

- ``` - -=== "output (value is `true`)" - - ```html -

Lorem ipsum www.google.com

- ``` - -### excludeTrailingPunctuationFromURLs - -Exclude trailing punctuation from autolinked URLs: `.` `!` `?` `(` `)` - -This option applies only to links generated by [`simplifiedAutoLink`](#simplifiedautolink). - -* type: `boolean` -* default value: `false` -* introduced in: `1.5.1` - -=== "input" - - ``` - check this link www.google.com. - ``` - -=== "output (value is `false`)" - - ```html -

check this link www.google.com.

- ``` - -=== "output (value is `true`)" - - ```html -

check this link www.google.com.

- ``` - -### literalMidWordUnderscores - -Treat underscores in the middle of words as literal characters. - -Underscores allow you to specify the words that should be emphasized. However, in some cases, this may be unwanted behavior. With this option enabled, underscores in the middle of words will no longer be interpreted as `` and ``, but as literal underscores. - -* type: `boolean` -* default value: `false` -* introduced in: `1.2.0` - -=== "input" - - ``` - some text with__underscores__in the middle - ``` - -=== "output (value is `false`)" - - ```html -

some text withunderscoresin the middle

- ``` - -=== "output (value is `true`)" - - ```html -

some text with__underscores__in the middle

- ``` - -### strikethrough - -Enable support for strikethrough (``). - -* type: `boolean` -* default value: `false` -* introduced in: `1.2.0` - -=== "input" - - ``` - ~~strikethrough~~ - ``` - -=== "output (value is `true`)" - - ```html - strikethrough - ``` - -### tables - -Enable support for tables syntax. - -* type: `boolean` -* default value: `false` -* introduced in: `1.2.0` - -=== "example" - - ``` - | h1 | h2 | h3 | - |:------|:-------:|--------:| - | 100 | [a][1] | ![b][2] | - | *foo* | **bar** | ~~baz~~ | - ``` - -### tablesHeaderId - -Generate automatic IDs for table headings. Works only when [`tables: true`](#tables). - -* type: `boolean` -* default value: `false` -* introduced in: `1.2.0` - -### ghCodeBlocks - -Enable support for GFM code block style syntax (fenced codeblocks). - -* type: `boolean` -* default value: `true` -* introduced in: `0.3.1` - -=== "example" - - ``` - ``` - some code here - ``` - ``` - -### tasklists - -Enable support for GitHub style tasklists. - -* type: `boolean` -* default value: `false` -* introduced in: `1.2.0` - -=== "example" - - ``` - - [x] This task is done - - [ ] This task is still pending - ``` - -### ghMentions - -Enables support for GitHub `@mentions` that allows you to link to the GitHub profile page of the mentioned username. - -* type: `boolean` -* default value: `false` -* introduced in: `1.6.0` - -=== "input" - - ``` - hello there @tivie - ``` - -=== "output (value is `false`)" - - ```html -

hello there @tivie

- ``` - -=== "output (value is `true`)" - - ```html -

hello there @tivie

- ``` - -### ghMentionsLink - -Specify where the link generated by `@mentions` should point to. Works only when [`ghMentions: true`](#ghmentions). - -* type: `boolean` -* default value: `https://github.com/{u}` -* introduced in: `1.6.2` - -=== "input" - - ``` - hello there @tivie - ``` - -=== "output (value is `https://github.com/{u}`)" - - ```html -

hello there @tivie

- ``` - -=== "output (value is `http://mysite.com/{u}/profile`)" - - ```html -

hello there @tivie

- ``` - -### smoothLivePreview - -Resolve an awkward effect when a paragraph is followed by a list. This effect appears on some circumstances, in live preview editors. - -* type: `boolean` -* default value: `false` -* introduced in: `1.2.1` - -!!! example "awkward effect" - - ![](http://i.imgur.com/YQ9iHTL.gif​) - -### smartIndentationFix - -Resolve indentation problems related to ES6 template strings in the midst of indented code. - -* type: `boolean` -* default value: `false` -* introduced in: `1.4.2` - ### disableForced4SpacesIndentedSublists Disable the rule of 4 spaces to indent sub-lists. If enabled, this option effectively reverts to the old behavior where you can indent sub-lists with 2 or 3 spaces. @@ -504,133 +112,6 @@ Disable the rule of 4 spaces to indent sub-lists. If enabled, this option effect ``` -### simpleLineBreaks - -Parse line breaks as `
` in paragraphs (GitHub-style behavior). - -* type: `boolean` -* default value: `false` -* introduced in: `1.5.1` - -=== "input" - - ``` - a line - wrapped in two - ``` - -=== "output (value is `false`)" - - ```html -

a line - wrapped in two

- ``` - -=== "output (value is `true`)" - - ```html -

a line
- wrapped in two

- ``` - -### requireSpaceBeforeHeadingText - -Require a space between a heading `#` and the heading text. - -* type: `boolean` -* default value: `false` -* introduced in: `1.5.3` - -=== "input" - - ``` - #heading - ``` - -=== "output (value is `false`)" - - ```html -

heading

- ``` - -=== "output (value is `true`)" - - ```html -

#heading

- ``` - -### encodeEmails - -Enable automatic obfuscation of email addresses. During this process, email addresses are encoded via Character Entities, transforming ASCII email addresses into their equivalent decimal entities. - -* type: `boolean` -* default value: `false` -* introduced in: `1.6.1` - -=== "input" - - ``` - - ``` - -=== "output (value is `false`)" - - ```html - myself@example.com - ``` - -=== "output (value is `true`)" - - ```html - myself@example.com - ``` - -### openLinksInNewWindow - -Open links in new windows. - -* type: `boolean` -* default value: `false` -* introduced in: `1.7.0` - -=== "input" - - ``` - [link](https://google.com) - ``` - -=== "output (value is `false`)" - - ```html - link - ``` - -=== "output (value is `true`)" - - ```html - link - ``` - -### backslashEscapesHTMLTags - -Support escaping of HTML tags. - -* type: `boolean` -* default value: `false` -* introduced in: `1.7.2` - -=== "input" - - ```html - \
foo\
- ``` - -=== "output (value is `true`)" - - ```html -

<div>foo</div>

- ``` - ### emoji Enable emoji support. For more info on available emojis, see https://github.com/showdownjs/showdown/wiki/Emojis (since v.1.8.0) @@ -659,31 +140,212 @@ Enable emoji support. For more info on available emojis, see https://github.com/ !!! hint "Full list of supported emojies" - Check the [Showdown Wiki](https://github.com/showdownjs/showdown/wiki/Emojis#emoji-list) for a full list of supported emojies. + Check the [Showdown Wiki](https://github.com/showdownjs/showdown/wiki/Emojis#emoji-list) for a full list of supported emojies. -### underline +### encodeEmails -Enable support for underline. If enabled, underscores will no longer be parsed as `` and ``. +Enable automatic obfuscation of email addresses. During this process, email addresses are encoded via Character Entities, transforming ASCII email addresses into their equivalent decimal entities. * type: `boolean` * default value: `false` -* status: `Experimental` +* introduced in: `1.6.1` + +=== "input" + + ``` + + ``` + +=== "output (value is `false`)" + + ```html + myself@example.com + ``` + +=== "output (value is `true`)" + + ```html + myself@example.com + ``` + +### excludeTrailingPunctuationFromURLs + +Exclude trailing punctuation from autolinked URLs: `.` `!` `?` `(` `)` + +This option applies only to links generated by [`simplifiedAutoLink`](#simplifiedautolink). + +* type: `boolean` +* default value: `false` +* introduced in: `1.5.1` + +=== "input" + + ``` + check this link www.google.com. + ``` + +=== "output (value is `false`)" + + ```html +

check this link www.google.com.

+ ``` + +=== "output (value is `true`)" + + ```html +

check this link www.google.com.

+ ``` + +### ghCodeBlocks + +Enable support for GFM code block style syntax (fenced codeblocks). + +* type: `boolean` +* default value: `true` +* introduced in: `0.3.1` === "example" ``` - __underlined word__ // double underscores - - ___underlined word___ // triple underscores + ``` + some code here + ``` ``` -### completeHTMLDocument +### ghCompatibleHeaderId -Output a complete HTML document, including ``, ``, and `` tags instead of an HTML fragment. +Generate heading IDs compatible with GitHub style: spaces are replaced with dashes, and certain non-alphanumeric chars are removed. + +!!! warning "" + This option can be overridden with the [`noHeaderId`](#noheaderid) option. * type: `boolean` * default value: `false` -* introduced in: `1.8.5` +* introduced in: `1.5.5` + +=== "input" + + ``` + # This is a heading with @#$% + ``` + +=== "output (value is `false`)" + + ```html +

This is a heading

+ ``` + +=== "output (value is `true`)" + + ```html +

This is a heading with @#$%

+ ``` + +### ghMentions + +Enables support for GitHub `@mentions` that allows you to link to the GitHub profile page of the mentioned username. + +* type: `boolean` +* default value: `false` +* introduced in: `1.6.0` + +=== "input" + + ``` + hello there @tivie + ``` + +=== "output (value is `false`)" + + ```html +

hello there @tivie

+ ``` + +=== "output (value is `true`)" + + ```html +

hello there @tivie

+ ``` + +### ghMentionsLink + +Specify where the link generated by `@mentions` should point to. Works only when [`ghMentions: true`](#ghmentions). + +* type: `boolean` +* default value: `https://github.com/{u}` +* introduced in: `1.6.2` + +=== "input" + + ``` + hello there @tivie + ``` + +=== "output (value is `https://github.com/{u}`)" + + ```html +

hello there @tivie

+ ``` + +=== "output (value is `http://mysite.com/{u}/profile`)" + + ```html +

hello there @tivie

+ ``` + +### headerLevelStart + +Set starting level for the heading tags. + +* type: `integer` +* default value: `1` +* introduced in: `1.1.0` + +=== "input" + + ``` + # This is a heading + ``` + +=== "output (value is `1`)" + + ```html +

This is a heading

+ ``` + +=== "output (value is `3`)" + + ```html +

This is a heading

+ ``` + +### literalMidWordUnderscores + +Treat underscores in the middle of words as literal characters. + +Underscores allow you to specify the words that should be emphasized. However, in some cases, this may be unwanted behavior. With this option enabled, underscores in the middle of words will no longer be interpreted as `` and ``, but as literal underscores. + +* type: `boolean` +* default value: `false` +* introduced in: `1.2.0` + +=== "input" + + ``` + some text with__underscores__in the middle + ``` + +=== "output (value is `false`)" + + ```html +

some text withunderscoresin the middle

+ ``` + +=== "output (value is `true`)" + + ```html +

some text with__underscores__in the middle

+ ``` ### metadata @@ -722,6 +384,268 @@ Enable support for document metadata (front-matter). You can define metadata at } ``` +### noHeaderId + +Disable automatic generation of heading IDs. + +!!! warning "" + Setting the option to `true` overrides the following options: + + * [`prefixHeaderId`](#prefixheaderid) + * [`customizedHeaderId`](#customizedheaderid) + * [`ghCompatibleHeaderId`](#ghcompatibleheaderid) + +* type: `boolean` +* default value: `false` +* introduced in: `1.1.0` + +=== "input" + + ``` + # This is a heading + ``` + +=== "output (value is `false`)" + + ```html +

This is a heading

+ ``` + +=== "output (value is `true`)" + + ```html +

This is a heading

+ ``` + +### omitExtraWLInCodeBlocks + +Omit trailing newline in code blocks (which is set by default before the closing tag). This option affects both indented and fenced (gfm style) code blocks. + +* type: `boolean` +* default value: `false` +* introduced in: `1.0.0` + +=== "input" + + ``` + var foo = 'bar'; + ``` + +=== "output (value is `false`)" + + ```html +
var foo = 'bar';
+    
+ ``` + +=== "output (value is `true`)" + + ```html +
var foo = 'bar';
+ ``` + +### openLinksInNewWindow + +Open links in new windows. + +* type: `boolean` +* default value: `false` +* introduced in: `1.7.0` + +=== "input" + + ``` + [link](https://google.com) + ``` + +=== "output (value is `false`)" + + ```html + link + ``` + +=== "output (value is `true`)" + + ```html + link + ``` + +### parseImgDimensions + +Set image dimensions from within Markdown syntax. + +* type: `boolean` +* default value: `false` +* introduced in: `1.1.0` + +=== "example" + + ``` + ![foo](foo.jpg =100x80) set width to 100px and height to 80px + ![bar](bar.jpg =100x*) set width to 100px and height to "auto" + ![baz](baz.jpg =80%x5em) set width to 80% and height to 5em + ``` + +### prefixHeaderId + +Add a prefix to the generated heading ID: + +* Passing a string will add that string to the heading ID. +* Passing `true` will add a generic `section` prefix. + +!!! warning "" + This option can be overridden with the [`noHeaderId`](#noheaderid) option. + +* type: `string / boolean` +* default value: `false` + +=== "input" + + ``` + # This is a heading + ``` + +=== "output (value is `false`)" + + ```html +

This is a heading

+ ``` + +=== "output (value is `true`)" + + ```html +

This is a heading

+ ``` + +=== "output (value is `showdown`)" + + ```html +

This is a heading

+ ``` + +### rawHeaderId + +Replace ` ` (space), `'` (single quote), and `"` (double quote) with `-` (dash) in the generated heading IDs, including prefixes. + +!!! danger "" + **Use with caution** as it might result in malformed IDs. + +* type: +* default value: +* introduced in: `1.7.3` + +### rawPrefixHeaderId + +Prevent Showndown from modifying the prefix. Works only when [`prefixHeaderId`](#prefixheaderid) is set to a string value. + +!!! danger "" + **Use with caution** as it might result in malformed IDs. For example, when the prefix contains special characters like `"` `\` `/` or others. + +* type: `boolean` +* default value: `false` +* introduced in: `1.7.3` + +### requireSpaceBeforeHeadingText + +Require a space between a heading `#` and the heading text. + +* type: `boolean` +* default value: `false` +* introduced in: `1.5.3` + +=== "input" + + ``` + #heading + ``` + +=== "output (value is `false`)" + + ```html +

heading

+ ``` + +=== "output (value is `true`)" + + ```html +

#heading

+ ``` + +### simpleLineBreaks + +Parse line breaks as `
` in paragraphs (GitHub-style behavior). + +* type: `boolean` +* default value: `false` +* introduced in: `1.5.1` + +=== "input" + + ``` + a line + wrapped in two + ``` + +=== "output (value is `false`)" + + ```html +

a line + wrapped in two

+ ``` + +=== "output (value is `true`)" + + ```html +

a line
+ wrapped in two

+ ``` + +### simplifiedAutoLink + +Enable automatic linking for plain text URLs. + +* type: `boolean` +* default value: `false` +* introduced in: `1.2.0` + +=== "input" + + ``` + Lorem ipsum www.google.com + ``` + +=== "output (value is `false`)" + + ```html +

Lorem ipsum www.google.com

+ ``` + +=== "output (value is `true`)" + + ```html +

Lorem ipsum www.google.com

+ ``` + +### smartIndentationFix + +Resolve indentation problems related to ES6 template strings in the midst of indented code. + +* type: `boolean` +* default value: `false` +* introduced in: `1.4.2` + +### smoothLivePreview + +Resolve an awkward effect when a paragraph is followed by a list. This effect appears on some circumstances, in live preview editors. + +* type: `boolean` +* default value: `false` +* introduced in: `1.2.1` + +!!! example "awkward effect" + + ![](http://i.imgur.com/YQ9iHTL.gif​) + ### splitAdjacentBlockquotes Split adjacent blockquote blocks. @@ -771,3 +695,79 @@ Split adjacent blockquote blocks. ``` + +### strikethrough + +Enable support for strikethrough (``). + +* type: `boolean` +* default value: `false` +* introduced in: `1.2.0` + +=== "input" + + ``` + ~~strikethrough~~ + ``` + +=== "output (value is `true`)" + + ```html + strikethrough + ``` + +### tables + +Enable support for tables syntax. + +* type: `boolean` +* default value: `false` +* introduced in: `1.2.0` + +=== "example" + + ``` + | h1 | h2 | h3 | + |:------|:-------:|--------:| + | 100 | [a][1] | ![b][2] | + | *foo* | **bar** | ~~baz~~ | + ``` + +### tablesHeaderId + +Generate automatic IDs for table headings. Works only when [`tables: true`](#tables). + +* type: `boolean` +* default value: `false` +* introduced in: `1.2.0` + +### tasklists + +Enable support for GitHub style tasklists. + +* type: `boolean` +* default value: `false` +* introduced in: `1.2.0` + +=== "example" + + ``` + - [x] This task is done + - [ ] This task is still pending + ``` + +### underline + +Enable support for underline. If enabled, underscores will no longer be parsed as `` and ``. + +* type: `boolean` +* default value: `false` +* status: `Experimental` + +=== "example" + + ``` + __underlined word__ // double underscores + + ___underlined word___ // triple underscores + ``` From 8d9b8f2f9282d050a0263d498b789372a9d76b54 Mon Sep 17 00:00:00 2001 From: Antonio Date: Wed, 30 Mar 2022 01:27:06 +0300 Subject: [PATCH 05/10] docs: added page about flavors --- docs/flavors.md | 23 +++++++++++++++++++++++ mkdocs.yml | 3 ++- 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 docs/flavors.md diff --git a/docs/flavors.md b/docs/flavors.md new file mode 100644 index 0000000..0850735 --- /dev/null +++ b/docs/flavors.md @@ -0,0 +1,23 @@ +## Overview + +You can use _flavors_ (or presets) to set the preferred options automatically. In this way, 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 (v1.3.1 onwards) + * `github`: [GitHub Flavored Markdown, or GFM](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax) + +## Set flavor + +=== "Globally" + + ```js + showdown.setFlavor('github'); + ``` + +=== "Locally" + + ```js + converter.setFlavor('github'); + ``` \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index 727eb4a..aaed006 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -35,4 +35,5 @@ nav: - Compatibility: compatibility.md - Configuration: - Showdown options: configuration.md - - Available options: available-options.md \ No newline at end of file + - Available options: available-options.md + - Flavors: flavors.md \ No newline at end of file From 6e6dde5c555d38b402382c40f6cea7c216c3b06d Mon Sep 17 00:00:00 2001 From: Antonio Date: Wed, 30 Mar 2022 02:13:37 +0300 Subject: [PATCH 06/10] docs: added page describing cli tool --- docs/cli.md | 153 ++++++++++++++++++++++++++++++++++++++++++++++++++++ mkdocs.yml | 3 +- 2 files changed, 155 insertions(+), 1 deletion(-) create mode 100644 docs/cli.md diff --git a/docs/cli.md b/docs/cli.md new file mode 100644 index 0000000..ddda916 --- /dev/null +++ b/docs/cli.md @@ -0,0 +1,153 @@ +Showdown comes bundled with a Command-line interface (CLI) tool that allows you to run Showdown converter from the command line. + +## Requirements + +* [Node.js](https://nodejs.org/en/) + +## Quick start guide + +1. Check that Showdown CLI is accessible. + + * If you installed Showdown globally via `npm install showdown -g`, you can access the CLI tool help by typing `showdown -h` in the command line: + + === "input" + + ```sh + showdown -h + ``` + + === "output" + + ``` + Usage: showdown [options] + + CLI to Showdownjs markdown parser v3.0.0-alpha + + Options: + -V, --version output the version number + -q, --quiet Quiet mode. Only print errors + -m, --mute Mute mode. Does not print anything + -h, --help display help for command + + Commands: + makehtml [options] Converts markdown into html + help [command] display help for command + ``` + + * If you installed Showdown locally via `npm install showdown`, open the folder where Showdown is installed, and type `node ./bin/showdown.js -h` in the command line: + + === "input" + + ```sh + node ./bin/showdown.js -h + ``` + + === "output" + + ``` + Usage: showdown [options] + + CLI to Showdownjs markdown parser v3.0.0-alpha + + Options: + -V, --version output the version number + -q, --quiet Quiet mode. Only print errors + -m, --mute Mute mode. Does not print anything + -h, --help display help for command + + Commands: + makehtml [options] Converts markdown into html + help [command] display help for command + ``` + +1. Use `makehtml` command to convert your document to HTML. For example: + + !!! example "Convert `foo.md` into `bar.html`" + + ```sh + showdown makehtml -i foo.md -o bar.html + ``` + +## Commands + +### `makehtml` + +Convert a Markdown input into HTML. + +**Usage** + +```sh +showdown makehtml [options] +``` + +#### Options + +###### `-i / --input` + +* Short format: `-i` +* Alias: `--input` +* Description: Input source. Usually a `.md` file. If omitted or empty, reads from `stdin`. +* Examples: + + !!! example "" + + ```sh + // Read from stdin and output to stdout + showdown makehtml -i + + // Read from the foo.md file and output to stdout + showdown makehtml --input foo.md + ``` + +###### `-o/--output` + +* Short format: `-o` +* Alias: `--output` +* Description: Output target. Usually a `.html` file. If omitted or empty, writes to `stdout`. +* Example: + + !!! example "" + + ```sh + // Read from the foo.md file and output to bar.html + showdown makehtml -i foo.md -o bar.html + ``` + +###### `-a/--append` + +* Short format: `-a` +* Alias: `--append` +* Description: Append data to output instead of overwriting. +* Example: + + !!! example "" + + ```sh + showdown makehtml -a + ``` + +###### `-u/--encoding` + +* Short format: `-u` +* Alias: `--encoding` +* Description: Specify the input encoding. +* Example: + + !!! example "" + + ```sh + showdown makehtml -u UTF8 + ``` + +###### `-e/--extensions` + +* Short format: `-e` +* Alias: `--extension` +* Description: Load the specified extension(s). Should be valid path(s) to Node-compatible extensions. +* Example: + + !!! example "" + + ```sh + showdown makehtml -e ~/twitter.js -e ~/youtube.js + ``` \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index aaed006..8d772f4 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -36,4 +36,5 @@ nav: - Configuration: - Showdown options: configuration.md - Available options: available-options.md - - Flavors: flavors.md \ No newline at end of file + - Flavors: flavors.md + - CLI: cli.md \ No newline at end of file From 568445fa4329459971aeeefcfdaec5675cdcbb04 Mon Sep 17 00:00:00 2001 From: Antonio Date: Wed, 30 Mar 2022 20:12:35 +0300 Subject: [PATCH 07/10] docs: added integrations --- docs/integrations.md | 20 ++++++++++++++++++++ mkdocs.yml | 3 ++- 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 docs/integrations.md diff --git a/docs/integrations.md b/docs/integrations.md new file mode 100644 index 0000000..bc85664 --- /dev/null +++ b/docs/integrations.md @@ -0,0 +1,20 @@ +## AngularJS + +ShowdownJS project provides seamless integration with AngularJS via a plugin. + +Check [`ng-showdown`](https://github.com/showdownjs/ngShowdown) repository for more information. + +## TypeScript + +If you're using TypeScript, you may want to use the types from the [DefinitelyTyped][definitely-typed] repository. + +## SystemJS/JSPM + +To integrate ShowdownJS with SystemJS, you can use a third-party [system-md plugin](https://github.com/guybedford/system-md). + +## Vue.js + +To use ShowdownJS as a Vue component, you can check [vue-showdown](https://vue-showdown.js.org/). + + +[definitely-typed]: https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/showdown \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index 8d772f4..b87fdf0 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -37,4 +37,5 @@ nav: - Showdown options: configuration.md - Available options: available-options.md - Flavors: flavors.md - - CLI: cli.md \ No newline at end of file + - CLI: cli.md + - Integrations: integrations.md \ No newline at end of file From bdddfb91313b09c4e41cab63267092a824c8143f Mon Sep 17 00:00:00 2001 From: Antonio Date: Wed, 30 Mar 2022 21:29:13 +0300 Subject: [PATCH 08/10] docs: added page describing markdown's xss vulnerability --- docs/quickstart.md | 5 +++ docs/xss.md | 110 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 115 insertions(+) create mode 100644 docs/xss.md diff --git a/docs/quickstart.md b/docs/quickstart.md index 30e6f86..1f47fed 100644 --- a/docs/quickstart.md +++ b/docs/quickstart.md @@ -94,6 +94,11 @@ Once installed, you can use Showndown according to the chosen method:

hello, markdown!

``` +!!! warning "Potential XSS vulnerabilities" + Showdown doesn't sanitize the input since Markdown relies on it to parse certain features correctly into HTML. As a result, this may lead to potential XSS injection vulnerabilities. + + Please refer to the [Markdown's XSS vulnerability](xss.md) page for more information. + ## Other installation methods ### Tarball diff --git a/docs/xss.md b/docs/xss.md new file mode 100644 index 0000000..f5bdc20 --- /dev/null +++ b/docs/xss.md @@ -0,0 +1,110 @@ +# Markdown's XSS vulnerability + +## Introduction + +Cross-Site Scripting (XSS) is a well-known technique to gain access to the private information of users on a website. The attacker injects spurious HTML content (a script) on the web page. This script can read the user’s cookies and do other malicious actions (like steal credentials). As a countermeasure, you should always filter user input for suspicious content. Showdown doesn’t include an XSS filter, so you must provide your own. But be careful in how you do it. + +## Markdown is inherently unsafe + +Markdown syntax allows the inclusion of arbitrary HTML. For example, below is a perfectly valid Markdown: + +```md +This is a regular paragraph. + + + +
Foo
+ +This is another regular paragraph. +``` + +This means that an attacker could do something like this: + +```md +This is a regular paragraph. + + + +This is another regular paragraph. +``` + +While `alert('xss');` is hardly problematic (maybe just annoying) a real-world scenario might be a lot worse. Obviously, you can easily prevent this kind of this straightforward attack. For example, you can define a whitelist for Showdown that will contain a limited set of allowed HTML tags. However, an attacker can easily circumvent this "defense". + +## Whitelist / blacklist can't prevent XSS + +Consider the following Markdown content: + +```md +hello *you* +``` + +As you can see, it's a link, nothing malicious about this. And `` tags are pretty innocuous, right? Showdown should definitely allow them. But what if the content is slightly altered, like this: + +```md +hello *you* +``` + +Now this is a lot more problematic. Once again, it's not that hard to filter Showdown's input to expunge problematic attributes (such as `href` in `` tags) of scripting attacks. In fact, a regular HTML XSS prevention library should catch this kind of straightforward attack. + +At this point you're probably thinking that the best way is to follow Stackoverflow's cue and disallow embedded HTML in Markdown. Unfortunately it's still not enough. + +## Strip HTML tags is not enough + +Consider the following Markdown input: + +```md +[some text](javascript:alert('xss')) +``` + +Showdown will correctly parse this piece of Markdown input as: + +```html +some text +``` + +In this case, it was Markdown's syntax itself to create the dangerous link. HTML XSS filter cannot catch this. And unless you start striping dangerous words like *javascript* (which would make this article extremely hard to write), there's nothing you can really do to filter XSS attacks from your input. Things get even harder when you tightly mix HTML with Markdown. + +## Mixed HTML/Markdown XSS attack + +Consider the following piece of Markdown: + +```md +> hello href="javascript:alert('xss')">*you* +``` + +If you apply an XSS filter to filter bad HTML in this Markdown input, the XSS filter, expecting HTML, will likely think the `` tag ends with the first character on the second line and will leave the text snippet untouched. It will probably fail to see that the `href="javascript:…"` is part of the `` element and leave it alone. But when Markdown converts this to HTML, you get this: + +```html +
+

hello you

+
+``` + +After parsing with Markdown, the first `>` on the second line disappears because it was the blockquote marker in the Markdown blockquote syntax. As a result, you’ve got a link containing an XSS attack! + +Did Markdown generate the HTML? No, the HTML was already in plain sight in the input. The XSS filter couldn’t catch it because the input doesn’t follow HTML rules: it’s a mix of Markdown and HTML, and the filter doesn’t know a dime about Markdown. + +## Mitigate XSS + +So, is it all lost? Not really. The answer is not to filter the *input* but rather the *output*. After the *input* text is converted into full-fledged HTML, you can reliably apply the correct XSS filters to remove any dangerous or malicious content. + +Also, client-side validations are not reliable. It should be a given, but in case you're wondering, you should (almost) never trust data sent by the client. If there's some critical operation you must perform on the data (such as XSS filtering), you should do it *SERVER-SIDE* not client-side. + +HTML XSS filtering libraries are useful here since they prevent most of the attacks. However, you should not use them blindly: a library can't predict all the contexts and situations your application may face. + +## Conclusion + +Showdown tries to convert the input text as closely as possible, without any concerns for XSS attacks or malicious intent. So, the basic rules are: + +* **removing HTML entities from Markdown does not prevent XSS**. Markdown syntax can generate XSS attacks. +* **XSS filtering should be done after Showdown has processed input, not before or during**. If you filter before, it will break some of Markdown’s features and will leave security holes. +* **perform the necessary filtering server-side, not client-side**. XSS filtering libraries are useful but should not be used blindly. + +## Disclaimer + +This page is based on the excellent article: ["Markdown and XSS"][1] by [Michel Fortin][2] + +[1]: https://michelf.ca/blog/2010/markdown-and-xss/ +[2]: https://github.com/michelf From d11e5cf6e0d1be435fb7c1e446a952f574dc29a1 Mon Sep 17 00:00:00 2001 From: Antonio Date: Wed, 30 Mar 2022 23:35:17 +0300 Subject: [PATCH 09/10] docs: added extensions overview page --- docs/extensions.md | 36 ++++++++++++++++++++++++++++++++++++ mkdocs.yml | 4 +++- 2 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 docs/extensions.md diff --git a/docs/extensions.md b/docs/extensions.md new file mode 100644 index 0000000..320cefa --- /dev/null +++ b/docs/extensions.md @@ -0,0 +1,36 @@ +Showdown allows you to load additional functionality via extensions. You can find a list of known Showdown extensions [here][ext-wiki]. + +You can also check the [boilerplate repo][boilerplate-repo], to create your own extension(s). + +## Usage + +=== "Server-side" + + ```js + // Using a bundled extension + var showdown = require('showdown'); + var converter = new showdown.Converter({ extensions: ['twitter'] }); + + // Using a custom extension + var mine = require('./custom-extensions/mine'); + var converter = new showdown.Converter({ extensions: ['twitter', mine] }); + ``` + +=== "Client-side" + + ```js + + + + ``` + +=== "CLI" + + In the CLI tool, use the [`-e` flag](/cli/#-e-extensions) to load an extension. + + ```sh + showdown -e twitter -i foo.md -o bar.html + ``` + +[ext-wiki]: https://github.com/showdownjs/showdown/wiki/extensions +[boilerplate-repo]: https://github.com/showdownjs/extension-boilerplate \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index b87fdf0..a1d77cd 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -38,4 +38,6 @@ nav: - Available options: available-options.md - Flavors: flavors.md - CLI: cli.md - - Integrations: integrations.md \ No newline at end of file + - Integrations: integrations.md + - Extensions: + - Overview: extensions.md \ No newline at end of file From 010f94fd04a75f31ccab0d193e36d36d4eb09a26 Mon Sep 17 00:00:00 2001 From: Antonio Date: Thu, 31 Mar 2022 01:29:59 +0300 Subject: [PATCH 10/10] docs: added create extension page --- docs/create-extension.md | 182 +++++++++++++++++++++++++++++++++++++++ mkdocs.yml | 3 +- 2 files changed, 184 insertions(+), 1 deletion(-) create mode 100644 docs/create-extension.md diff --git a/docs/create-extension.md b/docs/create-extension.md new file mode 100644 index 0000000..d087a43 --- /dev/null +++ b/docs/create-extension.md @@ -0,0 +1,182 @@ +A Showdown extension is a function that returns an array of language or outputs extensions (henceforth called "sub-extensions"). + +```js +var myext = function () { + var myext1 = { + type: 'lang', + regex: /markdown/g, + replace: 'showdown' + }; + var myext2 = { + /* extension code */ + }; + return [myext1, myext2]; +} +``` + +Each sub-extension (`myext1` and `myext2` in the example above) should be an object that defines the behavior of the corresponding sub-extension. + +## Sub-extension object properties + +A sub-extension object should have a [`type` property](#type) that defines the type of the sub-extension, and either [`regex` and `replace` properties](#regex-and-replace) or a [`filter` property](#filter). + +### Type + +**Type** is a **required** property that defines the nature of the corresponding sub-extensions. It takes one of the two values: + +* **`lang`**: language extension to add new Markdown syntax to Showdown. + + `lang` extensions have the **highest priority** in the subparser order, so they are called after [escaping and normalizing](#escape-and-normalization) the input text and before calling any other subparser (or extension). + + !!! example "When to use `lang` type" + + For example, if you want the `^^youtube http://www.youtube.com/watch?v=oHg5SJYRHA0` syntax to automatically be rendered as an embedded YouTube video. + +* **`output`**: output extension (or modifier) to alter the HTML output generated by Showdown. + + `output` extensions have the **lowest priority** in the subparser order, so they are called right before the cleanup step and after calling all other subparsers. + + !!! example "When to use `output` type" + + For example, if you want the `
` to become `
`. + +### Regex and replace + +`regex`/`replace` properties are similar to the Javascript's `string.replace` function and work the same way: + +* `regex`: a `string` or a `RegExp` object. + + If `regex` is a `string`, it will automatically be assigned a `g` (global) modifier, that is, all matches of that string will be replaced. + +* `replace` a `string` or a `function`. + + If `replace` is a `string`, you can use the `$1` syntax for group substitution, exactly as if it were making use of `string.replace`. + +!!! example "Regex and replace example" + + In this example, all the occurrences of `markdown` will be replaced with `showndown`. + + ```js + var myext = { + type: 'lang', + regex: /markdown/g, + replace: 'showdown' + }; + ``` + +### Filter + +Alternately, if you'd like to have more control over the modification process, you can use `filter` property. + +This property should be used as a function that acts as a callback. The callback should receive the following parameters: + +1. `text`: the source text within the Showdown's engine. +1. `converter`: the full instance of the current Showdown's converter object. +1. `options`: the options used to initialize the converter + +!!! warning "" + The filter function **should return the transformed text**. If it doesn't, it will fail **silently** and return an empty output. + +!!! example "Filter example" + + ```js + var myext = { + type: 'lang', + filter: function (text, converter, options) { + // ... do stuff to text ... + return text; + } + }; + ``` + +!!! warning "Use `filter` with care" + + Although Filter extensions are more powerful, they have a few pitfalls that you should keep in mind before using them, especially regarding the `converter` parameter. + + Since the `converter` parameter passed to the filter function is the fully initialized instance, any change made to it will be propagated outside the scope of the filter function and will remain there until a new converter instance is created. So, **it is not recommended to make ANY change to the converter object**. + + Another aspect is that if you call the `converter` recursively, it will call your extension itself at some point. It may lead to infinite recursion in some circumstances, and it's up to you to prevent this. A simple solution is to place a kind of safeguard to disable your extension if it's called more than x times: + + ```js + var x = 0; + var myext = { + type: 'lang', + filter: function (text, converter) { + if (x < 3) { + ++x; + someSubText = converter.makeHtml(someSubText); + } + } + }; + ``` + +## Register an extension + + +To let Showdown know what extensions are available, you need to register them in the Showdown global object. + +To register an extension, call the `showdown.extension` function with two parameters: the first one is the extension name; the second one is the actual extension. + +```js +showdown.extension('myext', myext); +``` + +## Test an extension + +The Showdown test runner is configured to automatically test cases for extensions. + +To add test cases for an extension: + +1. Create a new folder under `./test/extensions` that matches with the name of the `.js` file in `./src/extensions`. +1. Place any test cases into the filter using the `md/html` format. These cases will automatically be executed when running tests. + +## Additional information + +### Escape and normalization + +Showdown performs the following escape/normalization: + +* Replaces `¨` (trema) with `¨T` +* Replaces `$` (dollar sign) with `¨D` +* Normalizes line endings (`\r`, `\r\n` are converted into `\n`) +* Uses `\r` as a char placeholder + +!!! note "" + This only applies to **language extensions** since these chars are unescaped before output extensions are run. + +!!! warning "" + + Keep in mind that these modifications happen **before language extensions** are run, so if your extension relies on any of those chars, you have to make the appropriate adjustments. + + +### Implementation concerns + +One of the concerns is maintaining both client-side and server-side compatibility. You can do this with a few lines of boilerplate code.: + +```js +(function (extension) { + if (typeof showdown !== 'undefined') { + // global (browser or node.js global) + extension(showdown); + } else if (typeof define === 'function' && define.amd) { + // AMD + define(['showdown'], extension); + } else if (typeof exports === 'object') { + // Node, CommonJS-like + module.exports = extension(require('showdown')); + } else { + // showdown was not found so an error is thrown + throw Error('Could not find showdown library'); + } +}(function (showdown) { + // loading extension into showdown + showdown.extension('myext', function () { + var myext = { /* ... actual extension code ... */ }; + return [myext]; + }); +})); +``` + +In the code above, the extension definition is wrapped in a self-executing function to prevent pollution of the global scope. It has another benefit of creating several scope layers that can be useful for interaction between sub-extensions global-wise or local-wise. + +It is also loaded conditionally to make it compatible with different loading mechanisms (such as browser, CommonJS, or AMD). diff --git a/mkdocs.yml b/mkdocs.yml index a1d77cd..6dd4ae7 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -40,4 +40,5 @@ nav: - CLI: cli.md - Integrations: integrations.md - Extensions: - - Overview: extensions.md \ No newline at end of file + - Overview: extensions.md + - Create an extension: create-extension.md \ No newline at end of file