fix(cli): cli now works properly

The CLI was completely rewrote. Changed dependency from yargs to
commanderjs,
which is cleaner, faster and has no dependencies.
Also added a complete testsuite for the cli.

Merged branch 'cli_refactor' into develop

Closes #893, #894
This commit is contained in:
Estevao Soares dos Santos 2022-03-03 12:15:50 +00:00
parent bd093ab493
commit c3411a567d
21 changed files with 896 additions and 1199 deletions

View File

@ -13,12 +13,12 @@ module.exports = function (grunt) {
pkg: grunt.file.readJSON('package.json'),
concat: {
options: {
sourceMap: true,
banner: ';/*! <%= pkg.name %> v <%= pkg.version %> - <%= grunt.template.today("dd-mm-yyyy") %> */\n(function(){\n',
footer: '}).call(this);\n'
},
dist: {
options: {
sourceMap: true,
banner: ';/*! <%= pkg.name %> v <%= pkg.version %> - <%= grunt.template.today("dd-mm-yyyy") %> */\n(function(){\n',
footer: '}).call(this);\n'
},
src: [
'src/options.js',
'src/showdown.js',
@ -30,6 +30,12 @@ module.exports = function (grunt) {
],
dest: 'dist/<%= pkg.name %>.js'
},
cli: {
src: [
'src/cli/cli.js'
],
dest: 'bin/showdown.js'
},
test: {
src: '<%= concat.dist.src %>',
dest: '.build/<%= pkg.name %>.js',
@ -42,14 +48,23 @@ module.exports = function (grunt) {
clean: ['.build/'],
uglify: {
options: {
sourceMap: true,
banner: '/*! <%= pkg.name %> v <%= pkg.version %> - <%= grunt.template.today("dd-mm-yyyy") %> */'
},
dist: {
options: {
sourceMap: true,
banner: '/*! <%= pkg.name %> v <%= pkg.version %> - <%= grunt.template.today("dd-mm-yyyy") %> */'
},
files: {
'dist/<%= pkg.name %>.min.js': ['<%= concat.dist.dest %>']
}
},
cli: {
options: {
sourceMap: false,
banner: '#!/usr/bin/env node'
},
files: {
'bin/showdown.js': ['<%= concat.cli.dest %>']
}
}
},
@ -136,6 +151,15 @@ module.exports = function (grunt) {
ignoreLeaks: false,
reporter: 'spec'
}
},
cli: {
src: 'test/node/testsuite.cli.js',
options: {
globals: ['should'],
timeout: 3000,
ignoreLeaks: false,
reporter: 'spec'
}
}
}
};
@ -202,14 +226,14 @@ module.exports = function (grunt) {
/**
* Tasks
*/
grunt.registerTask('test', ['clean', 'lint', 'concat:test', 'simplemocha:unit', 'simplemocha:functional', 'clean']);
grunt.registerTask('test-functional', ['concat:test', 'simplemocha:functional', 'clean']);
grunt.registerTask('test-unit', ['concat:test', 'simplemocha:unit', 'clean']);
grunt.registerTask('test-cli', ['clean', 'lint', 'concat:test', 'simplemocha:cli', 'clean']);
grunt.registerTask('performance', ['concat:test', 'performancejs', 'clean']);
grunt.registerTask('build', ['test', 'concat:dist', 'uglify', 'endline']);
grunt.registerTask('build', ['test', 'concat:dist', 'concat:cli', 'uglify:dist', 'uglify:cli', 'endline']);
grunt.registerTask('build-without-test', ['concat:dist', 'uglify', 'endline']);
grunt.registerTask('prep-release', ['build', 'generate-changelog']);
grunt.registerTask('prep-release', ['build', 'performance', 'generate-changelog']);
// Default task(s).
grunt.registerTask('default', ['test']);

Binary file not shown.

BIN
dist/showdown.js vendored

Binary file not shown.

BIN
dist/showdown.js.map vendored

Binary file not shown.

BIN
dist/showdown.min.js vendored

Binary file not shown.

Binary file not shown.

251
package-lock.json generated
View File

@ -9,14 +9,15 @@
"version": "2.0.0-alpha1",
"license": "MIT",
"dependencies": {
"jsdom": "^19.0.0",
"yargs": "^17.2.1"
"commander": "^9.0.0",
"jsdom": "^19.0.0"
},
"bin": {
"showdown": "bin/showdown.js"
},
"devDependencies": {
"chai": "^4.3.4",
"chai": "*",
"chai-match": "*",
"grunt": "^1.4.1",
"grunt-contrib-clean": "^2.0.0",
"grunt-contrib-concat": "^2.0.0",
@ -32,14 +33,14 @@
"quiet-grunt": "^0.2.0",
"semver": "^7.3.0",
"semver-sort": "^1.0.0",
"sinon": "^12.0.1",
"sinon": "*",
"source-map-support": "^0.5.21"
}
},
"node_modules/@eslint/eslintrc": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.1.0.tgz",
"integrity": "sha512-C1DfL7XX4nPqGd6jcP01W9pVM1HYCuUkFk1432D7F0v3JSlUIeOYn9oCoi3eoLZ+iwBSb29BMFxxny0YrrEZqg==",
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.0.tgz",
"integrity": "sha512-igm9SjJHNEJRiUnecP/1R5T3wKLEJ7pL6e2P+GUSfCd0dGjPYYZve08uzw8L2J8foVHFz+NGu12JxRcU2gGo6w==",
"dev": true,
"dependencies": {
"ajv": "^6.12.4",
@ -113,9 +114,9 @@
}
},
"node_modules/@sinonjs/fake-timers": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz",
"integrity": "sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==",
"version": "9.1.0",
"resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-9.1.0.tgz",
"integrity": "sha512-M8vapsv9qQupMdzrVzkn5rb9jG7aUTEPAZdMtME2PuBaefksFZVE2C1g4LBRTkF/k3nRDNbDc5tp5NFC1PEYxA==",
"dev": true,
"dependencies": {
"@sinonjs/commons": "^1.7.0"
@ -257,6 +258,7 @@
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
"dev": true,
"engines": {
"node": ">=8"
}
@ -265,6 +267,7 @@
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
"dependencies": {
"color-convert": "^2.0.1"
},
@ -484,6 +487,12 @@
"node": ">=4"
}
},
"node_modules/chai-match": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/chai-match/-/chai-match-1.1.1.tgz",
"integrity": "sha1-OfsKLmt8j2OG3P6tSNFIqRX6bEY=",
"dev": true
},
"node_modules/chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
@ -565,6 +574,7 @@
"version": "7.0.4",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
"integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
"dev": true,
"dependencies": {
"string-width": "^4.2.0",
"strip-ansi": "^6.0.0",
@ -575,6 +585,7 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"dependencies": {
"color-name": "~1.1.4"
},
@ -585,7 +596,8 @@
"node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"node_modules/colors": {
"version": "1.1.2",
@ -607,6 +619,14 @@
"node": ">= 0.8"
}
},
"node_modules/commander": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-9.0.0.tgz",
"integrity": "sha512-JJfP2saEKbQqvW+FI93OYUB4ByV5cizMpFMiiJI8xDbBvQvSkIk0VvQdn1CZ8mqAO8Loq2h0gYTYtDFUZUeERw==",
"engines": {
"node": "^12.20.0 || >=14"
}
},
"node_modules/compare-func": {
"version": "1.3.4",
"resolved": "https://registry.npmjs.org/compare-func/-/compare-func-1.3.4.tgz",
@ -1274,7 +1294,8 @@
"node_modules/emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
"dev": true
},
"node_modules/entities": {
"version": "1.0.0",
@ -1295,6 +1316,7 @@
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
"dev": true,
"engines": {
"node": ">=6"
}
@ -1389,12 +1411,12 @@
}
},
"node_modules/eslint": {
"version": "8.9.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.9.0.tgz",
"integrity": "sha512-PB09IGwv4F4b0/atrbcMFboF/giawbBLVC7fyDamk5Wtey4Jh2K+rYaBhCAbUyEI4QzB1ly09Uglc9iCtFaG2Q==",
"version": "8.10.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.10.0.tgz",
"integrity": "sha512-tcI1D9lfVec+R4LE1mNDnzoJ/f71Kl/9Cv4nG47jOueCMBrCCKYXr4AUVS7go6mWYGFD4+EoN6+eXSrEbRzXVw==",
"dev": true,
"dependencies": {
"@eslint/eslintrc": "^1.1.0",
"@eslint/eslintrc": "^1.2.0",
"@humanwhocodes/config-array": "^0.9.2",
"ajv": "^6.10.0",
"chalk": "^4.0.0",
@ -1806,20 +1828,6 @@
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
"dev": true
},
"node_modules/fsevents": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
"dev": true,
"hasInstallScript": true,
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
"node_modules/function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
@ -1836,6 +1844,7 @@
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
"dev": true,
"engines": {
"node": "6.* || 8.* || >= 10.*"
}
@ -2978,6 +2987,7 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
"dev": true,
"engines": {
"node": ">=8"
}
@ -3951,24 +3961,6 @@
"url": "https://github.com/chalk/supports-color?sponsor=1"
}
},
"node_modules/mocha/node_modules/yargs": {
"version": "16.2.0",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
"integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
"dev": true,
"dependencies": {
"cliui": "^7.0.2",
"escalade": "^3.1.1",
"get-caller-file": "^2.0.5",
"require-directory": "^2.1.1",
"string-width": "^4.2.0",
"y18n": "^5.0.5",
"yargs-parser": "^20.2.2"
},
"engines": {
"node": ">=10"
}
},
"node_modules/modify-values": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/modify-values/-/modify-values-1.0.1.tgz",
@ -4732,6 +4724,7 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
"integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
@ -4928,16 +4921,16 @@
"dev": true
},
"node_modules/sinon": {
"version": "12.0.1",
"resolved": "https://registry.npmjs.org/sinon/-/sinon-12.0.1.tgz",
"integrity": "sha512-iGu29Xhym33ydkAT+aNQFBINakjq69kKO6ByPvTsm3yyIACfyQttRTP03aBP/I8GfhFmLzrnKwNNkr0ORb1udg==",
"version": "13.0.1",
"resolved": "https://registry.npmjs.org/sinon/-/sinon-13.0.1.tgz",
"integrity": "sha512-8yx2wIvkBjIq/MGY1D9h1LMraYW+z1X0mb648KZnKSdvLasvDu7maa0dFaNYdTDczFgbjNw2tOmWdTk9saVfwQ==",
"dev": true,
"dependencies": {
"@sinonjs/commons": "^1.8.3",
"@sinonjs/fake-timers": "^8.1.0",
"@sinonjs/samsam": "^6.0.2",
"@sinonjs/fake-timers": "^9.0.0",
"@sinonjs/samsam": "^6.1.1",
"diff": "^5.0.0",
"nise": "^5.1.0",
"nise": "^5.1.1",
"supports-color": "^7.2.0"
},
"funding": {
@ -5045,6 +5038,7 @@
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"dev": true,
"dependencies": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
@ -5058,6 +5052,7 @@
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"dev": true,
"dependencies": {
"ansi-regex": "^5.0.1"
},
@ -5252,9 +5247,9 @@
"dev": true
},
"node_modules/uglify-js": {
"version": "3.15.1",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.15.1.tgz",
"integrity": "sha512-FAGKF12fWdkpvNJZENacOH0e/83eG6JyVQyanIJaBXCN1J11TUQv1T1/z8S+Z0CG0ZPk1nPcreF/c7lrTd0TEQ==",
"version": "3.15.2",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.15.2.tgz",
"integrity": "sha512-peeoTk3hSwYdoc9nrdiEJk+gx1ALCtTjdYuKSXMTDqq7n1W7dHPqWDdSi+BPL0ni2YMeHD7hKUSdbj3TZauY2A==",
"dev": true,
"bin": {
"uglifyjs": "bin/uglifyjs"
@ -5459,6 +5454,7 @@
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
"dev": true,
"dependencies": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
@ -5523,6 +5519,7 @@
"version": "5.0.8",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
"integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
"dev": true,
"engines": {
"node": ">=10"
}
@ -5534,20 +5531,21 @@
"dev": true
},
"node_modules/yargs": {
"version": "17.3.1",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.3.1.tgz",
"integrity": "sha512-WUANQeVgjLbNsEmGk20f+nlHgOqzRFpiGWVaBrYGYIGANIIu3lWjoyi0fNlFmJkvfhCZ6BXINe7/W2O2bV4iaA==",
"version": "16.2.0",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
"integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
"dev": true,
"dependencies": {
"cliui": "^7.0.2",
"escalade": "^3.1.1",
"get-caller-file": "^2.0.5",
"require-directory": "^2.1.1",
"string-width": "^4.2.3",
"string-width": "^4.2.0",
"y18n": "^5.0.5",
"yargs-parser": "^21.0.0"
"yargs-parser": "^20.2.2"
},
"engines": {
"node": ">=12"
"node": ">=10"
}
},
"node_modules/yargs-parser": {
@ -5607,14 +5605,6 @@
"node": ">=8"
}
},
"node_modules/yargs/node_modules/yargs-parser": {
"version": "21.0.0",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.0.tgz",
"integrity": "sha512-z9kApYUOCwoeZ78rfRYYWdiU/iNL6mwwYlkkZfJoyMR1xps+NEBX5X7XmRpxkZHhXJ6+Ey00IwKxBBSW9FIjyA==",
"engines": {
"node": ">=12"
}
},
"node_modules/yocto-queue": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
@ -5630,9 +5620,9 @@
},
"dependencies": {
"@eslint/eslintrc": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.1.0.tgz",
"integrity": "sha512-C1DfL7XX4nPqGd6jcP01W9pVM1HYCuUkFk1432D7F0v3JSlUIeOYn9oCoi3eoLZ+iwBSb29BMFxxny0YrrEZqg==",
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.0.tgz",
"integrity": "sha512-igm9SjJHNEJRiUnecP/1R5T3wKLEJ7pL6e2P+GUSfCd0dGjPYYZve08uzw8L2J8foVHFz+NGu12JxRcU2gGo6w==",
"dev": true,
"requires": {
"ajv": "^6.12.4",
@ -5696,9 +5686,9 @@
}
},
"@sinonjs/fake-timers": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz",
"integrity": "sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==",
"version": "9.1.0",
"resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-9.1.0.tgz",
"integrity": "sha512-M8vapsv9qQupMdzrVzkn5rb9jG7aUTEPAZdMtME2PuBaefksFZVE2C1g4LBRTkF/k3nRDNbDc5tp5NFC1PEYxA==",
"dev": true,
"requires": {
"@sinonjs/commons": "^1.7.0"
@ -5811,12 +5801,14 @@
"ansi-regex": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
"dev": true
},
"ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
"requires": {
"color-convert": "^2.0.1"
}
@ -5988,6 +5980,12 @@
"type-detect": "^4.0.5"
}
},
"chai-match": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/chai-match/-/chai-match-1.1.1.tgz",
"integrity": "sha1-OfsKLmt8j2OG3P6tSNFIqRX6bEY=",
"dev": true
},
"chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
@ -6045,6 +6043,7 @@
"version": "7.0.4",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
"integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
"dev": true,
"requires": {
"string-width": "^4.2.0",
"strip-ansi": "^6.0.0",
@ -6055,6 +6054,7 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"requires": {
"color-name": "~1.1.4"
}
@ -6062,7 +6062,8 @@
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
"colors": {
"version": "1.1.2",
@ -6078,6 +6079,11 @@
"delayed-stream": "~1.0.0"
}
},
"commander": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-9.0.0.tgz",
"integrity": "sha512-JJfP2saEKbQqvW+FI93OYUB4ByV5cizMpFMiiJI8xDbBvQvSkIk0VvQdn1CZ8mqAO8Loq2h0gYTYtDFUZUeERw=="
},
"compare-func": {
"version": "1.3.4",
"resolved": "https://registry.npmjs.org/compare-func/-/compare-func-1.3.4.tgz",
@ -6635,7 +6641,8 @@
"emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
"dev": true
},
"entities": {
"version": "1.0.0",
@ -6655,7 +6662,8 @@
"escalade": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw=="
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
"dev": true
},
"escape-string-regexp": {
"version": "4.0.0",
@ -6719,12 +6727,12 @@
}
},
"eslint": {
"version": "8.9.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.9.0.tgz",
"integrity": "sha512-PB09IGwv4F4b0/atrbcMFboF/giawbBLVC7fyDamk5Wtey4Jh2K+rYaBhCAbUyEI4QzB1ly09Uglc9iCtFaG2Q==",
"version": "8.10.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-8.10.0.tgz",
"integrity": "sha512-tcI1D9lfVec+R4LE1mNDnzoJ/f71Kl/9Cv4nG47jOueCMBrCCKYXr4AUVS7go6mWYGFD4+EoN6+eXSrEbRzXVw==",
"dev": true,
"requires": {
"@eslint/eslintrc": "^1.1.0",
"@eslint/eslintrc": "^1.2.0",
"@humanwhocodes/config-array": "^0.9.2",
"ajv": "^6.10.0",
"chalk": "^4.0.0",
@ -7041,13 +7049,6 @@
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
"dev": true
},
"fsevents": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
"dev": true,
"optional": true
},
"function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
@ -7063,7 +7064,8 @@
"get-caller-file": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
"dev": true
},
"get-func-name": {
"version": "2.0.0",
@ -7941,7 +7943,8 @@
"is-fullwidth-code-point": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
"dev": true
},
"is-glob": {
"version": "4.0.3",
@ -8686,21 +8689,6 @@
"requires": {
"has-flag": "^4.0.0"
}
},
"yargs": {
"version": "16.2.0",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
"integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
"dev": true,
"requires": {
"cliui": "^7.0.2",
"escalade": "^3.1.1",
"get-caller-file": "^2.0.5",
"require-directory": "^2.1.1",
"string-width": "^4.2.0",
"y18n": "^5.0.5",
"yargs-parser": "^20.2.2"
}
}
}
},
@ -9293,7 +9281,8 @@
"require-directory": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
"integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I="
"integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
"dev": true
},
"resolve": {
"version": "1.22.0",
@ -9437,16 +9426,16 @@
"dev": true
},
"sinon": {
"version": "12.0.1",
"resolved": "https://registry.npmjs.org/sinon/-/sinon-12.0.1.tgz",
"integrity": "sha512-iGu29Xhym33ydkAT+aNQFBINakjq69kKO6ByPvTsm3yyIACfyQttRTP03aBP/I8GfhFmLzrnKwNNkr0ORb1udg==",
"version": "13.0.1",
"resolved": "https://registry.npmjs.org/sinon/-/sinon-13.0.1.tgz",
"integrity": "sha512-8yx2wIvkBjIq/MGY1D9h1LMraYW+z1X0mb648KZnKSdvLasvDu7maa0dFaNYdTDczFgbjNw2tOmWdTk9saVfwQ==",
"dev": true,
"requires": {
"@sinonjs/commons": "^1.8.3",
"@sinonjs/fake-timers": "^8.1.0",
"@sinonjs/samsam": "^6.0.2",
"@sinonjs/fake-timers": "^9.0.0",
"@sinonjs/samsam": "^6.1.1",
"diff": "^5.0.0",
"nise": "^5.1.0",
"nise": "^5.1.1",
"supports-color": "^7.2.0"
}
},
@ -9543,6 +9532,7 @@
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"dev": true,
"requires": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
@ -9553,6 +9543,7 @@
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"dev": true,
"requires": {
"ansi-regex": "^5.0.1"
}
@ -9693,9 +9684,9 @@
"dev": true
},
"uglify-js": {
"version": "3.15.1",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.15.1.tgz",
"integrity": "sha512-FAGKF12fWdkpvNJZENacOH0e/83eG6JyVQyanIJaBXCN1J11TUQv1T1/z8S+Z0CG0ZPk1nPcreF/c7lrTd0TEQ==",
"version": "3.15.2",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.15.2.tgz",
"integrity": "sha512-peeoTk3hSwYdoc9nrdiEJk+gx1ALCtTjdYuKSXMTDqq7n1W7dHPqWDdSi+BPL0ni2YMeHD7hKUSdbj3TZauY2A==",
"dev": true
},
"unc-path-regex": {
@ -9856,6 +9847,7 @@
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
"dev": true,
"requires": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
@ -9893,7 +9885,8 @@
"y18n": {
"version": "5.0.8",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
"integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="
"integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
"dev": true
},
"yallist": {
"version": "4.0.0",
@ -9902,24 +9895,18 @@
"dev": true
},
"yargs": {
"version": "17.3.1",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.3.1.tgz",
"integrity": "sha512-WUANQeVgjLbNsEmGk20f+nlHgOqzRFpiGWVaBrYGYIGANIIu3lWjoyi0fNlFmJkvfhCZ6BXINe7/W2O2bV4iaA==",
"version": "16.2.0",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
"integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
"dev": true,
"requires": {
"cliui": "^7.0.2",
"escalade": "^3.1.1",
"get-caller-file": "^2.0.5",
"require-directory": "^2.1.1",
"string-width": "^4.2.3",
"string-width": "^4.2.0",
"y18n": "^5.0.5",
"yargs-parser": "^21.0.0"
},
"dependencies": {
"yargs-parser": {
"version": "21.0.0",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.0.tgz",
"integrity": "sha512-z9kApYUOCwoeZ78rfRYYWdiU/iNL6mwwYlkkZfJoyMR1xps+NEBX5X7XmRpxkZHhXJ6+Ey00IwKxBBSW9FIjyA=="
}
"yargs-parser": "^20.2.2"
}
},
"yargs-parser": {

View File

@ -1,6 +1,6 @@
{
"name": "showdown",
"version": "2.0.0-alpha1",
"version": "2.0.0",
"description": "A Markdown to HTML converter written in Javascript",
"author": "Estevão Santos",
"homepage": "http://showdownjs.com/",
@ -38,8 +38,13 @@
"bin": {
"showdown": "bin/showdown.js"
},
"files": [
"bin",
"dist"
],
"devDependencies": {
"chai": "^4.3.4",
"chai": "*",
"chai-match": "*",
"grunt": "^1.4.1",
"grunt-contrib-clean": "^2.0.0",
"grunt-contrib-concat": "^2.0.0",
@ -55,11 +60,11 @@
"quiet-grunt": "^0.2.0",
"semver": "^7.3.0",
"semver-sort": "^1.0.0",
"sinon": "^12.0.1",
"sinon": "*",
"source-map-support": "^0.5.21"
},
"dependencies": {
"jsdom": "^19.0.0",
"yargs": "^17.2.1"
"commander": "^9.0.0"
}
}

File diff suppressed because one or more lines are too long

View File

@ -1,744 +1,43 @@
# Performance Tests for showdown
## [version 2.0.0-alpha1](https://github.com/showdownjs/showdown/tree/2.0.0-alpha1)
## [version 2.0.0](https://github.com/showdownjs/showdown/tree/2.0.0)
### Test Suite: Basic (50 cycles)
| test | avgTime | max | min |
|:-----|--------:|----:|----:|
|Simple "Hello World"|0.330|9.462|0.086|
|performance.testfile.md|32.210|56.635|27.395|
|Simple "Hello World"|0.581|12.279|0.151|
|performance.testfile.md|35.491|79.405|29.046|
### Test Suite: subParsers (20 cycles)
| test | avgTime | max | min |
|:-----|--------:|----:|----:|
|hashHTMLBlocks|4.055|7.506|2.413|
|anchors|0.342|0.600|0.286|
|autoLinks|0.091|0.193|0.070|
|blockQuotes|2.896|5.991|1.987|
|codeBlocks|0.303|1.578|0.190|
|codeSpans|0.285|0.533|0.237|
|detab|0.136|0.873|0.086|
|encodeAmpsAndAngles|0.104|0.166|0.097|
|encodeBackslashEscapes|0.081|0.141|0.068|
|encodeCode|0.942|1.342|0.850|
|escapeSpecialCharsWithinTagAttributes|0.212|0.436|0.159|
|githubCodeBlocks|0.176|0.305|0.143|
|hashBlock|0.047|0.094|0.036|
|hashElement|0.003|0.046|0.001|
|hashHTMLSpans|4.276|5.772|3.965|
|hashPreCodeTags|0.144|0.324|0.110|
|headers|1.418|4.438|1.062|
|horizontalRule|0.227|0.403|0.195|
|images|0.175|0.435|0.129|
|italicsAndBold|0.375|2.407|0.228|
|lists|2.918|3.716|2.526|
|outdent|0.164|0.270|0.138|
|paragraphs|6.444|8.106|5.759|
|spanGamut|4.294|6.106|3.842|
|strikethrough|0.005|0.090|0.000|
|stripLinkDefinitions|0.230|0.286|0.221|
|tables|0.002|0.034|0.001|
|unescapeSpecialChars|0.011|0.080|0.007|
## [version 1.9.0](https://github.com/showdownjs/showdown/tree/1.9.0)
### Test Suite: Basic (50 cycles)
| test | avgTime | max | min |
|:-----|--------:|----:|----:|
|Simple "Hello World"|0.476|9.945|0.088|
|performance.testfile.md|32.208|61.885|28.234|
### Test Suite: subParsers (20 cycles)
| test | avgTime | max | min |
|:-----|--------:|----:|----:|
|hashHTMLBlocks|5.827|23.030|2.429|
|anchors|0.363|0.636|0.294|
|autoLinks|0.120|0.319|0.071|
|blockQuotes|2.884|6.237|2.040|
|codeBlocks|0.290|1.131|0.189|
|codeSpans|0.314|0.875|0.234|
|detab|0.095|0.141|0.086|
|encodeAmpsAndAngles|0.155|1.186|0.095|
|encodeBackslashEscapes|0.087|0.144|0.069|
|encodeCode|0.918|1.279|0.865|
|escapeSpecialCharsWithinTagAttributes|0.245|0.711|0.156|
|githubCodeBlocks|0.160|0.291|0.142|
|hashBlock|0.043|0.067|0.038|
|hashElement|0.003|0.035|0.000|
|hashHTMLSpans|4.273|6.304|3.983|
|hashPreCodeTags|0.133|0.344|0.110|
|headers|1.454|3.874|1.098|
|horizontalRule|0.230|0.300|0.202|
|images|0.191|0.476|0.135|
|italicsAndBold|0.310|0.866|0.236|
|lists|3.135|4.249|2.662|
|outdent|0.167|0.262|0.140|
|paragraphs|6.383|7.885|5.680|
|spanGamut|4.106|5.310|3.698|
|strikethrough|0.005|0.087|0.000|
|stripLinkDefinitions|0.245|0.376|0.221|
|tables|0.003|0.049|0.001|
|unescapeSpecialChars|0.010|0.057|0.007|
## [version 1.8.4](https://github.com/showdownjs/showdown/tree/1.8.4)
### Test Suite: Basic (50 cycles)
| test | avgTime | max | min |
|:-----|--------:|----:|----:|
|Simple "Hello World"|0.736|11.076|0.117|
|performance.testfile.md|32.918|62.427|27.941|
### Test Suite: subParsers (20 cycles)
| test | avgTime | max | min |
|:-----|--------:|----:|----:|
|hashHTMLBlocks|5.260|17.333|2.340|
|anchors|0.522|2.898|0.307|
|autoLinks|0.124|0.300|0.071|
|blockQuotes|2.244|3.333|2.015|
|codeBlocks|0.244|0.817|0.190|
|codeSpans|0.354|1.201|0.243|
|detab|0.096|0.143|0.088|
|encodeAmpsAndAngles|0.138|0.198|0.096|
|encodeBackslashEscapes|0.093|0.184|0.071|
|encodeCode|0.961|1.611|0.858|
|escapeSpecialCharsWithinTagAttributes|0.252|0.520|0.158|
|githubCodeBlocks|0.262|0.390|0.161|
|hashBlock|0.052|0.129|0.037|
|hashElement|0.003|0.040|0.000|
|hashHTMLSpans|4.240|4.673|4.044|
|hashPreCodeTags|0.134|0.337|0.113|
|headers|1.412|4.475|1.077|
|horizontalRule|0.358|2.686|0.196|
|images|0.184|0.480|0.130|
|italicsAndBold|0.300|0.458|0.234|
|lists|3.074|4.651|2.626|
|outdent|0.204|0.931|0.137|
|paragraphs|6.406|8.020|5.821|
|spanGamut|4.136|6.038|3.840|
|strikethrough|0.007|0.132|0.000|
|stripLinkDefinitions|0.248|0.403|0.217|
|tables|0.003|0.040|0.001|
|unescapeSpecialChars|0.009|0.039|0.007|
## [version 1.8.3](https://github.com/showdownjs/showdown/tree/1.8.3)
### Test Suite: Basic (50 cycles)
| test | avgTime | max | min |
|:-----|--------:|----:|----:|
|Simple "Hello World"|0.927|32.654|0.147|
|performance.testfile.md|32.485|62.282|28.403|
### Test Suite: subParsers (20 cycles)
| test | avgTime | max | min |
|:-----|--------:|----:|----:|
|hashHTMLBlocks|5.454|18.356|2.385|
|anchors|0.504|3.110|0.290|
|autoLinks|0.114|0.284|0.069|
|blockQuotes|2.269|3.374|1.997|
|codeBlocks|0.250|0.840|0.192|
|codeSpans|0.352|1.231|0.249|
|detab|0.115|0.179|0.087|
|encodeAmpsAndAngles|0.105|0.162|0.095|
|encodeBackslashEscapes|0.108|0.235|0.075|
|encodeCode|0.994|1.915|0.847|
|escapeSpecialCharsWithinTagAttributes|0.237|0.475|0.160|
|githubCodeBlocks|0.202|0.771|0.151|
|hashBlock|0.071|0.493|0.039|
|hashElement|0.002|0.036|0.001|
|hashHTMLSpans|4.162|4.708|3.959|
|hashPreCodeTags|0.130|0.331|0.112|
|headers|1.409|4.622|1.044|
|horizontalRule|0.351|2.655|0.196|
|images|0.199|0.545|0.131|
|italicsAndBold|0.269|0.357|0.235|
|lists|3.057|4.403|2.686|
|outdent|0.153|0.307|0.136|
|paragraphs|6.455|7.901|5.708|
|spanGamut|4.256|5.542|3.930|
|strikethrough|0.005|0.089|0.000|
|stripLinkDefinitions|0.248|0.394|0.225|
|tables|0.002|0.028|0.001|
|unescapeSpecialChars|0.009|0.039|0.007|
## [version 1.8.2](https://github.com/showdownjs/showdown/tree/1.8.2)
### Test Suite: Basic (50 cycles)
| test | avgTime | max | min |
|:-----|--------:|----:|----:|
|Simple "Hello World"|0.361|8.977|0.104|
|performance.testfile.md|33.109|56.478|29.179|
### Test Suite: subParsers (20 cycles)
| test | avgTime | max | min |
|:-----|--------:|----:|----:|
|hashHTMLBlocks|5.488|20.714|2.321|
|anchors|0.506|3.158|0.292|
|autoLinks|0.141|0.365|0.072|
|blockQuotes|2.300|3.642|2.046|
|codeBlocks|0.243|0.877|0.189|
|codeSpans|0.268|1.176|0.159|
|detab|0.095|0.172|0.089|
|encodeAmpsAndAngles|0.108|0.230|0.097|
|encodeBackslashEscapes|0.078|0.119|0.074|
|encodeCode|1.002|1.544|0.851|
|escapeSpecialCharsWithinTagAttributes|0.256|0.566|0.164|
|githubCodeBlocks|0.253|0.999|0.152|
|hashBlock|0.042|0.080|0.037|
|hashElement|0.002|0.032|0.000|
|hashHTMLSpans|4.444|5.282|3.987|
|hashPreCodeTags|0.152|0.265|0.117|
|headers|1.465|4.970|1.059|
|horizontalRule|0.245|0.562|0.205|
|images|0.312|2.615|0.131|
|italicsAndBold|0.287|0.427|0.244|
|lists|3.261|4.098|2.792|
|outdent|0.179|0.377|0.141|
|paragraphs|6.661|9.047|5.884|
|spanGamut|4.561|6.173|4.009|
|strikethrough|0.005|0.097|0.000|
|stripLinkDefinitions|0.251|0.402|0.216|
|tables|0.006|0.086|0.001|
|unescapeSpecialChars|0.013|0.064|0.008|
## [version 1.8.0](https://github.com/showdownjs/showdown/tree/1.8.0)
### Test Suite: Basic (50 cycles)
| test | avgTime | max | min |
|:-----|--------:|----:|----:|
|Simple "Hello World"|0.357|9.000|0.091|
|performance.testfile.md|31.434|57.439|26.735|
### Test Suite: subParsers (20 cycles)
| test | avgTime | max | min |
|:-----|--------:|----:|----:|
|hashHTMLBlocks|4.177|7.661|2.346|
|anchors|0.542|3.749|0.300|
|autoLinks|0.087|0.183|0.069|
|blockQuotes|2.049|3.552|1.815|
|codeBlocks|0.264|1.163|0.185|
|codeSpans|0.271|0.790|0.163|
|detab|0.092|0.120|0.086|
|encodeAmpsAndAngles|0.106|0.146|0.097|
|encodeBackslashEscapes|0.091|0.152|0.077|
|encodeCode|0.962|1.552|0.862|
|escapeSpecialCharsWithinTagAttributes|0.239|0.487|0.173|
|githubCodeBlocks|0.222|0.914|0.140|
|hashBlock|0.063|0.402|0.035|
|hashElement|0.001|0.025|0.000|
|hashHTMLSpans|4.303|4.889|4.021|
|hashPreCodeTags|0.164|0.541|0.110|
|headers|1.159|3.779|0.968|
|horizontalRule|0.244|0.419|0.194|
|images|0.324|3.058|0.133|
|italicsAndBold|0.289|0.419|0.237|
|lists|2.671|3.139|2.494|
|outdent|0.159|0.253|0.139|
|paragraphs|5.594|6.833|5.159|
|spanGamut|5.069|9.600|4.128|
|strikethrough|0.003|0.062|0.000|
|stripLinkDefinitions|0.271|0.400|0.225|
|tables|0.002|0.031|0.000|
|unescapeSpecialChars|0.008|0.038|0.007|
## [version 1.7.6](https://github.com/showdownjs/showdown/tree/1.7.6)
### Test Suite: Basic (50 cycles)
| test | avgTime | max | min |
|:-----|--------:|----:|----:|
|Simple "Hello World"|0.313|6.267|0.092|
|performance.testfile.md|30.962|54.583|26.381|
### Test Suite: subParsers (20 cycles)
| test | avgTime | max | min |
|:-----|--------:|----:|----:|
|hashHTMLBlocks|4.099|7.072|2.360|
|anchors|0.574|4.502|0.294|
|autoLinks|0.087|0.210|0.066|
|blockQuotes|2.176|4.602|1.823|
|codeBlocks|0.282|0.885|0.193|
|codeSpans|0.265|0.764|0.166|
|detab|0.102|0.155|0.091|
|encodeAmpsAndAngles|0.107|0.175|0.098|
|encodeBackslashEscapes|0.120|0.872|0.073|
|encodeCode|0.983|1.842|0.873|
|escapeSpecialCharsWithinTagAttributes|0.301|0.389|0.277|
|githubCodeBlocks|0.204|0.889|0.146|
|hashBlock|0.063|0.415|0.035|
|hashElement|0.002|0.032|0.000|
|hashHTMLSpans|4.131|4.411|3.988|
|hashPreCodeTags|0.262|2.429|0.108|
|headers|1.264|4.308|0.953|
|horizontalRule|0.230|0.331|0.194|
|images|0.184|0.564|0.134|
|italicsAndBold|0.312|0.828|0.251|
|lists|2.642|3.274|2.451|
|outdent|0.159|0.240|0.144|
|paragraphs|6.724|12.672|5.367|
|spanGamut|4.991|9.206|4.173|
|strikethrough|0.003|0.058|0.000|
|stripLinkDefinitions|0.246|0.390|0.219|
|tables|0.002|0.044|0.000|
|unescapeSpecialChars|0.010|0.051|0.007|
## [version 1.7.5](https://github.com/showdownjs/showdown/tree/1.7.5)
### Test Suite: Basic (50 cycles)
| test | avgTime | max | min |
|:-----|--------:|----:|----:|
|Simple "Hello World"|0.562|14.434|0.118|
|performance.testfile.md|30.396|57.886|26.628|
### Test Suite: subParsers (20 cycles)
| test | avgTime | max | min |
|:-----|--------:|----:|----:|
|hashHTMLBlocks|4.280|8.392|2.357|
|anchors|0.602|5.341|0.285|
|autoLinks|0.092|0.193|0.065|
|blockQuotes|2.068|4.430|1.736|
|codeBlocks|0.279|0.937|0.181|
|codeSpans|0.222|0.592|0.158|
|detab|0.120|0.145|0.091|
|encodeAmpsAndAngles|0.116|0.222|0.096|
|encodeBackslashEscapes|0.140|0.914|0.071|
|encodeCode|1.195|2.009|0.861|
|escapeSpecialCharsWithinTagAttributes|0.307|0.468|0.269|
|githubCodeBlocks|0.197|0.837|0.144|
|hashBlock|0.060|0.442|0.036|
|hashElement|0.002|0.041|0.000|
|hashHTMLSpans|4.289|4.712|4.002|
|hashPreCodeTags|0.281|2.439|0.108|
|headers|1.221|4.603|0.908|
|horizontalRule|0.208|0.352|0.193|
|images|0.182|0.634|0.128|
|italicsAndBold|0.335|1.276|0.239|
|lists|3.143|6.411|2.393|
|outdent|0.398|0.585|0.159|
|paragraphs|5.926|11.596|4.961|
|spanGamut|4.443|6.012|4.024|
|strikethrough|0.003|0.055|0.000|
|stripLinkDefinitions|0.243|0.424|0.215|
|tables|0.003|0.049|0.000|
|unescapeSpecialChars|0.008|0.041|0.006|
## [version 1.7.4](https://github.com/showdownjs/showdown/tree/1.7.4)
### Test Suite: Basic (50 cycles)
| test | avgTime | max | min |
|:-----|--------:|----:|----:|
|Simple "Hello World"|0.972|25.186|0.160|
|performance.testfile.md|30.397|61.913|26.550|
### Test Suite: subParsers (20 cycles)
| test | avgTime | max | min |
|:-----|--------:|----:|----:|
|hashHTMLBlocks|3.999|6.603|2.314|
|anchors|0.527|3.823|0.285|
|autoLinks|0.090|0.188|0.063|
|blockQuotes|2.057|4.122|1.780|
|codeBlocks|0.247|1.085|0.186|
|codeSpans|0.263|1.017|0.162|
|detab|0.123|0.158|0.097|
|encodeAmpsAndAngles|0.118|0.171|0.096|
|encodeBackslashEscapes|0.079|0.146|0.071|
|encodeCode|0.945|1.453|0.866|
|escapeSpecialCharsWithinTagAttributes|0.285|0.438|0.246|
|githubCodeBlocks|0.225|0.969|0.142|
|hashBlock|0.068|0.577|0.036|
|hashElement|0.002|0.041|0.000|
|hashHTMLSpans|4.126|4.528|3.950|
|hashPreCodeTags|0.149|0.537|0.110|
|headers|1.171|3.877|0.884|
|horizontalRule|0.381|3.457|0.197|
|images|0.195|0.618|0.133|
|italicsAndBold|0.298|0.562|0.245|
|lists|3.790|6.139|2.612|
|outdent|0.167|0.276|0.139|
|paragraphs|5.349|6.076|4.897|
|spanGamut|4.370|6.111|3.946|
|strikethrough|0.003|0.048|0.000|
|stripLinkDefinitions|0.255|0.401|0.218|
|tables|0.002|0.033|0.000|
|unescapeSpecialChars|0.009|0.040|0.007|
## [version 1.7.3](https://github.com/showdownjs/showdown/tree/1.7.3)
### Test Suite: Basic (50 cycles)
| test | avgTime | max | min |
|:-----|--------:|----:|----:|
|Simple "Hello World"|0.277|5.743|0.088|
|performance.testfile.md|30.733|54.768|26.972|
### Test Suite: subParsers (20 cycles)
| test | avgTime | max | min |
|:-----|--------:|----:|----:|
|hashHTMLBlocks|4.316|8.271|2.339|
|anchors|0.525|3.812|0.288|
|autoLinks|0.085|0.220|0.063|
|blockQuotes|2.033|3.622|1.745|
|codeBlocks|0.251|1.060|0.178|
|codeSpans|0.246|0.749|0.157|
|detab|0.142|0.752|0.087|
|encodeAmpsAndAngles|0.100|0.129|0.095|
|encodeBackslashEscapes|0.079|0.125|0.070|
|encodeCode|0.977|1.774|0.852|
|escapeSpecialCharsWithinTagAttributes|0.271|0.441|0.244|
|githubCodeBlocks|0.235|0.985|0.139|
|hashBlock|0.068|0.550|0.036|
|hashElement|0.002|0.030|0.000|
|hashHTMLSpans|4.197|4.564|4.006|
|hashPreCodeTags|0.139|0.543|0.106|
|headers|1.148|4.214|0.880|
|horizontalRule|0.214|0.273|0.199|
|images|0.310|3.095|0.120|
|italicsAndBold|0.279|0.378|0.235|
|lists|3.843|8.278|2.630|
|outdent|0.193|0.386|0.144|
|paragraphs|5.541|8.153|4.836|
|spanGamut|4.638|5.775|4.142|
|strikethrough|0.003|0.052|0.000|
|stripLinkDefinitions|0.167|0.275|0.142|
|tables|0.002|0.036|0.000|
|unescapeSpecialChars|0.009|0.032|0.008|
## [version 1.7.2](https://github.com/showdownjs/showdown/tree/1.7.2)
### Test Suite: Basic (50 cycles)
| test | avgTime | max | min |
|:-----|--------:|----:|----:|
|Simple "Hello World"|0.292|5.780|0.087|
|performance.testfile.md|30.396|53.860|26.054|
### Test Suite: subParsers (20 cycles)
| test | avgTime | max | min |
|:-----|--------:|----:|----:|
|hashHTMLBlocks|4.303|7.798|2.377|
|anchors|0.347|0.647|0.287|
|autoLinks|0.088|0.165|0.063|
|blockQuotes|2.101|5.121|1.738|
|codeBlocks|0.239|0.878|0.184|
|codeSpans|0.252|0.628|0.160|
|detab|0.094|0.129|0.088|
|encodeAmpsAndAngles|0.131|0.733|0.093|
|encodeBackslashEscapes|0.080|0.116|0.070|
|encodeCode|0.939|1.480|0.857|
|escapeSpecialCharsWithinTagAttributes|0.285|0.473|0.243|
|githubCodeBlocks|0.214|1.047|0.140|
|hashBlock|0.068|0.553|0.036|
|hashElement|0.002|0.030|0.000|
|hashHTMLSpans|4.323|6.162|4.004|
|hashPreCodeTags|0.147|0.558|0.109|
|headers|1.176|4.491|0.884|
|horizontalRule|0.216|0.264|0.193|
|images|0.156|0.559|0.118|
|italicsAndBold|0.322|1.013|0.237|
|lists|2.753|5.613|2.328|
|outdent|0.163|0.232|0.140|
|paragraphs|5.109|6.168|4.741|
|spanGamut|4.423|6.149|4.001|
|strikethrough|0.003|0.051|0.000|
|stripLinkDefinitions|0.160|0.226|0.142|
|tables|0.002|0.043|0.000|
|unescapeSpecialChars|0.011|0.046|0.007|
## [version 1.7.1](https://github.com/showdownjs/showdown/tree/1.7.1)
### Test Suite: Basic (50 cycles)
| test | avgTime | max | min |
|:-----|--------:|----:|----:|
|Simple "Hello World"|1.074|20.566|0.324|
|performance.testfile.md|30.463|82.116|26.022|
### Test Suite: subParsers (20 cycles)
| test | avgTime | max | min |
|:-----|--------:|----:|----:|
|hashHTMLBlocks|4.233|9.062|2.359|
|anchors|0.351|0.763|0.286|
|autoLinks|0.089|0.190|0.065|
|blockQuotes|2.074|4.989|1.729|
|codeBlocks|0.256|0.937|0.179|
|codeSpans|0.242|0.839|0.158|
|detab|0.099|0.168|0.086|
|encodeAmpsAndAngles|0.131|0.646|0.093|
|encodeBackslashEscapes|0.076|0.140|0.070|
|encodeCode|0.994|1.706|0.865|
|escapeSpecialCharsWithinTagAttributes|0.267|0.375|0.250|
|githubCodeBlocks|0.192|0.966|0.140|
|hashBlock|0.059|0.397|0.036|
|hashElement|0.002|0.031|0.000|
|hashHTMLSpans|4.117|5.585|3.890|
|hashPreCodeTags|0.142|0.529|0.108|
|headers|1.145|4.103|0.864|
|horizontalRule|0.217|0.366|0.194|
|images|0.151|0.553|0.117|
|italicsAndBold|0.312|1.241|0.236|
|lists|4.023|7.077|2.498|
|outdent|0.175|0.261|0.148|
|paragraphs|6.557|8.645|4.997|
|spanGamut|5.073|6.347|4.137|
|strikethrough|0.006|0.110|0.000|
|stripLinkDefinitions|0.164|0.277|0.142|
|tables|0.004|0.080|0.000|
|unescapeSpecialChars|0.009|0.046|0.007|
## [version 1.7.0](https://github.com/showdownjs/showdown/tree/1.7.0)
### Test Suite: Basic (50 cycles)
| test | avgTime | max | min |
|:-----|--------:|----:|----:|
|Simple "Hello World"|0.393|9.953|0.097|
|performance.testfile.md|29.416|54.253|25.949|
### Test Suite: subParsers (20 cycles)
| test | avgTime | max | min |
|:-----|--------:|----:|----:|
|hashHTMLBlocks|4.062|7.185|2.326|
|anchors|0.488|4.086|0.281|
|autoLinks|0.086|0.200|0.063|
|blockQuotes|2.071|4.554|1.733|
|codeBlocks|0.253|0.864|0.178|
|codeSpans|0.261|0.592|0.160|
|detab|0.095|0.130|0.089|
|encodeAmpsAndAngles|0.103|0.192|0.095|
|encodeBackslashEscapes|0.106|0.589|0.071|
|encodeCode|0.927|1.182|0.835|
|escapeSpecialCharsWithinTagAttributes|0.276|0.617|0.245|
|githubCodeBlocks|0.195|0.980|0.139|
|hashBlock|0.062|0.483|0.035|
|hashElement|0.001|0.025|0.000|
|hashHTMLSpans|4.120|4.610|3.859|
|hashPreCodeTags|0.147|0.535|0.105|
|headers|1.308|4.253|0.856|
|horizontalRule|0.220|0.374|0.194|
|images|0.150|0.507|0.116|
|italicsAndBold|0.306|0.872|0.241|
|lists|3.447|4.893|2.407|
|outdent|0.267|0.868|0.181|
|paragraphs|5.867|8.331|4.970|
|spanGamut|5.039|7.124|4.116|
|strikethrough|0.004|0.073|0.000|
|stripLinkDefinitions|0.153|0.243|0.140|
|tables|0.002|0.044|0.000|
|unescapeSpecialChars|0.009|0.041|0.007|
## [version 1.6.4](https://github.com/showdownjs/showdown/tree/1.6.4)
### Test Suite: Basic (50 cycles)
| test | avgTime | max | min |
|:-----|--------:|----:|----:|
|Simple "Hello World"|0.376|6.381|0.183|
|performance.testfile.md|33.835|61.049|30.186|
### Test Suite: subParsers (20 cycles)
| test | avgTime | max | min |
|:-----|--------:|----:|----:|
|hashHTMLBlocks|2.564|8.347|1.871|
|anchors|0.499|4.222|0.270|
|autoLinks|0.080|0.174|0.061|
|blockQuotes|3.343|7.306|2.850|
|codeBlocks|0.221|0.822|0.172|
|codeSpans|0.229|0.744|0.156|
|detab|0.097|0.154|0.086|
|encodeAmpsAndAngles|0.117|0.200|0.094|
|encodeBackslashEscapes|0.086|0.230|0.068|
|encodeCode|0.885|1.165|0.816|
|escapeSpecialCharsWithinTagAttributes|0.298|0.495|0.240|
|githubCodeBlocks|0.183|0.785|0.133|
|hashBlock|0.044|0.098|0.035|
|hashElement|0.002|0.033|0.000|
|hashHTMLSpans|4.200|4.552|3.987|
|hashPreCodeTags|0.130|0.313|0.106|
|headers|1.224|4.010|0.945|
|horizontalRule|0.412|4.175|0.196|
|images|0.088|0.203|0.073|
|italicsAndBold|0.276|0.414|0.233|
|lists|5.005|6.109|4.663|
|outdent|0.152|0.337|0.139|
|paragraphs|5.336|7.117|4.843|
|spanGamut|4.450|6.153|3.857|
|strikethrough|0.003|0.049|0.000|
|stripLinkDefinitions|0.180|0.316|0.147|
|tables|0.003|0.055|0.000|
|unescapeSpecialChars|0.009|0.047|0.007|
## [version 1.6.3](https://github.com/showdownjs/showdown/tree/1.6.3)
### Test Suite: Basic (50 cycles)
| test | avgTime | max | min |
|:-----|--------:|----:|----:|
|Simple "Hello World"|0.388|6.064|0.174|
|performance.testfile.md|26.899|49.063|24.845|
### Test Suite: subParsers (20 cycles)
| test | avgTime | max | min |
|:-----|--------:|----:|----:|
|hashHTMLBlocks|2.616|8.181|1.899|
|anchors|0.515|4.691|0.264|
|autoLinks|0.093|0.188|0.073|
|blockQuotes|4.518|8.953|3.036|
|codeBlocks|0.223|0.348|0.188|
|codeSpans|0.318|1.095|0.177|
|detab|0.092|0.137|0.087|
|encodeAmpsAndAngles|0.044|0.089|0.038|
|encodeBackslashEscapes|0.108|0.265|0.078|
|encodeCode|1.535|9.896|0.865|
|escapeSpecialCharsWithinTagAttributes|0.294|0.523|0.253|
|githubCodeBlocks|0.208|0.790|0.142|
|hashBlock|0.042|0.123|0.036|
|hashElement|0.002|0.029|0.000|
|hashHTMLSpans|0.410|1.598|0.240|
|hashPreCodeTags|0.132|0.395|0.110|
|headers|1.015|1.502|0.806|
|horizontalRule|0.220|0.357|0.195|
|images|0.158|0.978|0.077|
|italicsAndBold|0.288|0.639|0.241|
|lists|5.151|6.331|4.629|
|outdent|0.180|0.363|0.143|
|paragraphs|4.548|6.309|4.002|
|spanGamut|1.519|1.864|1.372|
|strikethrough|0.003|0.065|0.000|
|stripLinkDefinitions|0.179|0.313|0.144|
|tables|0.004|0.063|0.000|
|unescapeSpecialChars|0.011|0.049|0.007|
## [version 1.6.2](https://github.com/showdownjs/showdown/tree/1.6.2)
### Test Suite: Basic (50 cycles)
| test | avgTime | max | min |
|:-----|--------:|----:|----:|
|Simple "Hello World"|0.613|5.894|0.169|
|performance.testfile.md|25.970|62.882|23.710|
### Test Suite: subParsers (20 cycles)
| test | avgTime | max | min |
|:-----|--------:|----:|----:|
|hashHTMLBlocks|2.669|8.479|1.885|
|anchors|0.500|3.841|0.268|
|autoLinks|0.098|0.211|0.072|
|blockQuotes|3.222|5.826|2.791|
|codeBlocks|0.177|0.371|0.157|
|codeSpans|0.218|0.483|0.151|
|detab|0.135|0.655|0.085|
|encodeAmpsAndAngles|0.042|0.118|0.036|
|encodeBackslashEscapes|0.080|0.133|0.068|
|encodeCode|0.560|0.982|0.484|
|escapeSpecialCharsWithinTagAttributes|0.353|0.568|0.291|
|githubCodeBlocks|0.180|0.773|0.127|
|hashBlock|0.058|0.312|0.037|
|hashElement|0.003|0.046|0.000|
|hashHTMLSpans|0.475|2.325|0.234|
|hashPreCodeTags|0.122|0.307|0.107|
|headers|0.858|0.954|0.780|
|horizontalRule|0.227|0.418|0.197|
|images|0.171|1.453|0.077|
|italicsAndBold|0.101|0.202|0.088|
|lists|4.931|5.460|4.556|
|outdent|0.163|0.315|0.142|
|paragraphs|3.790|5.564|3.278|
|spanGamut|1.442|2.012|1.203|
|strikethrough|0.004|0.082|0.000|
|stripBlankLines|0.086|0.130|0.080|
|stripLinkDefinitions|0.160|0.217|0.145|
|tables|0.004|0.076|0.000|
|unescapeSpecialChars|0.010|0.058|0.007|
## [version 1.6.1](https://github.com/showdownjs/showdown/tree/1.6.1)
### Test Suite: Basic (50 cycles)
| test | avgTime | max | min |
|:-----|--------:|----:|----:|
|Simple "Hello World"|0.317|5.498|0.161|
|readme.md|26.014|46.799|24.245|
### Test Suite: subParsers (20 cycles)
| test | avgTime | max | min |
|:-----|--------:|----:|----:|
|hashHTMLBlocks|2.641|7.792|1.936|
|anchors|0.475|4.063|0.259|
|autoLinks|0.089|0.197|0.069|
|blockQuotes|3.213|6.054|2.880|
|codeBlocks|0.162|0.269|0.153|
|codeSpans|0.169|0.399|0.141|
|detab|0.125|0.665|0.086|
|encodeAmpsAndAngles|0.042|0.089|0.038|
|encodeBackslashEscapes|0.076|0.133|0.068|
|encodeCode|0.577|0.970|0.479|
|escapeSpecialCharsWithinTagAttributes|0.246|0.350|0.221|
|githubCodeBlocks|0.177|0.815|0.125|
|hashBlock|0.065|0.430|0.038|
|hashElement|0.002|0.034|0.000|
|hashHTMLSpans|0.424|2.321|0.241|
|hashPreCodeTags|0.122|0.238|0.104|
|headers|0.804|0.946|0.726|
|horizontalRule|0.219|0.274|0.194|
|images|0.124|0.902|0.071|
|italicsAndBold|0.101|0.150|0.090|
|lists|4.939|5.421|4.624|
|outdent|0.165|0.337|0.140|
|paragraphs|3.495|4.555|3.171|
|spanGamut|1.319|1.992|1.147|
|strikethrough|0.007|0.143|0.000|
|stripBlankLines|0.094|0.155|0.082|
|stripLinkDefinitions|0.176|0.311|0.146|
|tables|0.002|0.039|0.000|
|unescapeSpecialChars|0.008|0.034|0.007|
## [version 1.6.0](https://github.com/showdownjs/showdown/tree/1.6.0)
### Test Suite: Basic (50 cycles)
| test | avgTime | max | min |
|:-----|--------:|----:|----:|
|Simple "Hello World"|0.308|5.369|0.157|
|readme.md|25.818|47.795|23.775|
### Test Suite: subParsers (20 cycles)
| test | avgTime | max | min |
|:-----|--------:|----:|----:|
|hashHTMLBlocks|2.653|8.558|1.880|
|anchors|0.517|4.142|0.271|
|autoLinks|0.089|0.194|0.071|
|blockGamut|17.372|22.941|14.082|
|blockQuotes|3.011|4.110|2.774|
|codeBlocks|0.243|0.834|0.193|
|codeSpans|0.227|0.458|0.191|
|detab|0.095|0.133|0.090|
|encodeAmpsAndAngles|0.040|0.073|0.038|
|encodeBackslashEscapes|0.100|0.510|0.068|
|encodeCode|0.532|0.706|0.479|
|escapeSpecialCharsWithinTagAttributes|0.386|0.702|0.327|
|githubCodeBlocks|0.214|0.778|0.156|
|hashBlock|0.057|0.280|0.035|
|hashElement|0.002|0.033|0.000|
|hashHTMLSpans|0.384|1.997|0.236|
|hashPreCodeTags|0.133|0.200|0.116|
|headers|0.944|2.468|0.782|
|images|0.120|0.486|0.086|
|italicsAndBold|0.111|0.445|0.088|
|lists|5.783|13.249|4.464|
|outdent|0.306|0.956|0.225|
|paragraphs|6.583|8.811|4.499|
|spanGamut|2.437|3.067|1.647|
|strikethrough|0.005|0.100|0.000|
|stripBlankLines|0.121|0.175|0.092|
|stripLinkDefinitions|0.247|0.573|0.171|
|tables|0.006|0.099|0.000|
|unescapeSpecialChars|0.017|0.066|0.011|
|hashHTMLBlocks|4.561|7.807|2.461|
|anchors|2.910|6.510|1.056|
|blockQuotes|4.142|19.023|2.541|
|codeBlocks|0.264|0.858|0.194|
|codeSpans|0.365|1.421|0.278|
|detab|0.055|0.116|0.047|
|encodeAmpsAndAngles|0.145|0.796|0.092|
|encodeBackslashEscapes|0.087|0.266|0.063|
|encodeCode|0.605|1.144|0.522|
|escapeSpecialCharsWithinTagAttributes|0.206|0.287|0.184|
|githubCodeBlocks|0.251|1.003|0.192|
|hashBlock|0.038|0.104|0.034|
|hashElement|0.005|0.053|0.001|
|hashHTMLSpans|5.229|9.835|4.240|
|hashPreCodeTags|0.155|0.705|0.117|
|headers|2.278|4.825|1.631|
|horizontalRule|0.159|0.276|0.148|
|images|0.159|0.390|0.124|
|italicsAndBold|0.280|0.773|0.211|
|lists|4.253|8.173|3.146|
|outdent|0.181|0.238|0.162|
|paragraphs|8.968|11.331|7.857|
|spanGamut|2.985|4.162|2.486|
|strikethrough|0.007|0.099|0.001|
|stripLinkDefinitions|1.911|2.855|1.447|
|tables|0.008|0.127|0.002|
|unescapeSpecialChars|0.013|0.073|0.010|

View File

@ -1,50 +1,324 @@
/**
* Created by tivie
*/
'use strict';
var fs = require('fs'),
json = JSON.parse(fs.readFileSync('package.json', 'utf8')),
version = json.version,
Command = require('commander').Command,
program = new Command(),
showdown;
var yargs = require('yargs');
yargs
.version()
.alias('v', 'version')
.option('h', {
alias: 'help',
description: 'Show help'
})
.option('q', {
alias: 'quiet',
description: 'Quiet mode. Only print errors',
type: 'boolean',
default: false
})
.option('m', {
alias: 'mute',
description: 'Mute mode. Does not print anything',
type: 'boolean',
default: false
})
.usage('Usage: showdown <command> [options]')
.demand(1, 'You must provide a valid command')
.command('makehtml', 'Converts markdown into html')
.example('showdown makehtml -i foo.md -o bar.html', 'Converts \'foo.md\' to \'bar.html\'')
.wrap(yargs.terminalWidth());
var argv = yargs.argv,
command = argv._[0];
if (command === 'makehtml') {
require('./makehtml.cmd.js').run(function (err) {
if (err) {
console.error(err);
}
});
// require shodown. We use conditional loading for each use case
if (fs.existsSync('../dist/showdown.js')) {
// production. File lives in bin directory
showdown = require('../dist/showdown');
} else if (fs.existsSync('../../.build/showdown.js')) {
// testing envo, uses the concatenated stuff for testing
showdown = require('../../.build/showdown.js');
} else {
yargs.showHelp();
process.exit(0);
// cold testing (manual) of cli.js in the src file. We load the dist file
showdown = require('../../dist/showdown');
}
if (argv.help) {
yargs.showHelp();
process.exit(0);
program
.name('showdown')
.description('CLI to Showdownjs markdown parser v' + version)
.version(version)
.usage('<command> [options]')
.option('-q, --quiet', 'Quiet mode. Only print errors')
.option('-m, --mute', 'Mute mode. Does not print anything');
program.command('makehtml')
.description('Converts markdown into html')
.addHelpText('after', '\n\nExamples:')
.addHelpText('after', ' showdown makehtml -i Reads from stdin and outputs to stdout')
.addHelpText('after', ' showdown makehtml -i foo.md -o bar.html Reads \'foo.md\' and writes to \'bar.html\'')
.addHelpText('after', ' showdown makehtml -i --flavor="github" Parses stdin using GFM style')
.addHelpText('after', '\nNote for windows users:')
.addHelpText('after', 'When reading from stdin, use option -u to set the proper encoding or run `chcp 65001` prior to calling showdown cli to set the command line to utf-8')
.option('-i, --input [file]', 'Input source. Usually a md file. If omitted or empty, reads from stdin. Windows users see note below.', true)
.option('-o, --output [file]', 'Output target. Usually a html file. If omitted or empty, writes to stdout', true)
.option('-u, --encoding <encoding>', 'Sets the input encoding', 'utf8')
.option('-y, --output-encoding <encoding>', 'Sets the output encoding', 'utf8')
.option('-a, --append', 'Append data to output instead of overwriting. Ignored if writing to stdout', false)
.option('-e, --extensions <extensions...>', 'Load the specified extensions. Should be valid paths to node compatible extensions')
.option('-p, --flavor <flavor>', 'Run with a predetermined flavor of options. Default is vanilla', 'vanilla')
.option('-c, --config <config...>', 'Enables showdown makehtml parser config options. Overrides flavor')
.option('--config-help', 'Shows configuration options for showdown parser')
.action(makehtmlCommand);
program.parse();
//
// HELPER FUCNTIONS
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Messenger helper object to the CLI
* @param {string} writeMode
* @param {boolean} supress
* @param {boolean} mute
* @constructor
*/
function Messenger (writeMode, supress, mute) {
'use strict';
writeMode = writeMode || 'stderr';
supress = (!!supress || !!mute);
mute = !!mute;
this._print = (writeMode === 'stdout') ? console.log : console.error;
this.errorExit = function (e) {
if (!mute) {
console.error('ERROR: ' + e.message);
console.error('Run \'showdown <command> -h\' for help');
}
process.exit(1);
};
this.okExit = function () {
if (!mute) {
this._print('\n');
this._print('DONE!');
}
process.exit(0);
};
this.printMsg = function (msg) {
if (supress || mute || !msg) {
return;
}
this._print(msg);
};
this.printError = function (msg) {
if (mute) {
return;
}
console.error(msg);
};
}
/**
* Helper function to show Showdown Options
*/
function showShowdownOptions () {
'use strict';
var showdownOptions = showdown.getDefaultOptions(false);
console.log('\nshowdown makehtml config options:');
// show showdown options
for (var sopt in showdownOptions) {
if (showdownOptions.hasOwnProperty(sopt)) {
console.log(' ' + sopt + ':', '[default=' + showdownOptions[sopt].defaultValue + ']',showdownOptions[sopt].describe);
}
}
console.log('\n\nExample: showdown makehtml -c openLinksInNewWindow ghMentions ghMentionsLink="https://google.com"');
}
/**
* Helper function to parse showdown options
* @param {{}} configOptions
* @param {{}} defaultOptions
* @returns {{}}
*/
function parseShowdownOptions (configOptions, defaultOptions) {
'use strict';
var shOpt = defaultOptions;
// first prepare passed options
if (configOptions) {
for (var i = 0; i < configOptions.length; ++i) {
var opt = configOptions[i],
key = configOptions[i],
val = true;
if (/=/.test(opt)) {
key = opt.split('=')[0];
val = opt.split('=')[1];
}
shOpt[key] = val;
}
}
return shOpt;
}
/**
* Reads stdin
* @returns {string}
*/
function readFromStdIn (encoding) {
'use strict';
var size = fs.fstatSync(process.stdin.fd).size;
if (size <= 0) {
throw new Error('Could not read from stdin, reason: stdin is empty');
}
encoding = encoding || 'utf8';
try {
return size > 0 ? fs.readFileSync(process.stdin.fd, encoding).toString() : '';
} catch (e) {
throw new Error('Could not read from stdin, reason: ' + e.message);
}
}
/**
* Reads from a file
* @param {string} file Filepath to dile
* @param {string} encoding Encoding of the file
* @returns {Buffer}
*/
function readFromFile (file, encoding) {
'use strict';
try {
return fs.readFileSync(file, encoding);
} catch (err) {
throw new Error('Could not read from file ' + file + ', reason: ' + err.message);
}
}
/**
* Writes to stdout
* @param {string} html
* @returns {boolean}
*/
function writeToStdOut (html) {
'use strict';
if (!process.stdout.write(html)) {
throw new Error('Could not write to StdOut');
}
}
/**
* Writes to file
* @param {string} html HTML to write
* @param {string} file Filepath
* @param {boolean} append If the result should be appended
*/
function writeToFile (html, file, append) {
'use strict';
// If a flag is passed, it means we should append instead of overwriting.
// Only works with files, obviously
var write = (append) ? fs.appendFileSync : fs.writeFileSync;
try {
write(file, html);
} catch (err) {
throw new Error('Could not write to file ' + file + ', readon: ' + err.message);
}
}
/**
* makehtml command
* @param {{}} options
* @param {Command} cmd
*/
function makehtmlCommand (options, cmd) {
'use strict';
// show configuration options for showdown helper if configHelp was passed
if (options.configHelp) {
showShowdownOptions();
return;
}
var quiet = !!(cmd.parent._optionValues.quiet),
mute = !!(cmd.parent._optionValues.mute),
readMode = (!options.input || options.input === '' || options.input === true) ? 'stdin' : 'file',
writeMode = (!options.output || options.output === '' || options.output === true) ? 'stdout' : 'file',
msgMode = (writeMode === 'file') ? 'stdout' : 'stderr',
// initiate Messenger helper, can maybe be replaced with commanderjs internal stuff
messenger = new Messenger(msgMode, quiet, mute),
defaultOptions = showdown.getDefaultOptions(true),
md, html;
// deal with flavor first since config flag overrides flavor individual options
if (options.flavor) {
messenger.printMsg('Enabling flavor ' + options.flavor + '...');
defaultOptions = showdown.getFlavorOptions(options.flavor);
if (!defaultOptions) {
messenger.errorExit(new Error('Flavor ' + options.flavor + ' is not recognised'));
return;
}
messenger.printMsg('OK!');
}
// store config options in the options.config as an object
options.config = parseShowdownOptions(options.config, defaultOptions);
// print enabled options
for (var o in options.config) {
if (options.config.hasOwnProperty(o) && options.config[o] === true) {
messenger.printMsg('Enabling option ' + o);
}
}
// initialize the converter
messenger.printMsg('\nInitializing converter...');
var converter;
try {
converter = new showdown.Converter(options.config);
} catch (e) {
messenger.errorExit(e);
return;
}
messenger.printMsg('OK!');
// load extensions
if (options.extensions) {
messenger.printMsg('\nLoading extensions...');
for (var i = 0; i < options.extensions.length; ++i) {
try {
messenger.printMsg(options.extensions[i]);
var ext = require(options.extensions[i]);
converter.addExtension(ext, options.extensions[i]);
messenger.printMsg(options.extensions[i] + ' loaded...');
} catch (e) {
messenger.printError('Could not load extension ' + options.extensions[i] + '. Reason:');
messenger.errorExit(e);
}
}
}
messenger.printMsg('...');
// read the input
messenger.printMsg('Reading data from ' + readMode + '...');
if (readMode === 'stdin') {
try {
md = readFromStdIn(options.encoding);
} catch (err) {
messenger.errorExit(err);
return;
}
} else {
try {
md = readFromFile(options.input, options.encoding);
} catch (err) {
messenger.errorExit(err);
return;
}
}
// process the input
messenger.printMsg('Parsing markdown...');
html = converter.makeHtml(md);
// write the output
messenger.printMsg('Writing data to ' + writeMode + '...');
if (writeMode === 'stdout') {
try {
writeToStdOut(html);
} catch (err) {
messenger.errorExit(err);
return;
}
} else {
try {
writeToFile(html, options.output, options.append);
} catch (err) {
messenger.errorExit(err);
return;
}
}
messenger.okExit();
}

View File

@ -1,200 +0,0 @@
var yargs = require('yargs'),
fs = require('fs'),
Messenger = require('./messenger.js'),
showdown = require('../../dist/showdown'),
showdownOptions = showdown.getDefaultOptions(false);
yargs.reset()
.usage('Usage: showdown makehtml [options]')
.example('showdown makehtml -i', 'Reads from stdin and outputs to stdout')
.example('showdown makehtml -i foo.md -o bar.html', 'Reads \'foo.md\' and writes to \'bar.html\'')
.example('showdown makehtml -i --flavor="github"', 'Parses stdin using GFM style')
.version()
.alias('v', 'version')
.config('c')
.alias('c', 'config')
.help('h')
.alias('h', 'help')
.option('i', {
alias : 'input',
describe: 'Input source. Usually a md file. If omitted or empty, reads from stdin',
type: 'string'
})
.option('o', {
alias : 'output',
describe: 'Output target. Usually a html file. If omitted or empty, writes to stdout',
type: 'string',
default: false
})
.option('u', {
alias : 'encoding',
describe: 'Input encoding',
type: 'string'
})
.option('a', {
alias : 'append',
describe: 'Append data to output instead of overwriting',
type: 'string',
default: false
})
.option('e', {
alias : 'extensions',
describe: 'Load the specified extensions. Should be valid paths to node compatible extensions',
type: 'array'
})
.option('p', {
alias : 'flavor',
describe: 'Run with a predetermined flavor of options. Default is vanilla',
type: 'string'
})
.option('q', {
alias: 'quiet',
description: 'Quiet mode. Only print errors',
type: 'boolean',
default: false
})
.option('m', {
alias: 'mute',
description: 'Mute mode. Does not print anything',
type: 'boolean',
default: false
});
// load showdown default options
for (var opt in showdownOptions) {
if (showdownOptions.hasOwnProperty(opt)) {
if (showdownOptions[opt].defaultValue === false) {
showdownOptions[opt].default = null;
} else {
showdownOptions[opt].default = showdownOptions[opt].defaultValue;
}
yargs.option(opt, showdownOptions[opt]);
}
}
function run (cb) {
'use strict';
var argv = yargs.argv,
readMode = (!argv.i || argv.i === '') ? 'stdin' : 'file',
writeMode = (!argv.o || argv.o === '') ? 'stdout' : 'file',
msgMode = (writeMode === 'file') ? 'stdout' : 'stderr',
/**
* MSG object
* @type {Messenger}
*/
messenger = new Messenger(msgMode, argv.q, argv.m),
write = (writeMode === 'stdout') ? writeToStdOut : writeToFile,
enc = argv.encoding || 'utf8',
flavor = argv.p,
append = argv.a || false,
options = parseOptions(flavor),
converter = new showdown.Converter(options),
html;
// Load extensions
if (argv.e) {
messenger.printMsg('Loading extensions');
for (var i = 0; i < argv.e.length; ++i) {
try {
var ext = require(argv.e[i]);
converter.addExtension(ext, argv.e[i]);
} catch (e) {
messenger.printError('Could not load extension ' + argv.e[i] + '. Reason:');
messenger.errorExit(e);
}
}
}
messenger.printMsg('...');
// read the input
messenger.printMsg('Reading data from ' + readMode + '...');
readFrom(argv.i, enc, function (err, md) {
if (err) {
return cb(err);
}
// process the input
messenger.printMsg('Parsing markdown...');
html = converter.makeHtml(md);
// write the output
messenger.printMsg('Writing data to ' + writeMode + '...');
write(html, append);
messenger.okExit();
cb();
});
function parseOptions (flavor) {
var options = {},
flavorOpts = showdown.getFlavorOptions(flavor) || {};
// if flavor is not undefined, let's tell the user we're loading that preset
if (flavor) {
messenger.printMsg('Loading ' + flavor + ' flavor.');
}
for (var opt in argv) {
if (argv.hasOwnProperty(opt)) {
// first we load the default options
if (showdownOptions.hasOwnProperty(opt) && showdownOptions[opt].default !== null) {
options[opt] = showdownOptions[opt].default;
}
// we now override defaults with flavor, if a flavor was indeed passed
if (flavorOpts.hasOwnProperty(opt)) {
options[opt] = flavorOpts[opt];
}
// lastly we override with explicit passed options
// being careful not to pass CLI specific options, such as -v, -h or --extensions
if (showdownOptions.hasOwnProperty(opt)) {
if (argv[opt] === true) {
messenger.printMsg('Enabling option ' + opt);
options[opt] = argv[opt];
} else if (argv[opt] === false) {
options[opt] = argv[opt];
}
}
}
}
return options;
}
function readFrom (src, enc, cb) {
var stream = process.stdin;
if (src && src.length) {
stream = fs.createReadStream(src, {encoding: enc});
} else {
process.stdin.setEncoding(enc);
process.stdin.resume();
}
var data = '';
stream.on('data', function (chunk) {
data += chunk.toString();
});
stream.on('end',function () {
cb(null, data);
});
stream.on('error', cb);
}
function writeToStdOut (html) {
return process.stdout.write(html);
}
function writeToFile (html, append) {
// If a flag is passed, it means we should append instead of overwriting.
// Only works with files, obviously
var write = (append) ? fs.appendFileSync : fs.writeFileSync;
try {
write(argv.o, html);
} catch (err) {
messenger.errorExit(err);
}
}
}
module.exports = exports = {
run: run
};

View File

@ -1,40 +0,0 @@
function Messenger (writeMode, supress, mute) {
'use strict';
writeMode = writeMode || 'stderr';
supress = (!!supress || !!mute);
mute = !!mute;
this._print = (writeMode === 'stdout') ? console.log : console.error;
this.errorExit = function (e) {
if (!mute) {
console.error('ERROR: ' + e.message);
console.error('Run \'showdown <command> -h\' for help');
}
process.exit(1);
};
this.okExit = function () {
if (!mute) {
this._print('\n');
this._print('DONE!');
}
process.exit(0);
};
this.printMsg = function (msg) {
if (supress || mute || !msg) {
return;
}
this._print(msg);
};
this.printError = function (msg) {
if (mute) {
return;
}
console.error(msg);
};
}
module.exports = Messenger;

View File

@ -93,77 +93,77 @@ function getDefaultOpts (simple) {
},
smartIndentationFix: {
defaultValue: false,
description: 'Tries to smartly fix indentation in es6 strings',
describe: 'Tries to smartly fix indentation in es6 strings',
type: 'boolean'
},
disableForced4SpacesIndentedSublists: {
defaultValue: false,
description: 'Disables the requirement of indenting nested sublists by 4 spaces',
describe: 'Disables the requirement of indenting nested sublists by 4 spaces',
type: 'boolean'
},
simpleLineBreaks: {
defaultValue: false,
description: 'Parses simple line breaks as <br> (GFM Style)',
describe: 'Parses simple line breaks as <br> (GFM Style)',
type: 'boolean'
},
requireSpaceBeforeHeadingText: {
defaultValue: false,
description: 'Makes adding a space between `#` and the header text mandatory (GFM Style)',
describe: 'Makes adding a space between `#` and the header text mandatory (GFM Style)',
type: 'boolean'
},
ghMentions: {
defaultValue: false,
description: 'Enables github @mentions',
describe: 'Enables github @mentions',
type: 'boolean'
},
ghMentionsLink: {
defaultValue: 'https://github.com/{u}',
description: 'Changes the link generated by @mentions. Only applies if ghMentions option is enabled.',
describe: 'Changes the link generated by @mentions. Only applies if ghMentions option is enabled.',
type: 'string'
},
encodeEmails: {
defaultValue: true,
description: 'Encode e-mail addresses through the use of Character Entities, transforming ASCII e-mail addresses into its equivalent decimal entities',
describe: 'Encode e-mail addresses through the use of Character Entities, transforming ASCII e-mail addresses into its equivalent decimal entities',
type: 'boolean'
},
openLinksInNewWindow: {
defaultValue: false,
description: 'Open all links in new windows',
describe: 'Open all links in new windows',
type: 'boolean'
},
backslashEscapesHTMLTags: {
defaultValue: false,
description: 'Support for HTML Tag escaping. ex: \<div>foo\</div>',
describe: 'Support for HTML Tag escaping. ex: \<div>foo\</div>',
type: 'boolean'
},
emoji: {
defaultValue: false,
description: 'Enable emoji support. Ex: `this is a :smile: emoji`',
describe: 'Enable emoji support. Ex: `this is a :smile: emoji`',
type: 'boolean'
},
underline: {
defaultValue: false,
description: 'Enable support for underline. Syntax is double or triple underscores: `__underline word__`. With this option enabled, underscores no longer parses into `<em>` and `<strong>`',
describe: 'Enable support for underline. Syntax is double or triple underscores: `__underline word__`. With this option enabled, underscores no longer parses into `<em>` and `<strong>`',
type: 'boolean'
},
ellipsis: {
defaultValue: true,
description: 'Replaces three dots with the ellipsis unicode character',
describe: 'Replaces three dots with the ellipsis unicode character',
type: 'boolean'
},
completeHTMLDocument: {
defaultValue: false,
description: 'Outputs a complete html document, including `<html>`, `<head>` and `<body>` tags',
describe: 'Outputs a complete html document, including `<html>`, `<head>` and `<body>` tags',
type: 'boolean'
},
metadata: {
defaultValue: false,
description: 'Enable support for document metadata (defined at the top of the document between `«««` and `»»»` or between `---` and `---`).',
describe: 'Enable support for document metadata (defined at the top of the document between `«««` and `»»»` or between `---` and `---`).',
type: 'boolean'
},
splitAdjacentBlockquotes: {
defaultValue: false,
description: 'Split adjacent blockquote blocks',
describe: 'Split adjacent blockquote blocks',
type: 'boolean'
},
moreStyling: {

View File

@ -187,7 +187,7 @@ showdown.subParser = function (name, func) {
* Gets or registers an extension
* @static
* @param {string} name
* @param {object|function=} ext
* @param {object|object[]|function=} ext
* @returns {*}
*/
showdown.extension = function (name, ext) {

View File

@ -1,3 +1,2 @@
<h1 id="sometitle">some title</h1>
<p>Test <strong>bold</strong> and <em>italic</em></p>

View File

@ -0,0 +1,14 @@
var showdown = require('../../.build/showdown.js');
var ext = {
type: 'lang',
regex: /foo/g,
replace: 'bar'
};
showdown.extension('mockextension', function () {
'use strict';
return [ext];
});
module.exports = ext;

View File

@ -49,10 +49,7 @@ function runTests () {
showdown.subParser('makehtml.hashHTMLBlocks')(testMDFile, options, globals);
})
.add('anchors', function () {
showdown.subParser('makehtml.anchors')(testMDFile, options, globals);
})
.add('autoLinks', function () {
showdown.subParser('makehtml.autoLinks')(testMDFile, options, globals);
showdown.subParser('makehtml.links')(testMDFile, options, globals);
})
.add('blockQuotes', function () {
showdown.subParser('makehtml.blockQuotes')(testMDFile, options, globals);

293
test/unit/cli.js Normal file
View File

@ -0,0 +1,293 @@
var fs = require('fs'),
path = require('path'),
chai = require('chai'),
expect = chai.expect,
chaiMatch = require('chai-match'),
execSync = require('child_process').execSync,
spawnSync = require('child_process').spawnSync,
cmd = 'node src/cli/cli.js',
packageJson = JSON.parse(fs.readFileSync('package.json', 'utf8'));
require('sinon');
chai.should();
chai.use(chaiMatch);
/**
* Spawns a CLI process synchrously
* @param {string|null} command
* @param {string[]} args
* @param {{}} [options]
* @returns {{output: *, stdout: string, stderr: string, status: number}}
*/
function spawnCLI (command, args, options) {
'use strict';
var nargs = ['src/cli/cli.js'];
if (command) { nargs.push(command);}
args = nargs.concat(args);
var otp = spawnSync('node', args, options),
stdout = otp.stdout.toString(),
stderr = otp.stderr.toString(),
output = otp.output[0],
status = otp.status;
return {stdout: stdout, stderr: stderr, output: output, status: status};
}
describe('showdown cli', function () {
'use strict';
describe('without commands', function () {
it('should display help if no commands are specified', function () {
var proc = spawnCLI(null, [], {});
proc.status.should.equal(1);
proc.stderr.should.contain('CLI to Showdownjs markdown parser');
proc.stderr.should.contain('Usage:');
proc.stderr.should.contain('Options:');
proc.stderr.should.contain('Commands:');
proc.stdout.should.equal('');
});
describe('-h', function () {
it('should display help', function () {
var proc = spawnCLI(null, ['-h'], {});
proc.status.should.equal(0);
proc.stdout.should.contain('CLI to Showdownjs markdown parser');
proc.stdout.should.contain('Usage:');
proc.stdout.should.contain('Options:');
proc.stdout.should.contain('Commands:');
proc.stderr.should.equal('');
});
});
describe('-v', function () {
it('should display version', function () {
var proc = spawnCLI(null, ['-V'], {});
proc.status.should.equal(0);
proc.stdout.should.match(/^\d{1,2}\.\d{1,3}\.\d{1,3}/);
proc.stdout.should.match(/^(\d{1,2}\.\d{1,3}\.\d{1,3})/).and.capture(0).equals(packageJson.version);
proc.stderr.should.equal('');
});
});
});
describe('makehtml command', function () {
describe('makehtml without flags', function () {
it('should read from stdin and output to stdout', function () {
var proc = spawnCLI('makehtml', [], {
input: '**foo**',
encoding: 'utf-8'
});
proc.status.should.equal(0);
proc.stdout.should.equal('<p><strong>foo</strong></p>');
proc.stderr.should.not.equal('');
});
});
describe('makehtml -p', function () {
it('should enable a flavor', function () {
var proc = spawnCLI('makehtml', ['-p', 'github'], {
input: 'this is a :smile:', // test the emoji option as a proxy
encoding: 'utf-8'
});
proc.status.should.equal(0);
proc.stderr.should.contain('Enabling flavor github...');
proc.stdout.should.equal('<p>this is a 😄</p>');
//'Here in London'.should.match(/(here|there) in (\w+)/i).and.capture(1).equals('London');
});
it('should give an error if a flavor is not recognised', function () {
var proc = spawnCLI('makehtml', ['-p', 'foobar'], {
input: '**foo**',
encoding: 'utf-8'
});
proc.status.should.equal(1);
});
});
describe('makehtml -c', function () {
it('should not parse emoji if config option is not passed', function () {
var proc = spawnCLI('makehtml', [], {
input: 'this is a :smile:',
encoding: 'utf-8'
});
proc.status.should.equal(0);
proc.stderr.should.not.contain('Enabling option emoji');
proc.stdout.should.equal('<p>this is a :smile:</p>');
});
it('should enable a showdown option', function () {
var proc = spawnCLI('makehtml', ['-c', 'emoji'], {
input: 'this is a :smile:',
encoding: 'utf-8'
});
proc.status.should.equal(0);
proc.stderr.should.contain('Enabling option emoji');
proc.stdout.should.equal('<p>this is a 😄</p>');
});
it('should ignore unrecognized options', function () {
var proc = spawnCLI('makehtml', ['-c', 'foobar'], {
input: 'foo',
encoding: 'utf-8'
});
proc.status.should.equal(0);
proc.stderr.should.contain('Enabling option foobar');
proc.stdout.should.equal('<p>foo</p>');
});
});
describe('makehtml -m', function () {
it('should mute information', function () {
var proc = spawnCLI('makehtml', ['-m', '-i'], {input: '**foo**'});
proc.status.should.equal(0);
expect(proc.output).to.be.null; // jshint ignore:line
proc.stdout.should.equal('<p><strong>foo</strong></p>');
proc.stderr.should.equal('');
});
it('should mute everything, even errors', function () {
var proc = spawnCLI('makehtml', ['-m', '-i']);
proc.status.should.equal(1);
expect(proc.output).to.be.null; // jshint ignore:line
proc.stdout.should.equal('');
proc.stderr.should.equal('');
});
it('should not mute parsed html', function () {
var proc = spawnCLI('makehtml', ['-m', '-i'], {
input: '**foo**',
encoding: 'utf-8'
});
proc.status.should.equal(0);
proc.stdout.should.equal('<p><strong>foo</strong></p>');
proc.stderr.should.equal('');
});
});
describe('makehtml -q', function () {
it('should not display information', function () {
var proc = spawnCLI('makehtml', ['-q', '-i'], {input: '**foo**'});
proc.status.should.equal(0);
expect(proc.output).to.be.null; // jshint ignore:line
proc.stdout.should.equal('<p><strong>foo</strong></p>');
proc.stderr.should.match(/^\s*DONE!\s*$/);
});
it('should display errors', function () {
var proc = spawnCLI('makehtml', ['-q', '-i']);
proc.status.should.equal(1);
expect(proc.output).to.be.null; // jshint ignore:line
proc.stdout.should.equal('');
proc.stderr.should.match(/^ERROR:/);
});
it('should not mute parsed html', function () {
var proc = spawnCLI('makehtml', ['-q', '-i'], {
input: '**foo**',
encoding: 'utf-8'
});
proc.status.should.equal(0);
proc.stdout.should.equal('<p><strong>foo</strong></p>');
proc.stderr.should.match(/^\s*DONE!\s*$/);
});
});
describe('makehtml -i -o', function () {
it('should read from stdin and output to stdout', function () {
var proc = spawnCLI('makehtml', ['-i', '-o'], {
input: '**foo**',
encoding: 'utf-8'
});
proc.status.should.equal(0);
proc.stdout.should.equal('<p><strong>foo</strong></p>');
proc.stderr.should.not.equal('');
});
});
describe('makehtml -i <file> -o', function () {
it('should read from a file and output to stdout', function () {
var expectedOtp = fs.readFileSync('test/cli/basic.html', 'utf8').toString().trim(),
proc = spawnCLI('makehtml', ['-i', 'test/cli/basic.md'], {encoding: 'utf-8'});
proc.status.should.equal(0);
proc.stdout.should.equal(expectedOtp);
proc.stderr.should.not.equal('');
});
});
describe('makehtml -i -o <file>', function () {
it('should read from stdin and output to a file', function () {
execSync(cmd + ' makehtml -m -i -o .build/io1.html', {
encoding: 'utf8',
input: '**foo**'
});
var otp = fs.readFileSync('.build/io1.html', 'utf8').toString().trim(),
expectedOtp = '<p><strong>foo</strong></p>';
otp.trim().should.equal(expectedOtp);
});
});
describe('makehtml -i <file> -o <file>', function () {
it('should read from a file and output to a file', function () {
var expectedOtp = fs.readFileSync('test/cli/basic.html', 'utf8').toString().trim(),
proc = spawnCLI('makehtml', ['-i', 'test/cli/basic.md', '-o', '.build/io2.html'], {encoding: 'utf-8'}),
otp = fs.readFileSync('.build/io2.html', 'utf8').toString().trim();
otp.trim().should.equal(expectedOtp);
proc.stdout.should.not.equal(expectedOtp);
proc.stderr.should.equal('');
proc.status.should.equal(0);
});
});
describe('makehtml -a', function () {
it('should read from stdin and append to a file', function () {
fs.writeFileSync('.build/io3.html', '<p>foo</p>');
var expectedOtp = '<p>foo</p><p><strong>foo</strong></p>',
proc = spawnCLI('makehtml', ['-i', '-o', '.build/io3.html', '-a'], {
encoding: 'utf8',
input: '**foo**'
}),
otp = fs.readFileSync('.build/io3.html', 'utf8').toString().trim();
proc.status.should.equal(0);
otp.trim().should.equal(expectedOtp);
// since the output is to a file, messages are logged to stdout
proc.stdout.should.not.equal(expectedOtp);
// stderr should be empty
proc.stderr.should.equal('');
});
it('should ignore -a flag if -o <file> is missing', function () {
var expectedOtp = '<p><strong>foo</strong></p>',
proc = spawnCLI('makehtml', ['-a'], {encoding: 'utf8', input: '**foo**'});
proc.status.should.equal(0);
proc.stderr.should.not.equal('');
proc.stdout.should.equal(expectedOtp);
});
});
describe('makehtml -e', function () {
it('should load the extension', function () {
var expectedOtp = '<p><strong>bar</strong></p>',
extPath = path.resolve(__dirname + '/../mocks/mock-extension.js'),
proc = spawnCLI('makehtml', ['-i', '-o', '-e', extPath], {
encoding: 'utf8',
input: '**foo**'
});
proc.status.should.equal(0, 'Process exited with error state');
proc.stdout.trim().should.equal(expectedOtp);
});
});
});
});

View File

@ -0,0 +1,25 @@
/**
* Created by Estevao on 15-01-2015.
*/
describe('showdown.Converter', function () {
'use strict';
require('source-map-support').install();
require('chai').should();
var jsdom = require('jsdom'),
document = new jsdom.JSDOM('', {}).window.document, // jshint ignore:line
showdown = require('../../.build/showdown.js');
describe('makeMarkdown()', function () {
var converter = new showdown.Converter();
it('should parse a simple html string', function () {
var html = '<a href="/somefoo.html">a link</a>\n';
var md = '[a link](</somefoo.html>)';
converter.makeMarkdown(html, document).should.equal(md);
});
});
});

View File

@ -3,6 +3,7 @@ require('chai').should();
var expect = require('chai').expect,
showdown = require('../../.build/showdown.js');
describe('showdown.options', function () {
'use strict';
@ -34,21 +35,37 @@ describe('showdown.extension()', function () {
return extObjMock;
};
describe('should register', function () {
it('an extension object', function () {
describe('file loading', function () {
beforeEach(function () {
this.extension = require('../mocks/mock-extension');
});
it('should register an extension from a file', function () {
showdown.extension('mockextension').should.be.an('array');
showdown.extension('mockextension').should.eql([this.extension]);
});
afterEach(function () {
showdown.resetExtensions();
});
});
describe('objects', function () {
it('should register an extension object', function () {
showdown.extension('foo', extObjMock);
showdown.extension('foo').should.eql([extObjMock]);
showdown.resetExtensions();
});
it('an extension function', function () {
showdown.extension('foo', extObjFunc);
showdown.extension('foo').should.eql([extObjMock]);
showdown.resetExtensions();
it('should register an extension function', function () {
showdown.extension('bar', extObjFunc);
showdown.extension('bar').should.eql([extObjMock]);
});
it('a listener extension', function () {
showdown.extension('foo', {
it('should register a listener extension', function () {
showdown.extension('baz', {
type: 'listener',
listeners: {
foo: function (name, txt) {
@ -56,19 +73,16 @@ describe('showdown.extension()', function () {
}
}
});
showdown.resetExtensions();
});
});
describe('should refuse to register', function () {
it('a generic object', function () {
it('should refuse to register a generic object', function () {
var fn = function () {
showdown.extension('foo', {});
};
expect(fn).to.throw();
});
it('an extension with invalid type', function () {
it('should refuse to register an extension with invalid type', function () {
var fn = function () {
showdown.extension('foo', {
type: 'foo'
@ -77,7 +91,7 @@ describe('showdown.extension()', function () {
expect(fn).to.throw(/type .+? is not recognized\. Valid values: "lang\/language", "output\/html" or "listener"/);
});
it('an extension without regex or filter', function () {
it('should refuse to register an extension without regex or filter', function () {
var fn = function () {
showdown.extension('foo', {
type: 'lang'
@ -86,7 +100,7 @@ describe('showdown.extension()', function () {
expect(fn).to.throw(/extensions must define either a "regex" property or a "filter" method/);
});
it('a listener extension without a listeners property', function () {
it('should refuse to register a listener extension without a listeners property', function () {
var fn = function () {
showdown.extension('foo', {
type: 'listener'
@ -94,7 +108,13 @@ describe('showdown.extension()', function () {
};
expect(fn).to.throw(/Extensions of type "listener" must have a property called "listeners"/);
});
afterEach(function () {
showdown.resetExtensions();
});
});
});
describe('showdown.getAllExtensions()', function () {