diff --git a/.eslintrc.json b/.eslintrc.json index 2afad32..5027d33 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,4 +1,7 @@ { + "env": { + "es6": true + }, "rules": { "indent": [2, 2, {"SwitchCase": 1, "VariableDeclarator": 2}], "curly": [2, "all"], diff --git a/.github/workflows/browserstack.yml b/.github/workflows/browserstack.yml new file mode 100644 index 0000000..fbed2da --- /dev/null +++ b/.github/workflows/browserstack.yml @@ -0,0 +1,63 @@ +name: 'BrowserStack Test' + +on: + push: + branches: [ master, develop ] + pull_request: + branches: [ master, develop ] + +jobs: + ubuntu-job: + name: 'BrowserStack Test on Ubuntu' + runs-on: ubuntu-latest + steps: + - name: set up env vars + # Only the first line of commit msg + run: echo "COMMIT_MSG=$(printf "%s" "${{ github.event.head_commit.message }}" | head -n 1)" >> $GITHUB_ENV + + - name: '📦 Checkout the repository' + uses: actions/checkout@v2 + + - name: '🚚 Upgrade NPM' + run: npm install -g npm + + - name: '⚙ Setup Node.js v17.x' + uses: actions/setup-node@v2 + with: + node-version: 17.x + cache: 'npm' + + - name: '📖 Get current package version' + id: package-version + uses: martinbeentjes/npm-get-version-action@v1.1.0 + + - name: '📝 Print build version and commit msg' + run: 'printf "version: %s\n build:%s\n message:%s\n" "${{ steps.package-version.outputs.current-version}}" "${{ github.run_id }}" "$COMMIT_MSG"' + + - name: '📱 BrowserStack Env Setup' # Invokes the setup-env action + uses: browserstack/github-actions/setup-env@master + with: + username: ${{ secrets.BROWSERSTACK_USERNAME }} + access-key: ${{ secrets.BROWSERSTACK_ACCESSKEY }} + project-name: 'showdown' + build-name: ${{ steps.package-version.outputs.current-version}}-${{ github.run_id }} + + - name: '🚇 BrowserStack Local Tunnel Setup' # Invokes the setup-local action + uses: browserstack/github-actions/setup-local@master + with: + local-testing: start + local-identifier: random + + - name: '🚚 Install dependencies for CI' + run: npm ci + + - name: '🏗 Building src files for testing' + run: npx grunt concat:test + + - name: '✅ Running test on BrowserStack with Karma' + run: npx karma start karma.browserstack.js + + - name: '🛑 BrowserStackLocal Stop' # Terminating the BrowserStackLocal tunnel connection + uses: browserstack/github-actions/setup-local@master + with: + local-testing: stop diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index a8c4b50..3066b65 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -2,14 +2,12 @@ name: documentation on: push: - branches: + branches: - master paths: - 'mkdocs.yml' - 'docs/**' - '.github/workflows/docs.yml' - paths-ignore: - - 'README.md' jobs: build_docs: @@ -30,4 +28,4 @@ jobs: -H "Authorization: token ${TOKEN}" \ -H "Accept: application/vnd.github.v3+json" \ https://api.github.com/repos/${OWNER}/${REPO}/dispatches \ - -d '{ "event_type": "e: \"'"${COMMIT}"'\" by '"${COMMITTER}"'", "client_payload": { "source": "showdown" } }' \ No newline at end of file + -d '{ "event_type": "e: \"'"${COMMIT}"'\" by '"${COMMITTER}"'", "client_payload": { "source": "showdown" } }' diff --git a/.gitignore b/.gitignore index 56ba81a..e7f01d3 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ node_modules npm-debug.log /*.test.* +*.log diff --git a/.jshintignore b/.jshintignore index 54c5705..a003b6b 100644 --- a/.jshintignore +++ b/.jshintignore @@ -3,3 +3,4 @@ dist/**/*.js build/**/*.js src/options.js bin/* +/karma.browserstack.js diff --git a/.jshintrc b/.jshintrc index 3557d07..83563e0 100644 --- a/.jshintrc +++ b/.jshintrc @@ -19,7 +19,6 @@ "smarttabs": true, "onevar": true, "globals": { - "angular": true, "module": true, "define": true, "window": true, diff --git a/Gruntfile.js b/Gruntfile.js index 5d0cc45..1cc7853 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -8,6 +8,16 @@ module.exports = function (grunt) { require('quiet-grunt'); } + /** + * Load common tasks for legacy and normal tests + */ + grunt.loadNpmTasks('grunt-contrib-clean'); + grunt.loadNpmTasks('grunt-contrib-concat'); + grunt.loadNpmTasks('grunt-contrib-uglify'); + grunt.loadNpmTasks('grunt-mocha-test'); + grunt.loadNpmTasks('grunt-endline'); + grunt.loadNpmTasks('grunt-contrib-jshint'); + // Project configuration. var config = { pkg: grunt.file.readJSON('package.json'), @@ -124,40 +134,40 @@ module.exports = function (grunt) { } }, - simplemocha: { + mochaTest: { functional: { src: 'test/functional/**/*.js', options: { - globals: ['should'], timeout: 3000, ignoreLeaks: true, - reporter: 'spec' + reporter: 'spec', + require: ['test/bootstrap.js'] } }, unit: { src: 'test/unit/**/*.js', options: { - globals: ['should'], timeout: 3000, ignoreLeaks: true, - reporter: 'spec' + reporter: 'spec', + require: ['test/bootstrap.js'] } }, single: { options: { - globals: ['should'], timeout: 3000, ignoreLeaks: false, - reporter: 'spec' + reporter: 'spec', + require: ['test/bootstrap.js'] } }, cli: { src: 'test/unit/cli.js', options: { - globals: ['should'], timeout: 3000, ignoreLeaks: false, - reporter: 'spec' + reporter: 'spec', + require: ['test/bootstrap.js'] } } } @@ -165,16 +175,6 @@ module.exports = function (grunt) { grunt.initConfig(config); - /** - * Load common tasks for legacy and normal tests - */ - grunt.loadNpmTasks('grunt-contrib-clean'); - grunt.loadNpmTasks('grunt-contrib-concat'); - grunt.loadNpmTasks('grunt-contrib-uglify'); - grunt.loadNpmTasks('grunt-simple-mocha'); - grunt.loadNpmTasks('grunt-endline'); - grunt.loadNpmTasks('grunt-contrib-jshint'); - /** * Generate Changelog */ @@ -210,23 +210,23 @@ module.exports = function (grunt) { grunt.registerTask('single-test', function (file) { 'use strict'; grunt.config.merge({ - simplemocha: { + mochaTest: { single: { src: file } } }); - grunt.task.run(['lint', 'concat:test', 'simplemocha:single', 'clean']); + grunt.task.run(['lint', 'concat:test', 'mochaTest:single', 'clean']); }); /** * 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('test', ['clean', 'lint', 'concat:test', 'mochaTest:unit', 'mochaTest:functional', 'clean']); + grunt.registerTask('test-functional', ['concat:test', 'mochaTest:functional', 'clean']); + grunt.registerTask('test-unit', ['concat:test', 'mochaTest:unit', 'clean']); + grunt.registerTask('test-cli', ['clean', 'lint', 'concat:test', 'mochaTest:cli', 'clean']); grunt.registerTask('performance', ['concat:test', 'performancejs', 'clean']); grunt.registerTask('build', ['test', 'concat:dist', 'concat:cli', 'uglify:dist', 'uglify:cli', 'endline']); diff --git a/README.md b/README.md index 85a8173..1c4516e 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,9 @@ ![Build Status: Linux](https://github.com/showdownjs/showdown/actions/workflows/node.linux.yml/badge.svg) ![Build Status: Windows](https://github.com/showdownjs/showdown/actions/workflows/node.win.yml/badge.svg) +[![Browserstack Tests](https://automate.browserstack.com/badge.svg?badge_key=VTIvTDNqWVdaTHljbS9RNmYrcTBiL0Uxc3dkRDhaN1dPaXpPb2VOc1B2VT0tLU1Ib09kVjVzMjhFcHExbWFSWlJEV3c9PQ==--1fb92e1730e4a00630d17d533822de6403ca65ec)](https://automate.browserstack.com/public-build/VTIvTDNqWVdaTHljbS9RNmYrcTBiL0Uxc3dkRDhaN1dPaXpPb2VOc1B2VT0tLU1Ib09kVjVzMjhFcHExbWFSWlJEV3c9PQ==--1fb92e1730e4a00630d17d533822de6403ca65ec) [![npm version](https://badge.fury.io/js/showdown.svg)](http://badge.fury.io/js/showdown) [![Bower version](https://badge.fury.io/bo/showdown.svg)](http://badge.fury.io/bo/showdown) -[![Join the chat at https://gitter.im/showdownjs/showdown](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/showdownjs/showdown?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.me/tiviesantos) ------ diff --git a/TASKS.TODO.md b/TASKS.TODO.md index c9395f1..c353049 100644 --- a/TASKS.TODO.md +++ b/TASKS.TODO.md @@ -101,12 +101,12 @@ ## CLI - [ ] Refactor the CLI - [ ] **#381**: *Support for src and dst directories in showdown cli* -- [ ] **#584**: *Fails to read from stdin* -- [ ] **#554**: *CLI not working with jsdom v10* +- [X] **#584**: *Fails to read from stdin* +- [X] **#554**: *CLI not working with jsdom v10* ## Other stuff - [X] Regexp rewrite for more performance oompf -- [ ] Full unit testing +- [X] Full unit testing - [ ] Better error reporting ## Stuff that probably won't make it to v2.0 @@ -138,3 +138,9 @@ This should address: - [ ] Options - [ ] Extensions (and the new event system) - [ ] Cookbook (with stuff for backwards compatibility, specially regarding removed options) + +## Browser Testing + +- [X] Implement unit tests in Karma +- [ ] Implement functional tests in Karma +- [ ] Integrate with browserstack diff --git a/dist/showdown.js b/dist/showdown.js index 347181b..e746ab1 100644 --- a/dist/showdown.js +++ b/dist/showdown.js @@ -1,5 +1,5 @@ -;/*! showdown v 2.0.0 - 10-03-2022 */ -(function(){ +;/*! showdown v 2.0.0 - 10-03-2022 */ +(function(){ /** * Created by Tivie on 13-07-2015. */ @@ -202,7 +202,7 @@ function allOptionsOn () { } return ret; } - + /** * Created by Tivie on 06-01-2015. */ @@ -582,7 +582,7 @@ showdown.validateExtension = function (ext) { } return true; }; - + /** * showdownjs helper functions */ @@ -912,9 +912,10 @@ showdown.helper.splitAtIndex = function (str, index) { * Since it has a random component, subsequent calls to this function produce different results * * @param {string} mail + * @param {string} seed * @returns {string} */ -showdown.helper.encodeEmailAddress = function (mail) { +showdown.helper.encodeEmailAddress = function (mail, seed) { 'use strict'; var encode = [ function (ch) { @@ -2970,7 +2971,7 @@ showdown.helper.emojis = { 'trollface': '', 'showdown': '' }; - + /** * These are all the transformations that form block-level * tags like paragraphs, headers, and list items. @@ -3003,7 +3004,7 @@ showdown.subParser('makehtml.blockGamut', function (text, options, globals) { return text; }); - + showdown.subParser('makehtml.blockQuotes', function (text, options, globals) { 'use strict'; @@ -3046,7 +3047,7 @@ showdown.subParser('makehtml.blockQuotes', function (text, options, globals) { text = globals.converter._dispatch('makehtml.blockQuotes.after', text, options, globals).getText(); return text; }); - + /** * Process Markdown `
` blocks.
  */
@@ -3085,7 +3086,7 @@ showdown.subParser('makehtml.codeBlocks', function (text, options, globals) {
   text = globals.converter._dispatch('makehtml.codeBlocks.after', text, options, globals).getText();
   return text;
 });
-
+
 /**
  *
  *   *  Backtick quotes are used for  spans.
@@ -3134,7 +3135,7 @@ showdown.subParser('makehtml.codeSpans', function (text, options, globals) {
   text = globals.converter._dispatch('makehtml.codeSpans.after', text, options, globals).getText();
   return text;
 });
-
+
 /**
  * Create a full HTML document from the processed markdown
  */
@@ -3197,7 +3198,7 @@ showdown.subParser('makehtml.completeHTMLDocument', function (text, options, glo
   text = globals.converter._dispatch('makehtml.completeHTMLDocument.after', text, options, globals).getText();
   return text;
 });
-
+
 /**
  * Convert all tabs to spaces
  */
@@ -3231,7 +3232,7 @@ showdown.subParser('makehtml.detab', function (text, options, globals) {
   text = globals.converter._dispatch('makehtml.detab.after', text, options, globals).getText();
   return text;
 });
-
+
 showdown.subParser('makehtml.ellipsis', function (text, options, globals) {
   'use strict';
 
@@ -3247,7 +3248,7 @@ showdown.subParser('makehtml.ellipsis', function (text, options, globals) {
 
   return text;
 });
-
+
 /**
  * Turn emoji codes into emojis
  *
@@ -3275,7 +3276,7 @@ showdown.subParser('makehtml.emoji', function (text, options, globals) {
 
   return text;
 });
-
+
 /**
  * Smart processing for ampersands and angle brackets that need to be encoded.
  */
@@ -3299,7 +3300,7 @@ showdown.subParser('makehtml.encodeAmpsAndAngles', function (text, options, glob
   text = globals.converter._dispatch('makehtml.encodeAmpsAndAngles.after', text, options, globals).getText();
   return text;
 });
-
+
 /**
  * Returns the string, with after processing the following backslash escape sequences.
  *
@@ -3321,7 +3322,7 @@ showdown.subParser('makehtml.encodeBackslashEscapes', function (text, options, g
   text = globals.converter._dispatch('makehtml.encodeBackslashEscapes.after', text, options, globals).getText();
   return text;
 });
-
+
 /**
  * Encode/escape certain characters inside Markdown code runs.
  * The point is that in code, these characters are literals,
@@ -3345,7 +3346,7 @@ showdown.subParser('makehtml.encodeCode', function (text, options, globals) {
   text = globals.converter._dispatch('makehtml.encodeCode.after', text, options, globals).getText();
   return text;
 });
-
+
 /**
  * Within tags -- meaning between < and > -- encode [\ ` * _ ~ =] so they
  * don't conflict with their use in Markdown for code, italics and strong.
@@ -3372,7 +3373,7 @@ showdown.subParser('makehtml.escapeSpecialCharsWithinTagAttributes', function (t
   text = globals.converter._dispatch('makehtml.escapeSpecialCharsWithinTagAttributes.after', text, options, globals).getText();
   return text;
 });
-
+
 /**
  * Handle github codeblocks prior to running HashHTML so that
  * HTML contained within the codeblock gets escaped properly
@@ -3423,7 +3424,7 @@ showdown.subParser('makehtml.githubCodeBlocks', function (text, options, globals
 
   return globals.converter._dispatch('makehtml.githubCodeBlocks.after', text, options, globals).getText();
 });
-
+
 showdown.subParser('makehtml.hashBlock', function (text, options, globals) {
   'use strict';
   text = globals.converter._dispatch('makehtml.hashBlock.before', text, options, globals).getText();
@@ -3432,7 +3433,7 @@ showdown.subParser('makehtml.hashBlock', function (text, options, globals) {
   text = globals.converter._dispatch('makehtml.hashBlock.after', text, options, globals).getText();
   return text;
 });
-
+
 /**
  * Hash and escape  elements that should not be parsed as markdown
  */
@@ -3451,7 +3452,7 @@ showdown.subParser('makehtml.hashCodeTags', function (text, options, globals) {
   text = globals.converter._dispatch('makehtml.hashCodeTags.after', text, options, globals).getText();
   return text;
 });
-
+
 showdown.subParser('makehtml.hashElement', function (text, options, globals) {
   'use strict';
 
@@ -3471,7 +3472,7 @@ showdown.subParser('makehtml.hashElement', function (text, options, globals) {
     return blockText;
   };
 });
-
+
 showdown.subParser('makehtml.hashHTMLBlocks', function (text, options, globals) {
   'use strict';
   text = globals.converter._dispatch('makehtml.hashHTMLBlocks.before', text, options, globals).getText();
@@ -3571,7 +3572,7 @@ showdown.subParser('makehtml.hashHTMLBlocks', function (text, options, globals)
   text = globals.converter._dispatch('makehtml.hashHTMLBlocks.after', text, options, globals).getText();
   return text;
 });
-
+
 /**
  * Hash span elements that should not be parsed as markdown
  */
@@ -3630,7 +3631,7 @@ showdown.subParser('makehtml.unhashHTMLSpans', function (text, options, globals)
   text = globals.converter._dispatch('makehtml.unhashHTMLSpans.after', text, options, globals).getText();
   return text;
 });
-
+
 /**
  * Hash and escape 
 elements that should not be parsed as markdown
  */
@@ -3650,7 +3651,7 @@ showdown.subParser('makehtml.hashPreCodeTags', function (text, options, globals)
   text = globals.converter._dispatch('makehtml.hashPreCodeTags.after', text, options, globals).getText();
   return text;
 });
-
+
 showdown.subParser('makehtml.headers', function (text, options, globals) {
   'use strict';
 
@@ -3777,7 +3778,7 @@ showdown.subParser('makehtml.headers', function (text, options, globals) {
   text = globals.converter._dispatch('makehtml.headers.after', text, options, globals).getText();
   return text;
 });
-
+
 /**
  * Turn Markdown horizontal rule shortcuts into 
tags. * @@ -3796,7 +3797,7 @@ showdown.subParser('makehtml.horizontalRule', function (text, options, globals) text = globals.converter._dispatch('makehtml.horizontalRule.after', text, options, globals).getText(); return text; }); - + /** * Turn Markdown image shortcuts into tags. */ @@ -3907,7 +3908,7 @@ showdown.subParser('makehtml.images', function (text, options, globals) { text = globals.converter._dispatch('makehtml.images.after', text, options, globals).getText(); return text; }); - + showdown.subParser('makehtml.italicsAndBold', function (text, options, globals) { 'use strict'; @@ -3974,7 +3975,7 @@ showdown.subParser('makehtml.italicsAndBold', function (text, options, globals) text = globals.converter._dispatch('makehtml.italicsAndBold.after', text, options, globals).getText(); return text; }); - + //// // makehtml/links.js // Copyright (c) 2018 ShowdownJS @@ -4403,7 +4404,7 @@ showdown.subParser('makehtml.italicsAndBold', function (text, options, globals) return text; }); })(); - + /** * Form HTML ordered (numbered) and unordered (bulleted) lists. */ @@ -4665,7 +4666,7 @@ showdown.subParser('makehtml.lists', function (text, options, globals) { text = globals.converter._dispatch('makehtml.lists.after', text, options, globals).getText(); return text; }); - + /** * Parse metadata at the top of the document */ @@ -4720,7 +4721,7 @@ showdown.subParser('makehtml.metadata', function (text, options, globals) { text = globals.converter._dispatch('makehtml.metadata.after', text, options, globals).getText(); return text; }); - + /** * Remove one level of line-leading tabs or spaces */ @@ -4738,7 +4739,7 @@ showdown.subParser('makehtml.outdent', function (text, options, globals) { text = globals.converter._dispatch('makehtml.outdent.after', text, options, globals).getText(); return text; }); - + /** * */ @@ -4809,7 +4810,7 @@ showdown.subParser('makehtml.paragraphs', function (text, options, globals) { text = text.replace(/\n+$/g, ''); return globals.converter._dispatch('makehtml.paragraphs.after', text, options, globals).getText(); }); - + /** * Run extension */ @@ -4830,7 +4831,7 @@ showdown.subParser('makehtml.runExtension', function (ext, text, options, global return text; }); - + /** * These are all the transformations that occur *within* block-level * tags like paragraphs, headers, and list items. @@ -4881,7 +4882,7 @@ showdown.subParser('makehtml.spanGamut', function (text, options, globals) { text = globals.converter._dispatch('makehtml.spanGamut.after', text, options, globals).getText(); return text; }); - + showdown.subParser('makehtml.strikethrough', function (text, options, globals) { 'use strict'; @@ -4893,7 +4894,7 @@ showdown.subParser('makehtml.strikethrough', function (text, options, globals) { return text; }); - + /** * Strips link definitions from text, stores the URLs and titles in * hash references. @@ -4954,7 +4955,7 @@ showdown.subParser('makehtml.stripLinkDefinitions', function (text, options, glo return text; }); - + showdown.subParser('makehtml.tables', function (text, options, globals) { 'use strict'; @@ -5098,7 +5099,7 @@ showdown.subParser('makehtml.tables', function (text, options, globals) { return text; }); - + showdown.subParser('makehtml.underline', function (text, options, globals) { 'use strict'; @@ -5131,7 +5132,7 @@ showdown.subParser('makehtml.underline', function (text, options, globals) { return text; }); - + /** * Swap back in all the special characters we've hidden. */ @@ -5147,7 +5148,7 @@ showdown.subParser('makehtml.unescapeSpecialChars', function (text, options, glo text = globals.converter._dispatch('makehtml.unescapeSpecialChars.after', text, options, globals).getText(); return text; }); - + showdown.subParser('makeMarkdown.blockquote', function (node, globals) { 'use strict'; @@ -5170,13 +5171,13 @@ showdown.subParser('makeMarkdown.blockquote', function (node, globals) { txt = '> ' + txt.split('\n').join('\n> '); return txt; }); - + showdown.subParser('makeMarkdown.break', function () { 'use strict'; return ' \n'; }); - + showdown.subParser('makeMarkdown.codeBlock', function (node, globals) { 'use strict'; @@ -5184,13 +5185,13 @@ showdown.subParser('makeMarkdown.codeBlock', function (node, globals) { num = node.getAttribute('precodenum'); return '```' + lang + '\n' + globals.preList[num] + '\n```'; }); - + showdown.subParser('makeMarkdown.codeSpan', function (node) { 'use strict'; return '`' + node.innerHTML + '`'; }); - + showdown.subParser('makeMarkdown.emphasis', function (node, globals) { 'use strict'; @@ -5206,7 +5207,7 @@ showdown.subParser('makeMarkdown.emphasis', function (node, globals) { } return txt; }); - + showdown.subParser('makeMarkdown.header', function (node, globals, headerLevel) { 'use strict'; @@ -5224,13 +5225,13 @@ showdown.subParser('makeMarkdown.header', function (node, globals, headerLevel) } return txt; }); - + showdown.subParser('makeMarkdown.hr', function () { 'use strict'; return '---'; }); - + showdown.subParser('makeMarkdown.image', function (node) { 'use strict'; @@ -5249,7 +5250,7 @@ showdown.subParser('makeMarkdown.image', function (node) { } return txt; }); - + showdown.subParser('makeMarkdown.input', function (node, globals) { 'use strict'; @@ -5266,7 +5267,7 @@ showdown.subParser('makeMarkdown.input', function (node, globals) { } return txt; }); - + showdown.subParser('makeMarkdown.links', function (node, globals) { 'use strict'; @@ -5287,7 +5288,7 @@ showdown.subParser('makeMarkdown.links', function (node, globals) { } return txt; }); - + showdown.subParser('makeMarkdown.list', function (node, globals, type) { 'use strict'; @@ -5319,7 +5320,7 @@ showdown.subParser('makeMarkdown.list', function (node, globals, type) { return txt.trim(); }); - + showdown.subParser('makeMarkdown.listItem', function (node, globals) { 'use strict'; @@ -5345,7 +5346,7 @@ showdown.subParser('makeMarkdown.listItem', function (node, globals) { return listItemTxt; }); - + showdown.subParser('makeMarkdown.node', function (node, globals, spansOnly) { @@ -5474,7 +5475,7 @@ showdown.subParser('makeMarkdown.node', function (node, globals, spansOnly) { return txt; }); - + showdown.subParser('makeMarkdown.paragraph', function (node, globals) { 'use strict'; @@ -5492,14 +5493,14 @@ showdown.subParser('makeMarkdown.paragraph', function (node, globals) { return txt; }); - + showdown.subParser('makeMarkdown.pre', function (node, globals) { 'use strict'; var num = node.getAttribute('prenum'); return '
' + globals.preList[num] + '
'; }); - + showdown.subParser('makeMarkdown.strikethrough', function (node, globals) { 'use strict'; @@ -5515,7 +5516,7 @@ showdown.subParser('makeMarkdown.strikethrough', function (node, globals) { } return txt; }); - + showdown.subParser('makeMarkdown.strong', function (node, globals) { 'use strict'; @@ -5531,7 +5532,7 @@ showdown.subParser('makeMarkdown.strong', function (node, globals) { } return txt; }); - + showdown.subParser('makeMarkdown.table', function (node, globals) { 'use strict'; @@ -5602,7 +5603,7 @@ showdown.subParser('makeMarkdown.table', function (node, globals) { return txt.trim(); }); - + showdown.subParser('makeMarkdown.tableCell', function (node, globals) { 'use strict'; @@ -5618,7 +5619,7 @@ showdown.subParser('makeMarkdown.tableCell', function (node, globals) { } return txt.trim(); }); - + showdown.subParser('makeMarkdown.txt', function (node) { 'use strict'; @@ -5662,7 +5663,7 @@ showdown.subParser('makeMarkdown.txt', function (node) { return txt; }); - + /** * Created by Estevao on 31-05-2015. */ @@ -6265,7 +6266,7 @@ showdown.Converter = function (converterOptions) { metadata.raw = raw; }; }; - + var root = this; // AMD Loader @@ -6283,6 +6284,6 @@ if (typeof define === 'function' && define.amd) { } else { root.showdown = showdown; } -}).call(this); +}).call(this); -//# sourceMappingURL=showdown.js.map +//# sourceMappingURL=showdown.js.map diff --git a/docs/available-options.md b/docs/available-options.md new file mode 100644 index 0000000..9cbc3c0 --- /dev/null +++ b/docs/available-options.md @@ -0,0 +1,773 @@ +!!! warning "" + Starting from the version `1.6.0` and earlier, all the options are `disabled` by default in the cli tool. + +### backslashEscapesHTMLTags + +Support escaping of HTML tags. + +* type: `boolean` +* default value: `false` +* introduced in: `1.7.2` + +=== "input" + + ```html + \
foo\
+ ``` + +=== "output (value is `true`)" + + ```html +

<div>foo</div>

+ ``` + +### completeHTMLDocument + +Output a complete HTML document, including ``, ``, and `` tags instead of an HTML fragment. + +* type: `boolean` +* default value: `false` +* introduced in: `1.8.5` + +### customizedHeaderId + +Set custom ID for a heading. + +!!! warning "" + This option can be overridden with the [`noHeaderId`](#noheaderid) option. + +* type: `boolean` +* default value: `false` +* introduced in: `1.7.0` + +=== "code" + + ```html + ## Sample heading {mycustomid} + ``` + +=== "output" + + ```html +

This is a heading

+ ``` + +!!! hint "" + For better readability and human-friendliness of the heading IDs, it is also recommended to set the [`ghCompatibleHeaderId`](#ghcompatibleheaderid) option to `true`. + +### disableForced4SpacesIndentedSublists + +Disable the rule of 4 spaces to indent sub-lists. If enabled, this option effectively reverts to the old behavior where you can indent sub-lists with 2 or 3 spaces. + +* type: `boolean` +* default value: `false` +* introduced in: `1.5.0` + +=== "input" + + ``` + - one + - two + + ... + + - one + - two + ``` + +=== "output (value is `false`)" + + ```html +
    +
  • one
  • +
  • two
  • +
+

...

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

...

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

this is a :smile: emoji

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

this is a 😄 emoji

+ ``` + +!!! hint "Full list of supported emojies" + + Check the [Showdown Wiki](https://github.com/showdownjs/showdown/wiki/Emojis#emoji-list) for a full list of supported emojies. + +### encodeEmails + +Enable automatic obfuscation of email addresses. During this process, email addresses are encoded via Character Entities, transforming ASCII email addresses into their equivalent decimal entities. + +* type: `boolean` +* default value: `false` +* introduced in: `1.6.1` + +=== "input" + + ``` + + ``` + +=== "output (value is `false`)" + + ```html + myself@example.com + ``` + +=== "output (value is `true`)" + + ```html + myself@example.com + ``` + +### excludeTrailingPunctuationFromURLs + +Exclude trailing punctuation from autolinked URLs: `.` `!` `?` `(` `)` + +This option applies only to links generated by [`simplifiedAutoLink`](#simplifiedautolink). + +* type: `boolean` +* default value: `false` +* introduced in: `1.5.1` + +=== "input" + + ``` + check this link www.google.com. + ``` + +=== "output (value is `false`)" + + ```html +

check this link www.google.com.

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

check this link www.google.com.

+ ``` + +### ghCodeBlocks + +Enable support for GFM code block style syntax (fenced codeblocks). + +* type: `boolean` +* default value: `true` +* introduced in: `0.3.1` + +=== "example" + + ``` + ``` + some code here + ``` + ``` + +### ghCompatibleHeaderId + +Generate heading IDs compatible with GitHub style: spaces are replaced with dashes, and certain non-alphanumeric chars are removed. + +!!! warning "" + This option can be overridden with the [`noHeaderId`](#noheaderid) option. + +* type: `boolean` +* default value: `false` +* introduced in: `1.5.5` + +=== "input" + + ``` + # This is a heading with @#$% + ``` + +=== "output (value is `false`)" + + ```html +

This is a heading

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

This is a heading with @#$%

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

hello there @tivie

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

hello there @tivie

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

hello there @tivie

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

hello there @tivie

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

This is a heading

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

This is a heading

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

some text withunderscoresin the middle

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

some text with__underscores__in the middle

+ ``` + +### metadata + +Enable support for document metadata (front-matter). You can define metadata at the top of a document between `««« »»»` or `--- ---` symbols. + +* type: `boolean` +* default value: `false` +* introduced in: `1.8.5` + +=== "input" + + ```js + let ref = `referenced value`; + + var markdown = ` + --- + first: Lorem + second: Ipsum + ref_variable: ${ref} + --- + ` + + var conv = new showdown.Converter({metadata: true}); + var html = conv.makeHtml(markdown); + var metadata = conv.getMetadata(); + ``` + +=== "output (value is `true`)" + + ```js + // console.log(metadata) + { + first: 'Lorem', + second: 'Ipsum', + ref_variable: 'referenced value' + } + ``` + +### noHeaderId + +Disable automatic generation of heading IDs. + +!!! warning "" + Setting the option to `true` overrides the following options: + + * [`prefixHeaderId`](#prefixheaderid) + * [`customizedHeaderId`](#customizedheaderid) + * [`ghCompatibleHeaderId`](#ghcompatibleheaderid) + +* type: `boolean` +* default value: `false` +* introduced in: `1.1.0` + +=== "input" + + ``` + # This is a heading + ``` + +=== "output (value is `false`)" + + ```html +

This is a heading

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

This is a heading

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

This is a heading

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

This is a heading

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

This is a heading

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

heading

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

#heading

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

a line + wrapped in two

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

a line
+ wrapped in two

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

Lorem ipsum www.google.com

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

Lorem ipsum www.google.com

+ ``` + +### smartIndentationFix + +Resolve indentation problems related to ES6 template strings in the midst of indented code. + +* type: `boolean` +* default value: `false` +* introduced in: `1.4.2` + +### smoothLivePreview + +Resolve an awkward effect when a paragraph is followed by a list. This effect appears on some circumstances, in live preview editors. + +* type: `boolean` +* default value: `false` +* introduced in: `1.2.1` + +!!! example "awkward effect" + + ![](http://i.imgur.com/YQ9iHTL.gif​) + +### splitAdjacentBlockquotes + +Split adjacent blockquote blocks. + +* type: `boolean` +* default value: `false` +* introduced in: `1.8.6` + +=== "input" + + ``` + > Quote #1 + >> Sub-quote 1 + + > Quote #2 + >> Sub-quote 2 + ``` + +=== "output (value is `false`)" + + ```html +
+

Quote #1

+
+

Sub-quote 1

+
+

Quote #2

+
+

Sub-quote 2

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

Quote #1

+
+

Sub-quote 1

+
+
+
+

Quote #2

+
+

Sub-quote 2

+
+
+ ``` + +### strikethrough + +Enable support for strikethrough (``). + +* type: `boolean` +* default value: `false` +* introduced in: `1.2.0` + +=== "input" + + ``` + ~~strikethrough~~ + ``` + +=== "output (value is `true`)" + + ```html + strikethrough + ``` + +### tables + +Enable support for tables syntax. + +* type: `boolean` +* default value: `false` +* introduced in: `1.2.0` + +=== "example" + + ``` + | h1 | h2 | h3 | + |:------|:-------:|--------:| + | 100 | [a][1] | ![b][2] | + | *foo* | **bar** | ~~baz~~ | + ``` + +### tablesHeaderId + +Generate automatic IDs for table headings. Works only when [`tables: true`](#tables). + +* type: `boolean` +* default value: `false` +* introduced in: `1.2.0` + +### tasklists + +Enable support for GitHub style tasklists. + +* type: `boolean` +* default value: `false` +* introduced in: `1.2.0` + +=== "example" + + ``` + - [x] This task is done + - [ ] This task is still pending + ``` + +### underline + +Enable support for underline. If enabled, underscores will no longer be parsed as `` and ``. + +* type: `boolean` +* default value: `false` +* status: `Experimental` + +=== "example" + + ``` + __underlined word__ // double underscores + + ___underlined word___ // triple underscores + ``` diff --git a/docs/cli.md b/docs/cli.md new file mode 100644 index 0000000..ddda916 --- /dev/null +++ b/docs/cli.md @@ -0,0 +1,153 @@ +Showdown comes bundled with a Command-line interface (CLI) tool that allows you to run Showdown converter from the command line. + +## Requirements + +* [Node.js](https://nodejs.org/en/) + +## Quick start guide + +1. Check that Showdown CLI is accessible. + + * If you installed Showdown globally via `npm install showdown -g`, you can access the CLI tool help by typing `showdown -h` in the command line: + + === "input" + + ```sh + showdown -h + ``` + + === "output" + + ``` + Usage: showdown [options] + + CLI to Showdownjs markdown parser v3.0.0-alpha + + Options: + -V, --version output the version number + -q, --quiet Quiet mode. Only print errors + -m, --mute Mute mode. Does not print anything + -h, --help display help for command + + Commands: + makehtml [options] Converts markdown into html + help [command] display help for command + ``` + + * If you installed Showdown locally via `npm install showdown`, open the folder where Showdown is installed, and type `node ./bin/showdown.js -h` in the command line: + + === "input" + + ```sh + node ./bin/showdown.js -h + ``` + + === "output" + + ``` + Usage: showdown [options] + + CLI to Showdownjs markdown parser v3.0.0-alpha + + Options: + -V, --version output the version number + -q, --quiet Quiet mode. Only print errors + -m, --mute Mute mode. Does not print anything + -h, --help display help for command + + Commands: + makehtml [options] Converts markdown into html + help [command] display help for command + ``` + +1. Use `makehtml` command to convert your document to HTML. For example: + + !!! example "Convert `foo.md` into `bar.html`" + + ```sh + showdown makehtml -i foo.md -o bar.html + ``` + +## Commands + +### `makehtml` + +Convert a Markdown input into HTML. + +**Usage** + +```sh +showdown makehtml [options] +``` + +#### Options + +###### `-i / --input` + +* Short format: `-i` +* Alias: `--input` +* Description: Input source. Usually a `.md` file. If omitted or empty, reads from `stdin`. +* Examples: + + !!! example "" + + ```sh + // Read from stdin and output to stdout + showdown makehtml -i + + // Read from the foo.md file and output to stdout + showdown makehtml --input foo.md + ``` + +###### `-o/--output` + +* Short format: `-o` +* Alias: `--output` +* Description: Output target. Usually a `.html` file. If omitted or empty, writes to `stdout`. +* Example: + + !!! example "" + + ```sh + // Read from the foo.md file and output to bar.html + showdown makehtml -i foo.md -o bar.html + ``` + +###### `-a/--append` + +* Short format: `-a` +* Alias: `--append` +* Description: Append data to output instead of overwriting. +* Example: + + !!! example "" + + ```sh + showdown makehtml -a + ``` + +###### `-u/--encoding` + +* Short format: `-u` +* Alias: `--encoding` +* Description: Specify the input encoding. +* Example: + + !!! example "" + + ```sh + showdown makehtml -u UTF8 + ``` + +###### `-e/--extensions` + +* Short format: `-e` +* Alias: `--extension` +* Description: Load the specified extension(s). Should be valid path(s) to Node-compatible extensions. +* Example: + + !!! example "" + + ```sh + showdown makehtml -e ~/twitter.js -e ~/youtube.js + ``` \ No newline at end of file diff --git a/docs/configuration.md b/docs/configuration.md new file mode 100644 index 0000000..760a97d --- /dev/null +++ b/docs/configuration.md @@ -0,0 +1,60 @@ +You can change Showdown's default behavior via options. + +## Set option + +### Globally + +Setting an option globally affects all Showdown instances. + +```js +showdown.setOption('optionKey', 'value'); +``` + +### Locally + +Setting an option locally affects the specified Converter object only. You can set local options via: + +=== "Constructor" + + ```js + var converter = new showdown.Converter({optionKey: 'value'}); + ``` + +=== "setOption() method" + + ```js + var converter = new showdown.Converter(); + converter.setOption('optionKey', 'value'); + ``` + +## Get option + +Showdown provides both local and global methods to retrieve previously set options: + +=== "getOption()" + + ```js + // Global + var myOption = showdown.getOption('optionKey'); + + //Local + var myOption = converter.getOption('optionKey'); + ``` + +=== "getOptions()" + + ```js + // Global + var showdownGlobalOptions = showdown.getOptions(); + + //Local + var thisConverterSpecificOptions = converter.getOptions(); + ``` + +### Get default options + +You can get Showdown's default options with: + +```js +var defaultOptions = showdown.getDefaultOptions(); +``` \ No newline at end of file diff --git a/docs/create-extension.md b/docs/create-extension.md new file mode 100644 index 0000000..d087a43 --- /dev/null +++ b/docs/create-extension.md @@ -0,0 +1,182 @@ +A Showdown extension is a function that returns an array of language or outputs extensions (henceforth called "sub-extensions"). + +```js +var myext = function () { + var myext1 = { + type: 'lang', + regex: /markdown/g, + replace: 'showdown' + }; + var myext2 = { + /* extension code */ + }; + return [myext1, myext2]; +} +``` + +Each sub-extension (`myext1` and `myext2` in the example above) should be an object that defines the behavior of the corresponding sub-extension. + +## Sub-extension object properties + +A sub-extension object should have a [`type` property](#type) that defines the type of the sub-extension, and either [`regex` and `replace` properties](#regex-and-replace) or a [`filter` property](#filter). + +### Type + +**Type** is a **required** property that defines the nature of the corresponding sub-extensions. It takes one of the two values: + +* **`lang`**: language extension to add new Markdown syntax to Showdown. + + `lang` extensions have the **highest priority** in the subparser order, so they are called after [escaping and normalizing](#escape-and-normalization) the input text and before calling any other subparser (or extension). + + !!! example "When to use `lang` type" + + For example, if you want the `^^youtube http://www.youtube.com/watch?v=oHg5SJYRHA0` syntax to automatically be rendered as an embedded YouTube video. + +* **`output`**: output extension (or modifier) to alter the HTML output generated by Showdown. + + `output` extensions have the **lowest priority** in the subparser order, so they are called right before the cleanup step and after calling all other subparsers. + + !!! example "When to use `output` type" + + For example, if you want the `
` to become `
`. + +### Regex and replace + +`regex`/`replace` properties are similar to the Javascript's `string.replace` function and work the same way: + +* `regex`: a `string` or a `RegExp` object. + + If `regex` is a `string`, it will automatically be assigned a `g` (global) modifier, that is, all matches of that string will be replaced. + +* `replace` a `string` or a `function`. + + If `replace` is a `string`, you can use the `$1` syntax for group substitution, exactly as if it were making use of `string.replace`. + +!!! example "Regex and replace example" + + In this example, all the occurrences of `markdown` will be replaced with `showndown`. + + ```js + var myext = { + type: 'lang', + regex: /markdown/g, + replace: 'showdown' + }; + ``` + +### Filter + +Alternately, if you'd like to have more control over the modification process, you can use `filter` property. + +This property should be used as a function that acts as a callback. The callback should receive the following parameters: + +1. `text`: the source text within the Showdown's engine. +1. `converter`: the full instance of the current Showdown's converter object. +1. `options`: the options used to initialize the converter + +!!! warning "" + The filter function **should return the transformed text**. If it doesn't, it will fail **silently** and return an empty output. + +!!! example "Filter example" + + ```js + var myext = { + type: 'lang', + filter: function (text, converter, options) { + // ... do stuff to text ... + return text; + } + }; + ``` + +!!! warning "Use `filter` with care" + + Although Filter extensions are more powerful, they have a few pitfalls that you should keep in mind before using them, especially regarding the `converter` parameter. + + Since the `converter` parameter passed to the filter function is the fully initialized instance, any change made to it will be propagated outside the scope of the filter function and will remain there until a new converter instance is created. So, **it is not recommended to make ANY change to the converter object**. + + Another aspect is that if you call the `converter` recursively, it will call your extension itself at some point. It may lead to infinite recursion in some circumstances, and it's up to you to prevent this. A simple solution is to place a kind of safeguard to disable your extension if it's called more than x times: + + ```js + var x = 0; + var myext = { + type: 'lang', + filter: function (text, converter) { + if (x < 3) { + ++x; + someSubText = converter.makeHtml(someSubText); + } + } + }; + ``` + +## Register an extension + + +To let Showdown know what extensions are available, you need to register them in the Showdown global object. + +To register an extension, call the `showdown.extension` function with two parameters: the first one is the extension name; the second one is the actual extension. + +```js +showdown.extension('myext', myext); +``` + +## Test an extension + +The Showdown test runner is configured to automatically test cases for extensions. + +To add test cases for an extension: + +1. Create a new folder under `./test/extensions` that matches with the name of the `.js` file in `./src/extensions`. +1. Place any test cases into the filter using the `md/html` format. These cases will automatically be executed when running tests. + +## Additional information + +### Escape and normalization + +Showdown performs the following escape/normalization: + +* Replaces `¨` (trema) with `¨T` +* Replaces `$` (dollar sign) with `¨D` +* Normalizes line endings (`\r`, `\r\n` are converted into `\n`) +* Uses `\r` as a char placeholder + +!!! note "" + This only applies to **language extensions** since these chars are unescaped before output extensions are run. + +!!! warning "" + + Keep in mind that these modifications happen **before language extensions** are run, so if your extension relies on any of those chars, you have to make the appropriate adjustments. + + +### Implementation concerns + +One of the concerns is maintaining both client-side and server-side compatibility. You can do this with a few lines of boilerplate code.: + +```js +(function (extension) { + if (typeof showdown !== 'undefined') { + // global (browser or node.js global) + extension(showdown); + } else if (typeof define === 'function' && define.amd) { + // AMD + define(['showdown'], extension); + } else if (typeof exports === 'object') { + // Node, CommonJS-like + module.exports = extension(require('showdown')); + } else { + // showdown was not found so an error is thrown + throw Error('Could not find showdown library'); + } +}(function (showdown) { + // loading extension into showdown + showdown.extension('myext', function () { + var myext = { /* ... actual extension code ... */ }; + return [myext]; + }); +})); +``` + +In the code above, the extension definition is wrapped in a self-executing function to prevent pollution of the global scope. It has another benefit of creating several scope layers that can be useful for interaction between sub-extensions global-wise or local-wise. + +It is also loaded conditionally to make it compatible with different loading mechanisms (such as browser, CommonJS, or AMD). diff --git a/docs/extensions.md b/docs/extensions.md new file mode 100644 index 0000000..320cefa --- /dev/null +++ b/docs/extensions.md @@ -0,0 +1,36 @@ +Showdown allows you to load additional functionality via extensions. You can find a list of known Showdown extensions [here][ext-wiki]. + +You can also check the [boilerplate repo][boilerplate-repo], to create your own extension(s). + +## Usage + +=== "Server-side" + + ```js + // Using a bundled extension + var showdown = require('showdown'); + var converter = new showdown.Converter({ extensions: ['twitter'] }); + + // Using a custom extension + var mine = require('./custom-extensions/mine'); + var converter = new showdown.Converter({ extensions: ['twitter', mine] }); + ``` + +=== "Client-side" + + ```js + + + + ``` + +=== "CLI" + + In the CLI tool, use the [`-e` flag](/cli/#-e-extensions) to load an extension. + + ```sh + showdown -e twitter -i foo.md -o bar.html + ``` + +[ext-wiki]: https://github.com/showdownjs/showdown/wiki/extensions +[boilerplate-repo]: https://github.com/showdownjs/extension-boilerplate \ No newline at end of file diff --git a/docs/flavors.md b/docs/flavors.md new file mode 100644 index 0000000..0850735 --- /dev/null +++ b/docs/flavors.md @@ -0,0 +1,23 @@ +## Overview + +You can use _flavors_ (or presets) to set the preferred options automatically. In this way, Showdown behaves like popular Markdown flavors. + +Currently, the following flavors are available: + + * `original`: Original Markdown flavor as in [John Gruber's spec](https://daringfireball.net/projects/markdown/) + * `vanilla`: Showdown base flavor (v1.3.1 onwards) + * `github`: [GitHub Flavored Markdown, or GFM](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax) + +## Set flavor + +=== "Globally" + + ```js + showdown.setFlavor('github'); + ``` + +=== "Locally" + + ```js + converter.setFlavor('github'); + ``` \ No newline at end of file diff --git a/docs/integrations.md b/docs/integrations.md new file mode 100644 index 0000000..bc85664 --- /dev/null +++ b/docs/integrations.md @@ -0,0 +1,20 @@ +## AngularJS + +ShowdownJS project provides seamless integration with AngularJS via a plugin. + +Check [`ng-showdown`](https://github.com/showdownjs/ngShowdown) repository for more information. + +## TypeScript + +If you're using TypeScript, you may want to use the types from the [DefinitelyTyped][definitely-typed] repository. + +## SystemJS/JSPM + +To integrate ShowdownJS with SystemJS, you can use a third-party [system-md plugin](https://github.com/guybedford/system-md). + +## Vue.js + +To use ShowdownJS as a Vue component, you can check [vue-showdown](https://vue-showdown.js.org/). + + +[definitely-typed]: https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/showdown \ No newline at end of file diff --git a/docs/quickstart.md b/docs/quickstart.md index 30e6f86..1f47fed 100644 --- a/docs/quickstart.md +++ b/docs/quickstart.md @@ -94,6 +94,11 @@ Once installed, you can use Showndown according to the chosen method:

hello, markdown!

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

hello you

+
+``` + +After parsing with Markdown, the first `>` on the second line disappears because it was the blockquote marker in the Markdown blockquote syntax. As a result, you’ve got a link containing an XSS attack! + +Did Markdown generate the HTML? No, the HTML was already in plain sight in the input. The XSS filter couldn’t catch it because the input doesn’t follow HTML rules: it’s a mix of Markdown and HTML, and the filter doesn’t know a dime about Markdown. + +## Mitigate XSS + +So, is it all lost? Not really. The answer is not to filter the *input* but rather the *output*. After the *input* text is converted into full-fledged HTML, you can reliably apply the correct XSS filters to remove any dangerous or malicious content. + +Also, client-side validations are not reliable. It should be a given, but in case you're wondering, you should (almost) never trust data sent by the client. If there's some critical operation you must perform on the data (such as XSS filtering), you should do it *SERVER-SIDE* not client-side. + +HTML XSS filtering libraries are useful here since they prevent most of the attacks. However, you should not use them blindly: a library can't predict all the contexts and situations your application may face. + +## Conclusion + +Showdown tries to convert the input text as closely as possible, without any concerns for XSS attacks or malicious intent. So, the basic rules are: + +* **removing HTML entities from Markdown does not prevent XSS**. Markdown syntax can generate XSS attacks. +* **XSS filtering should be done after Showdown has processed input, not before or during**. If you filter before, it will break some of Markdown’s features and will leave security holes. +* **perform the necessary filtering server-side, not client-side**. XSS filtering libraries are useful but should not be used blindly. + +## Disclaimer + +This page is based on the excellent article: ["Markdown and XSS"][1] by [Michel Fortin][2] + +[1]: https://michelf.ca/blog/2010/markdown-and-xss/ +[2]: https://github.com/michelf diff --git a/karma.browserstack.js b/karma.browserstack.js new file mode 100644 index 0000000..341e42c --- /dev/null +++ b/karma.browserstack.js @@ -0,0 +1,80 @@ +module.exports = function (config) { + config.set({ + // global config of your BrowserStack account + browserStack: { + username: process.env.BROWSERSTACK_USERNAME, + accessKey: process.env.BROWSERSTACK_ACCESSKEY, + project: process.env.BROWSERSTACK_PROJECT_NAME || 'showdown', + build: process.env.BROWSERSTACK_BUILD_NAME || require('./package.json').version, + name: process.env.COMMIT_MSG || 'Unit Testing' + }, + + // define browsers + customLaunchers: { + bstack_chrome_windows: { + base: 'BrowserStack', + browser: 'chrome', + browser_version: '49', + os: 'Windows', + os_version: '10' + }, + bstack_firefox_windows: { + base: 'BrowserStack', + browser: 'firefox', + browser_version: '44', + os: 'Windows', + os_version: '10' + }, + bstack_edge_windows: { + base: 'BrowserStack', + browser: 'edge', + browser_version: '15', + os: 'Windows', + os_version: '10' + }, + bstack_ie11_windows: { + base: 'BrowserStack', + browser: 'ie', + browser_version: '11', + os: 'Windows', + os_version: '10' + }, + bstack_macos_safari: { + base: 'BrowserStack', + browser: 'safari', + browser_version: '10.1', + os: 'OS X', + os_version: 'Sierra' + }, + bstack_iphoneX: { + base: 'BrowserStack', + browser: 'safari', + os: 'ios', + os_version: '11.0', + device: 'iPhone X', + real_mobile: true + }, + bstack_android: { + base: 'BrowserStack', + browser: 'chrome', + os: 'android', + os_version:'4.4', + device: 'Samsung Galaxy Tab 4', + realMobile: true + } + }, + + browsers: ['bstack_chrome_windows', 'bstack_firefox_windows', 'bstack_ie11_windows', 'bstack_edge_windows', 'bstack_iphoneX', 'bstack_macos_safari', 'bstack_android'], + frameworks: ['mocha', 'chai'], + reporters: ['dots', 'BrowserStack'], + files: [ + { pattern: '.build/showdown.js'}, + { pattern: 'src/options.js'}, + // tests + { pattern: 'test/unit/showdown*.js' } + //{ pattern: 'test/functional/showdown*.js' }, + ], + singleRun: true, + concurrency: Infinity + }); +}; diff --git a/karma.conf.js b/karma.conf.js new file mode 100644 index 0000000..ade836f --- /dev/null +++ b/karma.conf.js @@ -0,0 +1,36 @@ +module.exports = function (config) { + config.set({ + client: { + captureConsole: true + }, + browserConsoleLogOptions: { + level: 'log', + format: '%b %T: %m', + terminal: true + }, + logLevel: config.LOG_LOG, + frameworks: ['mocha', 'chai'], + files: [ + { pattern: '.build/showdown.js'}, + { pattern: 'src/options.js'}, + // tests + { pattern: 'test/unit/showdown*.js' }, + { pattern: 'test/functional/showdown*.js' }, + ], + reporters: ['progress'], + port: 9876, // karma web server port + colors: true, + browsers: ['ChromeHeadless', 'FirefoxHeadless', 'jsdom'], + autoWatch: false, + singleRun: true, // Karma captures browsers, runs the tests and exits + //concurrency: Infinity, + customLaunchers: { + 'FirefoxHeadless': { + base: 'Firefox', + flags: [ + '-headless', + ] + } + }, + }); +}; diff --git a/mkdocs.yml b/mkdocs.yml index 16401f6..6dd4ae7 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -32,4 +32,13 @@ nav: - Donations: donations.md - Quickstart: - Quickstart: quickstart.md - - Compatibility: compatibility.md \ No newline at end of file + - Compatibility: compatibility.md + - Configuration: + - Showdown options: configuration.md + - Available options: available-options.md + - Flavors: flavors.md + - CLI: cli.md + - Integrations: integrations.md + - Extensions: + - Overview: extensions.md + - Create an extension: create-extension.md \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index c487f26..473b1b6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,8 +10,7 @@ "license": "MIT", "dependencies": { "commander": "^9.0.0", - "jsdom": "^19.0.0", - "semver-sort": "^1.0.0" + "jsdom": "^19.0.0" }, "bin": { "showdown": "bin/showdown.js" @@ -28,10 +27,19 @@ "grunt-conventional-github-releaser": "^1.0.0", "grunt-endline": "^0.7.0", "grunt-eslint": "^24.0.0", + "grunt-mocha-test": "^0.13.3", "grunt-simple-mocha": "^0.4.0", + "karma": "^6.3.17", + "karma-browserstack-launcher": "^1.6.0", + "karma-chai": "^0.1.0", + "karma-chrome-launcher": "^3.1.1", + "karma-firefox-launcher": "^2.1.2", + "karma-jsdom-launcher": "^12.0.0", + "karma-mocha": "^2.0.1", "load-grunt-tasks": "^5.1.0", "performance-now": "^2.1.0", "quiet-grunt": "^0.2.0", + "semver-sort": "^1.0.0", "sinon": "*", "source-map-support": "^0.5.21" }, @@ -40,17 +48,26 @@ "url": "https://www.paypal.me/tiviesantos" } }, + "node_modules/@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "dev": true, + "engines": { + "node": ">=0.1.90" + } + }, "node_modules/@eslint/eslintrc": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.0.tgz", - "integrity": "sha512-igm9SjJHNEJRiUnecP/1R5T3wKLEJ7pL6e2P+GUSfCd0dGjPYYZve08uzw8L2J8foVHFz+NGu12JxRcU2gGo6w==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.1.tgz", + "integrity": "sha512-bxvbYnBPN1Gibwyp6NrpnFzA3YtRL3BBAyEAFVIpNTm2Rn4Vy87GA5M4aSn3InRrlsbX5N0GW7XIx+U4SAEKdQ==", "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", "espree": "^9.3.1", "globals": "^13.9.0", - "ignore": "^4.0.6", + "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", "minimatch": "^3.0.4", @@ -66,15 +83,6 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, - "node_modules/@eslint/eslintrc/node_modules/ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, "node_modules/@eslint/eslintrc/node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -142,6 +150,15 @@ "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", "dev": true }, + "node_modules/@socket.io/base64-arraybuffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@socket.io/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", + "integrity": "sha512-dOlCBKnDw4iShaIsH/bxujKTM18+2TOAsYz+KSc11Am38H4q5Xw8Bbz97ZYdrVNM+um3p7w86Bvvmcn9q+5+eQ==", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/@tootallnate/once": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", @@ -150,12 +167,36 @@ "node": ">= 10" } }, + "node_modules/@types/component-emitter": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.11.tgz", + "integrity": "sha512-SRXjM+tfsSlA9VuG8hGO2nft2p8zjXCK1VcC6N4NXbBbYbSia9kzCChYQajIjzIqOOOuh5Ock6MmV2oux4jDZQ==", + "dev": true + }, + "node_modules/@types/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==", + "dev": true + }, + "node_modules/@types/cors": { + "version": "2.8.12", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz", + "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==", + "dev": true + }, "node_modules/@types/minimatch": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==", "dev": true }, + "node_modules/@types/node": { + "version": "17.0.23", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.23.tgz", + "integrity": "sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw==", + "dev": true + }, "node_modules/@ungap/promise-all-settled": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", @@ -173,6 +214,19 @@ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "dev": true }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/acorn": { "version": "8.7.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", @@ -392,6 +446,15 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "node_modules/base64id": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", + "dev": true, + "engines": { + "node": "^4.5.0 || >= 5.9" + } + }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -401,6 +464,42 @@ "node": ">=8" } }, + "node_modules/body-parser": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==", + "dev": true, + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.8.1", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.9.7", + "raw-body": "2.4.3", + "type-is": "~1.6.18" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -434,12 +533,98 @@ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, + "node_modules/browserstack": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/browserstack/-/browserstack-1.5.3.tgz", + "integrity": "sha512-AO+mECXsW4QcqC9bxwM29O7qWa7bJT94uBFzeb5brylIQwawuEziwq20dPYbins95GlWzOawgyDNdjYAo32EKg==", + "dev": true, + "dependencies": { + "https-proxy-agent": "^2.2.1" + } + }, + "node_modules/browserstack-local": { + "version": "1.4.9", + "resolved": "https://registry.npmjs.org/browserstack-local/-/browserstack-local-1.4.9.tgz", + "integrity": "sha512-V+q8HQwRQFr9nd32xR66ZZ3VDWa3Kct4IMMudhKgcuD7cWrvvFARZOibx71II+Rf7P5nMQpWWxl9z/3p927nbg==", + "dev": true, + "dependencies": { + "https-proxy-agent": "^4.0.0", + "is-running": "^2.1.0", + "ps-tree": "=1.2.0", + "temp-fs": "^0.9.9" + } + }, + "node_modules/browserstack-local/node_modules/agent-base": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-5.1.1.tgz", + "integrity": "sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g==", + "dev": true, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/browserstack-local/node_modules/https-proxy-agent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-4.0.0.tgz", + "integrity": "sha512-zoDhWrkR3of1l9QAL8/scJZyLu8j/gBkcwcaQOZh7Gyh/+uJQzGVETdgT30akuwkpL8HTRfssqI3BZuV18teDg==", + "dev": true, + "dependencies": { + "agent-base": "5", + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/browserstack/node_modules/agent-base": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", + "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", + "dev": true, + "dependencies": { + "es6-promisify": "^5.0.0" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/browserstack/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/browserstack/node_modules/https-proxy-agent": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", + "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", + "dev": true, + "dependencies": { + "agent-base": "^4.3.0", + "debug": "^3.1.0" + }, + "engines": { + "node": ">= 4.5.0" + } + }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -623,9 +808,9 @@ } }, "node_modules/commander": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.0.0.tgz", - "integrity": "sha512-JJfP2saEKbQqvW+FI93OYUB4ByV5cizMpFMiiJI8xDbBvQvSkIk0VvQdn1CZ8mqAO8Loq2h0gYTYtDFUZUeERw==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.1.0.tgz", + "integrity": "sha512-i0/MaqBtdbnJ4XQs4Pmyb+oFQl+q0lsAmokVUH92SlSw4fkeAcG3bVon+Qt7hmtF+u3Het6o4VgrcY3qAoEB6w==", "engines": { "node": "^12.20.0 || >=14" } @@ -640,6 +825,12 @@ "dot-prop": "^3.0.0" } }, + "node_modules/component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -661,6 +852,36 @@ "typedarray": "^0.0.6" } }, + "node_modules/connect": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", + "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/connect/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/connect/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, "node_modules/console-browserify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", @@ -670,6 +891,15 @@ "date-now": "^0.1.4" } }, + "node_modules/content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/conventional-changelog": { "version": "1.1.24", "resolved": "https://registry.npmjs.org/conventional-changelog/-/conventional-changelog-1.1.24.tgz", @@ -991,12 +1221,34 @@ "node": ">=0.10.0" } }, + "node_modules/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/core-util-is": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", "dev": true }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dev": true, + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -1044,6 +1296,12 @@ "node": ">=0.10.0" } }, + "node_modules/custom-event": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", + "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=", + "dev": true + }, "node_modules/dargs": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/dargs/-/dargs-4.1.0.tgz", @@ -1069,6 +1327,15 @@ "node": ">=12" } }, + "node_modules/date-format": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.6.tgz", + "integrity": "sha512-B9vvg5rHuQ8cbUXE/RMWMyX2YA5TecT3jKF5fLtGNlzPlU7zblSPmAm2OImDbWL+LDOQ6pUm+4LOFz+ywS41Zw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, "node_modules/date-now": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", @@ -1085,9 +1352,9 @@ } }, "node_modules/debug": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", - "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dependencies": { "ms": "2.1.2" }, @@ -1161,6 +1428,15 @@ "node": ">=0.4.0" } }, + "node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/detect-file": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", @@ -1170,6 +1446,12 @@ "node": ">=0.10.0" } }, + "node_modules/di": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", + "integrity": "sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=", + "dev": true + }, "node_modules/diff": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", @@ -1191,6 +1473,18 @@ "node": ">=6.0.0" } }, + "node_modules/dom-serialize": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", + "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=", + "dev": true, + "dependencies": { + "custom-event": "~1.0.0", + "ent": "~2.2.0", + "extend": "^3.0.0", + "void-elements": "^2.0.0" + } + }, "node_modules/dom-serializer": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", @@ -1276,12 +1570,87 @@ "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", "dev": true }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true + }, "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==", "dev": true }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/engine.io": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.1.3.tgz", + "integrity": "sha512-rqs60YwkvWTLLnfazqgZqLa/aKo+9cueVfEi/dZ8PyGyaf8TLOxj++4QMIgeG3Gn0AhrWiFXvghsoY9L9h25GA==", + "dev": true, + "dependencies": { + "@types/cookie": "^0.4.1", + "@types/cors": "^2.8.12", + "@types/node": ">=10.0.0", + "accepts": "~1.3.4", + "base64id": "2.0.0", + "cookie": "~0.4.1", + "cors": "~2.8.5", + "debug": "~4.3.1", + "engine.io-parser": "~5.0.3", + "ws": "~8.2.3" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/engine.io-parser": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.3.tgz", + "integrity": "sha512-BtQxwF27XUNnSafQLvDi0dQ8s3i6VgzSoQMJacpIcGNrlUdfHSKbgm3jmjCVvQluGzqwujQMPAoMai3oYSTurg==", + "dev": true, + "dependencies": { + "@socket.io/base64-arraybuffer": "~1.0.2" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/engine.io/node_modules/ws": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", + "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==", + "dev": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/ent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", + "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=", + "dev": true + }, "node_modules/entities": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", @@ -1297,6 +1666,21 @@ "is-arrayish": "^0.2.1" } }, + "node_modules/es6-promise": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", + "dev": true + }, + "node_modules/es6-promisify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", + "dev": true, + "dependencies": { + "es6-promise": "^4.0.3" + } + }, "node_modules/escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -1306,6 +1690,12 @@ "node": ">=6" } }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true + }, "node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -1396,12 +1786,12 @@ } }, "node_modules/eslint": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.10.0.tgz", - "integrity": "sha512-tcI1D9lfVec+R4LE1mNDnzoJ/f71Kl/9Cv4nG47jOueCMBrCCKYXr4AUVS7go6mWYGFD4+EoN6+eXSrEbRzXVw==", + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.12.0.tgz", + "integrity": "sha512-it1oBL9alZg1S8UycLm5YDMAkIhtH6FtAzuZs6YvoGVldWjbS08BkAdb/ymP9LlAyq8koANu32U7Ib/w+UNh8Q==", "dev": true, "dependencies": { - "@eslint/eslintrc": "^1.2.0", + "@eslint/eslintrc": "^1.2.1", "@humanwhocodes/config-array": "^0.9.2", "ajv": "^6.10.0", "chalk": "^4.0.0", @@ -1580,12 +1970,45 @@ "node": ">=0.10.0" } }, + "node_modules/event-stream": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", + "dev": true, + "dependencies": { + "duplexer": "~0.1.1", + "from": "~0", + "map-stream": "~0.1.0", + "pause-stream": "0.0.11", + "split": "0.3", + "stream-combiner": "~0.0.4", + "through": "~2.3.1" + } + }, + "node_modules/event-stream/node_modules/split": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", + "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", + "dev": true, + "dependencies": { + "through": "2" + }, + "engines": { + "node": "*" + } + }, "node_modules/eventemitter2": { "version": "0.4.14", "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", "integrity": "sha1-j2G3XN4BKy6esoTUVFWDtWQ7Yas=", "dev": true }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true + }, "node_modules/exit": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", @@ -1676,6 +2099,39 @@ "node": ">=8" } }, + "node_modules/finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -1773,6 +2229,26 @@ "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", "dev": true }, + "node_modules/follow-redirects": { + "version": "1.14.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", + "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", @@ -1807,6 +2283,26 @@ "node": ">= 6" } }, + "node_modules/from": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", + "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=", + "dev": true + }, + "node_modules/fs-extra": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.1.tgz", + "integrity": "sha512-NbdoVMZso2Lsrn/QwLXOy6rm0ufY2zEOKCDzJR/0kBsb0E6qed0P3iYK+Ath3BfvXEeu4JhEtXLgILx5psUfag==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -2128,9 +2624,9 @@ } }, "node_modules/globals": { - "version": "13.12.1", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.1.tgz", - "integrity": "sha512-317dFlgY2pdJZ9rspXDks7073GpDmXdfbM3vYYp0HAMKGDh1FfWPleI2ljVNLQX5M5lXcAslTcPTrOrMEFOjyw==", + "version": "13.13.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.13.0.tgz", + "integrity": "sha512-EQ7Q18AJlPwp3vUDL4mKA0KXrXyNIQyWon6T6XQiBQF0XHvRsiCSrWmmeATpUzdJN2HhWZU6Pdl0a9zdep5p6A==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -2609,6 +3105,34 @@ "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==", "dev": true }, + "node_modules/grunt-mocha-test": { + "version": "0.13.3", + "resolved": "https://registry.npmjs.org/grunt-mocha-test/-/grunt-mocha-test-0.13.3.tgz", + "integrity": "sha512-zQGEsi3d+ViPPi7/4jcj78afKKAKiAA5n61pknQYi25Ugik+aNOuRmiOkmb8mN2CeG8YxT+YdT1H1Q7B/eNkoQ==", + "dev": true, + "dependencies": { + "hooker": "^0.2.3", + "mkdirp": "^0.5.0" + }, + "engines": { + "node": ">= 0.10.4" + }, + "peerDependencies": { + "mocha": ">=1.20.0" + } + }, + "node_modules/grunt-mocha-test/node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, "node_modules/grunt-simple-mocha": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/grunt-simple-mocha/-/grunt-simple-mocha-0.4.1.tgz", @@ -2792,6 +3316,36 @@ "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true }, + "node_modules/http-errors": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "dev": true, + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dev": true, + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/http-proxy-agent": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", @@ -2952,6 +3506,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true, + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -3050,6 +3619,12 @@ "node": ">=0.10.0" } }, + "node_modules/is-running": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-running/-/is-running-2.1.0.tgz", + "integrity": "sha1-MKc/9cw4VOT8JUkICen1q/jeCeA=", + "dev": true + }, "node_modules/is-subset": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-subset/-/is-subset-0.1.1.tgz", @@ -3107,12 +3682,36 @@ "node": ">=0.10.0" } }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, + "node_modules/isbinaryfile": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.10.tgz", + "integrity": "sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==", + "dev": true, + "engines": { + "node": ">= 8.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/gjtorikian/" + } + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -3240,6 +3839,18 @@ "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", "dev": true }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, "node_modules/jsonparse": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", @@ -3271,6 +3882,151 @@ "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", "dev": true }, + "node_modules/karma": { + "version": "6.3.17", + "resolved": "https://registry.npmjs.org/karma/-/karma-6.3.17.tgz", + "integrity": "sha512-2TfjHwrRExC8yHoWlPBULyaLwAFmXmxQrcuFImt/JsAsSZu1uOWTZ1ZsWjqQtWpHLiatJOHL5jFjXSJIgCd01g==", + "dev": true, + "dependencies": { + "@colors/colors": "1.5.0", + "body-parser": "^1.19.0", + "braces": "^3.0.2", + "chokidar": "^3.5.1", + "connect": "^3.7.0", + "di": "^0.0.1", + "dom-serialize": "^2.2.1", + "glob": "^7.1.7", + "graceful-fs": "^4.2.6", + "http-proxy": "^1.18.1", + "isbinaryfile": "^4.0.8", + "lodash": "^4.17.21", + "log4js": "^6.4.1", + "mime": "^2.5.2", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.5", + "qjobs": "^1.2.0", + "range-parser": "^1.2.1", + "rimraf": "^3.0.2", + "socket.io": "^4.2.0", + "source-map": "^0.6.1", + "tmp": "^0.2.1", + "ua-parser-js": "^0.7.30", + "yargs": "^16.1.1" + }, + "bin": { + "karma": "bin/karma" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/karma-browserstack-launcher": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/karma-browserstack-launcher/-/karma-browserstack-launcher-1.6.0.tgz", + "integrity": "sha512-Y/UWPdHZkHIVH2To4GWHCTzmrsB6H7PBWy6pw+TWz5sr4HW2mcE+Uj6qWgoVNxvQU1Pfn5LQQzI6EQ65p8QbiQ==", + "dev": true, + "dependencies": { + "browserstack": "~1.5.1", + "browserstack-local": "^1.3.7", + "q": "~1.5.0" + }, + "peerDependencies": { + "karma": ">=0.9" + } + }, + "node_modules/karma-chai": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/karma-chai/-/karma-chai-0.1.0.tgz", + "integrity": "sha1-vuWtQEAFF4Ea40u5RfdikJEIt5o=", + "dev": true, + "peerDependencies": { + "chai": "*", + "karma": ">=0.10.9" + } + }, + "node_modules/karma-chrome-launcher": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-3.1.1.tgz", + "integrity": "sha512-hsIglcq1vtboGPAN+DGCISCFOxW+ZVnIqhDQcCMqqCp+4dmJ0Qpq5QAjkbA0X2L9Mi6OBkHi2Srrbmm7pUKkzQ==", + "dev": true, + "dependencies": { + "which": "^1.2.1" + } + }, + "node_modules/karma-chrome-launcher/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/karma-firefox-launcher": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/karma-firefox-launcher/-/karma-firefox-launcher-2.1.2.tgz", + "integrity": "sha512-VV9xDQU1QIboTrjtGVD4NCfzIH7n01ZXqy/qpBhnOeGVOkG5JYPEm8kuSd7psHE6WouZaQ9Ool92g8LFweSNMA==", + "dev": true, + "dependencies": { + "is-wsl": "^2.2.0", + "which": "^2.0.1" + } + }, + "node_modules/karma-jsdom-launcher": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/karma-jsdom-launcher/-/karma-jsdom-launcher-12.0.0.tgz", + "integrity": "sha512-vKgDkk6V52p5FtQaDSPMwbVSL1PL4SZ0dx/l+lx+zDfJ5rpWzbrVtRG+vY5Fy9KbLMtvaX4FuAR9IyDLoEQtuA==", + "dev": true, + "peerDependencies": { + "jsdom": "^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "karma": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0" + } + }, + "node_modules/karma-mocha": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/karma-mocha/-/karma-mocha-2.0.1.tgz", + "integrity": "sha512-Tzd5HBjm8his2OA4bouAsATYEpZrp9vC7z5E5j4C5Of5Rrs1jY67RAwXNcVmd/Bnk1wgvQRou0zGVLey44G4tQ==", + "dev": true, + "dependencies": { + "minimist": "^1.2.3" + } + }, + "node_modules/karma/node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/karma/node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/karma/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -3435,6 +4191,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/log4js": { + "version": "6.4.4", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.4.4.tgz", + "integrity": "sha512-ncaWPsuw9Vl1CKA406hVnJLGQKy1OHx6buk8J4rE2lVW+NW5Y82G5/DIloO7NkqLOUtNPEANaWC1kZYVjXssPw==", + "dev": true, + "dependencies": { + "date-format": "^4.0.6", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.0.6" + }, + "engines": { + "node": ">=8.0" + } + }, "node_modules/loud-rejection": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", @@ -3487,6 +4259,12 @@ "node": ">=4" } }, + "node_modules/map-stream": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", + "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=", + "dev": true + }, "node_modules/maxmin": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/maxmin/-/maxmin-2.1.0.tgz", @@ -3566,6 +4344,15 @@ "node": ">=0.8.0" } }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/meow": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/meow/-/meow-4.0.1.tgz", @@ -3730,13 +4517,13 @@ } }, "node_modules/micromatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", - "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", "dev": true, "dependencies": { - "braces": "^3.0.1", - "picomatch": "^2.2.3" + "braces": "^3.0.2", + "picomatch": "^2.3.1" }, "engines": { "node": ">=8.6" @@ -3755,19 +4542,19 @@ } }, "node_modules/mime-db": { - "version": "1.51.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", - "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "engines": { "node": ">= 0.6" } }, "node_modules/mime-types": { - "version": "2.1.34", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", - "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dependencies": { - "mime-db": "1.51.0" + "mime-db": "1.52.0" }, "engines": { "node": ">= 0.6" @@ -3786,9 +4573,9 @@ } }, "node_modules/minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", "dev": true }, "node_modules/minimist-options": { @@ -3826,9 +4613,9 @@ } }, "node_modules/mocha": { - "version": "9.2.1", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.1.tgz", - "integrity": "sha512-T7uscqjJVS46Pq1XDXyo9Uvey9gd3huT/DD9cYBb4K2Xc/vbKRPUWK067bxDQRK0yIz6Jxk73IrnimvASzBNAQ==", + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.2.tgz", + "integrity": "sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g==", "dev": true, "dependencies": { "@ungap/promise-all-settled": "1.1.2", @@ -3844,9 +4631,9 @@ "he": "1.2.0", "js-yaml": "4.1.0", "log-symbols": "4.1.0", - "minimatch": "3.0.4", + "minimatch": "4.2.1", "ms": "2.1.3", - "nanoid": "3.2.0", + "nanoid": "3.3.1", "serialize-javascript": "6.0.0", "strip-json-comments": "3.1.1", "supports-color": "8.1.1", @@ -3874,6 +4661,29 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, + "node_modules/mocha/node_modules/debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/mocha/node_modules/debug/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, "node_modules/mocha/node_modules/glob": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", @@ -3894,6 +4704,18 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/mocha/node_modules/glob/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/mocha/node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -3907,15 +4729,15 @@ } }, "node_modules/mocha/node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-4.2.1.tgz", + "integrity": "sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g==", "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, "engines": { - "node": "*" + "node": ">=10" } }, "node_modules/mocha/node_modules/ms": { @@ -3970,9 +4792,9 @@ } }, "node_modules/nanoid": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.2.0.tgz", - "integrity": "sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", + "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", "dev": true, "bin": { "nanoid": "bin/nanoid.cjs" @@ -3987,6 +4809,15 @@ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", @@ -4102,6 +4933,18 @@ "node": ">=0.10.0" } }, + "node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true, + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -4253,6 +5096,15 @@ "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -4345,6 +5197,15 @@ "node": "*" } }, + "node_modules/pause-stream": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", + "dev": true, + "dependencies": { + "through": "~2.3" + } + }, "node_modules/performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", @@ -4514,6 +5375,21 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, + "node_modules/ps-tree": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.2.0.tgz", + "integrity": "sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==", + "dev": true, + "dependencies": { + "event-stream": "=3.3.4" + }, + "bin": { + "ps-tree": "bin/ps-tree.js" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/psl": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", @@ -4537,6 +5413,27 @@ "teleport": ">=0.2.0" } }, + "node_modules/qjobs": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz", + "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==", + "dev": true, + "engines": { + "node": ">=0.9" + } + }, + "node_modules/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==", + "dev": true, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/quick-lru": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-1.1.0.tgz", @@ -4561,6 +5458,30 @@ "safe-buffer": "^5.1.0" } }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz", + "integrity": "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==", + "dev": true, + "dependencies": { + "bytes": "3.1.2", + "http-errors": "1.8.1", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/read-pkg": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", @@ -4698,6 +5619,12 @@ "node": ">=0.10.0" } }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", + "dev": true + }, "node_modules/resolve": { "version": "1.22.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", @@ -4758,6 +5685,12 @@ "node": ">=8" } }, + "node_modules/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", + "dev": true + }, "node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -4799,6 +5732,7 @@ "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, "bin": { "semver": "bin/semver" } @@ -4816,6 +5750,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/semver-sort/-/semver-sort-1.0.0.tgz", "integrity": "sha512-JicVlQKz/C//4BiPmbHEDou6HihXxo5xqB/8Hm9FaLJ6HHkRRvYgCECq4u/z0XF8kyJQ/KAZt++A/kYz/oOSSg==", + "dev": true, "dependencies": { "semver": "^5.0.3", "semver-regex": "^3.1.2" @@ -4828,6 +5763,7 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-3.1.3.tgz", "integrity": "sha512-Aqi54Mk9uYTjVexLnR67rTyBusmwd04cLkHy9hNvk3+G3nT2Oyg7E0l4XVbOaNwIvQ3hHeYxGcyEy+mKreyBFQ==", + "dev": true, "engines": { "node": ">=8" }, @@ -4844,6 +5780,12 @@ "randombytes": "^2.1.0" } }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -4889,6 +5831,43 @@ "url": "https://opencollective.com/sinon" } }, + "node_modules/socket.io": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.4.1.tgz", + "integrity": "sha512-s04vrBswdQBUmuWJuuNTmXUVJhP0cVky8bBDhdkf8y0Ptsu7fKU2LuLbts9g+pdmAdyMMn8F/9Mf1/wbtUN0fg==", + "dev": true, + "dependencies": { + "accepts": "~1.3.4", + "base64id": "~2.0.0", + "debug": "~4.3.2", + "engine.io": "~6.1.0", + "socket.io-adapter": "~2.3.3", + "socket.io-parser": "~4.0.4" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/socket.io-adapter": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.3.3.tgz", + "integrity": "sha512-Qd/iwn3VskrpNO60BeRyCyr8ZWw9CPZyitW4AQwmRZ8zCiyDiL+znRnWX6tDHXnWn1sJrM1+b6Mn6wEDJJ4aYQ==", + "dev": true + }, + "node_modules/socket.io-parser": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.4.tgz", + "integrity": "sha512-t+b0SS+IxG7Rxzda2EVvyBZbvFPBCjJoyHuE0P//7OAsN23GItzDRdWa6ALxZI/8R5ygK7jAR6t028/z+7295g==", + "dev": true, + "dependencies": { + "@types/component-emitter": "^1.2.10", + "component-emitter": "~1.3.0", + "debug": "~4.3.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -4976,6 +5955,38 @@ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, + "node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/stream-combiner": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", + "dev": true, + "dependencies": { + "duplexer": "~0.1.1" + } + }, + "node_modules/streamroller": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.0.6.tgz", + "integrity": "sha512-Qz32plKq/MZywYyhEatxyYc8vs994Gz0Hu2MSYXXLD233UyPeIeRBZARIIGwFer4Mdb8r3Y2UqKkgyDghM6QCg==", + "dev": true, + "dependencies": { + "date-format": "^4.0.6", + "debug": "^4.3.4", + "fs-extra": "^10.0.1" + }, + "engines": { + "node": ">=8.0" + } + }, "node_modules/string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -5073,6 +6084,30 @@ "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==" }, + "node_modules/temp-fs": { + "version": "0.9.9", + "resolved": "https://registry.npmjs.org/temp-fs/-/temp-fs-0.9.9.tgz", + "integrity": "sha1-gHFzBDeHByDpQxUy/igUNk+IA9c=", + "dev": true, + "dependencies": { + "rimraf": "~2.5.2" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/temp-fs/node_modules/rimraf": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.5.4.tgz", + "integrity": "sha1-loAAk8vxoMhr2VtGJUZ1NcKd+gQ=", + "dev": true, + "dependencies": { + "glob": "^7.0.5" + }, + "bin": { + "rimraf": "bin.js" + } + }, "node_modules/text-extensions": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz", @@ -5104,6 +6139,18 @@ "xtend": "~4.0.1" } }, + "node_modules/tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "dev": true, + "dependencies": { + "rimraf": "^3.0.0" + }, + "engines": { + "node": ">=8.17.0" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -5116,6 +6163,15 @@ "node": ">=8.0" } }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, "node_modules/tough-cookie": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz", @@ -5129,6 +6185,14 @@ "node": ">=6" } }, + "node_modules/tough-cookie/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "engines": { + "node": ">= 4.0.0" + } + }, "node_modules/tr46": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", @@ -5191,16 +6255,48 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", "dev": true }, + "node_modules/ua-parser-js": { + "version": "0.7.31", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.31.tgz", + "integrity": "sha512-qLK/Xe9E2uzmYI3qLeOmI0tEOt+TBBQyUIAh4aAgU05FVYzeZrKUdkAZfBNVGRaHVgV0TDkdEngJSw/SyQchkQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + } + ], + "engines": { + "node": "*" + } + }, "node_modules/uglify-js": { - "version": "3.15.2", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.15.2.tgz", - "integrity": "sha512-peeoTk3hSwYdoc9nrdiEJk+gx1ALCtTjdYuKSXMTDqq7n1W7dHPqWDdSi+BPL0ni2YMeHD7hKUSdbj3TZauY2A==", + "version": "3.15.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.15.3.tgz", + "integrity": "sha512-6iCVm2omGJbsu3JWac+p6kUiOpg3wFO2f8lIXjfEb8RrmLjzog1wTPMmwKB7swfzzqxj9YM+sGUM++u1qN4qJg==", "dev": true, "bin": { "uglifyjs": "bin/uglifyjs" @@ -5238,11 +6334,21 @@ "dev": true }, "node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true, "engines": { - "node": ">= 4.0.0" + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true, + "engines": { + "node": ">= 0.8" } }, "node_modules/uri-js": { @@ -5269,6 +6375,15 @@ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "dev": true, + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/v8-compile-cache": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", @@ -5297,6 +6412,24 @@ "spdx-expression-parse": "^3.0.0" } }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/void-elements": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", + "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/w3c-hr-time": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", @@ -5564,17 +6697,23 @@ } }, "dependencies": { + "@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "dev": true + }, "@eslint/eslintrc": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.0.tgz", - "integrity": "sha512-igm9SjJHNEJRiUnecP/1R5T3wKLEJ7pL6e2P+GUSfCd0dGjPYYZve08uzw8L2J8foVHFz+NGu12JxRcU2gGo6w==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.1.tgz", + "integrity": "sha512-bxvbYnBPN1Gibwyp6NrpnFzA3YtRL3BBAyEAFVIpNTm2Rn4Vy87GA5M4aSn3InRrlsbX5N0GW7XIx+U4SAEKdQ==", "dev": true, "requires": { "ajv": "^6.12.4", "debug": "^4.3.2", "espree": "^9.3.1", "globals": "^13.9.0", - "ignore": "^4.0.6", + "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", "minimatch": "^3.0.4", @@ -5587,12 +6726,6 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true - }, "js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -5656,17 +6789,47 @@ "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", "dev": true }, + "@socket.io/base64-arraybuffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@socket.io/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", + "integrity": "sha512-dOlCBKnDw4iShaIsH/bxujKTM18+2TOAsYz+KSc11Am38H4q5Xw8Bbz97ZYdrVNM+um3p7w86Bvvmcn9q+5+eQ==", + "dev": true + }, "@tootallnate/once": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==" }, + "@types/component-emitter": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.11.tgz", + "integrity": "sha512-SRXjM+tfsSlA9VuG8hGO2nft2p8zjXCK1VcC6N4NXbBbYbSia9kzCChYQajIjzIqOOOuh5Ock6MmV2oux4jDZQ==", + "dev": true + }, + "@types/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==", + "dev": true + }, + "@types/cors": { + "version": "2.8.12", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz", + "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==", + "dev": true + }, "@types/minimatch": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==", "dev": true }, + "@types/node": { + "version": "17.0.23", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.23.tgz", + "integrity": "sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw==", + "dev": true + }, "@ungap/promise-all-settled": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", @@ -5684,6 +6847,16 @@ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "dev": true }, + "accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, + "requires": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + } + }, "acorn": { "version": "8.7.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", @@ -5845,12 +7018,53 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "base64id": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", + "dev": true + }, "binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "dev": true }, + "body-parser": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==", + "dev": true, + "requires": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.8.1", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.9.7", + "raw-body": "2.4.3", + "type-is": "~1.6.18" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -5881,12 +7095,87 @@ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, + "browserstack": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/browserstack/-/browserstack-1.5.3.tgz", + "integrity": "sha512-AO+mECXsW4QcqC9bxwM29O7qWa7bJT94uBFzeb5brylIQwawuEziwq20dPYbins95GlWzOawgyDNdjYAo32EKg==", + "dev": true, + "requires": { + "https-proxy-agent": "^2.2.1" + }, + "dependencies": { + "agent-base": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", + "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", + "dev": true, + "requires": { + "es6-promisify": "^5.0.0" + } + }, + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "https-proxy-agent": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", + "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", + "dev": true, + "requires": { + "agent-base": "^4.3.0", + "debug": "^3.1.0" + } + } + } + }, + "browserstack-local": { + "version": "1.4.9", + "resolved": "https://registry.npmjs.org/browserstack-local/-/browserstack-local-1.4.9.tgz", + "integrity": "sha512-V+q8HQwRQFr9nd32xR66ZZ3VDWa3Kct4IMMudhKgcuD7cWrvvFARZOibx71II+Rf7P5nMQpWWxl9z/3p927nbg==", + "dev": true, + "requires": { + "https-proxy-agent": "^4.0.0", + "is-running": "^2.1.0", + "ps-tree": "=1.2.0", + "temp-fs": "^0.9.9" + }, + "dependencies": { + "agent-base": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-5.1.1.tgz", + "integrity": "sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g==", + "dev": true + }, + "https-proxy-agent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-4.0.0.tgz", + "integrity": "sha512-zoDhWrkR3of1l9QAL8/scJZyLu8j/gBkcwcaQOZh7Gyh/+uJQzGVETdgT30akuwkpL8HTRfssqI3BZuV18teDg==", + "dev": true, + "requires": { + "agent-base": "5", + "debug": "4" + } + } + } + }, "buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, + "bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true + }, "callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -6025,9 +7314,9 @@ } }, "commander": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.0.0.tgz", - "integrity": "sha512-JJfP2saEKbQqvW+FI93OYUB4ByV5cizMpFMiiJI8xDbBvQvSkIk0VvQdn1CZ8mqAO8Loq2h0gYTYtDFUZUeERw==" + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.1.0.tgz", + "integrity": "sha512-i0/MaqBtdbnJ4XQs4Pmyb+oFQl+q0lsAmokVUH92SlSw4fkeAcG3bVon+Qt7hmtF+u3Het6o4VgrcY3qAoEB6w==" }, "compare-func": { "version": "1.3.4", @@ -6039,6 +7328,12 @@ "dot-prop": "^3.0.0" } }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -6057,6 +7352,35 @@ "typedarray": "^0.0.6" } }, + "connect": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", + "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", + "dev": true, + "requires": { + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, "console-browserify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", @@ -6066,6 +7390,12 @@ "date-now": "^0.1.4" } }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "dev": true + }, "conventional-changelog": { "version": "1.1.24", "resolved": "https://registry.npmjs.org/conventional-changelog/-/conventional-changelog-1.1.24.tgz", @@ -6343,12 +7673,28 @@ } } }, + "cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "dev": true + }, "core-util-is": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", "dev": true }, + "cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dev": true, + "requires": { + "object-assign": "^4", + "vary": "^1" + } + }, "cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -6389,6 +7735,12 @@ "array-find-index": "^1.0.1" } }, + "custom-event": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", + "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=", + "dev": true + }, "dargs": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/dargs/-/dargs-4.1.0.tgz", @@ -6408,6 +7760,12 @@ "whatwg-url": "^10.0.0" } }, + "date-format": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.6.tgz", + "integrity": "sha512-B9vvg5rHuQ8cbUXE/RMWMyX2YA5TecT3jKF5fLtGNlzPlU7zblSPmAm2OImDbWL+LDOQ6pUm+4LOFz+ywS41Zw==", + "dev": true + }, "date-now": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", @@ -6421,9 +7779,9 @@ "dev": true }, "debug": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", - "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "requires": { "ms": "2.1.2" } @@ -6476,12 +7834,24 @@ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true + }, "detect-file": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", "dev": true }, + "di": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", + "integrity": "sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=", + "dev": true + }, "diff": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", @@ -6497,6 +7867,18 @@ "esutils": "^2.0.2" } }, + "dom-serialize": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", + "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=", + "dev": true, + "requires": { + "custom-event": "~1.0.0", + "ent": "~2.2.0", + "extend": "^3.0.0", + "void-elements": "^2.0.0" + } + }, "dom-serializer": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", @@ -6569,12 +7951,66 @@ "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", "dev": true }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true + }, "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==", "dev": true }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "dev": true + }, + "engine.io": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.1.3.tgz", + "integrity": "sha512-rqs60YwkvWTLLnfazqgZqLa/aKo+9cueVfEi/dZ8PyGyaf8TLOxj++4QMIgeG3Gn0AhrWiFXvghsoY9L9h25GA==", + "dev": true, + "requires": { + "@types/cookie": "^0.4.1", + "@types/cors": "^2.8.12", + "@types/node": ">=10.0.0", + "accepts": "~1.3.4", + "base64id": "2.0.0", + "cookie": "~0.4.1", + "cors": "~2.8.5", + "debug": "~4.3.1", + "engine.io-parser": "~5.0.3", + "ws": "~8.2.3" + }, + "dependencies": { + "ws": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", + "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==", + "dev": true, + "requires": {} + } + } + }, + "engine.io-parser": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.3.tgz", + "integrity": "sha512-BtQxwF27XUNnSafQLvDi0dQ8s3i6VgzSoQMJacpIcGNrlUdfHSKbgm3jmjCVvQluGzqwujQMPAoMai3oYSTurg==", + "dev": true, + "requires": { + "@socket.io/base64-arraybuffer": "~1.0.2" + } + }, + "ent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", + "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=", + "dev": true + }, "entities": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", @@ -6590,12 +8026,33 @@ "is-arrayish": "^0.2.1" } }, + "es6-promise": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", + "dev": true + }, + "es6-promisify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", + "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", + "dev": true, + "requires": { + "es6-promise": "^4.0.3" + } + }, "escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "dev": true }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true + }, "escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -6658,12 +8115,12 @@ } }, "eslint": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.10.0.tgz", - "integrity": "sha512-tcI1D9lfVec+R4LE1mNDnzoJ/f71Kl/9Cv4nG47jOueCMBrCCKYXr4AUVS7go6mWYGFD4+EoN6+eXSrEbRzXVw==", + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.12.0.tgz", + "integrity": "sha512-it1oBL9alZg1S8UycLm5YDMAkIhtH6FtAzuZs6YvoGVldWjbS08BkAdb/ymP9LlAyq8koANu32U7Ib/w+UNh8Q==", "dev": true, "requires": { - "@eslint/eslintrc": "^1.2.0", + "@eslint/eslintrc": "^1.2.1", "@humanwhocodes/config-array": "^0.9.2", "ajv": "^6.10.0", "chalk": "^4.0.0", @@ -6794,12 +8251,44 @@ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" }, + "event-stream": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", + "dev": true, + "requires": { + "duplexer": "~0.1.1", + "from": "~0", + "map-stream": "~0.1.0", + "pause-stream": "0.0.11", + "split": "0.3", + "stream-combiner": "~0.0.4", + "through": "~2.3.1" + }, + "dependencies": { + "split": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", + "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", + "dev": true, + "requires": { + "through": "2" + } + } + } + }, "eventemitter2": { "version": "0.4.14", "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", "integrity": "sha1-j2G3XN4BKy6esoTUVFWDtWQ7Yas=", "dev": true }, + "eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true + }, "exit": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", @@ -6874,6 +8363,38 @@ "to-regex-range": "^5.0.1" } }, + "finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dev": true, + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, "find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -6949,6 +8470,12 @@ "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", "dev": true }, + "follow-redirects": { + "version": "1.14.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", + "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==", + "dev": true + }, "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", @@ -6974,6 +8501,23 @@ "mime-types": "^2.1.12" } }, + "from": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", + "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=", + "dev": true + }, + "fs-extra": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.1.tgz", + "integrity": "sha512-NbdoVMZso2Lsrn/QwLXOy6rm0ufY2zEOKCDzJR/0kBsb0E6qed0P3iYK+Ath3BfvXEeu4JhEtXLgILx5psUfag==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -7222,9 +8766,9 @@ } }, "globals": { - "version": "13.12.1", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.1.tgz", - "integrity": "sha512-317dFlgY2pdJZ9rspXDks7073GpDmXdfbM3vYYp0HAMKGDh1FfWPleI2ljVNLQX5M5lXcAslTcPTrOrMEFOjyw==", + "version": "13.13.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.13.0.tgz", + "integrity": "sha512-EQ7Q18AJlPwp3vUDL4mKA0KXrXyNIQyWon6T6XQiBQF0XHvRsiCSrWmmeATpUzdJN2HhWZU6Pdl0a9zdep5p6A==", "dev": true, "requires": { "type-fest": "^0.20.2" @@ -7589,6 +9133,27 @@ } } }, + "grunt-mocha-test": { + "version": "0.13.3", + "resolved": "https://registry.npmjs.org/grunt-mocha-test/-/grunt-mocha-test-0.13.3.tgz", + "integrity": "sha512-zQGEsi3d+ViPPi7/4jcj78afKKAKiAA5n61pknQYi25Ugik+aNOuRmiOkmb8mN2CeG8YxT+YdT1H1Q7B/eNkoQ==", + "dev": true, + "requires": { + "hooker": "^0.2.3", + "mkdirp": "^0.5.0" + }, + "dependencies": { + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "requires": { + "minimist": "^1.2.6" + } + } + } + }, "grunt-simple-mocha": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/grunt-simple-mocha/-/grunt-simple-mocha-0.4.1.tgz", @@ -7734,6 +9299,30 @@ } } }, + "http-errors": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" + } + }, + "http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dev": true, + "requires": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + } + }, "http-proxy-agent": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", @@ -7858,6 +9447,12 @@ "has": "^1.0.3" } }, + "is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true + }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -7926,6 +9521,12 @@ "is-unc-path": "^1.0.0" } }, + "is-running": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-running/-/is-running-2.1.0.tgz", + "integrity": "sha1-MKc/9cw4VOT8JUkICen1q/jeCeA=", + "dev": true + }, "is-subset": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-subset/-/is-subset-0.1.1.tgz", @@ -7968,12 +9569,27 @@ "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", "dev": true }, + "is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "requires": { + "is-docker": "^2.0.0" + } + }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, + "isbinaryfile": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.10.tgz", + "integrity": "sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==", + "dev": true + }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -8077,6 +9693,16 @@ "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", "dev": true }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, "jsonparse": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", @@ -8099,6 +9725,125 @@ "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", "dev": true }, + "karma": { + "version": "6.3.17", + "resolved": "https://registry.npmjs.org/karma/-/karma-6.3.17.tgz", + "integrity": "sha512-2TfjHwrRExC8yHoWlPBULyaLwAFmXmxQrcuFImt/JsAsSZu1uOWTZ1ZsWjqQtWpHLiatJOHL5jFjXSJIgCd01g==", + "dev": true, + "requires": { + "@colors/colors": "1.5.0", + "body-parser": "^1.19.0", + "braces": "^3.0.2", + "chokidar": "^3.5.1", + "connect": "^3.7.0", + "di": "^0.0.1", + "dom-serialize": "^2.2.1", + "glob": "^7.1.7", + "graceful-fs": "^4.2.6", + "http-proxy": "^1.18.1", + "isbinaryfile": "^4.0.8", + "lodash": "^4.17.21", + "log4js": "^6.4.1", + "mime": "^2.5.2", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.5", + "qjobs": "^1.2.0", + "range-parser": "^1.2.1", + "rimraf": "^3.0.2", + "socket.io": "^4.2.0", + "source-map": "^0.6.1", + "tmp": "^0.2.1", + "ua-parser-js": "^0.7.30", + "yargs": "^16.1.1" + }, + "dependencies": { + "mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true + }, + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "requires": { + "minimist": "^1.2.6" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "karma-browserstack-launcher": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/karma-browserstack-launcher/-/karma-browserstack-launcher-1.6.0.tgz", + "integrity": "sha512-Y/UWPdHZkHIVH2To4GWHCTzmrsB6H7PBWy6pw+TWz5sr4HW2mcE+Uj6qWgoVNxvQU1Pfn5LQQzI6EQ65p8QbiQ==", + "dev": true, + "requires": { + "browserstack": "~1.5.1", + "browserstack-local": "^1.3.7", + "q": "~1.5.0" + } + }, + "karma-chai": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/karma-chai/-/karma-chai-0.1.0.tgz", + "integrity": "sha1-vuWtQEAFF4Ea40u5RfdikJEIt5o=", + "dev": true, + "requires": {} + }, + "karma-chrome-launcher": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-3.1.1.tgz", + "integrity": "sha512-hsIglcq1vtboGPAN+DGCISCFOxW+ZVnIqhDQcCMqqCp+4dmJ0Qpq5QAjkbA0X2L9Mi6OBkHi2Srrbmm7pUKkzQ==", + "dev": true, + "requires": { + "which": "^1.2.1" + }, + "dependencies": { + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "karma-firefox-launcher": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/karma-firefox-launcher/-/karma-firefox-launcher-2.1.2.tgz", + "integrity": "sha512-VV9xDQU1QIboTrjtGVD4NCfzIH7n01ZXqy/qpBhnOeGVOkG5JYPEm8kuSd7psHE6WouZaQ9Ool92g8LFweSNMA==", + "dev": true, + "requires": { + "is-wsl": "^2.2.0", + "which": "^2.0.1" + } + }, + "karma-jsdom-launcher": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/karma-jsdom-launcher/-/karma-jsdom-launcher-12.0.0.tgz", + "integrity": "sha512-vKgDkk6V52p5FtQaDSPMwbVSL1PL4SZ0dx/l+lx+zDfJ5rpWzbrVtRG+vY5Fy9KbLMtvaX4FuAR9IyDLoEQtuA==", + "dev": true, + "requires": {} + }, + "karma-mocha": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/karma-mocha/-/karma-mocha-2.0.1.tgz", + "integrity": "sha512-Tzd5HBjm8his2OA4bouAsATYEpZrp9vC7z5E5j4C5Of5Rrs1jY67RAwXNcVmd/Bnk1wgvQRou0zGVLey44G4tQ==", + "dev": true, + "requires": { + "minimist": "^1.2.6" + } + }, "kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -8232,6 +9977,19 @@ "is-unicode-supported": "^0.1.0" } }, + "log4js": { + "version": "6.4.4", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.4.4.tgz", + "integrity": "sha512-ncaWPsuw9Vl1CKA406hVnJLGQKy1OHx6buk8J4rE2lVW+NW5Y82G5/DIloO7NkqLOUtNPEANaWC1kZYVjXssPw==", + "dev": true, + "requires": { + "date-format": "^4.0.6", + "debug": "^4.3.4", + "flatted": "^3.2.5", + "rfdc": "^1.3.0", + "streamroller": "^3.0.6" + } + }, "loud-rejection": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", @@ -8272,6 +10030,12 @@ "integrity": "sha1-plzSkIepJZi4eRJXpSPgISIqwfk=", "dev": true }, + "map-stream": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", + "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=", + "dev": true + }, "maxmin": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/maxmin/-/maxmin-2.1.0.tgz", @@ -8332,6 +10096,12 @@ } } }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "dev": true + }, "meow": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/meow/-/meow-4.0.1.tgz", @@ -8459,13 +10229,13 @@ } }, "micromatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", - "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", "dev": true, "requires": { - "braces": "^3.0.1", - "picomatch": "^2.2.3" + "braces": "^3.0.2", + "picomatch": "^2.3.1" } }, "mime": { @@ -8475,16 +10245,16 @@ "dev": true }, "mime-db": { - "version": "1.51.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", - "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==" + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" }, "mime-types": { - "version": "2.1.34", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", - "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "requires": { - "mime-db": "1.51.0" + "mime-db": "1.52.0" } }, "minimatch": { @@ -8497,9 +10267,9 @@ } }, "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", "dev": true }, "minimist-options": { @@ -8527,9 +10297,9 @@ "dev": true }, "mocha": { - "version": "9.2.1", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.1.tgz", - "integrity": "sha512-T7uscqjJVS46Pq1XDXyo9Uvey9gd3huT/DD9cYBb4K2Xc/vbKRPUWK067bxDQRK0yIz6Jxk73IrnimvASzBNAQ==", + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.2.tgz", + "integrity": "sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g==", "dev": true, "requires": { "@ungap/promise-all-settled": "1.1.2", @@ -8545,9 +10315,9 @@ "he": "1.2.0", "js-yaml": "4.1.0", "log-symbols": "4.1.0", - "minimatch": "3.0.4", + "minimatch": "4.2.1", "ms": "2.1.3", - "nanoid": "3.2.0", + "nanoid": "3.3.1", "serialize-javascript": "6.0.0", "strip-json-comments": "3.1.1", "supports-color": "8.1.1", @@ -8564,6 +10334,23 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, + "debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "requires": { + "ms": "2.1.2" + }, + "dependencies": { + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, "glob": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", @@ -8576,6 +10363,17 @@ "minimatch": "^3.0.4", "once": "^1.3.0", "path-is-absolute": "^1.0.0" + }, + "dependencies": { + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + } } }, "js-yaml": { @@ -8588,9 +10386,9 @@ } }, "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-4.2.1.tgz", + "integrity": "sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g==", "dev": true, "requires": { "brace-expansion": "^1.1.7" @@ -8638,9 +10436,9 @@ } }, "nanoid": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.2.0.tgz", - "integrity": "sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", + "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", "dev": true }, "natural-compare": { @@ -8649,6 +10447,12 @@ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, + "negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true + }, "neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", @@ -8743,6 +10547,15 @@ "isobject": "^3.0.1" } }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true, + "requires": { + "ee-first": "1.1.1" + } + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -8858,6 +10671,12 @@ "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true + }, "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -8931,6 +10750,15 @@ "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", "dev": true }, + "pause-stream": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", + "dev": true, + "requires": { + "through": "~2.3" + } + }, "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", @@ -9054,6 +10882,15 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, + "ps-tree": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.2.0.tgz", + "integrity": "sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==", + "dev": true, + "requires": { + "event-stream": "=3.3.4" + } + }, "psl": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", @@ -9070,6 +10907,18 @@ "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", "dev": true }, + "qjobs": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz", + "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==", + "dev": true + }, + "qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==", + "dev": true + }, "quick-lru": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-1.1.0.tgz", @@ -9091,6 +10940,24 @@ "safe-buffer": "^5.1.0" } }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true + }, + "raw-body": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz", + "integrity": "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==", + "dev": true, + "requires": { + "bytes": "3.1.2", + "http-errors": "1.8.1", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + }, "read-pkg": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", @@ -9197,6 +11064,12 @@ "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", "dev": true }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", + "dev": true + }, "resolve": { "version": "1.22.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", @@ -9241,6 +11114,12 @@ } } }, + "rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", + "dev": true + }, "rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -9272,7 +11151,8 @@ "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true }, "semver-regex": { "version": "1.0.0", @@ -9284,6 +11164,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/semver-sort/-/semver-sort-1.0.0.tgz", "integrity": "sha512-JicVlQKz/C//4BiPmbHEDou6HihXxo5xqB/8Hm9FaLJ6HHkRRvYgCECq4u/z0XF8kyJQ/KAZt++A/kYz/oOSSg==", + "dev": true, "requires": { "semver": "^5.0.3", "semver-regex": "^3.1.2" @@ -9292,7 +11173,8 @@ "semver-regex": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-3.1.3.tgz", - "integrity": "sha512-Aqi54Mk9uYTjVexLnR67rTyBusmwd04cLkHy9hNvk3+G3nT2Oyg7E0l4XVbOaNwIvQ3hHeYxGcyEy+mKreyBFQ==" + "integrity": "sha512-Aqi54Mk9uYTjVexLnR67rTyBusmwd04cLkHy9hNvk3+G3nT2Oyg7E0l4XVbOaNwIvQ3hHeYxGcyEy+mKreyBFQ==", + "dev": true } } }, @@ -9305,6 +11187,12 @@ "randombytes": "^2.1.0" } }, + "setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true + }, "shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -9340,6 +11228,37 @@ "supports-color": "^7.2.0" } }, + "socket.io": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.4.1.tgz", + "integrity": "sha512-s04vrBswdQBUmuWJuuNTmXUVJhP0cVky8bBDhdkf8y0Ptsu7fKU2LuLbts9g+pdmAdyMMn8F/9Mf1/wbtUN0fg==", + "dev": true, + "requires": { + "accepts": "~1.3.4", + "base64id": "~2.0.0", + "debug": "~4.3.2", + "engine.io": "~6.1.0", + "socket.io-adapter": "~2.3.3", + "socket.io-parser": "~4.0.4" + } + }, + "socket.io-adapter": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.3.3.tgz", + "integrity": "sha512-Qd/iwn3VskrpNO60BeRyCyr8ZWw9CPZyitW4AQwmRZ8zCiyDiL+znRnWX6tDHXnWn1sJrM1+b6Mn6wEDJJ4aYQ==", + "dev": true + }, + "socket.io-parser": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.4.tgz", + "integrity": "sha512-t+b0SS+IxG7Rxzda2EVvyBZbvFPBCjJoyHuE0P//7OAsN23GItzDRdWa6ALxZI/8R5ygK7jAR6t028/z+7295g==", + "dev": true, + "requires": { + "@types/component-emitter": "^1.2.10", + "component-emitter": "~1.3.0", + "debug": "~4.3.1" + } + }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -9420,6 +11339,32 @@ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "dev": true + }, + "stream-combiner": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", + "dev": true, + "requires": { + "duplexer": "~0.1.1" + } + }, + "streamroller": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.0.6.tgz", + "integrity": "sha512-Qz32plKq/MZywYyhEatxyYc8vs994Gz0Hu2MSYXXLD233UyPeIeRBZARIIGwFer4Mdb8r3Y2UqKkgyDghM6QCg==", + "dev": true, + "requires": { + "date-format": "^4.0.6", + "debug": "^4.3.4", + "fs-extra": "^10.0.1" + } + }, "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -9490,6 +11435,26 @@ "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==" }, + "temp-fs": { + "version": "0.9.9", + "resolved": "https://registry.npmjs.org/temp-fs/-/temp-fs-0.9.9.tgz", + "integrity": "sha1-gHFzBDeHByDpQxUy/igUNk+IA9c=", + "dev": true, + "requires": { + "rimraf": "~2.5.2" + }, + "dependencies": { + "rimraf": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.5.4.tgz", + "integrity": "sha1-loAAk8vxoMhr2VtGJUZ1NcKd+gQ=", + "dev": true, + "requires": { + "glob": "^7.0.5" + } + } + } + }, "text-extensions": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz", @@ -9518,6 +11483,15 @@ "xtend": "~4.0.1" } }, + "tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "dev": true, + "requires": { + "rimraf": "^3.0.0" + } + }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -9527,6 +11501,12 @@ "is-number": "^7.0.0" } }, + "toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "dev": true + }, "tough-cookie": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz", @@ -9535,6 +11515,13 @@ "psl": "^1.1.33", "punycode": "^2.1.1", "universalify": "^0.1.2" + }, + "dependencies": { + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" + } } }, "tr46": { @@ -9578,16 +11565,32 @@ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", "dev": true }, + "ua-parser-js": { + "version": "0.7.31", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.31.tgz", + "integrity": "sha512-qLK/Xe9E2uzmYI3qLeOmI0tEOt+TBBQyUIAh4aAgU05FVYzeZrKUdkAZfBNVGRaHVgV0TDkdEngJSw/SyQchkQ==", + "dev": true + }, "uglify-js": { - "version": "3.15.2", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.15.2.tgz", - "integrity": "sha512-peeoTk3hSwYdoc9nrdiEJk+gx1ALCtTjdYuKSXMTDqq7n1W7dHPqWDdSi+BPL0ni2YMeHD7hKUSdbj3TZauY2A==", + "version": "3.15.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.15.3.tgz", + "integrity": "sha512-6iCVm2omGJbsu3JWac+p6kUiOpg3wFO2f8lIXjfEb8RrmLjzog1wTPMmwKB7swfzzqxj9YM+sGUM++u1qN4qJg==", "dev": true }, "unc-path-regex": { @@ -9615,9 +11618,16 @@ } }, "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true }, "uri-js": { "version": "4.4.1", @@ -9640,6 +11650,12 @@ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "dev": true + }, "v8-compile-cache": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", @@ -9665,6 +11681,18 @@ "spdx-expression-parse": "^3.0.0" } }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "dev": true + }, + "void-elements": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", + "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=", + "dev": true + }, "w3c-hr-time": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", diff --git a/package.json b/package.json index 745c039..090fc1e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "showdown", - "version": "2.0.0", + "version": "3.0.0-alpha", "description": "A Markdown to HTML converter written in Javascript", "author": "Estevão Santos", "homepage": "http://showdownjs.com/", @@ -58,16 +58,27 @@ "grunt-conventional-github-releaser": "^1.0.0", "grunt-endline": "^0.7.0", "grunt-eslint": "^24.0.0", + "grunt-mocha-test": "^0.13.3", "grunt-simple-mocha": "^0.4.0", + "karma": "^6.3.17", + "karma-browserstack-launcher": "^1.6.0", + "karma-chai": "^0.1.0", + "karma-chrome-launcher": "^3.1.1", + "karma-firefox-launcher": "^2.1.2", + "karma-jsdom-launcher": "^12.0.0", + "karma-mocha": "^2.0.1", "load-grunt-tasks": "^5.1.0", "performance-now": "^2.1.0", "quiet-grunt": "^0.2.0", + "semver-sort": "^1.0.0", "sinon": "*", - "source-map-support": "^0.5.21", - "semver-sort": "^1.0.0" + "source-map-support": "^0.5.21" }, "dependencies": { "commander": "^9.0.0", "jsdom": "^19.0.0" + }, + "overrides": { + "minimist": "^1.2.6" } } diff --git a/src/helpers.js b/src/helpers.js index ac5f1c7..ed33147 100644 --- a/src/helpers.js +++ b/src/helpers.js @@ -47,7 +47,15 @@ showdown.helper.isFunction = function (a) { */ showdown.helper.isArray = function (a) { 'use strict'; - return Array.isArray(a); + let isArray; + if (!Array.isArray) { + isArray = function (arg) { + return Object.prototype.toString.call(arg) === '[object Array]'; + }; + } else { + isArray = Array.isArray; + } + return isArray(a); }; /** @@ -320,11 +328,48 @@ showdown.helper.splitAtIndex = function (str, index) { return [str.substring(0, index), str.substring(index)]; }; + +/** + * MurmurHash3's mixing function + * https://stackoverflow.com/questions/521295/seeding-the-random-number-generator-in-javascript/47593316#47593316 + * + * @param {string} string + * @returns {Number} + */ +/*jshint bitwise: false*/ +function xmur3 (str) { + for (var i = 0, h = 1779033703 ^ str.length; i < str.length; i++) { + h = Math.imul(h ^ str.charCodeAt(i), 3432918353); + h = h << 13 | h >>> 19; + } + return function () { + h = Math.imul(h ^ h >>> 16, 2246822507); + h = Math.imul(h ^ h >>> 13, 3266489909); + return (h ^= h >>> 16) >>> 0; + }; +} + +/** + * Random Number Generator + * https://stackoverflow.com/questions/521295/seeding-the-random-number-generator-in-javascript/47593316#47593316 + * + * @param {Number} seed + * @returns {Number} + */ +/*jshint bitwise: false*/ +function mulberry32 (a) { + return function () { + var t = a += 0x6D2B79F5; + t = Math.imul(t ^ t >>> 15, t | 1); + t ^= t + Math.imul(t ^ t >>> 7, t | 61); + return ((t ^ t >>> 14) >>> 0) / 4294967296; + }; +} + /** * Obfuscate an e-mail address through the use of Character Entities, * transforming ASCII characters into their equivalent decimal or hex entities. * - * Since it has a random component, subsequent calls to this function produce different results * * @param {string} mail * @returns {string} @@ -343,12 +388,15 @@ showdown.helper.encodeEmailAddress = function (mail) { } ]; + // RNG seeded with mail, so that we can get determined results for each email. + var rand = mulberry32(xmur3(mail)); + mail = mail.replace(/./g, function (ch) { if (ch === '@') { // this *must* be encoded. I insist. - ch = encode[Math.floor(Math.random() * 2)](ch); + ch = encode[Math.floor(rand() * 2)](ch); } else { - var r = Math.random(); + var r = rand(); // roughly 10% raw, 45% hex, 45% dec ch = ( r > 0.9 ? encode[2](ch) : r > 0.45 ? encode[1](ch) : encode[0](ch) @@ -405,9 +453,9 @@ showdown.helper.repeat = function (str, count) { /** * String.prototype.padEnd polyfill * - * @param str - * @param targetLength - * @param padString + * @param {string} str + * @param {int} targetLength + * @param {string} [padString] * @returns {string} */ showdown.helper.padEnd = function padEnd (str, targetLength, padString) { @@ -569,6 +617,26 @@ if (typeof (console) === 'undefined') { }; } +// Math.imul() polyfill +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/imul +if (!Math.imul) { + Math.imul = function (opA, opB) { + opB |= 0; // ensure that opB is an integer. opA will automatically be coerced. + // floating points give us 53 bits of precision to work with plus 1 sign bit + // automatically handled for our convienence: + // 1. 0x003fffff /*opA & 0x000fffff*/ * 0x7fffffff /*opB*/ = 0x1fffff7fc00001 + // 0x1fffff7fc00001 < Number.MAX_SAFE_INTEGER /*0x1fffffffffffff*/ + var result = (opA & 0x003fffff) * opB; + // 2. We can remove an integer coersion from the statement above because: + // 0x1fffff7fc00001 + 0xffc00000 = 0x1fffffff800001 + // 0x1fffffff800001 < Number.MAX_SAFE_INTEGER /*0x1fffffffffffff*/ + if (opA & 0xffc00000 /*!== 0*/) { + result += (opA & 0xffc00000) * opB | 0; + } + return result | 0; + }; +} + /** * Common regexes. * We declare some common regexes to improve performance diff --git a/src/subParsers/makehtml/metadata.js b/src/subParsers/makehtml/metadata.js index aa51ecd..c665287 100644 --- a/src/subParsers/makehtml/metadata.js +++ b/src/subParsers/makehtml/metadata.js @@ -34,12 +34,12 @@ showdown.subParser('makehtml.metadata', function (text, options, globals) { }); } - text = text.replace(/^\s*«««+(\S*?)\n([\s\S]+?)\n»»»+\n/, function (wholematch, format, content) { + text = text.replace(/^\s*«««+\s*(\S*?)\n([\s\S]+?)\n»»»+\s*\n/, function (wholematch, format, content) { parseMetadataContents(content); return '¨M'; }); - text = text.replace(/^\s*---+(\S*?)\n([\s\S]+?)\n---+\n/, function (wholematch, format, content) { + text = text.replace(/^\s*---+\s*(\S*?)\n([\s\S]+?)\n---+\s*\n/, function (wholematch, format, content) { if (format) { globals.metadata.format = format; } diff --git a/src/subParsers/makemarkdown/table.js b/src/subParsers/makemarkdown/table.js index 9b06003..606296c 100644 --- a/src/subParsers/makemarkdown/table.js +++ b/src/subParsers/makemarkdown/table.js @@ -1,70 +1,161 @@ -showdown.subParser('makeMarkdown.table', function (node, options, globals) { - 'use strict'; +showdown.subParser('makeMarkdown.table', + /** + * + * @param {DocumentFragment} node + * @param {{}} options + * @param {{}} globals + * @returns {string} + */ + function (node, options, globals) { + 'use strict'; - var txt = '', - tableArray = [[], []], - headings = node.querySelectorAll('thead>tr>th'), - rows = node.querySelectorAll('tbody>tr'), - i, ii; - for (i = 0; i < headings.length; ++i) { - var headContent = showdown.subParser('makeMarkdown.tableCell')(headings[i], options, globals), - allign = '---'; + var txt = '', + tableArray = [[], []], + headings, + rows = [], + colCount, + i, + ii; - if (headings[i].hasAttribute('style')) { - var style = headings[i].getAttribute('style').toLowerCase().replace(/\s/g, ''); - switch (style) { - case 'text-align:left;': - allign = ':---'; - break; - case 'text-align:right;': - allign = '---:'; - break; - case 'text-align:center;': - allign = ':---:'; - break; - } - } - tableArray[0][i] = headContent.trim(); - tableArray[1][i] = allign; - } - - for (i = 0; i < rows.length; ++i) { - var r = tableArray.push([]) - 1, - cols = rows[i].getElementsByTagName('td'); - - for (ii = 0; ii < headings.length; ++ii) { - var cellContent = ' '; - if (typeof cols[ii] !== 'undefined') { - cellContent = showdown.subParser('makeMarkdown.tableCell')(cols[ii], options, globals); - } - tableArray[r].push(cellContent); - } - } - - var cellSpacesCount = 3; - for (i = 0; i < tableArray.length; ++i) { - for (ii = 0; ii < tableArray[i].length; ++ii) { - var strLen = tableArray[i][ii].length; - if (strLen > cellSpacesCount) { - cellSpacesCount = strLen; - } - } - } - - for (i = 0; i < tableArray.length; ++i) { - for (ii = 0; ii < tableArray[i].length; ++ii) { - if (i === 1) { - if (tableArray[i][ii].slice(-1) === ':') { - tableArray[i][ii] = showdown.helper.padEnd(tableArray[i][ii].slice(0, -1), cellSpacesCount - 1, '-') + ':'; - } else { - tableArray[i][ii] = showdown.helper.padEnd(tableArray[i][ii], cellSpacesCount, '-'); + /** + * @param {Element} tr + */ + function iterateRow (tr) { + var children = tr.childNodes, + cols = []; + // we need to iterate by order, since td and th can be used interchangeably and in any order + // we will ignore malformed stuff, comments and floating text. + for (var i = 0; i < children.length; ++i) { + var childName = children[i].nodeName.toUpperCase(); + if (childName === 'TD' || childName === 'TH') { + cols.push(children[i]); } - } else { - tableArray[i][ii] = showdown.helper.padEnd(tableArray[i][ii], cellSpacesCount); + } + return cols; + } + + + // first lets look for + // we will ignore thead without children + // also, since markdown doesn't support tables with multiple heading rows, only the first one will be transformed + // the rest will count as regular rows + if (node.querySelectorAll(':scope>thead').length !== 0 && node.querySelectorAll(':scope>thead>tr').length !== 0) { + var thead = node.querySelectorAll(':scope>thead>tr'); + + // thead>tr can have td and th children + for (i = 0; i < thead.length; ++i) { + rows.push(iterateRow(thead[i])); } } - txt += '| ' + tableArray[i].join(' | ') + ' |\n'; - } - return txt.trim(); -}); + // now let's look for tbody + // we will ignore tbody without children + if (node.querySelectorAll(':scope>tbody').length !== 0 && node.querySelectorAll(':scope>tbody>tr').length !== 0) { + var tbody = node.querySelectorAll(':scope>tbody>tr'); + // tbody>tr can have td and th children, although th are not very screen reader friendly + for (i = 0; i < tbody.length; ++i) { + rows.push(iterateRow(tbody[i])); + } + } + + // now look for tfoot + if (node.querySelectorAll(':scope>tfoot').length !== 0 && node.querySelectorAll(':scope>tfoot>tr').length !== 0) { + var tfoot = node.querySelectorAll(':scope>tfoot>tr'); + // tfoot>tr can have td and th children, although th are not very screen reader friendly + for (i = 0; i < tfoot.length; ++i) { + rows.push(iterateRow(tfoot[i])); + } + } + + // lastly look for naked tr + if (node.querySelectorAll(':scope>tr').length !== 0) { + + var tr = node.querySelectorAll(':scope>tr'); + // tfoot>tr can have td and th children, although th are not very screen reader friendly + for (i = 0; i < tr.length; ++i) { + rows.push(iterateRow(tr[i])); + } + } + + // TODO: implement in tables https://developer.mozilla.org/pt-BR/docs/Web/HTML/Element/caption + // note: is ignored, since they are basically styling + + // we need now to account for cases of completely empty tables, like
or equivalent + if (rows.length === 0) { + // table is empty, return empty text + return txt; + } + + // count the first row. We need it to trim the table (if table rows have inconsistent number of columns) + colCount = rows[0].length; + + // let's shift the first row as a heading + headings = rows.shift(); + + for (i = 0; i < headings.length; ++i) { + var headContent = showdown.subParser('makeMarkdown.tableCell')(headings[i], globals), + align = '---'; + + if (headings[i].hasAttribute('style')) { + var style = headings[i].getAttribute('style').toLowerCase().replace(/\s/g, ''); + switch (style) { + case 'text-align:left;': + align = ':---'; + break; + case 'text-align:right;': + align = '---:'; + break; + case 'text-align:center;': + align = ':---:'; + break; + } + } + tableArray[0][i] = headContent.trim(); + tableArray[1][i] = align; + } + + // now iterate through the rows and create the pseudo output (not pretty yet) + for (i = 0; i < rows.length; ++i) { + var r = tableArray.push([]) - 1; + + for (ii = 0; ii < colCount; ++ii) { + var cellContent = ' '; + if (typeof rows[i][ii] !== 'undefined') { + // Note: if rows[i][ii] is undefined, it means the row has fewer elements than the header, + // and empty content will be added + cellContent = showdown.subParser('makeMarkdown.tableCell')(rows[i][ii], globals); + } + tableArray[r].push(cellContent); + } + } + + // now tidy up the output, aligning cells and stuff + var cellSpacesCount = 3; + for (i = 0; i < tableArray.length; ++i) { + for (ii = 0; ii < tableArray[i].length; ++ii) { + var strLen = tableArray[i][ii].length; + if (strLen > cellSpacesCount) { + cellSpacesCount = strLen; + } + } + } + + for (i = 0; i < tableArray.length; ++i) { + for (ii = 0; ii < tableArray[i].length; ++ii) { + if (i === 1) { + if (tableArray[i][ii].slice(-1) === ':') { + tableArray[i][ii] = showdown.helper.padEnd(tableArray[i][ii].slice(0, -1), cellSpacesCount - 1, '-') + ':'; + } else { + tableArray[i][ii] = showdown.helper.padEnd(tableArray[i][ii], cellSpacesCount, '-'); + } + + } else { + tableArray[i][ii] = showdown.helper.padEnd(tableArray[i][ii], cellSpacesCount); + } + } + txt += '| ' + tableArray[i].join(' | ') + ' |\n'; + } + + return txt.trim(); + } +); diff --git a/test/bootstrap.js b/test/bootstrap.js new file mode 100644 index 0000000..5c2ec14 --- /dev/null +++ b/test/bootstrap.js @@ -0,0 +1,6 @@ +//.webstorm.bootstrap.js +var chai = require('chai'); +global.chai = chai; +global.expect = chai.expect; +global.showdown = require('../.build/showdown.js'); +global.getDefaultOpts = require('./optionswp.js').getDefaultOpts; diff --git a/test/functional/makehtml/cases/features/#709.allow-whitespaces-after-end-in-metadata.html b/test/functional/makehtml/cases/features/#709.allow-whitespaces-after-end-in-metadata.html new file mode 100644 index 0000000..4475fc7 --- /dev/null +++ b/test/functional/makehtml/cases/features/#709.allow-whitespaces-after-end-in-metadata.html @@ -0,0 +1,8 @@ +

some markdown text

+
    +
  • a list
  • +
  • another list ---
  • +
  • and stuff
  • +
+

a paragraph --- with dashes

+
diff --git a/test/functional/makehtml/cases/features/#709.allow-whitespaces-after-end-in-metadata.md b/test/functional/makehtml/cases/features/#709.allow-whitespaces-after-end-in-metadata.md new file mode 100644 index 0000000..5c54a01 --- /dev/null +++ b/test/functional/makehtml/cases/features/#709.allow-whitespaces-after-end-in-metadata.md @@ -0,0 +1,16 @@ +--- + +title: This is the document title +language: en +author: Tivie + +--- +**some** markdown text + +- a list +- another list --- +- and stuff + +a paragraph --- with dashes + +--- diff --git a/test/functional/makehtml/makehtml.bootstrap.js b/test/functional/makehtml/makehtml.bootstrap.js index a4a092d..9ef7672 100644 --- a/test/functional/makehtml/makehtml.bootstrap.js +++ b/test/functional/makehtml/makehtml.bootstrap.js @@ -8,7 +8,7 @@ require('source-map-support').install(); require('chai').should(); - var fs = require('fs'); + let fs = require('fs'); function getTestSuite (dir) { return fs.readdirSync(dir) @@ -17,20 +17,20 @@ } function getJsonTestSuite (file) { - var json = JSON.parse(fs.readFileSync(file, 'utf8')); + let json = JSON.parse(fs.readFileSync(file, 'utf8')); return mapJson(json, file); } function filter () { return function (file) { - var ext = file.slice(-3); + let ext = file.slice(-3); return (ext === '.md'); }; } function map (dir) { return function (file) { - var oFile = 'file://' + process.cwd().replace(/\\/g, '/') + dir + file, + let oFile = 'file://' + process.cwd().replace(/\\/g, '/') + dir + file, name = file.replace('.md', ''), htmlPath = dir + name + '.html', html = fs.readFileSync(htmlPath, 'utf8'), @@ -47,12 +47,12 @@ } function mapJson (jsonArray, file) { - var tcObj = {}; - for (var i = 0; i < jsonArray.length; ++i) { - var section = jsonArray[i].section; - var name = jsonArray[i].section + '_' + jsonArray[i].example; - var md = jsonArray[i].markdown; - var html = jsonArray[i].html; + let tcObj = {}; + for (let i = 0; i < jsonArray.length; ++i) { + let section = jsonArray[i].section; + let name = jsonArray[i].section + '_' + jsonArray[i].example; + let md = jsonArray[i].markdown; + let html = jsonArray[i].html; if (!tcObj.hasOwnProperty(section)) { tcObj[section] = []; } diff --git a/test/functional/makehtml/testsuite.features.js b/test/functional/makehtml/testsuite.features.js index 8cbdfc0..2ef6c38 100644 --- a/test/functional/makehtml/testsuite.features.js +++ b/test/functional/makehtml/testsuite.features.js @@ -100,6 +100,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 === '#709.allow-whitespaces-after-end-in-metadata') { + converter = new showdown.Converter({metadata: true}); } else if (testsuite[i].name === 'relativePathBaseUrl') { converter = new showdown.Converter({relativePathBaseUrl: 'http://my.site.com/'}); } else { @@ -199,7 +201,7 @@ describe('makeHtml() features testsuite', function () { function testImageUrlExists (imgUrl) { // Strip the quotes - imgUrl = imgUrl.substr(0, imgUrl.length - 1).substr(1); + imgUrl = imgUrl.slice(1, -1); return function (done) { (imgUrl.startsWith('http://') ? http : https).get(imgUrl, function (res) { expect(res.statusCode).to.equal(200); diff --git a/test/functional/makemarkdown/cases/standard/table-complex.html b/test/functional/makemarkdown/cases/standard/table-complex.html new file mode 100644 index 0000000..840c185 --- /dev/null +++ b/test/functional/makemarkdown/cases/standard/table-complex.html @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
some table
head 1head 2head 3
row 1: col 1row 1: col 2row 1: col 3
row 2: col 1row 2: col 2row 2: col 3
footer 1footer 2footer 3
footer 4footer 5footer 6
+ diff --git a/test/functional/makemarkdown/cases/standard/table-complex.md b/test/functional/makemarkdown/cases/standard/table-complex.md new file mode 100644 index 0000000..d420caf --- /dev/null +++ b/test/functional/makemarkdown/cases/standard/table-complex.md @@ -0,0 +1,6 @@ +| head 1 | head 2 | head 3 | +| ------------ | ------------ | ------------ | +| row 1: col 1 | row 1: col 2 | row 1: col 3 | +| row 2: col 1 | row 2: col 2 | row 2: col 3 | +| footer 1 | footer 2 | footer 3 | +| footer 4 | footer 5 | footer 6 | diff --git a/test/functional/makemarkdown/cases/standard/table-header-only.html b/test/functional/makemarkdown/cases/standard/table-header-only.html new file mode 100644 index 0000000..e1afebc --- /dev/null +++ b/test/functional/makemarkdown/cases/standard/table-header-only.html @@ -0,0 +1,8 @@ + + + + + + + +
foobar
diff --git a/test/functional/makemarkdown/cases/standard/table-header-only.md b/test/functional/makemarkdown/cases/standard/table-header-only.md new file mode 100644 index 0000000..4e563e4 --- /dev/null +++ b/test/functional/makemarkdown/cases/standard/table-header-only.md @@ -0,0 +1,2 @@ +| foo | bar | +| --- | --- | diff --git a/test/functional/makemarkdown/cases/standard/table-mix-malformed.html b/test/functional/makemarkdown/cases/standard/table-mix-malformed.html new file mode 100644 index 0000000..f3c551b --- /dev/null +++ b/test/functional/makemarkdown/cases/standard/table-mix-malformed.html @@ -0,0 +1,6 @@ +
+ + + +
some stuff
+ diff --git a/test/functional/makemarkdown/cases/standard/table-mix-malformed.md b/test/functional/makemarkdown/cases/standard/table-mix-malformed.md new file mode 100644 index 0000000..e69de29 diff --git a/test/functional/makemarkdown/cases/standard/table-no-header.html b/test/functional/makemarkdown/cases/standard/table-no-header.html new file mode 100644 index 0000000..57a3eac --- /dev/null +++ b/test/functional/makemarkdown/cases/standard/table-no-header.html @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + +
foobar
baristayes
diff --git a/test/functional/makemarkdown/cases/standard/table-no-header.md b/test/functional/makemarkdown/cases/standard/table-no-header.md new file mode 100644 index 0000000..1a5f4dd --- /dev/null +++ b/test/functional/makemarkdown/cases/standard/table-no-header.md @@ -0,0 +1,4 @@ +| | | +| ------- | ------- | +| foo | bar | +| barista | yes | diff --git a/test/functional/makemarkdown/cases/standard/table-simple.html b/test/functional/makemarkdown/cases/standard/table-simple.html new file mode 100644 index 0000000..0938d8f --- /dev/null +++ b/test/functional/makemarkdown/cases/standard/table-simple.html @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + +
head 1head 2head 3
row 1: col 1row 1: col 2row 1: col 3
row 2: col 1row 2: col 2row 2: col 3
diff --git a/test/functional/makemarkdown/cases/standard/table-simple.md b/test/functional/makemarkdown/cases/standard/table-simple.md new file mode 100644 index 0000000..a367fc2 --- /dev/null +++ b/test/functional/makemarkdown/cases/standard/table-simple.md @@ -0,0 +1,4 @@ +| head 1 | head 2 | head 3 | +| ------------ | ------------ | ------------ | +| row 1: col 1 | row 1: col 2 | row 1: col 3 | +| row 2: col 1 | row 2: col 2 | row 2: col 3 | diff --git a/test/unit/optionswp.js b/test/optionswp.js similarity index 100% rename from test/unit/optionswp.js rename to test/optionswp.js diff --git a/test/unit/cli.js b/test/unit/cli.js index 6893dac..98ac1d0 100644 --- a/test/unit/cli.js +++ b/test/unit/cli.js @@ -62,10 +62,11 @@ describe('showdown cli', function () { describe('-v', function () { it('should display version', function () { - var proc = spawnCLI(null, ['-V'], {}); + let proc = spawnCLI(null, ['-V'], {}), + verRegex = /^(\d{1,2}\.\d{1,3}\.\d{1,3}(?:-(alpha)|(beta)|(rc-\d{1,2})))?/; 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.stdout.should.match(verRegex); + proc.stdout.should.match(verRegex).and.capture(0).equals(packageJson.version); proc.stderr.should.equal(''); }); }); diff --git a/test/unit/showdown.Converter.js b/test/unit/showdown.Converter.js index 0b8c7e0..7ff6b8d 100644 --- a/test/unit/showdown.Converter.js +++ b/test/unit/showdown.Converter.js @@ -1,16 +1,15 @@ /** * Created by Estevao on 31-05-2015. */ -require('source-map-support').install(); -require('chai').should(); -require('sinon'); -var showdown = require('../../.build/showdown.js'); +//let showdown = require('../../.build/showdown.js') || require('showdown'); +chai.should(); + describe('showdown.Converter', function () { 'use strict'; describe('option methods', function () { - var converter = new showdown.Converter(); + let converter = new showdown.Converter(); it('setOption() should set option foo=baz', function () { converter.setOption('foo', 'baz'); @@ -21,14 +20,14 @@ describe('showdown.Converter', function () { }); it('getOptions() should contain foo=baz', function () { - var options = converter.getOptions(); + let options = converter.getOptions(); options.should.have.ownProperty('foo'); options.foo.should.equal('baz'); }); }); describe('metadata methods', function () { - var converter = new showdown.Converter(); + let converter = new showdown.Converter(); it('_setMetadataPair() should set foo to bar', function () { converter._setMetadataPair('foo', 'bar'); @@ -47,18 +46,18 @@ describe('showdown.Converter', function () { * Test setFlavor('github') */ describe('github', function () { - var converter = new showdown.Converter(), + let converter = new showdown.Converter(), ghOpts = showdown.getFlavorOptions('github'); converter.setFlavor('github'); - for (var opt in ghOpts) { + for (let opt in ghOpts) { if (ghOpts.hasOwnProperty(opt)) { check(opt, ghOpts[opt]); } } function check (key, val) { - it('should set ' + opt + ' to ' + val, function () { + it('should set ' + key + ' to ' + val, function () { converter.getOption(key).should.equal(val); }); } @@ -72,19 +71,19 @@ describe('showdown.Converter', function () { describe('flavor', function () { it('should be vanilla by default', function () { - var converter = new showdown.Converter(); + let converter = new showdown.Converter(); converter.getFlavor().should.equal('vanilla'); }); it('should be changed if global option is changed', function () { showdown.setFlavor('github'); - var converter = new showdown.Converter(); + let converter = new showdown.Converter(); converter.getFlavor().should.equal('github'); showdown.setFlavor('vanilla'); }); it('should not be changed if converter is initialized before global change', function () { - var converter = new showdown.Converter(); + let converter = new showdown.Converter(); showdown.setFlavor('github'); converter.getFlavor().should.equal('vanilla'); showdown.setFlavor('vanilla'); @@ -93,7 +92,7 @@ describe('showdown.Converter', function () { }); describe('extension methods', function () { - var extObjMock = { + let extObjMock = { type: 'lang', filter: function () {} }, @@ -102,13 +101,13 @@ describe('showdown.Converter', function () { }; it('addExtension() should add an extension Object', function () { - var converter = new showdown.Converter(); + let converter = new showdown.Converter(); converter.addExtension(extObjMock); converter.getAllExtensions().language.should.contain(extObjMock); }); it('addExtension() should unwrap an extension wrapped in a function', function () { - var converter = new showdown.Converter(); + let converter = new showdown.Converter(); converter.addExtension(extObjFunc); converter.getAllExtensions().language.should.contain(extObjMock); @@ -116,7 +115,7 @@ describe('showdown.Converter', function () { it('useExtension() should use a previous registered extension in showdown', function () { showdown.extension('foo', extObjMock); - var converter = new showdown.Converter(); + let converter = new showdown.Converter(); converter.useExtension('foo'); converter.getAllExtensions().language.should.contain(extObjMock); @@ -124,7 +123,7 @@ describe('showdown.Converter', function () { }); it('removeExtension() should remove an added extension', function () { - var converter = new showdown.Converter(); + let converter = new showdown.Converter(); converter.addExtension(extObjMock); converter.removeExtension(extObjMock); @@ -133,7 +132,7 @@ describe('showdown.Converter', function () { }); describe('events', function () { - var events = [ + let events = [ 'makehtml.anchors', 'makehtml.autoLinks', 'makehtml.blockGamut', @@ -151,17 +150,17 @@ describe('showdown.Converter', function () { //'tables' ]; - for (var i = 0; i < events.length; ++i) { + for (let i = 0; i < events.length; ++i) { runListener(events[i] + '.before'); runListener(events[i] + '.after'); } function runListener (name) { it('should listen to ' + name, function () { - var converter = new showdown.Converter(); + let converter = new showdown.Converter(); converter.listen(name, function (event) { - var evtName = event.getName(); - var text = event.getCapturedText(); + let evtName = event.getName(); + let text = event.getCapturedText(); evtName.should.equal(name.toLowerCase()); text.should.match(/^[\s\S]*foo[\s\S]*$/); return text; diff --git a/test/unit/showdown.Converter.makeHtml.js b/test/unit/showdown.Converter.makeHtml.js index 26a9f59..4715ac4 100644 --- a/test/unit/showdown.Converter.makeHtml.js +++ b/test/unit/showdown.Converter.makeHtml.js @@ -1,16 +1,15 @@ /** - * Created by Estevao on 15-01-2015. + * Created by Tivie on 15-01-2015. */ -require('source-map-support').install(); -require('chai').should(); -require('sinon'); -var showdown = require('../../.build/showdown.js'); +//let showdown = require('../../.build/showdown.js') || require('showdown'); +chai.should(); + describe('showdown.Converter', function () { 'use strict'; describe('Converter.options extensions', function () { - var runCount; + let runCount; showdown.extension('testext', function () { return [{ type: 'output', @@ -21,7 +20,7 @@ describe('showdown.Converter', function () { }]; }); - var converter = new showdown.Converter({extensions: ['testext']}); + let converter = new showdown.Converter({extensions: ['testext']}); it('output extensions should run once', function () { runCount = 0; @@ -31,36 +30,36 @@ describe('showdown.Converter', function () { }); describe('makeHtml() with option omitExtraWLInCodeBlocks', function () { - var converter = new showdown.Converter({omitExtraWLInCodeBlocks: true}), + let converter = new showdown.Converter({omitExtraWLInCodeBlocks: true}), text = 'var foo = bar;', html = converter.makeHtml(' ' + text); it('should omit extra line after code tag', function () { - var expectedHtml = '
' + text + '
'; + let expectedHtml = '
' + text + '
'; html.should.equal(expectedHtml); }); }); describe('makeHtml() with option prefixHeaderId', function () { - var converter = new showdown.Converter(), + let converter = new showdown.Converter(), text = 'foo header'; it('should prefix header id with "section"', function () { converter.setOption('prefixHeaderId', true); - var html = converter.makeHtml('# ' + text), + let html = converter.makeHtml('# ' + text), expectedHtml = '

' + text + '

'; html.should.equal(expectedHtml); }); it('should prefix header id with custom string', function () { converter.setOption('prefixHeaderId', 'blabla'); - var html = converter.makeHtml('# ' + text), + let html = converter.makeHtml('# ' + text), expectedHtml = '

' + text + '

'; html.should.equal(expectedHtml); }); }); describe('makeHtml() with option metadata', function () { - var converter = new showdown.Converter(), + let converter = new showdown.Converter(), text1 = '---SIMPLE\n' + 'foo: bar\n' + @@ -75,7 +74,7 @@ describe('showdown.Converter', function () { it('should correctly set metadata', function () { converter.setOption('metadata', true); - var expectedHtml = '', + let expectedHtml = '', expectedObj = {foo: 'bar', baz: 'bazinga'}, expectedRaw = 'foo: bar\nbaz: bazinga', expectedFormat = 'SIMPLE'; @@ -87,7 +86,7 @@ describe('showdown.Converter', function () { it('consecutive calls should reset metadata', function () { converter.makeHtml(text2); - var expectedObj = {a: 'b', c: '123'}, + let expectedObj = {a: 'b', c: '123'}, expectedRaw = 'a: b\nc: 123', expectedFormat = 'TIVIE'; converter.getMetadata().should.eql(expectedObj); diff --git a/test/unit/showdown.Converter.makeMarkdown.js b/test/unit/showdown.Converter.makeMarkdown.js index 95e6e9c..2512764 100644 --- a/test/unit/showdown.Converter.makeMarkdown.js +++ b/test/unit/showdown.Converter.makeMarkdown.js @@ -1,21 +1,19 @@ /** * Created by Estevao on 15-01-2015. */ -require('source-map-support').install(); -require('chai').should(); -require('sinon'); -var showdown = require('../../.build/showdown.js'); +//let showdown = require('../../.build/showdown.js') || require('showdown'); +chai.should(); describe('showdown.Converter', function () { 'use strict'; describe('makeMarkdown()', function () { - var converter = new showdown.Converter(); + let converter = new showdown.Converter(); it('should parse a simple html string', function () { - var html = 'a link\n'; - var md = '[a link]()'; + let html = 'a link\n'; + let md = '[a link]()'; converter.makeMarkdown(html).should.equal(md); }); diff --git a/test/unit/showdown.helpers.js b/test/unit/showdown.helpers.js index 2995728..b76da71 100644 --- a/test/unit/showdown.helpers.js +++ b/test/unit/showdown.helpers.js @@ -1,10 +1,7 @@ /** * Created by Tivie on 27/01/2017. */ -require('source-map-support').install(); -require('chai').should(); -require('sinon'); -var showdown = require('../../.build/showdown.js'); +chai.should(); /*jshint expr: true*/ /*jshint -W053 */ /*jshint -W010 */ @@ -12,16 +9,21 @@ var showdown = require('../../.build/showdown.js'); describe('encodeEmailAddress()', function () { 'use strict'; - var encoder = showdown.helper.encodeEmailAddress, + let encoder = showdown.helper.encodeEmailAddress, email = 'foobar@example.com', - encodedEmail = encoder(email); + encodedEmail = encoder(email), + encodedEmail2 = encoder(email); it('should encode email', function () { encodedEmail.should.not.equal(email); }); + it('should encode email determinated', function () { + encodedEmail.should.equal(encodedEmail2); + }); + it('should decode to original email', function () { - var decodedEmail = encodedEmail.replace(/&#(.+?);/g, function (wm, cc) { + let decodedEmail = encodedEmail.replace(/&#(.+?);/g, function (wm, cc) { if (cc.charAt(0) === 'x') { //hex return String.fromCharCode('0' + cc); @@ -36,7 +38,7 @@ describe('encodeEmailAddress()', function () { describe('isString()', function () { 'use strict'; - var isString = showdown.helper.isString; + let isString = showdown.helper.isString; it('should return true for new String Object', function () { isString(new String('some string')).should.be.true; @@ -65,7 +67,7 @@ describe('isString()', function () { describe('isFunction()', function () { 'use strict'; - var isFunction = showdown.helper.isFunction; + let isFunction = showdown.helper.isFunction; it('should return true for closures', function () { isFunction(function () {}).should.be.true; @@ -76,8 +78,8 @@ describe('isFunction()', function () { isFunction(foo).should.be.true; }); - it('should return true for function variables', function () { - var bar = function () {}; + it('should return true for function letiables', function () { + let bar = function () {}; isFunction(bar).should.be.true; }); @@ -96,14 +98,14 @@ describe('isFunction()', function () { describe('isArray()', function () { 'use strict'; - var isArray = showdown.helper.isArray; + let isArray = showdown.helper.isArray; it('should return true for short syntax arrays', function () { isArray([]).should.be.true; }); it('should return true for array objects', function () { - var myArr = new Array(); + let myArr = new Array(); isArray(myArr).should.be.true; }); @@ -126,14 +128,14 @@ describe('isArray()', function () { describe('isUndefined()', function () { 'use strict'; - var isUndefined = showdown.helper.isUndefined; + let isUndefined = showdown.helper.isUndefined; it('should return true if nothing is passed', function () { isUndefined().should.be.true; }); - it('should return true if a variable is initialized but not defined', function () { - var myVar; + it('should return true if a letiable is initialized but not defined', function () { + let myVar; isUndefined(myVar).should.be.true; }); @@ -163,15 +165,15 @@ describe('isUndefined()', function () { describe('stdExtName()', function () { 'use strict'; - var stdExtName = showdown.helper.stdExtName; + let stdExtName = showdown.helper.stdExtName; it('should remove certain chars', function () { - var str = 'bla_- \nbla'; + let str = 'bla_- \nbla'; //[_?*+\/\\.^-] stdExtName(str).should.not.match(/[_?*+\/\\.^-]/g); }); it('should make everything lowercase', function () { - var str = 'BLABLA'; + let str = 'BLABLA'; //[_?*+\/\\.^-] stdExtName(str).should.equal('blabla'); }); @@ -179,7 +181,7 @@ describe('stdExtName()', function () { describe('forEach()', function () { 'use strict'; - var forEach = showdown.helper.forEach; + let forEach = showdown.helper.forEach; it('should throw an error if first parameter is undefined', function () { (function () {forEach();}).should.throw('obj param is required'); @@ -202,7 +204,7 @@ describe('forEach()', function () { }); it('should iterate array items', function () { - var myArray = ['banana', 'orange', 'grape']; + let myArray = ['banana', 'orange', 'grape']; forEach(myArray, function (val, key, obj) { key.should.be.a('number'); (key % 1).should.equal(0); @@ -212,7 +214,7 @@ describe('forEach()', function () { }); it('should iterate over object properties', function () { - var myObj = {foo: 'banana', bar: 'orange', baz: 'grape'}; + let myObj = {foo: 'banana', bar: 'orange', baz: 'grape'}; forEach(myObj, function (val, key, obj) { myObj.should.have.ownProperty(key); val.should.equal(myObj[key]); @@ -221,7 +223,7 @@ describe('forEach()', function () { }); it('should iterate only over object own properties', function () { - var Obj1 = {foo: 'banana'}, + let Obj1 = {foo: 'banana'}, myObj = Object.create(Obj1); myObj.bar = 'orange'; myObj.baz = 'grape'; @@ -239,10 +241,10 @@ describe('forEach()', function () { describe('matchRecursiveRegExp()', function () { 'use strict'; - var rRegExp = showdown.helper.matchRecursiveRegExp; + let rRegExp = showdown.helper.matchRecursiveRegExp; it('should match nested elements', function () { - var result = rRegExp('
a
', ']*>', '
', 'gim'); + let result = rRegExp('
a
', ']*>', '', 'gim'); result.should.deep.equal([['
a
', '
a
', '
', '
']]); }); @@ -251,9 +253,11 @@ describe('matchRecursiveRegExp()', function () { describe('repeat()', function () { 'use strict'; it('work produce the same output as String.prototype.repeat()', function () { - var str = 'foo', - expected = str.repeat(100), - actual = showdown.helper.repeat(str, 100); - expected.should.equal(actual); + if (typeof String.prototype.repeat !== 'undefined') { + let str = 'foo', + expected = str.repeat(100), + actual = showdown.helper.repeat(str, 100); + expected.should.equal(actual); + } }); }); diff --git a/test/unit/showdown.js b/test/unit/showdown.js index 0d9cbf4..d96e9fc 100644 --- a/test/unit/showdown.js +++ b/test/unit/showdown.js @@ -1,9 +1,7 @@ -require('source-map-support').install(); -require('chai').should(); -require('sinon'); -var expect = require('chai').expect, - showdown = require('../../.build/showdown.js'); - +/** + * Created by Tivie on 27/01/2017. + */ +//let showdown = require('../../.build/showdown.js') || require('showdown'); describe('showdown.options', function () { 'use strict'; @@ -19,7 +17,7 @@ describe('showdown.options', function () { describe('getDefaultOptions()', function () { it('should get default options', function () { - var opts = require('./optionswp.js').getDefaultOpts(true); + let opts = getDefaultOpts(true); expect(showdown.getDefaultOptions()).to.be.eql(opts); }); }); @@ -28,7 +26,7 @@ describe('showdown.options', function () { describe('showdown.extension()', function () { 'use strict'; - var extObjMock = { + let extObjMock = { type: 'lang', filter: function () {} }, @@ -36,6 +34,8 @@ describe('showdown.extension()', function () { return extObjMock; }; + /* + // very flimsy test describe('file loading', function () { beforeEach(function () { @@ -52,7 +52,7 @@ describe('showdown.extension()', function () { }); }); - + */ describe('objects', function () { it('should register an extension object', function () { @@ -77,14 +77,14 @@ describe('showdown.extension()', function () { }); it('should refuse to register a generic object', function () { - var fn = function () { + let fn = function () { showdown.extension('foo', {}); }; expect(fn).to.throw(); }); it('should refuse to register an extension with invalid type', function () { - var fn = function () { + let fn = function () { showdown.extension('foo', { type: 'foo' }); @@ -93,7 +93,7 @@ describe('showdown.extension()', function () { }); it('should refuse to register an extension without regex or filter', function () { - var fn = function () { + let fn = function () { showdown.extension('foo', { type: 'lang' }); @@ -102,7 +102,7 @@ describe('showdown.extension()', function () { }); it('should refuse to register a listener extension without a listeners property', function () { - var fn = function () { + let fn = function () { showdown.extension('foo', { type: 'listener' }); @@ -120,7 +120,7 @@ describe('showdown.extension()', function () { describe('showdown.getAllExtensions()', function () { 'use strict'; - var extObjMock = { + let extObjMock = { type: 'lang', filter: function () {} }; @@ -141,9 +141,9 @@ describe('showdown.setFlavor()', function () { it('should set options correctly', function () { showdown.setFlavor('github'); - var ghOpts = showdown.getFlavorOptions('github'), + let ghOpts = showdown.getFlavorOptions('github'), shOpts = showdown.getOptions(); - for (var opt in ghOpts) { + for (let opt in ghOpts) { if (ghOpts.hasOwnProperty(opt)) { shOpts.should.have.property(opt); shOpts[opt].should.equal(ghOpts[opt]); @@ -154,10 +154,10 @@ describe('showdown.setFlavor()', function () { it('should switch between flavors correctly', function () { showdown.setFlavor('github'); - var ghOpts = showdown.getFlavorOptions('github'), + let ghOpts = showdown.getFlavorOptions('github'), shOpts = showdown.getOptions(), dfOpts = showdown.getDefaultOptions(); - for (var opt in dfOpts) { + for (let opt in dfOpts) { if (ghOpts.hasOwnProperty(opt)) { shOpts[opt].should.equal(ghOpts[opt]); } else { @@ -165,9 +165,9 @@ describe('showdown.setFlavor()', function () { } } showdown.setFlavor('original'); - var orOpts = showdown.getFlavorOptions('original'); + let orOpts = showdown.getFlavorOptions('original'); shOpts = showdown.getOptions(); - for (opt in dfOpts) { + for (let opt in dfOpts) { if (orOpts.hasOwnProperty(opt)) { shOpts[opt].should.equal(orOpts[opt]); } else {