Merge branch 'master' into develop

# Conflicts:
#	Gruntfile.js
#	dist/showdown.js
#	dist/showdown.js.map
#	dist/showdown.min.js
#	dist/showdown.min.js.map
#	package-lock.json
#	package.json
#	src/converter.js
#	src/subParsers/makehtml/tables.js
pull/730/head^2
Estevao Soares dos Santos 2022-02-23 19:15:46 +00:00
commit e24d06e265
48 changed files with 9800 additions and 7030 deletions

View File

@ -1,41 +0,0 @@
# branches to build
#branches:
# whitelist
#only:
# - master
# What combinations to test
environment:
matrix:
- nodejs_version: "6"
platform: x64
- nodejs_version: "6"
platform: x86
- nodejs_version: "8"
platform: x86
- nodejs_version: "8"
platform: x64
- nodejs_version: "10"
platform: x64
cache:
- node_modules
install:
# Use version based on tag
- ps: $env:package_version = (Get-Content -Raw -Path package.json | ConvertFrom-Json).version
- ps: Update-AppveyorBuild -Version "$env:package_version-$env:APPVEYOR_BUILD_NUMBER"
# install node
# Get the latest stable version of Node.js or io.js
- ps: Install-Product node $env:nodejs_version
# install grunt-cli globally
- npm install -g grunt-cli
# install modules
- npm install
test_script:
# Output useful info for debugging
- node --version && npm --version
- ps: grunt test
# Don't actually build.
build: off

30
.github/workflows/node.linux.yml vendored Normal file
View File

@ -0,0 +1,30 @@
# This workflow will do a clean install of node dependencies, cache/restore them, build the source code and run tests across different versions of node
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
name: Node Linux CI
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [12.x, 14.x, 16.x, 17.x]
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- run: npm ci
- run: npm test

30
.github/workflows/node.win.yml vendored Normal file
View File

@ -0,0 +1,30 @@
# This workflow will do a clean install of node dependencies, cache/restore them, build the source code and run tests across different versions of node
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
name: Node Windows CI
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
build:
runs-on: windows-latest
strategy:
matrix:
node-version: [12.x, 14.x, 16.x, 17.x]
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- run: npm ci
- run: npm test

View File

@ -1,26 +0,0 @@
language: node_js
node_js:
- "6"
- "8"
- "10"
before_install:
- npm install -g grunt-cli
# travis build speed up
sudo: false
cache:
directories:
- node_modules
# scripts
script: grunt test
# hooks
notifications:
webhooks:
urls:
- https://webhooks.gitter.im/e/e369617839852624aa69
on_success: change # options: [always|never|change] default: always
on_failure: always # options: [always|never|change] default: always
on_start: false # default: false

View File

@ -3,6 +3,7 @@ Credits
- Showdown v2
* [Estevão Santos](https://github.com/tivie)
* [SyntaxRules](https://github.com/SyntaxRules)
- Showdown v1
* [Estevão Santos](https://github.com/tivie)

View File

@ -75,7 +75,7 @@ module.exports = function (grunt) {
eslint: {
options: {
useEslintrc: true
overrideConfigFile: '.eslintrc.json'
},
target: [
'Gruntfile.js',

20
LICENSE
View File

@ -1,21 +1,9 @@
MIT License
Copyright (c) 2018 ShowdownJS
Copyright (c) 2018,2021 ShowdownJS
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -1,7 +1,7 @@
![Showdown][sd-logo]
[![Build Status: Linux](https://travis-ci.org/showdownjs/showdown.svg?branch=master)](https://travis-ci.org/showdownjs/showdown)
[![Build Status: Windows](https://ci.appveyor.com/api/projects/status/github/showdownjs/showdown?branch=master&svg=true)](https://ci.appveyor.com/project/tivie/showdown/branch/master)
![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)
[![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)
@ -93,7 +93,7 @@ The converter itself might even work in things that aren't web browsers, like Ac
## Node compatibility
Showdown has been tested with node 0.8 and 0.10. However, it should work with previous versions, such as node 0.6.
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

16
SECURITY.md Normal file
View File

@ -0,0 +1,16 @@
# Security Policy
## Supported Versions
Security fixes are addressed for the following versions of Showdown.
| Version | Supported |
| ------- | ------------------ |
| 2.0.x | :white_check_mark: |
| 1.x.x | :x: (Known security issue with yargs dependecy) |
Showdown targets the node.js versions targeted in the [node.js release schedule](https://nodejs.org/en/about/releases/). Our test suite follows this release schedule. Consequently, older versions of node may become unusable.
## Reporting a Vulnerability
To report a vulnerability, please add an issue to our main github page: https://github.com/showdownjs/showdown/issues

3083
dist/showdown.js vendored

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

9950
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -30,7 +30,7 @@
"url": "https://github.com/showdownjs/showdown.git",
"web": "https://github.com/showdownjs/showdown"
},
"license": "BSD-3-Clause",
"license": "MIT",
"main": "./dist/showdown.js",
"scripts": {
"test": "grunt test"
@ -43,27 +43,27 @@
"dist"
],
"devDependencies": {
"chai": "4.1.x",
"grunt": "^1.0.3",
"grunt-contrib-clean": "1.1.x",
"grunt-contrib-concat": "1.0.x",
"grunt-contrib-jshint": "3.2.x",
"grunt-contrib-uglify": "~3.3.0",
"grunt-conventional-changelog": "6.1.x",
"grunt-conventional-github-releaser": "1.0.x",
"grunt-endline": "0.6.x",
"chai": "^4.3.4",
"grunt": "^1.4.1",
"grunt-contrib-clean": "^2.0.0",
"grunt-contrib-concat": "^2.0.0",
"grunt-contrib-jshint": "^3.1.0",
"grunt-contrib-uglify": "^5.0.1",
"grunt-conventional-changelog": "^6.1.0",
"grunt-conventional-github-releaser": "^1.0.0",
"grunt-endline": "^0.7.0",
"grunt-eslint": "^24.0.0",
"grunt-simple-mocha": "0.4.x",
"load-grunt-tasks": "3.5.x",
"performance-now": "2.0.x",
"quiet-grunt": "0.2.x",
"semver": "5.4.x",
"semver-sort": "0.0.x",
"sinon": "^5.1.1",
"source-map-support": "^0.5.9"
"grunt-simple-mocha": "^0.4.0",
"load-grunt-tasks": "^5.1.0",
"performance-now": "^2.1.0",
"quiet-grunt": "^0.2.0",
"semver": "^7.3.0",
"semver-sort": "^0.0.4",
"sinon": "^12.0.1",
"source-map-support": "^0.5.20"
},
"dependencies": {
"jsdom": "^11.0.0",
"yargs": "14.2.0"
"jsdom": "^18.0.1",
"yargs": "^17.2.1"
}
}

View File

@ -46,9 +46,9 @@ showdown.Converter = function (converterOptions) {
setConvFlavor = setFlavor,
/**
* Metadata of the document
* @type {{parsed: {}, raw: string, format: string}}
*/
* Metadata of the document
* @type {{parsed: {}, raw: string, format: string}}
*/
metadata = {
parsed: {},
raw: '',
@ -393,7 +393,7 @@ showdown.Converter = function (converterOptions) {
for (var n = 0; n < node.childNodes.length; ++n) {
var child = node.childNodes[n];
if (child.nodeType === 3) {
if (!/\S/.test(child.nodeValue)) {
if (!/\S/.test(child.nodeValue) && !/^[ ]+$/.test(child.nodeValue)) {
node.removeChild(child);
--n;
} else {
@ -532,12 +532,12 @@ showdown.Converter = function (converterOptions) {
var ext = extension[a];
for (var i = 0; i < langExtensions.length; ++i) {
if (langExtensions[i] === ext) {
langExtensions[i].splice(i, 1);
langExtensions.splice(i, 1);
}
}
for (var ii = 0; ii < outputModifiers.length; ++i) {
for (var ii = 0; ii < outputModifiers.length; ++ii) {
if (outputModifiers[ii] === ext) {
outputModifiers[ii].splice(i, 1);
outputModifiers.splice(ii, 1);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -165,7 +165,12 @@ function getDefaultOpts (simple) {
defaultValue: false,
description: 'Split adjacent blockquote blocks',
type: 'boolean'
}
},
relativePathBaseUrl: {
defaultValue: false,
describe: 'Prepends a base URL to relative paths',
type: 'string'
},
};
if (simple === false) {
return JSON.parse(JSON.stringify(defaultOptions));

View File

@ -36,6 +36,7 @@ showdown.subParser('makehtml.hashHTMLBlocks', function (text, options, globals)
'hgroup',
'output',
'video',
'details',
'p'
],
repFunc = function (wholeMatch, match, left, right) {

View File

@ -17,6 +17,12 @@ showdown.subParser('makehtml.images', function (text, options, globals) {
return writeImageTag (wholeMatch, altText, linkId, url, width, height, m5, title);
}
function writeImageTagBaseUrl (wholeMatch, altText, linkId, url, width, height, m5, title) {
url = showdown.helper.applyBaseUrl(options.relativePathBaseUrl, url);
return writeImageTag (wholeMatch, altText, linkId, url, width, height, m5, title);
}
function writeImageTag (wholeMatch, altText, linkId, url, width, height, m5, title) {
var gUrls = globals.gUrls,
@ -91,10 +97,10 @@ showdown.subParser('makehtml.images', function (text, options, globals) {
text = text.replace(base64RegExp, writeImageTagBase64);
// cases with crazy urls like ./image/cat1).png
text = text.replace(crazyRegExp, writeImageTag);
text = text.replace(crazyRegExp, writeImageTagBaseUrl);
// normal cases
text = text.replace(inlineRegExp, writeImageTag);
text = text.replace(inlineRegExp, writeImageTagBaseUrl);
// handle reference-style shortcuts: ![img text]
text = text.replace(refShortcutRegExp, writeImageTag);

View File

@ -23,7 +23,7 @@
* @param {{}} globals
* @returns {Function}
*/
function replaceAnchorTag (rgx, evtRootName, options, globals, emptyCase) {
function replaceAnchorTagReference (rgx, evtRootName, options, globals, emptyCase) {
emptyCase = !!emptyCase;
return function (wholeMatch, text, id, url, m5, m6, title) {
// bail we we find 2 newlines somewhere
@ -36,6 +36,15 @@
};
}
function replaceAnchorTagBaseUrl (rgx, evtRootName, options, globals, emptyCase) {
return function (wholeMatch, text, id, url, m5, m6, title) {
url = showdown.helper.applyBaseUrl(options.relativePathBaseUrl, url);
var evt = createEvent(rgx, evtRootName + '.captureStart', wholeMatch, text, id, url, title, options, globals);
return writeAnchorTag(evt, options, globals, emptyCase);
};
}
/**
* TODO Normalize this
* Helper function: Create a capture event
@ -192,21 +201,21 @@
// 1. Look for empty cases: []() and [empty]() and []("title")
var rgxEmpty = /\[(.*?)]()()()()\(<? ?>? ?(?:["'](.*)["'])?\)/g;
text = text.replace(rgxEmpty, replaceAnchorTag(rgxEmpty, evtRootName, options, globals, true));
text = text.replace(rgxEmpty, replaceAnchorTagBaseUrl(rgxEmpty, evtRootName, options, globals, true));
// 2. Look for cases with crazy urls like ./image/cat1).png
var rgxCrazy = /\[((?:\[[^\]]*]|[^\[\]])*)]()\s?\([ \t]?<([^>]*)>(?:[ \t]*((["'])([^"]*?)\5))?[ \t]?\)/g;
text = text.replace(rgxCrazy, replaceAnchorTag(rgxCrazy, evtRootName, options, globals));
text = text.replace(rgxCrazy, replaceAnchorTagBaseUrl(rgxCrazy, evtRootName, options, globals));
// 3. inline links with no title or titles wrapped in ' or ":
// [text](url.com) || [text](<url.com>) || [text](url.com "title") || [text](<url.com> "title")
//var rgx2 = /\[[ ]*[\s]?[ ]*([^\n\[\]]*?)[ ]*[\s]?[ ]*] ?()\(<?[ ]*[\s]?[ ]*([^\s'"]*)>?(?:[ ]*[\n]?[ ]*()(['"])(.*?)\5)?[ ]*[\s]?[ ]*\)/; // this regex is too slow!!!
var rgx2 = /\[([\S ]*?)]\s?()\( *<?([^\s'"]*?(?:\([\S]*?\)[\S]*?)?)>?\s*(?:()(['"])(.*?)\5)? *\)/g;
text = text.replace(rgx2, replaceAnchorTag(rgx2, evtRootName, options, globals));
text = text.replace(rgx2, replaceAnchorTagBaseUrl(rgx2, evtRootName, options, globals));
// 4. inline links with titles wrapped in (): [foo](bar.com (title))
var rgx3 = /\[([\S ]*?)]\s?()\( *<?([^\s'"]*?(?:\([\S]*?\)[\S]*?)?)>?\s+()()\((.*?)\) *\)/g;
text = text.replace(rgx3, replaceAnchorTag(rgx3, evtRootName, options, globals));
text = text.replace(rgx3, replaceAnchorTagBaseUrl(rgx3, evtRootName, options, globals));
text = globals.converter._dispatch(evtRootName + '.end', text, options, globals).getText();
@ -222,7 +231,7 @@
text = globals.converter._dispatch(evtRootName + '.start', text, options, globals).getText();
var rgx = /\[((?:\[[^\]]*]|[^\[\]])*)] ?(?:\n *)?\[(.*?)]()()()()/g;
text = text.replace(rgx, replaceAnchorTag(rgx, evtRootName, options, globals));
text = text.replace(rgx, replaceAnchorTagReference(rgx, evtRootName, options, globals));
text = globals.converter._dispatch(evtRootName + '.end', text, options, globals).getText();
@ -238,7 +247,7 @@
text = globals.converter._dispatch(evtRootName + '.start', text, options, globals).getText();
var rgx = /\[([^\[\]]+)]()()()()()/g;
text = text.replace(rgx, replaceAnchorTag(rgx, evtRootName, options, globals));
text = text.replace(rgx, replaceAnchorTagReference(rgx, evtRootName, options, globals));
text = globals.converter._dispatch(evtRootName + '.end', text, options, globals).getText();

View File

@ -40,7 +40,7 @@ showdown.subParser('makehtml.lists', function (text, options, globals) {
// attacklab: add sentinel to emulate \z
listStr += '¨0';
var rgx = /(\n)?(^ {0,3})([*+-]|\d+[.])[ \t]+((\[(x|X| )?])?[ \t]*[^\r]+?(\n{1,2}))(?=\n*(¨0| {0,3}([*+-]|\d+[.])[ \t]+))/gm,
var rgx = /(\n)?(^ {0,3})([*+-]|\d+[.])[ \t]+((\[(x|X| )])?[ \t]*[^\r]+?(\n{1,2}))(?=\n*(¨0| {0,3}([*+-]|\d+[.])[ \t]+))/gm,
isParagraphed = (/\n[ \t]*\n(?!¨0)/.test(listStr));
// Since version 1.5, nesting sublists requires 4 spaces (or 1 tab) indentation,
@ -48,7 +48,7 @@ showdown.subParser('makehtml.lists', function (text, options, globals) {
// activating this option reverts to old behavior
// This will be removed in version 2.0
if (options.disableForced4SpacesIndentedSublists) {
rgx = /(\n)?(^ {0,3})([*+-]|\d+[.])[ \t]+((\[(x|X| )?])?[ \t]*[^\r]+?(\n{1,2}))(?=\n*(¨0|\2([*+-]|\d+[.])[ \t]+))/gm;
rgx = /(\n)?(^ {0,3})([*+-]|\d+[.])[ \t]+((\[(x|X| )])?[ \t]*[^\r]+?(\n{1,2}))(?=\n*(¨0|\2([*+-]|\d+[.])[ \t]+))/gm;
}
listStr = listStr.replace(rgx, function (wholeMatch, m1, m2, m3, m4, taskbtn, checked) {

View File

@ -6,18 +6,25 @@
showdown.subParser('makehtml.stripLinkDefinitions', function (text, options, globals) {
'use strict';
var regex = /^ {0,3}\[(.+)]:[ \t]*\n?[ \t]*<?([^>\s]+)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*\n?[ \t]*(?:(\n*)["|'(](.+?)["|')][ \t]*)?(?:\n+|(?=¨0))/gm,
base64Regex = /^ {0,3}\[(.+)]:[ \t]*\n?[ \t]*<?(data:.+?\/.+?;base64,[A-Za-z0-9+/=\n]+?)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*\n?[ \t]*(?:(\n*)["|'(](.+?)["|')][ \t]*)?(?:\n\n|(?=¨0)|(?=\n\[))/gm;
var regex = /^ {0,3}\[([^\]]+)]:[ \t]*\n?[ \t]*<?([^>\s]+)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*\n?[ \t]*(?:(\n*)["|'(](.+?)["|')][ \t]*)?(?:\n+|(?=¨0))/gm,
base64Regex = /^ {0,3}\[([^\]]+)]:[ \t]*\n?[ \t]*<?(data:.+?\/.+?;base64,[A-Za-z0-9+/=\n]+?)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*\n?[ \t]*(?:(\n*)["|'(](.+?)["|')][ \t]*)?(?:\n\n|(?=¨0)|(?=\n\[))/gm;
// attacklab: sentinel workarounds for lack of \A and \Z, safari\khtml bug
text += '¨0';
var replaceFunc = function (wholeMatch, linkId, url, width, height, blankLines, title) {
// if there aren't two instances of linkId it must not be a reference link so back out
linkId = linkId.toLowerCase();
if (text.toLowerCase().split(linkId).length - 1 < 2) {
return wholeMatch;
}
if (url.match(/^data:.+?\/.+?;base64,/)) {
// remove newlines
globals.gUrls[linkId] = url.replace(/\s/g, '');
} else {
url = showdown.helper.applyBaseUrl(options.relativePathBaseUrl, url);
globals.gUrls[linkId] = showdown.subParser('makehtml.encodeAmpsAndAngles')(url, options, globals); // Link IDs are case-insensitive
}

View File

@ -1,8 +1,9 @@
<h1 id="mythings">my things</h1>
<ul>
<li>foo</li>
<li class="task-list-item" style="list-style-type: none;"><input type="checkbox" disabled style="margin: 0px 0.35em 0.25em -1.6em; vertical-align: middle;"> bar</li>
<li>[] bar</li>
<li class="task-list-item" style="list-style-type: none;"><input type="checkbox" disabled style="margin: 0px 0.35em 0.25em -1.6em; vertical-align: middle;"> baz</li>
<li class="task-list-item" style="list-style-type: none;"><input type="checkbox" disabled style="margin: 0px 0.35em 0.25em -1.6em; vertical-align: middle;" checked> bazinga</li>
<li class="task-list-item" style="list-style-type: none;"><input type="checkbox" disabled style="margin: 0px 0.35em 0.25em -1.6em; vertical-align: middle;" checked> bazinga 2</li>
</ul>
<p>otherthings</p>

View File

@ -4,5 +4,6 @@
- [] bar
- [ ] baz
- [x] bazinga
- [X] bazinga 2
otherthings

View File

@ -1,2 +1,3 @@
<p>🍎 and 💋</p>
<p>💋my🍎</p>
<p>👩‍❤️‍💋‍👨</p>

View File

@ -1,3 +1,5 @@
:apple: and :kiss:
:kiss:my:apple:
:couplekiss_man_woman:

View File

@ -1,2 +1,2 @@
<p>this is showdown's emoji <img width="20" height="20" align="absmiddle" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAS1BMVEX///8jJS0jJS0jJS0jJS0jJS0jJS0jJS0jJS0jJS0jJS0jJS0jJS0jJS0jJS0jJS0jJS3b1q3b1q3b1q3b1q3b1q3b1q3b1q3b1q0565CIAAAAGXRSTlMAQHCAYCCw/+DQwPCQUBAwoHCAEP+wwFBgS2fvBgAAAUZJREFUeAHs1cGy7BAUheFFsEDw/k97VTq3T6ge2EmdM+pvrP6Iwd74XV9Kb52xuMU4/uc1YNgZLFOeV8FGdhGrNk5SEgUyPxAEdj4LlMRDyhVAMVEa2M7TBSeVZAFPdqHgzSZJwPKgcLFLAooHDJo4EDCw4gAtBoJA5UFj4Ng5LOGLwVXZuoIlji/jeQHFk7+baHxrCjeUwB9+s88KndvlhcyBN5BSkYNQIVVb4pV+Npm7hhuKDs/uMP5KxT3WzSNNLIuuoDpMmuAVMruMSeDyQBi24DTr43LAY7ILA1QYaWkgfHzFthYYzg67SQsCbB8GhJUEGCtO9n0rSaCLxgJQjS/JSgMTg2eBDEHAJ+H350AsjYNYscrErgI2e/l+mdR967TCX/v6N0EhPECYCP0i+IAoYQOE8BogNhQMEMdrgAQWHaMAAGi5I5euoY9NAAAAAElFTkSuQmCC"></p>
<p>and this is github's emoji <img width="20" height="20" align="absmiddle" src="https://assets-cdn.github.com/images/icons/emoji/octocat.png"></p>
<p>and this is github's emoji <img width="20" height="20" align="absmiddle" src="https://github.githubassets.com/images/icons/emoji/octocat.png?v8"></p>

View File

@ -0,0 +1,9 @@
<p><a href="http://my.site.com/that_dude_mike.js">inline relative linky</a></p>
<p><a href="ftp://wikis.com/micky.txt">inline absolute linky</a></p>
<p><a href="http://my.site.com/painters/Michelangelo.html">global relative linky</a></p>
<p><a href="https://www.my-wikis-site.com/peeps/Michelangelo.html">global absolute linky</a></p>
<p><img src="http://my.site.com/mona-lisa.png" alt="inline relative image" /></p>
<p><img src="http://images.com/mona-lisa.png" alt="inline absolute image" /></p>
<p><img src="http://my.site.com/mona-lisa.png" alt="global relative image" /></p>
<p><img src="https://www.my-photo-site.com/mona-lisa.png" alt="global absolute image" /></p>
<p><a href="#holdin_it_down">just an anchor</a></p>

View File

@ -0,0 +1,22 @@
[inline relative linky](that_dude_mike.js)
[inline absolute linky](ftp://wikis.com/micky.txt)
[global relative linky][relative_linky]
[global absolute linky][absolute_linky]
![inline relative image](mona-lisa.png)
![inline absolute image](http://images.com/mona-lisa.png)
![global relative image][relative_image]
![global absolute image][absolute_image]
[just an anchor](#holdin_it_down)
[relative_linky]: painters/Michelangelo.html
[relative_image]: ./mona-lisa.png
[absolute_linky]: https://www.my-wikis-site.com/peeps/Michelangelo.html
[absolute_image]: https://www.my-photo-site.com/mona-lisa.png

View File

@ -0,0 +1 @@
<p><em>one</em> <em>two</em> <em>three</em></p>

View File

@ -0,0 +1 @@
*one* *two* *three*

View File

@ -0,0 +1,3 @@
<p>[We] are going to show [you]: sunshine!</p>
<p>[x]: take out the garbage<br />
[ ]: bring up the coal</p>

View File

@ -0,0 +1,4 @@
[We] are going to show [you]: sunshine!
[x]: take out the garbage
[ ]: bring up the coal

View File

@ -0,0 +1,5 @@
<p><a href="#Declare">Declare options</a></p>
<p><a href="#Declare%20current%20operation%20options">Declare options</a></p>
<p><a href="#Declare current operation options">Declare options</a></p>
<p><a href="https://spec.commonmark.org/0.30/#example-500">Common Mark Example</a></p>
<p><a href="spec.commonmark.org/0.30/#example-500">Common Mark Example</a></p>

View File

@ -0,0 +1,9 @@
[Declare options](#Declare)
[Declare options](#Declare%20current%20operation%20options)
[Declare options](<#Declare current operation options>)
[Common Mark Example](https://spec.commonmark.org/0.30/#example-500)
[Common Mark Example](spec.commonmark.org/0.30/#example-500)

View File

@ -0,0 +1,67 @@
<p>Reserved Keywords found at: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar</p>
<p><a href="">break</a></p>
<p><a href="">case</a></p>
<p><a href="">catch</a></p>
<p><a href="">class</a></p>
<p><a href="">const</a></p>
<p><a href="">continue</a></p>
<p><a href="">debugger</a></p>
<p><a href="">default</a></p>
<p><a href="">delete</a></p>
<p><a href="">do</a></p>
<p><a href="">else</a></p>
<p><a href="">export</a></p>
<p><a href="">extends</a></p>
<p><a href="">finally</a></p>
<p><a href="">for</a></p>
<p><a href="">function</a></p>
<p><a href="">if</a></p>
<p><a href="">import</a></p>
<p><a href="">in</a></p>
<p><a href="">instanceof</a></p>
<p><a href="">new</a></p>
<p><a href="">return</a></p>
<p><a href="">super</a></p>
<p><a href="">switch</a></p>
<p><a href="">this</a></p>
<p><a href="">throw</a></p>
<p><a href="">try</a></p>
<p><a href="">typeof</a></p>
<p><a href="">var</a></p>
<p><a href="">void</a></p>
<p><a href="">while</a></p>
<p><a href="">with</a></p>
<p><a href="">yield</a></p>
<p><a href="">enum</a></p>
<p><a href="">implements</a></p>
<p><a href="">interface</a></p>
<p><a href="">let</a></p>
<p><a href="">package</a></p>
<p><a href="">private</a></p>
<p><a href="">protected</a></p>
<p><a href="">public</a></p>
<p><a href="">static</a></p>
<p><a href="">yield</a></p>
<p><a href="">await</a></p>
<p><a href="">abstract</a></p>
<p><a href="">boolean</a></p>
<p><a href="">byte</a></p>
<p><a href="">char</a></p>
<p><a href="">double</a></p>
<p><a href="">final</a></p>
<p><a href="">float</a></p>
<p><a href="">goto</a></p>
<p><a href="">int</a></p>
<p><a href="">long</a></p>
<p><a href="">native</a></p>
<p><a href="">short</a></p>
<p><a href="">synchronized</a></p>
<p><a href="">throws</a></p>
<p><a href="">transient</a></p>
<p><a href="">volatile</a></p>
<p><a href="">null</a></p>
<p><a href="">true</a></p>
<p><a href="">false</a></p>
<p><a href="">arguments</a></p>
<p><a href="">get</a></p>
<p><a href="">set</a></p>

View File

@ -0,0 +1,133 @@
Reserved Keywords found at: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar
[break]()
[case]()
[catch]()
[class]()
[const]()
[continue]()
[debugger]()
[default]()
[delete]()
[do]()
[else]()
[export]()
[extends]()
[finally]()
[for]()
[function]()
[if]()
[import]()
[in]()
[instanceof]()
[new]()
[return]()
[super]()
[switch]()
[this]()
[throw]()
[try]()
[typeof]()
[var]()
[void]()
[while]()
[with]()
[yield]()
[enum]()
[implements]()
[interface]()
[let]()
[package]()
[private]()
[protected]()
[public]()
[static]()
[yield]()
[await]()
[abstract]()
[boolean]()
[byte]()
[char]()
[double]()
[final]()
[float]()
[goto]()
[int]()
[long]()
[native]()
[short]()
[synchronized]()
[throws]()
[transient]()
[volatile]()
[null]()
[true]()
[false]()
[arguments]()
[get]()
[set]()

View File

@ -0,0 +1,12 @@
<p><a href="/uri">link</a></p>
<p><a href="http://example.com/">link</a></p>
<p><a href="http://example.com">link</a></p>
<p><a href="https://example.com">link</a></p>
<p><a href="https://example.com/">link</a></p>
<p><a href="example.com">link</a></p>
<p><a href="www.example.com">link</a></p>
<p><a href="file://example.com">link</a></p>
<p><a href="file://www.example.com">link</a></p>
<p><a href="example.jpg">link</a></p>
<p><a href="example.io">link</a></p>
<p><a href="http://baidu.com" title="百度">百度</a></p>

View File

@ -0,0 +1,23 @@
[link](/uri)
[link](http://example.com/)
[link](http://example.com)
[link](https://example.com)
[link](https://example.com/)
[link](example.com)
[link](www.example.com)
[link](file://example.com)
[link](file://www.example.com)
[link](example.jpg)
[link](example.io)
[百度](http://baidu.com "百度")

View File

@ -0,0 +1,46 @@
<p>Object property names found at: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object</p>
<p><a href="">assign</a></p>
<p><a href="">create</a></p>
<p><a href="">defineProperty</a></p>
<p><a href="">defineProperties</a></p>
<p><a href="">entries</a></p>
<p><a href="">freeze</a></p>
<p><a href="">fromEntries</a></p>
<p><a href="">getOwnPropertyDescriptor</a></p>
<p><a href="">getOwnPropertyDescriptors</a></p>
<p><a href="">getOwnPropertyNames</a></p>
<p><a href="">getOwnPropertySymbols</a></p>
<p><a href="">getPrototypeOf</a></p>
<p><a href="">is</a></p>
<p><a href="">isExtensible</a></p>
<p><a href="">isFrozen</a></p>
<p><a href="">isSealed</a></p>
<p><a href="">keys</a></p>
<p><a href="">preventExtensions</a></p>
<p><a href="">seal</a></p>
<p><a href="">setPrototypeOf</a></p>
<p><a href="">values</a></p>
<p><a href="">prototype.constructor</a></p>
<p><a href="">prototype.<strong>proto</strong></a></p>
<p><a href="">prototype.<strong>defineGetter</strong></a></p>
<p><a href="">prototype.<strong>defineSetter</strong></a></p>
<p><a href="">prototype.<strong>lookupGetter</strong></a></p>
<p><a href="">prototype.<strong>lookupSetter</strong></a></p>
<p><a href="">prototype.hasOwnProperty</a></p>
<p><a href="">prototype.isPrototypeOf</a></p>
<p><a href="">prototype.propertyIsEnumerable</a></p>
<p><a href="">prototype.toLocaleString</a></p>
<p><a href="">prototype.toString</a></p>
<p><a href="">prototype.valueOf</a></p>
<p><a href="">constructor</a></p>
<p><a href=""><strong>proto</strong></a></p>
<p><a href=""><strong>defineGetter</strong></a></p>
<p><a href=""><strong>defineSetter</strong></a></p>
<p><a href=""><strong>lookupGetter</strong></a></p>
<p><a href=""><strong>lookupSetter</strong></a></p>
<p><a href="">hasOwnProperty</a></p>
<p><a href="">isPrototypeOf</a></p>
<p><a href="">propertyIsEnumerable</a></p>
<p><a href="">toLocaleString</a></p>
<p><a href="">toString</a></p>
<p><a href="">valueOf</a></p>

View File

@ -0,0 +1,91 @@
Object property names found at: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object
[assign]()
[create]()
[defineProperty]()
[defineProperties]()
[entries]()
[freeze]()
[fromEntries]()
[getOwnPropertyDescriptor]()
[getOwnPropertyDescriptors]()
[getOwnPropertyNames]()
[getOwnPropertySymbols]()
[getPrototypeOf]()
[is]()
[isExtensible]()
[isFrozen]()
[isSealed]()
[keys]()
[preventExtensions]()
[seal]()
[setPrototypeOf]()
[values]()
[prototype.constructor]()
[prototype.__proto__]()
[prototype.__defineGetter__]()
[prototype.__defineSetter__]()
[prototype.__lookupGetter__]()
[prototype.__lookupSetter__]()
[prototype.hasOwnProperty]()
[prototype.isPrototypeOf]()
[prototype.propertyIsEnumerable]()
[prototype.toLocaleString]()
[prototype.toString]()
[prototype.valueOf]()
[constructor]()
[__proto__]()
[__defineGetter__]()
[__defineSetter__]()
[__lookupGetter__]()
[__lookupSetter__]()
[hasOwnProperty]()
[isPrototypeOf]()
[propertyIsEnumerable]()
[toLocaleString]()
[toString]()
[valueOf]()

View File

@ -55,3 +55,7 @@
<h2>Secondary title</h2>
</hgroup>
<output name="result"></output>
<details>
<summary>Summarise me</summary>
<p>Explain the details</p>
</details>

View File

@ -66,3 +66,8 @@ the end
</hgroup>
<output name="result"></output>
<details>
<summary>Summarise me</summary>
<p>Explain the details</p>
</details>

View File

@ -18,7 +18,10 @@ var bootstrap = require('./makehtml.bootstrap.js'),
//literalMidWordAsterisksSuite = bootstrap.getTestSuite('test/functional/makehtml/cases/features/literalMidWordAsterisks/'),
completeHTMLOutputSuite = bootstrap.getTestSuite('test/functional/makehtml/cases/features/completeHTMLOutput/'),
metadataSuite = bootstrap.getTestSuite('test/functional/makehtml/cases/features/metadata/'),
splitAdjacentBlockquotesSuite = bootstrap.getTestSuite('test/functional/makehtml/cases/features/splitAdjacentBlockquotes/');
splitAdjacentBlockquotesSuite = bootstrap.getTestSuite('test/functional/makehtml/cases/features/splitAdjacentBlockquotes/'),
http = require('http'),
https = require('https'),
expect = require('chai').expect;
describe('makeHtml() features testsuite', function () {
'use strict';
@ -96,6 +99,8 @@ describe('makeHtml() features testsuite', function () {
converter = new showdown.Converter({openLinksInNewWindow: true});
} else if (testsuite[i].name === '#355.simplifiedAutoLink-URLs-inside-parenthesis-followed-by-another-character-are-not-parsed-correctly') {
converter = new showdown.Converter({simplifiedAutoLink: true});
} else if (testsuite[i].name === 'relativePathBaseUrl') {
converter = new showdown.Converter({relativePathBaseUrl: 'http://my.site.com/'});
} else {
converter = new showdown.Converter();
}
@ -188,7 +193,31 @@ describe('makeHtml() features testsuite', function () {
/** test emojis support **/
describe('emojis support', function () {
var converter,
suite = emojisSuite;
suite = emojisSuite,
imgSrcRegexp = /<img[^>]+src=("https?:\/\/[^"]+"|'https?:\/\/[^']+')/g;
function testImageUrlExists (imgUrl) {
// Strip the quotes
imgUrl = imgUrl.substr(0, imgUrl.length - 1).substr(1);
return function (done) {
(imgUrl.startsWith('http://') ? http : https).get(imgUrl, function (res) {
expect(res.statusCode).to.equal(200);
// Make sure we get some data and that it's a png
expect(parseInt(res.headers['content-length'], 10)).to.be.above(0);
expect(res.headers['content-type']).to.equal('image/png');
// Discard the data (but fetch it)
res.on('data', function () {});
res.on('end', function () {
done();
});
}).on('error', function (e) {
throw e;
});
};
}
for (var i = 0; i < suite.length; ++i) {
if (suite[i].name === 'simplifiedautolinks') {
converter = new showdown.Converter({emoji: true, simplifiedAutoLink: true});
@ -197,6 +226,11 @@ describe('makeHtml() features testsuite', function () {
}
it(suite[i].name.replace(/-/g, ' '), assertion(suite[i], converter));
var imgUrl = imgSrcRegexp.exec(suite[i].expected);
if (imgUrl) {
it('should use a working emoji URL', testImageUrlExists(imgUrl[1]));
}
}
});

View File

@ -32,3 +32,7 @@
<h2>Secondary title</h2>
</hgroup>
<output name="result"></output>
<details>
<summary>Summarise me</summary>
<p>Explain the details</p>
</details>

View File

@ -31,3 +31,5 @@ the end
<hgroup><h1>Main title</h1><h2>Secondary title</h2></hgroup>
<output name="result"></output>
<details><summary>Summarise me</summary><p>Explain the details</p></details>

View File

@ -122,6 +122,14 @@ describe('showdown.Converter', function () {
converter.getAllExtensions().language.should.contain(extObjMock);
showdown.resetExtensions();
});
it('removeExtension() should remove an added extension', function () {
var converter = new showdown.Converter();
converter.addExtension(extObjMock);
converter.removeExtension(extObjMock);
converter.getAllExtensions().language.should.not.contain(extObjMock);
});
});
describe('events', function () {