diff --git a/packages/ckeditor5-markdown-gfm/package.json b/packages/ckeditor5-markdown-gfm/package.json index a92258c9ab5..98bfb6a2981 100644 --- a/packages/ckeditor5-markdown-gfm/package.json +++ b/packages/ckeditor5-markdown-gfm/package.json @@ -10,7 +10,10 @@ "ckeditor5-plugin" ], "dependencies": { - "@ckeditor/ckeditor5-engine": "^21.0.0" + "@ckeditor/ckeditor5-engine": "^21.0.0", + "marked": "^0.7.0", + "turndown": "^6.0.0", + "turndown-plugin-gfm": "^1.0.2" }, "engines": { "node": ">=12.0.0", diff --git a/packages/ckeditor5-markdown-gfm/src/gfmdataprocessor.js b/packages/ckeditor5-markdown-gfm/src/gfmdataprocessor.js index 39bca1e5f4d..fd21b8eeeb4 100644 --- a/packages/ckeditor5-markdown-gfm/src/gfmdataprocessor.js +++ b/packages/ckeditor5-markdown-gfm/src/gfmdataprocessor.js @@ -7,11 +7,10 @@ * @module markdown-gfm/gfmdataprocessor */ -import marked from './lib/marked/marked'; -import toMarkdown from './lib/to-markdown/to-markdown'; import HtmlDataProcessor from '@ckeditor/ckeditor5-engine/src/dataprocessor/htmldataprocessor'; -import GFMRenderer from './lib/marked/renderer'; -import converters from './lib/to-markdown/converters'; + +import markdown2html from './markdown2html/markdown2html'; +import html2markdown, { turndownService } from './html2markdown/html2markdown'; /** * This data processor implementation uses GitHub Flavored Markdown as input/output data. @@ -36,6 +35,18 @@ export default class GFMDataProcessor { this._htmlDP = new HtmlDataProcessor( document ); } + /** + * Keeps the specified element in the output as HTML. This is useful if the editor contains + * features that produce HTML that are not part of the markdon standards. + * + * By default, all HTML tags are removed. + * + * @param element {String} The element name to be kept. + */ + keepHtml( element ) { + turndownService.keep( [ element ] ); + } + /** * Converts the provided Markdown string to view tree. * @@ -43,14 +54,7 @@ export default class GFMDataProcessor { * @returns {module:engine/view/documentfragment~DocumentFragment} The converted view element. */ toView( data ) { - const html = marked.parse( data, { - gfm: true, - breaks: true, - tables: true, - xhtml: true, - renderer: new GFMRenderer() - } ); - + const html = markdown2html( data ); return this._htmlDP.toView( html ); } @@ -63,7 +67,6 @@ export default class GFMDataProcessor { */ toData( viewFragment ) { const html = this._htmlDP.toData( viewFragment ); - - return toMarkdown( html, { gfm: true, converters } ); + return html2markdown( html ); } } diff --git a/packages/ckeditor5-markdown-gfm/src/html2markdown/html2markdown.js b/packages/ckeditor5-markdown-gfm/src/html2markdown/html2markdown.js new file mode 100644 index 00000000000..33de80c222f --- /dev/null +++ b/packages/ckeditor5-markdown-gfm/src/html2markdown/html2markdown.js @@ -0,0 +1,93 @@ +/** + * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved. + * For licensing, see LICENSE.md. + */ + +/** + * @module markdown-gfm/html2markdown + */ + +import TurndownService from 'turndown'; +import { gfm } from 'turndown-plugin-gfm'; + +// Override the original escape method by not escaping links. +const originalEscape = TurndownService.prototype.escape; + +function escape( string ) { + string = originalEscape( string ); + + // Escape "<". + string = string.replace( /]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()[\]{};:'".,<>?«»“”‘’])/g; + +TurndownService.prototype.escape = function( string ) { + // Urls should not be escaped. Our strategy is using a regex to find them and escape everything + // which is out of the matches parts. + + let escaped = ''; + let lastLinkEnd = 0; + + for ( const match of string.matchAll( regex ) ) { + const index = match.index; + + // Append the substring between the last match and the current one (if anything). + if ( index > lastLinkEnd ) { + escaped += escape( string.substring( lastLinkEnd, index ) ); + } + + const matchedURL = match[ 0 ]; + + escaped += matchedURL; + + lastLinkEnd = index + matchedURL.length; + } + + // Add text after the last link or at the string start if no matches. + if ( lastLinkEnd < string.length ) { + escaped += escape( string.substring( lastLinkEnd, string.length ) ); + } + + return escaped; +}; + +const turndownService = new TurndownService( { + codeBlockStyle: 'fenced', + hr: '---', + headingStyle: 'atx' +} ); + +turndownService.use( [ + gfm, + todoList +] ); + +/** + * Parses HTML to a markdown. + * + * @param {String} html + * @returns {String} + */ +export default function html2markdown( html ) { + return turndownService.turndown( html ); +} + +export { turndownService }; + +// This is a copy of the original taskListItems rule from turdown-plugin-gfm, with minor changes. +function todoList( turndownService ) { + turndownService.addRule( 'taskListItems', { + filter( node ) { + return node.type === 'checkbox' && + // Changes here as CKEditor outputs a deeper structure. + ( node.parentNode.nodeName === 'LI' || node.parentNode.parentNode.nodeName === 'LI' ); + }, + replacement( content, node ) { + return ( node.checked ? '[x]' : '[ ]' ) + ' '; + } + } ); +} diff --git a/packages/ckeditor5-markdown-gfm/src/lib/marked/marked.js b/packages/ckeditor5-markdown-gfm/src/lib/marked/marked.js deleted file mode 100644 index 3f35f63271f..00000000000 --- a/packages/ckeditor5-markdown-gfm/src/lib/marked/marked.js +++ /dev/null @@ -1,1286 +0,0 @@ -/** - * marked - a markdown parser - * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed) - * https://github.com/chjj/marked - */ - -;(function() { - -/** - * Block-Level Grammar - */ - -var block = { - newline: /^\n+/, - code: /^( {4}[^\n]+\n*)+/, - fences: noop, - hr: /^( *[-*_]){3,} *(?:\n+|$)/, - heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/, - nptable: noop, - lheading: /^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/, - blockquote: /^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/, - list: /^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/, - html: /^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/, - def: /^ *\[([^\]]+)\]: *]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/, - table: noop, - paragraph: /^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/, - text: /^[^\n]+/ -}; - -block.bullet = /(?:[*+-]|\d+\.)/; -block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/; -block.item = replace(block.item, 'gm') - (/bull/g, block.bullet) - (); - -block.list = replace(block.list) - (/bull/g, block.bullet) - ('hr', '\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))') - ('def', '\\n+(?=' + block.def.source + ')') - (); - -block.blockquote = replace(block.blockquote) - ('def', block.def) - (); - -block._tag = '(?!(?:' - + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code' - + '|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo' - + '|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b'; - -block.html = replace(block.html) - ('comment', //) - ('closed', /<(tag)[\s\S]+?<\/\1>/) - ('closing', /])*?>/) - (/tag/g, block._tag) - (); - -block.paragraph = replace(block.paragraph) - ('hr', block.hr) - ('heading', block.heading) - ('lheading', block.lheading) - ('blockquote', block.blockquote) - ('tag', '<' + block._tag) - ('def', block.def) - (); - -/** - * Normal Block Grammar - */ - -block.normal = merge({}, block); - -/** - * GFM Block Grammar - */ - -block.gfm = merge({}, block.normal, { - fences: /^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]*?)\s*\1 *(?:\n+|$)/, - paragraph: /^/, - heading: /^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/ -}); - -block.gfm.paragraph = replace(block.paragraph) - ('(?!', '(?!' - + block.gfm.fences.source.replace('\\1', '\\2') + '|' - + block.list.source.replace('\\1', '\\3') + '|') - (); - -/** - * GFM + Tables Block Grammar - */ - -block.tables = merge({}, block.gfm, { - nptable: /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/, - table: /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/ -}); - -/** - * Block Lexer - */ - -function Lexer(options) { - this.tokens = []; - this.tokens.links = {}; - this.options = options || marked.defaults; - this.rules = block.normal; - - if (this.options.gfm) { - if (this.options.tables) { - this.rules = block.tables; - } else { - this.rules = block.gfm; - } - } -} - -/** - * Expose Block Rules - */ - -Lexer.rules = block; - -/** - * Static Lex Method - */ - -Lexer.lex = function(src, options) { - var lexer = new Lexer(options); - return lexer.lex(src); -}; - -/** - * Preprocessing - */ - -Lexer.prototype.lex = function(src) { - src = src - .replace(/\r\n|\r/g, '\n') - .replace(/\t/g, ' ') - .replace(/\u00a0/g, ' ') - .replace(/\u2424/g, '\n'); - - return this.token(src, true); -}; - -/** - * Lexing - */ - -Lexer.prototype.token = function(src, top, bq) { - var src = src.replace(/^ +$/gm, '') - , next - , loose - , cap - , bull - , b - , item - , space - , i - , l; - - while (src) { - // newline - if (cap = this.rules.newline.exec(src)) { - src = src.substring(cap[0].length); - if (cap[0].length > 1) { - this.tokens.push({ - type: 'space' - }); - } - } - - // code - if (cap = this.rules.code.exec(src)) { - src = src.substring(cap[0].length); - cap = cap[0].replace(/^ {4}/gm, ''); - this.tokens.push({ - type: 'code', - text: !this.options.pedantic - ? cap.replace(/\n+$/, '') - : cap - }); - continue; - } - - // fences (gfm) - if (cap = this.rules.fences.exec(src)) { - src = src.substring(cap[0].length); - this.tokens.push({ - type: 'code', - lang: cap[2], - text: cap[3] || '' - }); - continue; - } - - // heading - if (cap = this.rules.heading.exec(src)) { - src = src.substring(cap[0].length); - this.tokens.push({ - type: 'heading', - depth: cap[1].length, - text: cap[2] - }); - continue; - } - - // table no leading pipe (gfm) - if (top && (cap = this.rules.nptable.exec(src))) { - src = src.substring(cap[0].length); - - item = { - type: 'table', - header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */), - align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */), - cells: cap[3].replace(/\n$/, '').split('\n') - }; - - for (i = 0; i < item.align.length; i++) { - if (/^ *-+: *$/.test(item.align[i])) { - item.align[i] = 'right'; - } else if (/^ *:-+: *$/.test(item.align[i])) { - item.align[i] = 'center'; - } else if (/^ *:-+ *$/.test(item.align[i])) { - item.align[i] = 'left'; - } else { - item.align[i] = null; - } - } - - for (i = 0; i < item.cells.length; i++) { - item.cells[i] = item.cells[i].split(/ *\| */); - } - - this.tokens.push(item); - - continue; - } - - // lheading - if (cap = this.rules.lheading.exec(src)) { - src = src.substring(cap[0].length); - this.tokens.push({ - type: 'heading', - depth: cap[2] === '=' ? 1 : 2, - text: cap[1] - }); - continue; - } - - // hr - if (cap = this.rules.hr.exec(src)) { - src = src.substring(cap[0].length); - this.tokens.push({ - type: 'hr' - }); - continue; - } - - // blockquote - if (cap = this.rules.blockquote.exec(src)) { - src = src.substring(cap[0].length); - - this.tokens.push({ - type: 'blockquote_start' - }); - - cap = cap[0].replace(/^ *> ?/gm, ''); - - // Pass `top` to keep the current - // "toplevel" state. This is exactly - // how markdown.pl works. - this.token(cap, top, true); - - this.tokens.push({ - type: 'blockquote_end' - }); - - continue; - } - - // list - if (cap = this.rules.list.exec(src)) { - src = src.substring(cap[0].length); - bull = cap[2]; - - this.tokens.push({ - type: 'list_start', - ordered: bull.length > 1 - }); - - // Get each top-level item. - cap = cap[0].match(this.rules.item); - - next = false; - l = cap.length; - i = 0; - - for (; i < l; i++) { - item = cap[i]; - - // Remove the list item's bullet - // so it is seen as the next token. - space = item.length; - item = item.replace(/^ *([*+-]|\d+\.) +/, ''); - - // Outdent whatever the - // list item contains. Hacky. - if (~item.indexOf('\n ')) { - space -= item.length; - item = !this.options.pedantic - ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '') - : item.replace(/^ {1,4}/gm, ''); - } - - // Determine whether the next list item belongs here. - // Backpedal if it does not belong in this list. - if (this.options.smartLists && i !== l - 1) { - b = block.bullet.exec(cap[i + 1])[0]; - if (bull !== b && !(bull.length > 1 && b.length > 1)) { - src = cap.slice(i + 1).join('\n') + src; - i = l - 1; - } - } - - // Determine whether item is loose or not. - // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/ - // for discount behavior. - loose = next || /\n\n(?!\s*$)/.test(item); - if (i !== l - 1) { - next = item.charAt(item.length - 1) === '\n'; - if (!loose) loose = next; - } - - this.tokens.push({ - type: loose - ? 'loose_item_start' - : 'list_item_start' - }); - - // Recurse. - this.token(item, false, bq); - - this.tokens.push({ - type: 'list_item_end' - }); - } - - this.tokens.push({ - type: 'list_end' - }); - - continue; - } - - // html - if (cap = this.rules.html.exec(src)) { - src = src.substring(cap[0].length); - this.tokens.push({ - type: this.options.sanitize - ? 'paragraph' - : 'html', - pre: !this.options.sanitizer - && (cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style'), - text: cap[0] - }); - continue; - } - - // def - if ((!bq && top) && (cap = this.rules.def.exec(src))) { - src = src.substring(cap[0].length); - this.tokens.links[cap[1].toLowerCase()] = { - href: cap[2], - title: cap[3] - }; - continue; - } - - // table (gfm) - if (top && (cap = this.rules.table.exec(src))) { - src = src.substring(cap[0].length); - - item = { - type: 'table', - header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */), - align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */), - cells: cap[3].replace(/(?: *\| *)?\n$/, '').split('\n') - }; - - for (i = 0; i < item.align.length; i++) { - if (/^ *-+: *$/.test(item.align[i])) { - item.align[i] = 'right'; - } else if (/^ *:-+: *$/.test(item.align[i])) { - item.align[i] = 'center'; - } else if (/^ *:-+ *$/.test(item.align[i])) { - item.align[i] = 'left'; - } else { - item.align[i] = null; - } - } - - for (i = 0; i < item.cells.length; i++) { - item.cells[i] = item.cells[i] - .replace(/^ *\| *| *\| *$/g, '') - .split(/ *\| */); - } - - this.tokens.push(item); - - continue; - } - - // top-level paragraph - if (top && (cap = this.rules.paragraph.exec(src))) { - src = src.substring(cap[0].length); - this.tokens.push({ - type: 'paragraph', - text: cap[1].charAt(cap[1].length - 1) === '\n' - ? cap[1].slice(0, -1) - : cap[1] - }); - continue; - } - - // text - if (cap = this.rules.text.exec(src)) { - // Top-level should never reach here. - src = src.substring(cap[0].length); - this.tokens.push({ - type: 'text', - text: cap[0] - }); - continue; - } - - if (src) { - throw new - Error('Infinite loop on byte: ' + src.charCodeAt(0)); - } - } - - return this.tokens; -}; - -/** - * Inline-Level Grammar - */ - -var inline = { - escape: /^\\([\\`*{}\[\]()#+\-.!_>])/, - autolink: /^<([^ >]+(@|:\/)[^ >]+)>/, - url: noop, - tag: /^|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/, - link: /^!?\[(inside)\]\(href\)/, - reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/, - nolink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/, - strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/, - em: /^\b_((?:[^_]|__)+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/, - code: /^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/, - br: /^ {2,}\n(?!\s*$)/, - del: noop, - text: /^[\s\S]+?(?=[\\?(?:\s+['"]([\s\S]*?)['"])?\s*/; - -inline.link = replace(inline.link) - ('inside', inline._inside) - ('href', inline._href) - (); - -inline.reflink = replace(inline.reflink) - ('inside', inline._inside) - (); - -/** - * Normal Inline Grammar - */ - -inline.normal = merge({}, inline); - -/** - * Pedantic Inline Grammar - */ - -inline.pedantic = merge({}, inline.normal, { - strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/, - em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/ -}); - -/** - * GFM Inline Grammar - */ - -inline.gfm = merge({}, inline.normal, { - escape: replace(inline.escape)('])', '~|])')(), - url: /^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/, - del: /^~~(?=\S)([\s\S]*?\S)~~/, - text: replace(inline.text) - (']|', '~]|') - ('|', '|https?://|') - () -}); - -/** - * GFM + Line Breaks Inline Grammar - */ - -inline.breaks = merge({}, inline.gfm, { - br: replace(inline.br)('{2,}', '*')(), - text: replace(inline.gfm.text)('{2,}', '*')() -}); - -/** - * Inline Lexer & Compiler - */ - -function InlineLexer(links, options) { - this.options = options || marked.defaults; - this.links = links; - this.rules = inline.normal; - this.renderer = this.options.renderer || new Renderer; - this.renderer.options = this.options; - - if (!this.links) { - throw new - Error('Tokens array requires a `links` property.'); - } - - if (this.options.gfm) { - if (this.options.breaks) { - this.rules = inline.breaks; - } else { - this.rules = inline.gfm; - } - } else if (this.options.pedantic) { - this.rules = inline.pedantic; - } -} - -/** - * Expose Inline Rules - */ - -InlineLexer.rules = inline; - -/** - * Static Lexing/Compiling Method - */ - -InlineLexer.output = function(src, links, options) { - var inline = new InlineLexer(links, options); - return inline.output(src); -}; - -/** - * Lexing/Compiling - */ - -InlineLexer.prototype.output = function(src) { - var out = '' - , link - , text - , href - , cap; - - while (src) { - // escape - if (cap = this.rules.escape.exec(src)) { - src = src.substring(cap[0].length); - out += cap[1]; - continue; - } - - // autolink - if (cap = this.rules.autolink.exec(src)) { - src = src.substring(cap[0].length); - if (cap[2] === '@') { - text = cap[1].charAt(6) === ':' - ? this.mangle(cap[1].substring(7)) - : this.mangle(cap[1]); - href = this.mangle('mailto:') + text; - } else { - text = escape(cap[1]); - href = text; - } - out += this.renderer.link(href, null, text); - continue; - } - - // url (gfm) - if (!this.inLink && (cap = this.rules.url.exec(src))) { - src = src.substring(cap[0].length); - text = escape(cap[1]); - href = text; - out += this.renderer.link(href, null, text); - continue; - } - - // tag - if (cap = this.rules.tag.exec(src)) { - if (!this.inLink && /^/i.test(cap[0])) { - this.inLink = false; - } - src = src.substring(cap[0].length); - out += this.options.sanitize - ? this.options.sanitizer - ? this.options.sanitizer(cap[0]) - : escape(cap[0]) - : cap[0] - continue; - } - - // link - if (cap = this.rules.link.exec(src)) { - src = src.substring(cap[0].length); - this.inLink = true; - out += this.outputLink(cap, { - href: cap[2], - title: cap[3] - }); - this.inLink = false; - continue; - } - - // reflink, nolink - if ((cap = this.rules.reflink.exec(src)) - || (cap = this.rules.nolink.exec(src))) { - src = src.substring(cap[0].length); - link = (cap[2] || cap[1]).replace(/\s+/g, ' '); - link = this.links[link.toLowerCase()]; - if (!link || !link.href) { - out += cap[0].charAt(0); - src = cap[0].substring(1) + src; - continue; - } - this.inLink = true; - out += this.outputLink(cap, link); - this.inLink = false; - continue; - } - - // strong - if (cap = this.rules.strong.exec(src)) { - src = src.substring(cap[0].length); - out += this.renderer.strong(this.output(cap[2] || cap[1])); - continue; - } - - // em - if (cap = this.rules.em.exec(src)) { - src = src.substring(cap[0].length); - out += this.renderer.em(this.output(cap[2] || cap[1])); - continue; - } - - // code - if (cap = this.rules.code.exec(src)) { - src = src.substring(cap[0].length); - out += this.renderer.codespan(escape(cap[2], true)); - continue; - } - - // br - if (cap = this.rules.br.exec(src)) { - src = src.substring(cap[0].length); - out += this.renderer.br(); - continue; - } - - // del (gfm) - if (cap = this.rules.del.exec(src)) { - src = src.substring(cap[0].length); - out += this.renderer.del(this.output(cap[1])); - continue; - } - - // text - if (cap = this.rules.text.exec(src)) { - src = src.substring(cap[0].length); - out += this.renderer.text(escape(this.smartypants(cap[0]))); - continue; - } - - if (src) { - throw new - Error('Infinite loop on byte: ' + src.charCodeAt(0)); - } - } - - return out; -}; - -/** - * Compile Link - */ - -InlineLexer.prototype.outputLink = function(cap, link) { - var href = escape(link.href) - , title = link.title ? escape(link.title) : null; - - return cap[0].charAt(0) !== '!' - ? this.renderer.link(href, title, this.output(cap[1])) - : this.renderer.image(href, title, escape(cap[1])); -}; - -/** - * Smartypants Transformations - */ - -InlineLexer.prototype.smartypants = function(text) { - if (!this.options.smartypants) return text; - return text - // em-dashes - .replace(/---/g, '\u2014') - // en-dashes - .replace(/--/g, '\u2013') - // opening singles - .replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018') - // closing singles & apostrophes - .replace(/'/g, '\u2019') - // opening doubles - .replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c') - // closing doubles - .replace(/"/g, '\u201d') - // ellipses - .replace(/\.{3}/g, '\u2026'); -}; - -/** - * Mangle Links - */ - -InlineLexer.prototype.mangle = function(text) { - if (!this.options.mangle) return text; - var out = '' - , l = text.length - , i = 0 - , ch; - - for (; i < l; i++) { - ch = text.charCodeAt(i); - if (Math.random() > 0.5) { - ch = 'x' + ch.toString(16); - } - out += '&#' + ch + ';'; - } - - return out; -}; - -/** - * Renderer - */ - -function Renderer(options) { - this.options = options || { }; -} - -Renderer.prototype.code = function(code, lang, escaped) { - if (this.options.highlight) { - var out = this.options.highlight(code, lang); - if (out != null && out !== code) { - escaped = true; - code = out; - } - } - - if (!lang) { - return '
'
-      + (escaped ? code : escape(code, true))
-      + '\n
'; - } - - return '
'
-    + (escaped ? code : escape(code, true))
-    + '\n
\n'; -}; - -Renderer.prototype.blockquote = function(quote) { - return '
\n' + quote + '
\n'; -}; - -Renderer.prototype.html = function(html) { - return html; -}; - -Renderer.prototype.heading = function(text, level, raw) { - return '' - + text - + '\n'; -}; - -Renderer.prototype.hr = function() { - return this.options.xhtml ? '
\n' : '
\n'; -}; - -Renderer.prototype.list = function(body, ordered) { - var type = ordered ? 'ol' : 'ul'; - return '<' + type + '>\n' + body + '\n'; -}; - -Renderer.prototype.listitem = function(text) { - return '
  • ' + text + '
  • \n'; -}; - -Renderer.prototype.paragraph = function(text) { - return '

    ' + text + '

    \n'; -}; - -Renderer.prototype.table = function(header, body) { - return '\n' - + '\n' - + header - + '\n' - + '\n' - + body - + '\n' - + '
    \n'; -}; - -Renderer.prototype.tablerow = function(content) { - return '\n' + content + '\n'; -}; - -Renderer.prototype.tablecell = function(content, flags) { - var type = flags.header ? 'th' : 'td'; - var tag = flags.align - ? '<' + type + ' style="text-align:' + flags.align + '">' - : '<' + type + '>'; - return tag + content + '\n'; -}; - -// span level renderer -Renderer.prototype.strong = function(text) { - return '' + text + ''; -}; - -Renderer.prototype.em = function(text) { - return '' + text + ''; -}; - -Renderer.prototype.codespan = function(text) { - return '' + text + ''; -}; - -Renderer.prototype.br = function() { - return this.options.xhtml ? '
    ' : '
    '; -}; - -Renderer.prototype.del = function(text) { - return '' + text + ''; -}; - -Renderer.prototype.link = function(href, title, text) { - if (this.options.sanitize) { - try { - var prot = decodeURIComponent(unescape(href)) - .replace(/[^\w:]/g, '') - .toLowerCase(); - } catch (e) { - return ''; - } - if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0) { - return ''; - } - } - var out = '
    '; - return out; -}; - -Renderer.prototype.image = function(href, title, text) { - var out = '' + text + '' : '>'; - return out; -}; - -Renderer.prototype.text = function(text) { - return text; -}; - -/** - * Parsing & Compiling - */ - -function Parser(options) { - this.tokens = []; - this.token = null; - this.options = options || marked.defaults; - this.options.renderer = this.options.renderer || new Renderer; - this.renderer = this.options.renderer; - this.renderer.options = this.options; -} - -/** - * Static Parse Method - */ - -Parser.parse = function(src, options, renderer) { - var parser = new Parser(options, renderer); - return parser.parse(src); -}; - -/** - * Parse Loop - */ - -Parser.prototype.parse = function(src) { - this.inline = new InlineLexer(src.links, this.options, this.renderer); - this.tokens = src.reverse(); - - var out = ''; - while (this.next()) { - out += this.tok(); - } - - return out; -}; - -/** - * Next Token - */ - -Parser.prototype.next = function() { - return this.token = this.tokens.pop(); -}; - -/** - * Preview Next Token - */ - -Parser.prototype.peek = function() { - return this.tokens[this.tokens.length - 1] || 0; -}; - -/** - * Parse Text Tokens - */ - -Parser.prototype.parseText = function() { - var body = this.token.text; - - while (this.peek().type === 'text') { - body += '\n' + this.next().text; - } - - return this.inline.output(body); -}; - -/** - * Parse Current Token - */ - -Parser.prototype.tok = function() { - switch (this.token.type) { - case 'space': { - return ''; - } - case 'hr': { - return this.renderer.hr(); - } - case 'heading': { - return this.renderer.heading( - this.inline.output(this.token.text), - this.token.depth, - this.token.text); - } - case 'code': { - return this.renderer.code(this.token.text, - this.token.lang, - this.token.escaped); - } - case 'table': { - var header = '' - , body = '' - , i - , row - , cell - , flags - , j; - - // header - cell = ''; - for (i = 0; i < this.token.header.length; i++) { - flags = { header: true, align: this.token.align[i] }; - cell += this.renderer.tablecell( - this.inline.output(this.token.header[i]), - { header: true, align: this.token.align[i] } - ); - } - header += this.renderer.tablerow(cell); - - for (i = 0; i < this.token.cells.length; i++) { - row = this.token.cells[i]; - - cell = ''; - for (j = 0; j < row.length; j++) { - cell += this.renderer.tablecell( - this.inline.output(row[j]), - { header: false, align: this.token.align[j] } - ); - } - - body += this.renderer.tablerow(cell); - } - return this.renderer.table(header, body); - } - case 'blockquote_start': { - var body = ''; - - while (this.next().type !== 'blockquote_end') { - body += this.tok(); - } - - return this.renderer.blockquote(body); - } - case 'list_start': { - var body = '' - , ordered = this.token.ordered; - - while (this.next().type !== 'list_end') { - body += this.tok(); - } - - return this.renderer.list(body, ordered); - } - case 'list_item_start': { - var body = ''; - - while (this.next().type !== 'list_item_end') { - body += this.token.type === 'text' - ? this.parseText() - : this.tok(); - } - - return this.renderer.listitem(body); - } - case 'loose_item_start': { - var body = ''; - - while (this.next().type !== 'list_item_end') { - body += this.tok(); - } - - return this.renderer.listitem(body); - } - case 'html': { - var html = !this.token.pre && !this.options.pedantic - ? this.inline.output(this.token.text) - : this.token.text; - return this.renderer.html(html); - } - case 'paragraph': { - return this.renderer.paragraph(this.inline.output(this.token.text)); - } - case 'text': { - return this.renderer.paragraph(this.parseText()); - } - } -}; - -/** - * Helpers - */ - -function escape(html, encode) { - return html - .replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&') - .replace(//g, '>') - .replace(/"/g, '"') - .replace(/'/g, '''); -} - -function unescape(html) { - // explicitly match decimal, hex, and named HTML entities - return html.replace(/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/g, function(_, n) { - n = n.toLowerCase(); - if (n === 'colon') return ':'; - if (n.charAt(0) === '#') { - return n.charAt(1) === 'x' - ? String.fromCharCode(parseInt(n.substring(2), 16)) - : String.fromCharCode(+n.substring(1)); - } - return ''; - }); -} - -function replace(regex, opt) { - regex = regex.source; - opt = opt || ''; - return function self(name, val) { - if (!name) return new RegExp(regex, opt); - val = val.source || val; - val = val.replace(/(^|[^\[])\^/g, '$1'); - regex = regex.replace(name, val); - return self; - }; -} - -function noop() {} -noop.exec = noop; - -function merge(obj) { - var i = 1 - , target - , key; - - for (; i < arguments.length; i++) { - target = arguments[i]; - for (key in target) { - if (Object.prototype.hasOwnProperty.call(target, key)) { - obj[key] = target[key]; - } - } - } - - return obj; -} - - -/** - * Marked - */ - -function marked(src, opt, callback) { - if (callback || typeof opt === 'function') { - if (!callback) { - callback = opt; - opt = null; - } - - opt = merge({}, marked.defaults, opt || {}); - - var highlight = opt.highlight - , tokens - , pending - , i = 0; - - try { - tokens = Lexer.lex(src, opt) - } catch (e) { - return callback(e); - } - - pending = tokens.length; - - var done = function(err) { - if (err) { - opt.highlight = highlight; - return callback(err); - } - - var out; - - try { - out = Parser.parse(tokens, opt); - } catch (e) { - err = e; - } - - opt.highlight = highlight; - - return err - ? callback(err) - : callback(null, out); - }; - - if (!highlight || highlight.length < 3) { - return done(); - } - - delete opt.highlight; - - if (!pending) return done(); - - for (; i < tokens.length; i++) { - (function(token) { - if (token.type !== 'code') { - return --pending || done(); - } - return highlight(token.text, token.lang, function(err, code) { - if (err) return done(err); - if (code == null || code === token.text) { - return --pending || done(); - } - token.text = code; - token.escaped = true; - --pending || done(); - }); - })(tokens[i]); - } - - return; - } - try { - if (opt) opt = merge({}, marked.defaults, opt); - return Parser.parse(Lexer.lex(src, opt), opt); - } catch (e) { - e.message += '\nPlease report this to https://github.com/chjj/marked.'; - if ((opt || marked.defaults).silent) { - return '

    An error occured:

    '
    -        + escape(e.message + '', true)
    -        + '
    '; - } - throw e; - } -} - -/** - * Options - */ - -marked.options = -marked.setOptions = function(opt) { - merge(marked.defaults, opt); - return marked; -}; - -marked.defaults = { - gfm: true, - tables: true, - breaks: false, - pedantic: false, - sanitize: false, - sanitizer: null, - mangle: true, - smartLists: false, - silent: false, - highlight: null, - langPrefix: 'lang-', - smartypants: false, - headerPrefix: '', - renderer: new Renderer, - xhtml: false -}; - -/** - * Expose - */ - -marked.Parser = Parser; -marked.parser = Parser.parse; - -marked.Renderer = Renderer; - -marked.Lexer = Lexer; -marked.lexer = Lexer.lex; - -marked.InlineLexer = InlineLexer; -marked.inlineLexer = InlineLexer.output; - -marked.parse = marked; - -if (typeof module !== 'undefined' && typeof exports === 'object') { - module.exports = marked; -} else if (typeof define === 'function' && define.amd) { - define(function() { return marked; }); -} else { - this.marked = marked; -} - -}).call(function() { - return this || (typeof window !== 'undefined' ? window : global); -}()); diff --git a/packages/ckeditor5-markdown-gfm/src/lib/marked/renderer.js b/packages/ckeditor5-markdown-gfm/src/lib/marked/renderer.js deleted file mode 100644 index 98d082b7c9d..00000000000 --- a/packages/ckeditor5-markdown-gfm/src/lib/marked/renderer.js +++ /dev/null @@ -1,175 +0,0 @@ -/** - * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved. - * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license - */ - -/** - * Original marked.js library renderer with fixes: - * - No formatting for output HTML string — all newlines between tags are removed to create clean output. - * - Changed long string concatenations to ES5 template strings. - * - Changed code style. - * - * @see {@link https://github.com/chjj/marked#renderer} Methods description. - * @param options - * @constructor - */ -function Renderer( options ) { - this.options = options || {}; -} - -Renderer.prototype.code = function( code, lang, escaped ) { - if ( this.options.highlight ) { - const out = this.options.highlight( code, lang ); - - if ( out !== null && out !== code ) { - escaped = true; - code = out; - } - } - - if ( !lang ) { - return `
    ${ escaped ? code : escape( code, true ) }
    `; - } - - const cssClass = this.options.langPrefix + escape( lang, true ); - - return `
    ${ escaped ? code : escape( code, true ) }
    `; -}; - -Renderer.prototype.blockquote = function( quote ) { - return `
    ${ quote }
    `; -}; - -Renderer.prototype.html = function( html ) { - return html; -}; - -Renderer.prototype.heading = function( text, level, raw ) { - return `${ text }`; -}; - -Renderer.prototype.hr = function() { - return this.options.xhtml ? '
    ' : '
    '; -}; - -Renderer.prototype.list = function( body, ordered ) { - const type = ordered ? 'ol' : 'ul'; - - return `<${ type }>${ body }`; -}; - -Renderer.prototype.listitem = function( text ) { - return `
  • ${ text }
  • `; -}; - -Renderer.prototype.paragraph = function( text ) { - return `

    ${ text }

    `; -}; - -Renderer.prototype.table = function( header, body ) { - return `${ header }${ body }
    `; -}; - -Renderer.prototype.tablerow = function( content ) { - return '' + content + ''; -}; - -Renderer.prototype.tablecell = function( content, flags ) { - const type = flags.header ? 'th' : 'td'; - const tag = flags.align ? `<${ type } align="${ flags.align }">` : `<${ type }>`; - - return tag + content + ``; -}; - -// span level renderer -Renderer.prototype.strong = function( text ) { - return `${ text }`; -}; - -Renderer.prototype.em = function( text ) { - return `${ text }`; -}; - -Renderer.prototype.codespan = function( text ) { - return `${ text.trim() }`; -}; - -Renderer.prototype.br = function() { - return this.options.xhtml ? '
    ' : '
    '; -}; - -Renderer.prototype.del = function( text ) { - return `${ text }`; -}; - -Renderer.prototype.link = function( href, title, text ) { - if ( this.options.sanitize ) { - let prot; - - try { - prot = decodeURIComponent( unescape( href ) ) - .replace( /[^\w:]/g, '' ) - .toLowerCase(); - } catch ( e ) { - return ''; - } - - if ( prot.indexOf( 'javascript:' ) === 0 || prot.indexOf( 'vbscript:' ) === 0 ) { // jshint ignore:line - return ''; - } - } - - let out = '
    '; - - return out; -}; - -Renderer.prototype.image = function( href, title, text ) { - let out = '' + text + '' : '>'; - - return out; -}; - -Renderer.prototype.text = function( text ) { - return text; -}; - -export default Renderer; - -function escape( html, encode ) { - return html - .replace( !encode ? /&(?!#?\w+;)/g : /&/g, '&' ) - .replace( //g, '>' ) - .replace( /"/g, '"' ) - .replace( /'/g, ''' ); -} - -function unescape( html ) { - // explicitly match decimal, hex, and named HTML entities - return html.replace( /&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/g, function( _, n ) { - n = n.toLowerCase(); - - if ( n === 'colon' ) { - return ':'; - } - - if ( n.charAt( 0 ) === '#' ) { - return n.charAt( 1 ) === 'x' ? - String.fromCharCode( parseInt( n.substring( 2 ), 16 ) ) : - String.fromCharCode( +n.substring( 1 ) ); // jscs:ignore - } - - return ''; - } ); -} diff --git a/packages/ckeditor5-markdown-gfm/src/lib/to-markdown/converters.js b/packages/ckeditor5-markdown-gfm/src/lib/to-markdown/converters.js deleted file mode 100644 index 0ea39fdce6d..00000000000 --- a/packages/ckeditor5-markdown-gfm/src/lib/to-markdown/converters.js +++ /dev/null @@ -1,68 +0,0 @@ -/** - * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved. - * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license - */ - -// Exports an array with custom converters used by to-markdown library. -export default [ - // Converting code blocks with class name matching output from marked library. - { - filter: ( node ) => { - const regexp = /lang-(.+)/; - - return node.nodeName === 'PRE' && - node.firstChild && - node.firstChild.nodeName === 'CODE' && - regexp.test( node.firstChild.className ); - }, - replacement: ( content, node ) => { - const regexp = /lang-(.+)/; - const lang = regexp.exec( node.firstChild.className )[ 1 ]; - - return '\n\n``` ' + lang + '\n' + node.firstChild.textContent + '\n```\n\n'; - } - }, - // Converting empty links. - { - filter: ( node ) => { - return node.nodeName === 'A' && !node.getAttribute( 'href' ); - }, - - replacement: ( content, node ) => { - const title = node.title ? `"${node.title}"` : ''; - - return `[${ content }](${ title })`; - } - }, - // Headers - fixing newline at the beginning. - { - filter: [ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6' ], - replacement: ( content, node ) => { - const hLevel = node.nodeName.charAt( 1 ); - let hPrefix = ''; - - for ( let i = 0; i < hLevel; i++ ) { - hPrefix += '#'; - } - - return hPrefix + ' ' + content + '\n'; - } - }, - // Inline code - fixing backticks inside code blocks. - { - filter: ( node ) => { - const hasSiblings = node.previousSibling || node.nextSibling; - const isCodeBlock = node.parentNode.nodeName === 'PRE' && !hasSiblings; - - return node.nodeName === 'CODE' && !isCodeBlock; - }, - replacement: ( content ) => { - // If content starts or ends with backtick - use double backtick. - if ( content.indexOf( '`' ) > -1 ) { - return '`` ' + content + ' ``'; - } - - return '`' + content + '`'; - } - } -]; diff --git a/packages/ckeditor5-markdown-gfm/src/lib/to-markdown/to-markdown.js b/packages/ckeditor5-markdown-gfm/src/lib/to-markdown/to-markdown.js deleted file mode 100644 index a2c984c5817..00000000000 --- a/packages/ckeditor5-markdown-gfm/src/lib/to-markdown/to-markdown.js +++ /dev/null @@ -1,785 +0,0 @@ -(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.toMarkdown = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 0) { - elem = inqueue.shift() - outqueue.push(elem) - children = elem.childNodes - for (i = 0; i < children.length; i++) { - if (children[i].nodeType === 1) inqueue.push(children[i]) - } - } - outqueue.shift() - return outqueue - } - - /* - * Contructs a Markdown string of replacement text for a given node - */ - - function getContent (node) { - var text = '' - for (var i = 0; i < node.childNodes.length; i++) { - if (node.childNodes[i].nodeType === 1) { - text += node.childNodes[i]._replacement - } else if (node.childNodes[i].nodeType === 3) { - text += node.childNodes[i].data - } else continue - } - return text - } - - /* - * Returns the HTML string of an element with its contents converted - */ - - function outer (node, content) { - return node.cloneNode(false).outerHTML.replace('><', '>' + content + '<') - } - - function canConvert (node, filter) { - if (typeof filter === 'string') { - return filter === node.nodeName.toLowerCase() - } - if (Array.isArray(filter)) { - return filter.indexOf(node.nodeName.toLowerCase()) !== -1 - } else if (typeof filter === 'function') { - return filter.call(toMarkdown, node) - } else { - throw new TypeError('`filter` needs to be a string, array, or function') - } - } - - function isFlankedByWhitespace (side, node) { - var sibling - var regExp - var isFlanked - - if (side === 'left') { - sibling = node.previousSibling - regExp = / $/ - } else { - sibling = node.nextSibling - regExp = /^ / - } - - if (sibling) { - if (sibling.nodeType === 3) { - isFlanked = regExp.test(sibling.nodeValue) - } else if (sibling.nodeType === 1 && !isBlock(sibling)) { - isFlanked = regExp.test(sibling.textContent) - } - } - return isFlanked - } - - function flankingWhitespace (node) { - var leading = '' - var trailing = '' - - if (!isBlock(node)) { - var hasLeading = /^[ \r\n\t]/.test(node.innerHTML) - var hasTrailing = /[ \r\n\t]$/.test(node.innerHTML) - - if (hasLeading && !isFlankedByWhitespace('left', node)) { - leading = ' ' - } - if (hasTrailing && !isFlankedByWhitespace('right', node)) { - trailing = ' ' - } - } - - return { leading: leading, trailing: trailing } - } - - /* - * Finds a Markdown converter, gets the replacement, and sets it on - * `_replacement` - */ - - function process (node) { - var replacement - var content = getContent(node) - - // Remove blank nodes - if (!isVoid(node) && !/A|TH|TD/.test(node.nodeName) && /^\s*$/i.test(content)) { - node._replacement = '' - return - } - - for (var i = 0; i < converters.length; i++) { - var converter = converters[i] - - if (canConvert(node, converter.filter)) { - if (typeof converter.replacement !== 'function') { - throw new TypeError( - '`replacement` needs to be a function that returns a string' - ) - } - - var whitespace = flankingWhitespace(node) - - if (whitespace.leading || whitespace.trailing) { - content = content.trim() - } - replacement = whitespace.leading + - converter.replacement.call(toMarkdown, content, node) + - whitespace.trailing - break - } - } - - node._replacement = replacement - } - - toMarkdown = function (input, options) { - options = options || {} - - if (typeof input !== 'string') { - throw new TypeError(input + ' is not a string') - } - - // Escape potential ol triggers - input = input.replace(/(\d+)\. /g, '$1\\. ') - - var clone = htmlToDom(input).body - var nodes = bfsOrder(clone) - var output - - converters = mdConverters.slice(0) - if (options.gfm) { - converters = gfmConverters.concat(converters) - } - - if (options.converters) { - converters = options.converters.concat(converters) - } - - // Process through nodes in reverse (so deepest child elements are first). - for (var i = nodes.length - 1; i >= 0; i--) { - process(nodes[i]) - } - output = getContent(clone) - - return output.replace(/^[\t\r\n]+|[\t\r\n\s]+$/g, '') - .replace(/\n\s+\n/g, '\n\n') - .replace(/\n{3,}/g, '\n\n') - } - - toMarkdown.isBlock = isBlock - toMarkdown.isVoid = isVoid - toMarkdown.outer = outer - - module.exports = toMarkdown - -},{"./lib/gfm-converters":2,"./lib/html-parser":3,"./lib/md-converters":4,"collapse-whitespace":7}],2:[function(require,module,exports){ - 'use strict' - - function cell (content, node) { - var index = Array.prototype.indexOf.call(node.parentNode.childNodes, node) - var prefix = ' ' - if (index === 0) prefix = '| ' - return prefix + content + ' |' - } - - var highlightRegEx = /highlight highlight-(\S+)/ - - module.exports = [ - { - filter: 'br', - replacement: function () { - return '\n' - } - }, - { - filter: ['del', 's', 'strike'], - replacement: function (content) { - return '~~' + content + '~~' - } - }, - - { - filter: function (node) { - return node.type === 'checkbox' && node.parentNode.nodeName === 'LI' - }, - replacement: function (content, node) { - return (node.checked ? '[x]' : '[ ]') + ' ' - } - }, - - { - filter: ['th', 'td'], - replacement: function (content, node) { - return cell(content, node) - } - }, - - { - filter: 'tr', - replacement: function (content, node) { - var borderCells = '' - var alignMap = { left: ':--', right: '--:', center: ':-:' } - - if (node.parentNode.nodeName === 'THEAD') { - for (var i = 0; i < node.childNodes.length; i++) { - var align = node.childNodes[i].attributes.align - var border = '---' - - if (align) border = alignMap[align.value] || border - - borderCells += cell(border, node.childNodes[i]) - } - } - return '\n' + content + (borderCells ? '\n' + borderCells : '') - } - }, - - { - filter: 'table', - replacement: function (content) { - return '\n\n' + content + '\n\n' - } - }, - - { - filter: ['thead', 'tbody', 'tfoot'], - replacement: function (content) { - return content - } - }, - - // Fenced code blocks - { - filter: function (node) { - return node.nodeName === 'PRE' && - node.firstChild && - node.firstChild.nodeName === 'CODE' - }, - replacement: function (content, node) { - return '\n\n```\n' + node.firstChild.textContent + '\n```\n\n' - } - }, - - // Syntax-highlighted code blocks - { - filter: function (node) { - return node.nodeName === 'PRE' && - node.parentNode.nodeName === 'DIV' && - highlightRegEx.test(node.parentNode.className) - }, - replacement: function (content, node) { - var language = node.parentNode.className.match(highlightRegEx)[1] - return '\n\n```' + language + '\n' + node.textContent + '\n```\n\n' - } - }, - - { - filter: function (node) { - return node.nodeName === 'DIV' && - highlightRegEx.test(node.className) - }, - replacement: function (content) { - return '\n\n' + content + '\n\n' - } - } - ] - -},{}],3:[function(require,module,exports){ - /* - * Set up window for Node.js - */ - - var _window = (typeof window !== 'undefined' ? window : this) - - /* - * Parsing HTML strings - */ - - function canParseHtmlNatively () { - var Parser = _window.DOMParser - var canParse = false - - // Adapted from https://gist.github.com/1129031 - // Firefox/Opera/IE throw errors on unsupported types - try { - // WebKit returns null on unsupported types - if (new Parser().parseFromString('', 'text/html')) { - canParse = true - } - } catch (e) {} - - return canParse - } - - function createHtmlParser () { - var Parser = function () {} - - // For Node.js environments - if (typeof document === 'undefined') { - var jsdom = require('jsdom') - Parser.prototype.parseFromString = function (string) { - return jsdom.jsdom(string, { - plugins: { - FetchExternalResources: [], - ProcessExternalResources: false - } - }) - } - } else { - if (!shouldUseActiveX()) { - Parser.prototype.parseFromString = function (string) { - var doc = document.implementation.createHTMLDocument('') - doc.open() - doc.write(string) - doc.close() - return doc - } - } else { - Parser.prototype.parseFromString = function (string) { - var doc = new window.ActiveXObject('htmlfile') - doc.designMode = 'on' // disable on-page scripts - doc.open() - doc.write(string) - doc.close() - return doc - } - } - } - return Parser - } - - function shouldUseActiveX () { - var useActiveX = false - - try { - document.implementation.createHTMLDocument('').open() - } catch (e) { - if (window.ActiveXObject) useActiveX = true - } - - return useActiveX - } - - module.exports = canParseHtmlNatively() ? _window.DOMParser : createHtmlParser() - -},{"jsdom":6}],4:[function(require,module,exports){ - 'use strict' - - module.exports = [ - { - filter: 'p', - replacement: function (content) { - return '\n\n' + content + '\n\n' - } - }, - - { - filter: 'br', - replacement: function () { - return ' \n' - } - }, - - { - filter: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'], - replacement: function (content, node) { - var hLevel = node.nodeName.charAt(1) - var hPrefix = '' - for (var i = 0; i < hLevel; i++) { - hPrefix += '#' - } - return '\n\n' + hPrefix + ' ' + content + '\n\n' - } - }, - - { - filter: 'hr', - replacement: function () { - return '\n\n* * *\n\n' - } - }, - - { - filter: ['em', 'i'], - replacement: function (content) { - return '_' + content + '_' - } - }, - - { - filter: ['strong', 'b'], - replacement: function (content) { - return '**' + content + '**' - } - }, - - // Inline code - { - filter: function (node) { - var hasSiblings = node.previousSibling || node.nextSibling - var isCodeBlock = node.parentNode.nodeName === 'PRE' && !hasSiblings - - return node.nodeName === 'CODE' && !isCodeBlock - }, - replacement: function (content) { - return '`' + content + '`' - } - }, - - { - filter: function (node) { - return node.nodeName === 'A' && node.getAttribute('href') - }, - replacement: function (content, node) { - var titlePart = node.title ? ' "' + node.title + '"' : '' - return '[' + content + '](' + node.getAttribute('href') + titlePart + ')' - } - }, - - { - filter: 'img', - replacement: function (content, node) { - var alt = node.alt || '' - var src = node.getAttribute('src') || '' - var title = node.title || '' - var titlePart = title ? ' "' + title + '"' : '' - return src ? '![' + alt + ']' + '(' + src + titlePart + ')' : '' - } - }, - - // Code blocks - { - filter: function (node) { - return node.nodeName === 'PRE' && node.firstChild.nodeName === 'CODE' - }, - replacement: function (content, node) { - return '\n\n ' + node.firstChild.textContent.replace(/\n/g, '\n ') + '\n\n' - } - }, - - { - filter: 'blockquote', - replacement: function (content) { - content = content.trim() - content = content.replace(/\n{3,}/g, '\n\n') - content = content.replace(/^/gm, '> ') - return '\n\n' + content + '\n\n' - } - }, - - { - filter: 'li', - replacement: function (content, node) { - content = content.replace(/^\s+/, '').replace(/\n/gm, '\n ') - var prefix = '* ' - var parent = node.parentNode - var index = Array.prototype.indexOf.call(parent.children, node) + 1 - - prefix = /ol/i.test(parent.nodeName) ? index + '. ' : '* ' - return prefix + content - } - }, - - { - filter: ['ul', 'ol'], - replacement: function (content, node) { - var strings = [] - for (var i = 0; i < node.childNodes.length; i++) { - strings.push(node.childNodes[i]._replacement) - } - - if (/li/i.test(node.parentNode.nodeName)) { - return '\n' + strings.join('\n') - } - return '\n\n' + strings.join('\n') + '\n\n' - } - }, - - { - filter: function (node) { - return this.isBlock(node) - }, - replacement: function (content, node) { - return '\n\n' + this.outer(node, content) + '\n\n' - } - }, - - // Anything else! - { - filter: function () { - return true - }, - replacement: function (content, node) { - return this.outer(node, content) - } - } - ] - -},{}],5:[function(require,module,exports){ - /** - * This file automatically generated from `build.js`. - * Do not manually edit. - */ - - module.exports = [ - "address", - "article", - "aside", - "audio", - "blockquote", - "canvas", - "dd", - "div", - "dl", - "fieldset", - "figcaption", - "figure", - "footer", - "form", - "h1", - "h2", - "h3", - "h4", - "h5", - "h6", - "header", - "hgroup", - "hr", - "main", - "nav", - "noscript", - "ol", - "output", - "p", - "pre", - "section", - "table", - "tfoot", - "ul", - "video" - ]; - -},{}],6:[function(require,module,exports){ - -},{}],7:[function(require,module,exports){ - 'use strict'; - - var voidElements = require('void-elements'); - Object.keys(voidElements).forEach(function (name) { - voidElements[name.toUpperCase()] = 1; - }); - - var blockElements = {}; - require('block-elements').forEach(function (name) { - blockElements[name.toUpperCase()] = 1; - }); - - /** - * isBlockElem(node) determines if the given node is a block element. - * - * @param {Node} node - * @returns {Boolean} - */ - function isBlockElem(node) { - return !!(node && blockElements[node.nodeName]); - } - - /** - * isVoid(node) determines if the given node is a void element. - * - * @param {Node} node - * @returns {Boolean} - */ - function isVoid(node) { - return !!(node && voidElements[node.nodeName]); - } - - /** - * whitespace(elem [, isBlock]) removes extraneous whitespace from an - * the given element. The function isBlock may optionally be passed in - * to determine whether or not an element is a block element; if none - * is provided, defaults to using the list of block elements provided - * by the `block-elements` module. - * - * @param {Node} elem - * @param {Function} blockTest - */ - function collapseWhitespace(elem, isBlock) { - if (!elem.firstChild || elem.nodeName === 'PRE') return; - - if (typeof isBlock !== 'function') { - isBlock = isBlockElem; - } - - var prevText = null; - var prevVoid = false; - - var prev = null; - var node = next(prev, elem); - - while (node !== elem) { - if (node.nodeType === 3) { - // Node.TEXT_NODE - var text = node.data.replace(/[ \r\n\t]+/g, ' '); - - if ((!prevText || / $/.test(prevText.data)) && !prevVoid && text[0] === ' ') { - text = text.substr(1); - } - - // `text` might be empty at this point. - if (!text) { - node = remove(node); - continue; - } - - node.data = text; - prevText = node; - } else if (node.nodeType === 1) { - // Node.ELEMENT_NODE - if (isBlock(node) || node.nodeName === 'BR') { - if (prevText) { - prevText.data = prevText.data.replace(/ $/, ''); - } - - prevText = null; - prevVoid = false; - } else if (isVoid(node)) { - // Avoid trimming space around non-block, non-BR void elements. - prevText = null; - prevVoid = true; - } - } else { - node = remove(node); - continue; - } - - var nextNode = next(prev, node); - prev = node; - node = nextNode; - } - - if (prevText) { - prevText.data = prevText.data.replace(/ $/, ''); - if (!prevText.data) { - remove(prevText); - } - } - } - - /** - * remove(node) removes the given node from the DOM and returns the - * next node in the sequence. - * - * @param {Node} node - * @returns {Node} node - */ - function remove(node) { - var next = node.nextSibling || node.parentNode; - - node.parentNode.removeChild(node); - - return next; - } - - /** - * next(prev, current) returns the next node in the sequence, given the - * current and previous nodes. - * - * @param {Node} prev - * @param {Node} current - * @returns {Node} - */ - function next(prev, current) { - if (prev && prev.parentNode === current || current.nodeName === 'PRE') { - return current.nextSibling || current.parentNode; - } - - return current.firstChild || current.nextSibling || current.parentNode; - } - - module.exports = collapseWhitespace; - -},{"block-elements":5,"void-elements":8}],8:[function(require,module,exports){ - /** - * This file automatically generated from `pre-publish.js`. - * Do not manually edit. - */ - - module.exports = { - "area": true, - "base": true, - "br": true, - "col": true, - "embed": true, - "hr": true, - "img": true, - "input": true, - "keygen": true, - "link": true, - "menuitem": true, - "meta": true, - "param": true, - "source": true, - "track": true, - "wbr": true - }; - -},{}]},{},[1])(1) -}); diff --git a/packages/ckeditor5-markdown-gfm/src/markdown2html/markdown2html.js b/packages/ckeditor5-markdown-gfm/src/markdown2html/markdown2html.js new file mode 100644 index 00000000000..3c481227ed5 --- /dev/null +++ b/packages/ckeditor5-markdown-gfm/src/markdown2html/markdown2html.js @@ -0,0 +1,32 @@ +/** + * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved. + * For licensing, see LICENSE.md. + */ + +/** + * @module markdown-gfm/markdown2html + */ + +import marked from 'marked'; + +/** + * Parses markdown string to an HTML. + * + * @param {String} markdown + * @returns {String} + */ +export default function markdown2html( markdown ) { + return marked.parse( markdown, { + gfm: true, + breaks: true, + tables: true, + xhtml: true, + headerIds: false + } ); +} + +export { marked }; + +// Disable the autolink rule in the lexer (point it to a regex that always fail). +marked.InlineLexer.rules.breaks.autolink = /^\b$/; +marked.InlineLexer.rules.breaks.url = /^\b$/; diff --git a/packages/ckeditor5-markdown-gfm/tests/_utils/utils.js b/packages/ckeditor5-markdown-gfm/tests/_utils/utils.js index 5340c63e5fb..f7b4043265e 100644 --- a/packages/ckeditor5-markdown-gfm/tests/_utils/utils.js +++ b/packages/ckeditor5-markdown-gfm/tests/_utils/utils.js @@ -14,18 +14,41 @@ import { StylesProcessor } from '@ckeditor/ckeditor5-engine/src/view/stylesmap'; * @param {String} markdown Markdown to be processed to view. * @param {String} viewString Expected view structure. * @param {String} [normalizedMarkdown] When converting back to the markdown it might be different than provided input + * @param {Object} [options] Additional options. + * @param {Function} [options.setup] A function that receives the data processor instance before its execution. * markdown string (which will be used if this parameter is not provided). */ -export function testDataProcessor( markdown, viewString, normalizedMarkdown ) { +export function testDataProcessor( markdown, viewString, normalizedMarkdown, options ) { const viewDocument = new ViewDocument( new StylesProcessor() ); + const dataProcessor = new MarkdownDataProcessor( viewDocument ); + + if ( options && options.setup ) { + options.setup( dataProcessor ); + } const viewFragment = dataProcessor.toView( markdown ); + const html = cleanHtml( stringify( viewFragment ) ); + // Check if view has correct data. - expect( stringify( viewFragment ) ).to.equal( viewString ); + expect( html ).to.equal( viewString ); // Check if converting back gives the same result. const normalized = typeof normalizedMarkdown !== 'undefined' ? normalizedMarkdown : markdown; - expect( dataProcessor.toData( viewFragment ) ).to.equal( normalized ); + expect( cleanMarkdown( dataProcessor.toData( viewFragment ) ) ).to.equal( normalized ); +} + +function cleanHtml( html ) { + // Space between table elements. + html = html.replace( /(th|td|tr)>\s+<(\/?(?:th|td|tr))/g, '$1><$2' ); + return html; +} + +function cleanMarkdown( markdown ) { + // Trim spaces at the end of the lines. + markdown = markdown.replace( / +$/gm, '' ); + // Trim linebreak at the very beginning. + markdown = markdown.replace( /^\s+/g, '' ); + return markdown; } diff --git a/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/blockquotes.js b/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/blockquotes.js index 24831e28d9d..65369f2a93a 100644 --- a/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/blockquotes.js +++ b/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/blockquotes.js @@ -23,9 +23,9 @@ describe( 'GFMDataProcessor', () => { it( 'should process nested blockquotes', () => { testDataProcessor( '> foo\n' + - '> \n' + + '>\n' + '> > bar\n' + - '> \n' + + '>\n' + '> foo', // GitHub is rendering as: @@ -51,7 +51,7 @@ describe( 'GFMDataProcessor', () => { it( 'should process list within a blockquote', () => { testDataProcessor( '> A list within a blockquote:\n' + - '> \n' + + '>\n' + '> * asterisk 1\n' + '> * asterisk 2\n' + '> * asterisk 3', @@ -80,13 +80,13 @@ describe( 'GFMDataProcessor', () => { it( 'should process blockquotes with code inside with ```', () => { testDataProcessor( '> Example 1:\n' + - '> \n' + + '>\n' + '> ```\n' + '> code 1\n' + '> ```\n' + - '> \n' + + '>\n' + '> Example 2:\n' + - '> \n' + + '>\n' + '> ```\n' + '> code 2\n' + '> ```', @@ -159,13 +159,13 @@ describe( 'GFMDataProcessor', () => { // When converting back to data, DataProcessor will normalize tabs to ```. '> Example 1:\n' + - '> \n' + + '>\n' + '> ```\n' + '> code 1\n' + '> ```\n' + - '> \n' + + '>\n' + '> Example 2:\n' + - '> \n' + + '>\n' + '> ```\n' + '> code 2\n' + '> ```' diff --git a/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/code.js b/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/code.js index ad1489b674c..9af7bc977d5 100644 --- a/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/code.js +++ b/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/code.js @@ -45,7 +45,7 @@ describe( 'GFMDataProcessor', () => { it( 'should properly process backticks inside code spans #2', () => { testDataProcessor( - '`` some `backticks` inside ``', + '``some `backticks` inside``', '

    some `backticks` inside

    ' ); @@ -142,17 +142,17 @@ describe( 'GFMDataProcessor', () => { '
    the lines in this block  \n' +
     				'all contain trailing spaces  
    ', - // When converting back tabs are normalized to ```. + // When converting back tabs are normalized to ```, while the test function remove trailing spaces. '```\n' + - 'the lines in this block \n' + - 'all contain trailing spaces \n' + + 'the lines in this block\n' + + 'all contain trailing spaces\n' + '```' ); } ); it( 'should process code block with language name', () => { testDataProcessor( - '``` js\n' + + '```js\n' + 'var a = \'hello\';\n' + 'console.log(a + \' world\');\n' + '```', @@ -160,7 +160,7 @@ describe( 'GFMDataProcessor', () => { // GitHub is rendering as special html with syntax highlighting. // We will need to handle this separately by some feature. - '
    var a = \'hello\';\n' +
    +				'
    var a = \'hello\';\n' +
     				'console.log(a + \' world\');
    ' ); } ); @@ -174,11 +174,11 @@ describe( 'GFMDataProcessor', () => { // GitHub is rendering as special html with syntax highlighting. // We will need to handle this separately by some feature. - '
    #!/bin/bash
    ', + '
    #!/bin/bash
    ', // When converting back ~~~ are normalized to ```. - '``` bash\n' + + '```bash\n' + '#!/bin/bash\n' + '```' ); @@ -186,7 +186,7 @@ describe( 'GFMDataProcessor', () => { it( 'should process code block with language name and using ``````` as delimiter', () => { testDataProcessor( - '``````` js\n' + + '```````js\n' + 'var a = \'hello\';\n' + 'console.log(a + \' world\');\n' + '```````', @@ -194,12 +194,12 @@ describe( 'GFMDataProcessor', () => { // GitHub is rendering as special html with syntax highlighting. // We will need to handle this separately by some feature. - '
    var a = \'hello\';\n' +
    +				'
    var a = \'hello\';\n' +
     				'console.log(a + \' world\');
    ', // When converting back ``````` are normalized to ```. - '``` js\n' + + '```js\n' + 'var a = \'hello\';\n' + 'console.log(a + \' world\');\n' + '```' @@ -216,12 +216,12 @@ describe( 'GFMDataProcessor', () => { // GitHub is rendering as special html with syntax highlighting. // We will need to handle this separately by some feature. - '
    var a = \'hello\';\n' +
    +				'
    var a = \'hello\';\n' +
     				'console.log(a + \' world\');
    ', // When converting back ~~~~~~~~~~ are normalized to ```. - '``` js\n' + + '```js\n' + 'var a = \'hello\';\n' + 'console.log(a + \' world\');\n' + '```' @@ -230,13 +230,13 @@ describe( 'GFMDataProcessor', () => { it( 'should process empty code block', () => { testDataProcessor( - '``` js\n' + + '```js\n' + '```', // GitHub is rendering as special html with syntax highlighting. // We will need to handle this separately by some feature. - '
    ', + '
    ', // When converting back, empty code blocks will be removed. // This might be an issue when switching from source to editor @@ -247,14 +247,14 @@ describe( 'GFMDataProcessor', () => { it( 'should process code block with empty line', () => { testDataProcessor( - '``` js\n' + + '```js\n' + '\n' + '```', // GitHub is rendering as special html with syntax highlighting. // We will need to handle this separately by some feature. - '
    ', + '
    ', // When converting back, empty code blocks will be removed. // This might be an issue when switching from source to editor @@ -273,7 +273,43 @@ describe( 'GFMDataProcessor', () => { '

    code `` code ```

    ', // When converting back ````` will be normalized to ``. - '`` code `` code ``` ``' + '`code `` code ``` `' + ); + } ); + + it( 'should handle triple ticks inside code', () => { + testDataProcessor( + '````\n' + + '```\n' + + 'Code\n' + + '```\n' + + '````', + + '
    ' +
    +				'```\n' +
    +				'Code\n' +
    +				'```' +
    +				'
    ' + ); + } ); + + it( 'should handle triple and quatruple ticks inside code', () => { + testDataProcessor( + '`````\n' + + '````\n' + + '```\n' + + 'Code\n' + + '```\n' + + '````\n' + + '`````', + + '
    ' +
    +				'````\n' +
    +				'```\n' +
    +				'Code\n' +
    +				'```\n' +
    +				'````' +
    +				'
    ' ); } ); } ); diff --git a/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/escaping.js b/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/escaping.js index cf1ef8b0411..733fc919b78 100644 --- a/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/escaping.js +++ b/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/escaping.js @@ -5,6 +5,7 @@ import MarkdownDataProcessor from '../../src/gfmdataprocessor'; import { stringify } from '@ckeditor/ckeditor5-engine/src/dev-utils/view'; +import { testDataProcessor } from '../../tests/_utils/utils'; import ViewDocument from '@ckeditor/ckeditor5-engine/src/view/document'; import { StylesProcessor } from '@ckeditor/ckeditor5-engine/src/view/stylesmap'; @@ -26,15 +27,15 @@ const testCases = { }; describe( 'GFMDataProcessor', () => { - let dataProcessor; - - beforeEach( () => { - const viewDocument = new ViewDocument( new StylesProcessor() ); - dataProcessor = new MarkdownDataProcessor( viewDocument ); - } ); - describe( 'escaping', () => { describe( 'toView', () => { + let dataProcessor; + + beforeEach( () => { + const viewDocument = new ViewDocument( new StylesProcessor() ); + dataProcessor = new MarkdownDataProcessor( viewDocument ); + } ); + for ( const key in testCases ) { const test = testCases[ key ].test; const result = testCases[ key ].result; @@ -70,5 +71,38 @@ describe( 'GFMDataProcessor', () => { expect( stringify( documentFragment ) ).to.equal( '
    \\`
    ' ); } ); } ); + + describe( 'HTML', () => { + // To note that the test util inlines entities in text nodes, hence the expected HTML in these tests + // contain the raw characters but we "know" that those are text nodes and therefore should be converted + // back to entities when outputting markdown. + + it( 'should escape <', () => { + testDataProcessor( '\\<', '

    <

    ' ); + } ); + + it( 'should escape HTML as text', () => { + testDataProcessor( '\\

    Test\\

    ', '

    Test

    ' ); + } ); + + it( 'should not escape \\< inside inline code', () => { + testDataProcessor( '`\\<`', '

    \\<

    ' ); + } ); + + it( 'should not touch escape-like HTML inside code blocks', () => { + testDataProcessor( + '```\n' + + '\\

    Test\\

    \n' + + '```', + '
    ' +
    +					'\\

    Test\\

    ' + + '
    ' ); + } ); + + // Necessary test as we're overriding Turndown's escape(). Just to be sure. + it( 'should still escape markdown characters', () => { + testDataProcessor( '\\* \\_', '

    * _

    ' ); + } ); + } ); } ); } ); diff --git a/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/headers.js b/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/headers.js index de4b7e52068..f3dde011c1b 100644 --- a/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/headers.js +++ b/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/headers.js @@ -95,7 +95,11 @@ describe( 'GFMDataProcessor', () => { '# header\n' + '# header', - '

    header

    header

    ' + '

    header

    header

    ', + + '# header\n' + + '\n' + + '# header' ); } ); @@ -105,7 +109,13 @@ describe( 'GFMDataProcessor', () => { '## header\n' + '### header', - '

    header

    header

    header

    ' + '

    header

    header

    header

    ', + + '# header\n' + + '\n' + + '## header\n' + + '\n' + + '### header' ); } ); diff --git a/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/horizontal-rules.js b/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/horizontal-rules.js index 8f1d534ecc3..f913db287b3 100644 --- a/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/horizontal-rules.js +++ b/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/horizontal-rules.js @@ -6,24 +6,24 @@ import { testDataProcessor } from '../_utils/utils'; describe( 'GFMDataProcessor', () => { - // Horizontal rules are are always rendered by GitHub as
    and normalized when converting - // back to * * *. + // Horizontal rules are always rendered by GitHub as
    and normalized when converting + // back to ---. describe( 'horizontal rules', () => { describe( 'dashes', () => { it( '#1', () => { - testDataProcessor( '---', '
    ', '* * *' ); + testDataProcessor( '---', '
    ', '---' ); } ); it( '#2', () => { - testDataProcessor( ' ---', '
    ', '* * *' ); + testDataProcessor( ' ---', '
    ', '---' ); } ); it( '#3', () => { - testDataProcessor( ' ---', '
    ', '* * *' ); + testDataProcessor( ' ---', '
    ', '---' ); } ); it( '#4', () => { - testDataProcessor( ' ---', '
    ', '* * *' ); + testDataProcessor( ' ---', '
    ', '---' ); } ); it( '#5 - code', () => { @@ -43,19 +43,19 @@ describe( 'GFMDataProcessor', () => { describe( 'dashes with spaces', () => { it( '#1', () => { - testDataProcessor( '- - -', '
    ', '* * *' ); + testDataProcessor( '- - -', '
    ', '---' ); } ); it( '#2', () => { - testDataProcessor( ' - - -', '
    ', '* * *' ); + testDataProcessor( ' - - -', '
    ', '---' ); } ); it( '#3', () => { - testDataProcessor( ' - - -', '
    ', '* * *' ); + testDataProcessor( ' - - -', '
    ', '---' ); } ); it( '#4', () => { - testDataProcessor( ' - - -', '
    ', '* * *' ); + testDataProcessor( ' - - -', '
    ', '---' ); } ); it( '#5 - code', () => { @@ -75,19 +75,19 @@ describe( 'GFMDataProcessor', () => { describe( 'asterisks', () => { it( '#1', () => { - testDataProcessor( '***', '
    ', '* * *' ); + testDataProcessor( '***', '
    ', '---' ); } ); it( '#2', () => { - testDataProcessor( ' ***', '
    ', '* * *' ); + testDataProcessor( ' ***', '
    ', '---' ); } ); it( '#3', () => { - testDataProcessor( ' ***', '
    ', '* * *' ); + testDataProcessor( ' ***', '
    ', '---' ); } ); it( '#4', () => { - testDataProcessor( ' ***', '
    ', '* * *' ); + testDataProcessor( ' ***', '
    ', '---' ); } ); it( '#5 - code', () => { @@ -107,19 +107,19 @@ describe( 'GFMDataProcessor', () => { describe( 'asterisks with spaces', () => { it( '#1', () => { - testDataProcessor( '* * *', '
    ', '* * *' ); + testDataProcessor( '* * *', '
    ', '---' ); } ); it( '#2', () => { - testDataProcessor( ' * * *', '
    ', '* * *' ); + testDataProcessor( ' * * *', '
    ', '---' ); } ); it( '#3', () => { - testDataProcessor( ' * * *', '
    ', '* * *' ); + testDataProcessor( ' * * *', '
    ', '---' ); } ); it( '#4', () => { - testDataProcessor( ' * * *', '
    ', '* * *' ); + testDataProcessor( ' * * *', '
    ', '---' ); } ); it( '#5 - code', () => { @@ -139,19 +139,19 @@ describe( 'GFMDataProcessor', () => { describe( 'underscores', () => { it( '#1', () => { - testDataProcessor( '___', '
    ', '* * *' ); + testDataProcessor( '___', '
    ', '---' ); } ); it( '#2', () => { - testDataProcessor( ' ___', '
    ', '* * *' ); + testDataProcessor( ' ___', '
    ', '---' ); } ); it( '#3', () => { - testDataProcessor( ' ___', '
    ', '* * *' ); + testDataProcessor( ' ___', '
    ', '---' ); } ); it( '#4', () => { - testDataProcessor( ' ___', '
    ', '* * *' ); + testDataProcessor( ' ___', '
    ', '---' ); } ); it( '#5 - code', () => { @@ -171,19 +171,19 @@ describe( 'GFMDataProcessor', () => { describe( 'underscores with spaces', () => { it( '#1', () => { - testDataProcessor( '_ _ _', '
    ', '* * *' ); + testDataProcessor( '_ _ _', '
    ', '---' ); } ); it( '#2', () => { - testDataProcessor( ' _ _ _', '
    ', '* * *' ); + testDataProcessor( ' _ _ _', '
    ', '---' ); } ); it( '#3', () => { - testDataProcessor( ' _ _ _', '
    ', '* * *' ); + testDataProcessor( ' _ _ _', '
    ', '---' ); } ); it( '#4', () => { - testDataProcessor( ' _ _ _', '
    ', '* * *' ); + testDataProcessor( ' _ _ _', '
    ', '---' ); } ); it( '#5 - code', () => { diff --git a/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/html.js b/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/html.js new file mode 100644 index 00000000000..d8170af08f7 --- /dev/null +++ b/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/html.js @@ -0,0 +1,26 @@ +/** + * @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved. + * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license + */ + +import { testDataProcessor } from '../_utils/utils'; + +describe( 'GFMDataProcessor', () => { + describe( 'html', () => { + it( 'should keep html', () => { + testDataProcessor( + 'test with html and not html', + + '

    test with html and not html

    ', + + 'test with html and not html', + + { + setup: dataProcessor => { + dataProcessor.keepHtml( 'keep' ); + } + } + ); + } ); + } ); +} ); diff --git a/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/images.js b/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/images.js index f89f7138684..a739fe9ed79 100644 --- a/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/images.js +++ b/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/images.js @@ -35,7 +35,7 @@ describe( 'GFMDataProcessor', () => { it( 'should process referenced images', () => { testDataProcessor( - '![alt text][logo]\n' + + '![alt text][logo]\n\n' + '[logo]: http://example.com/image.png "title text"', '

    alt text

    ', @@ -47,7 +47,7 @@ describe( 'GFMDataProcessor', () => { it( 'should process referenced images without title', () => { testDataProcessor( - '![alt text][logo]\n' + + '![alt text][logo]\n\n' + '[logo]: http://example.com/image.png', '

    alt text

    ', @@ -59,7 +59,7 @@ describe( 'GFMDataProcessor', () => { it( 'should process referenced images without alt text', () => { testDataProcessor( - '![][logo]\n' + + '![][logo]\n\n' + '[logo]: http://example.com/image.png "title text"', '

    ', diff --git a/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/links.js b/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/links.js index 93aff2c8126..9b8776d959e 100644 --- a/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/links.js +++ b/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/links.js @@ -7,57 +7,34 @@ import { testDataProcessor } from '../_utils/utils'; describe( 'GFMDataProcessor', () => { describe( 'links', () => { - it( 'should autolink', () => { - testDataProcessor( - 'Link: .', - '

    Link: http://example.com/.

    ', - - // When converting back it will be represented as standard markdown link. - 'Link: [http://example.com/](http://example.com/).' - ); - } ); - - it( 'should autolink #2', () => { + it( 'should not autolink', () => { testDataProcessor( 'Link: http://example.com/.', - '

    Link: http://example.com/.

    ', - - // When converting back it will be represented as standard markdown link. - 'Link: [http://example.com/](http://example.com/).' + '

    Link: http://example.com/.

    ' ); } ); - it( 'should autolink with params', () => { + it( 'should not autolink with params', () => { testDataProcessor( - 'Link: .', - '

    Link: http://example.com/?foo=1&bar=2.

    ', - - // When converting back it will be represented as standard markdown link. - 'Link: [http://example.com/?foo=1&bar=2](http://example.com/?foo=1&bar=2).' + 'Link: http://example.com/?foo=1&bar=2.', + '

    Link: http://example.com/?foo=1&bar=2.

    ' ); } ); - it( 'should autolink inside list', () => { + it( 'should not autolink inside list', () => { testDataProcessor( - '* ', - - '', - - // When converting back it will be represented as standard markdown link. - '* [http://example.com/](http://example.com/)' + '* http://example.com/', + '
    • http://example.com/
    ' ); } ); - it( 'should autolink inside blockquote', () => { + it( 'should not autolink inside blockquote', () => { testDataProcessor( - '> Blockquoted: ', + '> Blockquoted: http://example.com/', '
    ' + - '

    Blockquoted: http://example.com/

    ' + - '
    ', - - // When converting back it will be represented as standard markdown link. - '> Blockquoted: [http://example.com/](http://example.com/)' + '

    Blockquoted: http://example.com/

    ' + + '' ); } ); @@ -138,37 +115,17 @@ describe( 'GFMDataProcessor', () => { ); } ); - it( 'should process inline links with spaces in URL', () => { - testDataProcessor( - '[URL and title]( /url/has space )', - '

    URL and title

    ', - - // When converting back unneeded spaces will be removed. - '[URL and title](/url/has space)' - ); - } ); - - it( 'should process inline links with titles and spaces in URL', () => { - testDataProcessor( - '[URL and title]( /url/has space/ "url has space and title")', - '

    URL and title

    ', - - // When converting back unneeded spaces will be removed. - '[URL and title](/url/has space/ "url has space and title")' - ); - } ); - - it( 'should process empty link', () => { - testDataProcessor( - '[Empty]()', - - '

    Empty

    ' - ); - } ); + // it( 'should process empty link', () => { + // testDataProcessor( + // '[Empty]()', + // + // '

    Empty

    ' + // ); + // } ); it( 'should process reference links', () => { testDataProcessor( - 'Foo [bar] [1].\n' + + 'Foo [bar][1].\n\n' + '[1]: /url/ "Title"', '

    Foo bar.

    ', @@ -181,19 +138,7 @@ describe( 'GFMDataProcessor', () => { it( 'should process reference links - without space', () => { testDataProcessor( - 'Foo [bar][1].\n' + - '[1]: /url/ "Title"', - - '

    Foo bar.

    ', - - 'Foo [bar](/url/ "Title").' - ); - } ); - - it( 'should process reference links - with newline', () => { - testDataProcessor( - 'Foo [bar]\n' + - '[1].\n' + + 'Foo [bar][1].\n\n' + '[1]: /url/ "Title"', '

    Foo bar.

    ', @@ -204,18 +149,18 @@ describe( 'GFMDataProcessor', () => { it( 'should process reference links - with embedded brackets', () => { testDataProcessor( - 'With [embedded [brackets]] [b].\n' + + 'With [embedded [brackets]][b].\n\n' + '[b]: /url/', '

    With embedded [brackets].

    ', - 'With [embedded [brackets]](/url/).' + 'With [embedded \\[brackets\\]](/url/).' ); } ); it( 'should process reference links - with reference indented once', () => { testDataProcessor( - 'Indented [once][].\n' + + 'Indented [once][].\n\n' + ' [once]: /url', '

    Indented once.

    ', @@ -226,7 +171,7 @@ describe( 'GFMDataProcessor', () => { it( 'should process reference links - with reference indented twice', () => { testDataProcessor( - 'Indented [twice][].\n' + + 'Indented [twice][].\n\n' + ' [twice]: /url', '

    Indented twice.

    ', @@ -237,7 +182,7 @@ describe( 'GFMDataProcessor', () => { it( 'should process reference links - with reference indented three times', () => { testDataProcessor( - 'Indented [trice][].\n' + + 'Indented [trice][].\n\n' + ' [trice]: /url', '

    Indented trice.

    ', @@ -246,28 +191,9 @@ describe( 'GFMDataProcessor', () => { ); } ); - it( 'should NOT process reference links - with reference indented four times', () => { - testDataProcessor( - 'Indented [four][].\n' + - ' [four]: /url', - - // GitHub renders it as: - //

    Indented [four][].
    - // [four]: /url

    - // Marked converts it to the code block. - '

    Indented [four][].

    [four]: /url
    ', - - 'Indented [four][].\n' + - '\n' + - '```\n' + - '[four]: /url\n' + - '```' - ); - } ); - it( 'should process reference links when title and reference are same #1', () => { testDataProcessor( - '[this] [this]\n' + + '[this][this]\n\n' + '[this]: foo', '

    this

    ', @@ -278,7 +204,7 @@ describe( 'GFMDataProcessor', () => { it( 'should process reference links when title and reference are same #2', () => { testDataProcessor( - '[this][this]\n' + + '[this][this]\n\n' + '[this]: foo', '

    this

    ', @@ -289,7 +215,7 @@ describe( 'GFMDataProcessor', () => { it( 'should process reference links when only title is provided and is same as reference #1', () => { testDataProcessor( - '[this] []\n' + + '[this][]\n\n' + '[this]: foo', '

    this

    ', @@ -300,7 +226,7 @@ describe( 'GFMDataProcessor', () => { it( 'should process reference links when only title is provided and is same as reference #2', () => { testDataProcessor( - '[this][]\n' + + '[this][]\n\n' + '[this]: foo', '

    this

    ', @@ -311,7 +237,7 @@ describe( 'GFMDataProcessor', () => { it( 'should process reference links when only title is provided and is same as reference #3', () => { testDataProcessor( - '[this]\n' + + '[this]\n\n' + '[this]: foo', '

    this

    ', @@ -321,18 +247,12 @@ describe( 'GFMDataProcessor', () => { } ); it( 'should not process reference links when reference is not found #1', () => { - testDataProcessor( - '[this] []', - - '

    [this] []

    ' - ); - } ); - - it( 'should not process reference links when reference is not found #2', () => { testDataProcessor( '[this][]', - '

    [this][]

    ' + '

    [this][]

    ', + + '\\[this\\]\\[\\]' ); } ); @@ -340,35 +260,37 @@ describe( 'GFMDataProcessor', () => { testDataProcessor( '[this]', - '

    [this]

    ' + '

    [this]

    ', + + '\\[this\\]' ); } ); it( 'should process reference links nested in brackets #1', () => { testDataProcessor( - '[a reference inside [this][]]\n' + + '[a reference inside [this][]]\n\n' + '[this]: foo', '

    [a reference inside this]

    ', - '[a reference inside [this](foo)]' + '\\[a reference inside [this](foo)\\]' ); } ); it( 'should process reference links nested in brackets #2', () => { testDataProcessor( - '[a reference inside [this]]\n' + + '[a reference inside [this]]\n\n' + '[this]: foo', '

    [a reference inside this]

    ', - '[a reference inside [this](foo)]' + '\\[a reference inside [this](foo)\\]' ); } ); it( 'should not process reference links when title is same as reference but reference is different', () => { testDataProcessor( - '[this](/something/else/)\n' + + '[this](/something/else/)\n\n' + '[this]: foo', '

    this

    ', @@ -379,19 +301,19 @@ describe( 'GFMDataProcessor', () => { it( 'should not process reference links suppressed by backslashes', () => { testDataProcessor( - 'Suppress \\[this] and [this\\].\n' + + 'Suppress \\[this] and [this\\].\n\n' + '[this]: foo', '

    Suppress [this] and [this].

    ', - 'Suppress [this] and [this].' + 'Suppress \\[this\\] and \\[this\\].' ); } ); it( 'should process reference links when used across multiple lines #1', () => { testDataProcessor( 'This is [multiline\n' + - 'reference]\n' + + 'reference]\n\n' + '[multiline reference]: foo', '

    This is multiline

    reference

    ', @@ -404,7 +326,7 @@ describe( 'GFMDataProcessor', () => { it( 'should process reference links when used across multiple lines #2', () => { testDataProcessor( 'This is [multiline \n' + - 'reference]\n' + + 'reference]\n\n' + '[multiline reference]: foo', '

    This is multiline

    reference

    ', @@ -416,7 +338,7 @@ describe( 'GFMDataProcessor', () => { it( 'should process reference links case-insensitive', () => { testDataProcessor( - '[hi]\n' + + '[hi]\n\n' + '[HI]: /url', '

    hi

    ', diff --git a/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/lists.js b/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/lists.js index 056263f8275..468fbc85cbb 100644 --- a/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/lists.js +++ b/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/lists.js @@ -4,6 +4,10 @@ */ import { testDataProcessor } from '../_utils/utils'; +import MarkdownDataProcessor from '../../src/gfmdataprocessor'; +import HtmlDataProcessor from '@ckeditor/ckeditor5-engine/src/dataprocessor/htmldataprocessor'; +import ViewDocument from '@ckeditor/ckeditor5-engine/src/view/document'; +import { StylesProcessor } from '@ckeditor/ckeditor5-engine/src/view/stylesmap'; describe( 'GFMDataProcessor', () => { describe( 'lists', () => { @@ -340,4 +344,42 @@ describe( 'GFMDataProcessor', () => { ); } ); } ); + + describe( 'todo lists', () => { + it( 'should process todo lists', () => { + testDataProcessor( + '* [ ] Item 1\n' + + '* [x] Item 2', + + '
      ' + + '
    • Item 1
    • ' + + '
    • Item 2
    • ' + + '
    ' ); + } ); + + it( 'should process the HTML produced by the todo list feature', () => { + const viewDocument = new ViewDocument( new StylesProcessor() ); + + const htmlDataProcessor = new HtmlDataProcessor( viewDocument ); + const mdDataProcessor = new MarkdownDataProcessor( viewDocument ); + + const viewFragment = htmlDataProcessor.toView( + '
      ' + + '
    • ' + + '
    • ' + + '
    ' + ); + + expect( mdDataProcessor.toData( viewFragment ) ).to.equal( + '* [ ] Item 1\n' + + '* [x] Item 2' + ); + } ); + } ); } ); diff --git a/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/manual/gfmdataprocessor.js b/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/manual/gfmdataprocessor.js index 0316c8c8f2c..99caa35707a 100644 --- a/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/manual/gfmdataprocessor.js +++ b/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/manual/gfmdataprocessor.js @@ -5,17 +5,20 @@ /* globals document */ -import MarkdownDataProcessor from '../../../src/gfmdataprocessor'; +import Document from '@ckeditor/ckeditor5-engine/src/view/document'; +import { StylesProcessor } from '@ckeditor/ckeditor5-engine/src/view/stylesmap'; import { stringify, parse } from '@ckeditor/ckeditor5-engine/src/dev-utils/view'; +import MarkdownDataProcessor from '../../../src/gfmdataprocessor'; + const markdownTextArea = document.getElementById( 'markdown' ); const viewTextArea = document.getElementById( 'view' ); -const dataProcessor = new MarkdownDataProcessor(); +const dataProcessor = new MarkdownDataProcessor( new Document( new StylesProcessor() ) ); document.getElementById( 'button_to_view' ).addEventListener( 'click', convertToView ); document.getElementById( 'button_to_md' ).addEventListener( 'click', convertToMarkdown ); -markdownTextArea.value = '### Header\n\nFoo bar baz biz.'; +markdownTextArea.value = '### Header 3\n\nTodo:\n\n* [ ] Test me'; convertToView(); function convertToView() { diff --git a/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/paragraphs.js b/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/paragraphs.js index 6799f96b41f..8a198252426 100644 --- a/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/paragraphs.js +++ b/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/paragraphs.js @@ -40,25 +40,6 @@ describe( 'GFMDataProcessor', () => { //

    header

    '

    single line

    header

    ', - // To-markdown always put 2 empty lines after paragraph. - 'single line\n\n' + - '# header' - ); - } ); - - it( 'with header after #2', () => { - testDataProcessor( - 'single line\n' + - 'header\n' + - '===', - - // GitHub is rendering as: - //

    single line

    - // - //

    header

    - '

    single line

    header

    ', - - // To-markdown always put 2 empty lines after paragraph and normalize header to #. 'single line\n' + '\n' + '# header' @@ -78,17 +59,16 @@ describe( 'GFMDataProcessor', () => { // '

    single line

    quote

    ', - // To-markdown always put 2 empty lines after paragraph. - 'single line\n' + + 'single line' + '\n' + - '> quote' + '\n> quote' ); } ); it( 'with list after', () => { testDataProcessor( 'single line\n' + - '* item', + '* item', // GitHub is rendering as: //

    single line

    @@ -98,29 +78,10 @@ describe( 'GFMDataProcessor', () => { // '

    single line

    • item
    ', - // To-markdown always put 2 empty lines after paragraph. 'single line\n' + '\n' + '* item' ); } ); - - it( 'with div element after', () => { - testDataProcessor( - 'single line\n' + - '
    div element
    ', - - // GitHub is rendering as: - //

    single line

    - // - //
    div element
    - '

    single line

    div element
    ', - - // To-markdown always put 2 empty lines after paragraph. - 'single line\n' + - '\n' + - '
    div element
    ' - ); - } ); } ); } ); diff --git a/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/strikethrough.js b/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/strikethrough.js index c3613c4cb00..22859d2f595 100644 --- a/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/strikethrough.js +++ b/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/strikethrough.js @@ -9,7 +9,7 @@ describe( 'GFMDataProcessor', () => { describe( 'Strikethrough', () => { it( 'should process strikethrough text', () => { testDataProcessor( - '~~deleted~~', + '~deleted~', '

    deleted

    ' ); @@ -17,7 +17,7 @@ describe( 'GFMDataProcessor', () => { it( 'should process strikethrough inside text', () => { testDataProcessor( - 'This is ~~deleted content~~.', + 'This is ~deleted content~.', '

    This is deleted content.

    ' ); diff --git a/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/strong-emphasis.js b/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/strong-emphasis.js index ee305cfb835..43ea6477728 100644 --- a/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/strong-emphasis.js +++ b/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/strong-emphasis.js @@ -78,6 +78,18 @@ describe( 'GFMDataProcessor', () => { testDataProcessor( 'This should_not_be_emp.', + '

    This should_not_be_emp.

    ', + + // Turndow escape markdown markup characters used inside text. + 'This should\\_not\\_be\\_emp.' + ); + } ); + + it( 'should not render escape marks', () => { + testDataProcessor( + // Following the previous test. + 'This should\\_not\\_be\\_emp.', + '

    This should_not_be_emp.

    ' ); } ); diff --git a/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/tables.js b/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/tables.js index 70ed33c0834..ea7ce1ab9b8 100644 --- a/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/tables.js +++ b/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/tables.js @@ -119,7 +119,7 @@ describe( 'GFMDataProcessor', () => { testDataProcessor( 'Header 1|Header 2|Header 3|Header 4\n' + ':-------|:------:|-------:|--------\n' + - '*Cell 1* |**Cell 2** |~~Cell 3~~ |Cell 4', + '*Cell 1* |**Cell 2** |~Cell 3~ |Cell 4', '' + '' + @@ -151,7 +151,7 @@ describe( 'GFMDataProcessor', () => { // After converting back it will be normalized. '| Header 1 | Header 2 | Header 3 | Header 4 |\n' + '| :-- | :-: | --: | --- |\n' + - '| _Cell 1_ | **Cell 2** | ~~Cell 3~~ | Cell 4 |' + '| _Cell 1_ | **Cell 2** | ~Cell 3~ | Cell 4 |' ); } ); } ); diff --git a/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/text.js b/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/text.js new file mode 100644 index 00000000000..bd713fc631e --- /dev/null +++ b/packages/ckeditor5-markdown-gfm/tests/gfmdataprocessor/text.js @@ -0,0 +1,50 @@ +/** + * @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved. + * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license + */ + +import { testDataProcessor } from '../_utils/utils'; + +describe( 'GFMDataProcessor', () => { + describe( 'text', () => { + describe( 'urls', () => { + it( 'should not escape urls', () => { + testDataProcessor( + 'escape\\_this https://test.com/do_[not]-escape escape\\_this', + '

    escape_this https://test.com/do_[not]-escape escape_this

    ' + ); + } ); + + it( 'should not escape urls (data escaped between urls)', () => { + testDataProcessor( + 'escape\\_this https://test.com/do_[not]-escape escape\\_this https://test.com/do_[not]-escape', + '

    escape_this https://test.com/do_[not]-escape escape_this https://test.com/do_[not]-escape

    ' + ); + } ); + + it( 'should not escape urls (at start)', () => { + testDataProcessor( + 'https://test.com/do_[not]-escape escape\\_this', + '

    https://test.com/do_[not]-escape escape_this

    ' + ); + } ); + + it( 'should not escape urls (at end)', () => { + testDataProcessor( + 'escape\\_this https://test.com/do_[not]-escape', + '

    escape_this https://test.com/do_[not]-escape

    ' + ); + } ); + + [ + 'https://test.com/do_[not]-escape', + 'http://test.com/do_[not]-escape', + 'www.test.com/do_[not]-escape' + ].forEach( url => { + it( `should not escape urls (${ url })`, () => { + testDataProcessor( url, `

    ${ url }

    ` ); + } ); + } ); + } ); + } ); +} ); diff --git a/yarn.lock b/yarn.lock index 35b5f4cb25c..485a2835e3c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -259,9 +259,9 @@ js-tokens "^4.0.0" "@babel/parser@^7.10.3", "@babel/parser@^7.10.4", "@babel/parser@^7.11.0", "@babel/parser@^7.11.1", "@babel/parser@^7.6.0", "@babel/parser@^7.7.7", "@babel/parser@^7.9.6": - version "7.11.1" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.11.1.tgz#d91a387990b21e5d20047b336bb19b0553f02ff5" - integrity sha512-u9QMIRdKVF7hfEkb3nu2LgZDIzCQPv+yHD9Eg6ruoJLjkrQ9fFz4IBSlF/9XwoNri9+2F1IY+dYuOfZrXq8t3w== + version "7.11.3" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.11.3.tgz#9e1eae46738bcd08e23e867bab43e7b95299a8f9" + integrity sha512-REo8xv7+sDxkKvoxEywIdsNFiZLybwdI7hcT5uEPyQrSMB4YQ973BfC9OOrD/81MaIjh6UxdulIQXkjmiH3PcA== "@babel/plugin-proposal-async-generator-functions@^7.10.4": version "7.10.5" @@ -799,9 +799,9 @@ esutils "^2.0.2" "@babel/runtime@^7.8.4": - version "7.11.1" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.11.1.tgz#087afc57e7bf1073e792fe54f8fb3cfa752f9230" - integrity sha512-nH5y8fLvVl3HAb+ezbgcgwrH8QbClWo8xzkOu7+oyqngo3EVorwpWJQaqXPjGRpfj7mQvsJCl/S8knkfkPWqrw== + version "7.11.2" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.11.2.tgz#f549c13c754cc40b87644b9fa9f09a6a95fe0736" + integrity sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw== dependencies: regenerator-runtime "^0.13.4" @@ -1258,9 +1258,9 @@ "@types/node" ">= 8" "@octokit/types@^5.0.0", "@octokit/types@^5.0.1", "@octokit/types@^5.2.0": - version "5.2.1" - resolved "https://registry.yarnpkg.com/@octokit/types/-/types-5.2.1.tgz#c212f03b0492faf215fa2ae506d5ec18038c2a36" - integrity sha512-PugtgEw8u++zAyBpDpSkR8K1OsT2l8QWp3ECL6bZHFoq9PfHDoKeGFWSuX2Z+Ghy93k1fkKf8tsmqNBv+8dEfQ== + version "5.4.0" + resolved "https://registry.yarnpkg.com/@octokit/types/-/types-5.4.0.tgz#25f2f8e24fec09214553168c41c06383c9d0f529" + integrity sha512-D/uotqF69M50OIlwMqgyIg9PuLT2daOiBAYF0P40I2ekFA2ESwwBY5dxZe/UhXdPvIbNKDzuZmQrO7rMpuFbcg== dependencies: "@types/node" ">= 8" @@ -1339,10 +1339,10 @@ "@sinonjs/commons" "^1" "@sinonjs/samsam" "^5.0.2" -"@sinonjs/samsam@^5.0.2", "@sinonjs/samsam@^5.0.3": - version "5.0.3" - resolved "https://registry.yarnpkg.com/@sinonjs/samsam/-/samsam-5.0.3.tgz#86f21bdb3d52480faf0892a480c9906aa5a52938" - integrity sha512-QucHkc2uMJ0pFGjJUDP3F9dq5dx8QIaqISl9QgwLOh6P9yv877uONPGXh/OH/0zmM3tW1JjuJltAZV2l7zU+uQ== +"@sinonjs/samsam@^5.0.2", "@sinonjs/samsam@^5.1.0": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@sinonjs/samsam/-/samsam-5.1.0.tgz#3afe719232b541bb6cf3411a4c399a188de21ec0" + integrity sha512-42nyaQOVunX5Pm6GRJobmzbS7iLI+fhERITnETXzzwDZh+TtDr/Au3yAvXVjFmZ4wEUaE4Y3NFZfKv0bV0cbtg== dependencies: "@sinonjs/commons" "^1.6.0" lodash.get "^4.4.2" @@ -1634,6 +1634,11 @@ a-sync-waterfall@^1.0.0: resolved "https://registry.yarnpkg.com/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz#75b6b6aa72598b497a125e7a2770f14f4c8a1fa7" integrity sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA== +abab@^2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.4.tgz#6dfa57b417ca06d21b2478f0e638302f99c2405c" + integrity sha512-Eu9ELJWCz/c1e9gTiCY+FceWxcqzjYEbqMgtndnuSqZSUCOL73TWNK2mHfIj4Cw2E/ongOp+JISVNCmovt2KYQ== + abbrev@1, abbrev@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" @@ -1654,6 +1659,14 @@ acorn-globals@^3.0.0: dependencies: acorn "^4.0.4" +acorn-globals@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-6.0.0.tgz#46cdd39f0f8ff08a876619b55f5ac8a6dc770b45" + integrity sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg== + dependencies: + acorn "^7.1.1" + acorn-walk "^7.1.1" + acorn-jsx@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b" @@ -1671,6 +1684,11 @@ acorn-walk@^6.2.0: resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-6.2.0.tgz#123cb8f3b84c2171f1f7fb252615b1c78a6b1a8c" integrity sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA== +acorn-walk@^7.1.1: + version "7.2.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" + integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== + acorn@^3.0.4, acorn@^3.1.0, acorn@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" @@ -1945,24 +1963,20 @@ arrify@^1.0.1: resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= -arrify@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa" - integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug== - asap@^2.0.3, asap@~2.0.3: version "2.0.6" resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= -asn1.js@^4.0.0: - version "4.10.1" - resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" - integrity sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw== +asn1.js@^5.2.0: + version "5.4.1" + resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07" + integrity sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA== dependencies: bn.js "^4.0.0" inherits "^2.0.1" minimalistic-assert "^1.0.0" + safer-buffer "^2.1.0" asn1@~0.2.3: version "0.2.4" @@ -2070,9 +2084,9 @@ aws-sign2@~0.7.0: integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= aws4@^1.8.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.10.0.tgz#a17b3a8ea811060e74d47d306122400ad4497ae2" - integrity sha512-3YDiu347mtVtjpyV3u5kVqQLP242c06zwDOgpeRnybmXlYYsLbtTrUBUm8i8srONt+FWobl5aibnU1030PeeuA== + version "1.10.1" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.10.1.tgz#e1e82e4f3e999e2cfd61b161280d16a111f86428" + integrity sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA== babel-code-frame@^6.26.0: version "6.26.0" @@ -2434,6 +2448,11 @@ brorand@^1.0.1: resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= +browser-process-hrtime@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626" + integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow== + browser-stdout@1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" @@ -2501,14 +2520,14 @@ browserify-zlib@^0.2.0: pako "~1.0.5" browserslist@^4.0.0, browserslist@^4.12.0, browserslist@^4.8.5: - version "4.13.0" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.13.0.tgz#42556cba011e1b0a2775b611cba6a8eca18e940d" - integrity sha512-MINatJ5ZNrLnQ6blGvePd/QOz9Xtu+Ne+x29iQSCHfkU5BugKVJwZKn/iiL8UbpIpa3JhviKjz+XxMo0m2caFQ== + version "4.14.0" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.14.0.tgz#2908951abfe4ec98737b72f34c3bcedc8d43b000" + integrity sha512-pUsXKAF2lVwhmtpeA3LJrZ76jXuusrNyhduuQs7CDFf9foT4Y38aQOserd2lMe5DSSrjf3fx34oHwryuvxAUgQ== dependencies: - caniuse-lite "^1.0.30001093" - electron-to-chromium "^1.3.488" - escalade "^3.0.1" - node-releases "^1.1.58" + caniuse-lite "^1.0.30001111" + electron-to-chromium "^1.3.523" + escalade "^3.0.2" + node-releases "^1.1.60" buffer-from@^1.0.0: version "1.1.1" @@ -2692,11 +2711,6 @@ camelcase@^5.0.0, camelcase@^5.3.1: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== -camelcase@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.0.0.tgz#5259f7c30e35e278f1bdc2a4d91230b37cad981e" - integrity sha512-8KMDF1Vz2gzOq54ONPJS65IvTUaB1cHJ2DMM7MbPmLZljDH1qpzzLsWdiN9pHh6qvkRVDTi/07+eNGch/oLU4w== - caniuse-api@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0" @@ -2707,10 +2721,10 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001093, caniuse-lite@^1.0.30001109: - version "1.0.30001111" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001111.tgz#dd0ce822c70eb6c7c068e4a55c22e19ec1501298" - integrity sha512-xnDje2wchd/8mlJu8sXvWxOGvMgv+uT3iZ3bkIAynKOzToCssWCmkz/ZIkQBs/2pUB4uwnJKVORWQ31UkbVjOg== +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001111: + version "1.0.30001113" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001113.tgz#22016ab55b5a8b04fa00ca342d9ee1b98df48065" + integrity sha512-qMvjHiKH21zzM/VDZr6oosO6Ri3U0V2tC015jRXjOecwQCJtsU5zklTNTk31jQbIOP8gha0h1ccM/g0ECP+4BA== caseless@~0.12.0: version "0.12.0" @@ -2895,9 +2909,9 @@ chokidar@^2.1.8: fsevents "^1.2.7" chokidar@^3.0.0, chokidar@^3.3.0, chokidar@^3.4.0, chokidar@^3.4.1: - version "3.4.1" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.1.tgz#e905bdecf10eaa0a0b1db0c664481cc4cbc22ba1" - integrity sha512-TQTJyr2stihpC4Sya9hs2Xh+O2wf+igjL36Y75xx2WdHuiICcn/XJza46Jwt0eT5hVpQOzo3FpY3cj3RVYLX0g== + version "3.4.2" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.2.tgz#38dc8e658dec3809741eb3ef7bb0a47fe424232d" + integrity sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A== dependencies: anymatch "~3.1.1" braces "~3.0.2" @@ -3164,14 +3178,6 @@ commonmark@^0.29.1: minimist "~1.2.0" string.prototype.repeat "^0.2.0" -compare-func@^1.3.1: - version "1.3.4" - resolved "https://registry.yarnpkg.com/compare-func/-/compare-func-1.3.4.tgz#6b07c4c5e8341119baf44578085bda0f4a823516" - integrity sha512-sq2sWtrqKPkEXAC8tEJA1+BqAH9GbFkGBtUOqrUX57VSfwp8xyktctk+uLoRy5eccTdxzDcVIztlYDpKs3Jv1Q== - dependencies: - array-ify "^1.0.0" - dot-prop "^3.0.0" - compare-func@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/compare-func/-/compare-func-2.0.0.tgz#fb65e75edbddfd2e568554e8b5b05fff7a51fcb3" @@ -3287,11 +3293,11 @@ content-type@~1.0.4: integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== conventional-changelog-writer@^4.0.16: - version "4.0.16" - resolved "https://registry.yarnpkg.com/conventional-changelog-writer/-/conventional-changelog-writer-4.0.16.tgz#ca10f2691a8ea6d3c2eb74bd35bcf40aa052dda5" - integrity sha512-jmU1sDJDZpm/dkuFxBeRXvyNcJQeKhGtVcFFkwTphUAzyYWcwz2j36Wcv+Mv2hU3tpvLMkysOPXJTLO55AUrYQ== + version "4.0.17" + resolved "https://registry.yarnpkg.com/conventional-changelog-writer/-/conventional-changelog-writer-4.0.17.tgz#4753aaa138bf5aa59c0b274cb5937efcd2722e21" + integrity sha512-IKQuK3bib/n032KWaSb8YlBFds+aLmzENtnKtxJy3+HqDq5kohu3g/UdNbIHeJWygfnEbZjnCKFxAW0y7ArZAw== dependencies: - compare-func "^1.3.1" + compare-func "^2.0.0" conventional-commits-filter "^2.0.6" dateformat "^3.0.0" handlebars "^4.7.6" @@ -3663,6 +3669,23 @@ csso@^4.0.2: dependencies: css-tree "1.0.0-alpha.39" +cssom@^0.4.4: + version "0.4.4" + resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.4.4.tgz#5a66cf93d2d0b661d80bf6a44fb65f5c2e4e0a10" + integrity sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw== + +cssom@~0.3.6: + version "0.3.8" + resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a" + integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg== + +cssstyle@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-2.3.0.tgz#ff665a0ddbdc31864b09647f34163443d90b0852" + integrity sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A== + dependencies: + cssom "~0.3.6" + cuid@^2.1.4: version "2.1.8" resolved "https://registry.yarnpkg.com/cuid/-/cuid-2.1.8.tgz#cbb88f954171e0d5747606c0139fb65c5101eac0" @@ -3697,6 +3720,15 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" +data-urls@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-2.0.0.tgz#156485a72963a970f5d5821aaf642bef2bf2db9b" + integrity sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ== + dependencies: + abab "^2.0.3" + whatwg-mimetype "^2.3.0" + whatwg-url "^8.0.0" + date-fns@^1.29.0: version "1.30.1" resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.30.1.tgz#2e71bf0b119153dbb4cc4e88d9ea5acfb50dc05c" @@ -3763,6 +3795,11 @@ decamelize@^1.0.0, decamelize@^1.1.0, decamelize@^1.1.2, decamelize@^1.2.0: resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= +decimal.js@^10.2.0: + version "10.2.0" + resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.2.0.tgz#39466113a9e036111d02f82489b5fd6b0b5ed231" + integrity sha512-vDPw+rDgn3bZe1+F/pyEwb1oMG2XTlRVgAa6B4KccTEpYgF8w6eQllVbQcfIJnZyvzFtFpxnpGtx8dd7DJp/Rw== + decode-uri-component@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" @@ -4021,6 +4058,13 @@ domelementtype@^2.0.1: resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.0.1.tgz#1f8bdfe91f5a78063274e803b4bdcedf6e94f94d" integrity sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ== +domexception@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/domexception/-/domexception-2.0.1.tgz#fb44aefba793e1574b0af6aed2801d057529f304" + integrity sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg== + dependencies: + webidl-conversions "^5.0.0" + domhandler@^2.3.0: version "2.4.2" resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803" @@ -4060,13 +4104,6 @@ domutils@^2.0.0: domelementtype "^2.0.1" domhandler "^3.0.0" -dot-prop@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-3.0.0.tgz#1b708af094a49c9a0e7dbcad790aba539dac1177" - integrity sha1-G3CK8JSknJoOfbyteQq6U52sEXc= - dependencies: - is-obj "^1.0.0" - dot-prop@^5.1.0, dot-prop@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.2.0.tgz#c34ecc29556dc45f1f4c22697b6f4904e0cc4fcb" @@ -4082,9 +4119,9 @@ dreamopt@~0.6.0: wordwrap ">=0.0.2" duplexer@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1" - integrity sha1-rOb/gIwc5mtX0ev5eXessCM0z8E= + version "0.1.2" + resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" + integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== duplexify@^3.4.2, duplexify@^3.6.0: version "3.7.1" @@ -4129,10 +4166,10 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= -electron-to-chromium@^1.3.488: - version "1.3.520" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.520.tgz#dfda0a14a4aed785cbddfdb505ea122f75978392" - integrity sha512-q6H9E1sXDCjRHP+X06vcP+N0ki8ZvYoRPZfKnDuiRX10WWXxEHzKFVf4O9rBFMpuPtR3M+2KAdJnugJoBBp3Rw== +electron-to-chromium@^1.3.523: + version "1.3.533" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.533.tgz#d7e5ca4d57e9bc99af87efbe13e7be5dde729b0f" + integrity sha512-YqAL+NXOzjBnpY+dcOKDlZybJDCOzgsq4koW3fvyty/ldTmsb4QazZpOWmVvZ2m0t5jbBf7L0lIGU3BUipwG+A== elliptic@^6.5.3: version "6.5.3" @@ -4295,7 +4332,7 @@ es6-error@^4.0.1: resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.1.1.tgz#9e3af407459deed47e9a91f9b885a84eb05c561d" integrity sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg== -escalade@^3.0.1: +escalade@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.0.2.tgz#6a580d70edb87880f22b4c91d0d56078df6962c4" integrity sha512-gPYAU37hYCUhW5euPeR+Y74F7BL+IBsV93j5cvGriSaD1aG6MGsqsV1yamRdrWrb2j3aiZvb0X+UBOWpx3JWtQ== @@ -4315,7 +4352,7 @@ escape-string-regexp@^2.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== -escodegen@^1.9.0: +escodegen@^1.14.1, escodegen@^1.9.0: version "1.14.3" resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.14.3.tgz#4e7b81fba61581dc97582ed78cab7f0e8d63f503" integrity sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw== @@ -4460,9 +4497,9 @@ estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== estraverse@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.1.0.tgz#374309d39fd935ae500e7b92e8a6b4c720e59642" - integrity sha512-FyohXK+R0vE+y1nHLoBM7ZTyqRpqAlhdZHCWIWEviFLiGB8b04H6bQs8G+XTthacvT8VuwvteiP7RJSxMs8UEw== + version "5.2.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" + integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== esutils@^2.0.2: version "2.0.3" @@ -4840,9 +4877,9 @@ flush-write-stream@^1.0.0: readable-stream "^2.3.6" follow-redirects@^1.0.0: - version "1.12.1" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.12.1.tgz#de54a6205311b93d60398ebc01cf7015682312b6" - integrity sha512-tmRv0AVuR7ZyouUHLeNSiO6pqulF7dYa3s19c6t+wz9LD69/uSzdMxJ2S91nTI9U3rt/IldxpzMOFejp6f0hjg== + version "1.13.0" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.0.tgz#b42e8d93a2a7eea5ed88633676d6597bc8e384db" + integrity sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA== for-in@^1.0.1, for-in@^1.0.2: version "1.0.2" @@ -5041,9 +5078,9 @@ get-stream@^4.0.0: pump "^3.0.0" get-stream@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.1.0.tgz#01203cdc92597f9b909067c3e656cc1f4d3c4dc9" - integrity sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw== + version "5.2.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" + integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== dependencies: pump "^3.0.0" @@ -5639,6 +5676,13 @@ html-comment-regex@^1.1.0: resolved "https://registry.yarnpkg.com/html-comment-regex/-/html-comment-regex-1.1.2.tgz#97d4688aeb5c81886a364faa0cad1dda14d433a7" integrity sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ== +html-encoding-sniffer@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz#42a6dc4fd33f00281176e8b23759ca4e4fa185f3" + integrity sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ== + dependencies: + whatwg-encoding "^1.0.5" + html-escaper@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" @@ -5920,6 +5964,11 @@ invariant@^2.2.2, invariant@^2.2.4: dependencies: loose-envify "^1.0.0" +ip-regex@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9" + integrity sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk= + is-absolute-url@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6" @@ -6182,7 +6231,7 @@ is-number@^7.0.0: resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== -is-obj@^1.0.0, is-obj@^1.0.1: +is-obj@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= @@ -6234,6 +6283,11 @@ is-posix-bracket@^0.1.0: resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" integrity sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q= +is-potential-custom-element-name@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.0.tgz#0c52e54bcca391bb2c494b21e8626d7336c6e397" + integrity sha1-DFLlS8yjkbssSUsh6GJtczbG45c= + is-primitive@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" @@ -6476,9 +6530,9 @@ javascript-stringify@^2.0.1: integrity sha512-yV+gqbd5vaOYjqlbk16EG89xB5udgjqQF3C5FAORDg4f/IS1Yc5ERCv5e/57yBcfJYw05V5JyIXabhwb75Xxow== jest-worker@^26.2.1: - version "26.2.1" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.2.1.tgz#5d630ab93f666b53f911615bc13e662b382bd513" - integrity sha512-+XcGMMJDTeEGncRb5M5Zq9P7K4sQ1sirhjdOxsN1462h6lFo9w59bl2LVQmdGEEeU3m+maZCkS2Tcc9SfCHO4A== + version "26.3.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.3.0.tgz#7c8a97e4f4364b4f05ed8bca8ca0c24de091871f" + integrity sha512-Vmpn2F6IASefL+DVBhPzI2J9/GJUsqzomdeN+P+dK8/jKxbh8R3BtFnx3FIta7wYlPU62cpJMJQo4kuOowcMnw== dependencies: "@types/node" "*" merge-stream "^2.0.0" @@ -6495,14 +6549,14 @@ js-base64@^2.1.8: integrity sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ== js-beautify@^1.11.0: - version "1.11.0" - resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.11.0.tgz#afb873dc47d58986360093dcb69951e8bcd5ded2" - integrity sha512-a26B+Cx7USQGSWnz9YxgJNMmML/QG2nqIaL7VVYPCXbqiKz8PN0waSNvroMtvAK6tY7g/wPdNWGEP+JTNIBr6A== + version "1.12.0" + resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.12.0.tgz#6c7e6a47a6075a7c8e60c861e850440a5479d36e" + integrity sha512-hZCm93+sWHqrsB2ac38cPX4A9t6mfReq13ZUr/0dk6rCXNLIq0R4lu0EiuJc0Ip6RiWNtE0vECjXOhcy/jMt9Q== dependencies: config-chain "^1.1.12" editorconfig "^0.15.3" glob "^7.1.3" - mkdirp "~1.0.3" + mkdirp "^1.0.4" nopt "^4.0.3" js-stringify@^1.0.1, js-stringify@^1.0.2: @@ -6589,6 +6643,38 @@ jsbn@~0.1.0: taffydb "2.6.2" underscore "~1.8.3" +jsdom@^16.2.0: + version "16.4.0" + resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-16.4.0.tgz#36005bde2d136f73eee1a830c6d45e55408edddb" + integrity sha512-lYMm3wYdgPhrl7pDcRmvzPhhrGVBeVhPIqeHjzeiHN3DFmD1RBpbExbi8vU7BJdH8VAZYovR8DMt0PNNDM7k8w== + dependencies: + abab "^2.0.3" + acorn "^7.1.1" + acorn-globals "^6.0.0" + cssom "^0.4.4" + cssstyle "^2.2.0" + data-urls "^2.0.0" + decimal.js "^10.2.0" + domexception "^2.0.1" + escodegen "^1.14.1" + html-encoding-sniffer "^2.0.1" + is-potential-custom-element-name "^1.0.0" + nwsapi "^2.2.0" + parse5 "5.1.1" + request "^2.88.2" + request-promise-native "^1.0.8" + saxes "^5.0.0" + symbol-tree "^3.2.4" + tough-cookie "^3.0.1" + w3c-hr-time "^1.0.2" + w3c-xmlserializer "^2.0.0" + webidl-conversions "^6.1.0" + whatwg-encoding "^1.0.5" + whatwg-mimetype "^2.3.0" + whatwg-url "^8.0.0" + ws "^7.2.3" + xml-name-validator "^3.0.0" + jsesc@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" @@ -6934,9 +7020,9 @@ lint-staged@^10.2.6: stringify-object "^3.3.0" listr2@^2.1.0: - version "2.4.1" - resolved "https://registry.yarnpkg.com/listr2/-/listr2-2.4.1.tgz#006fc94ae77b3195403cbf3a4a563e2d6366224f" - integrity sha512-8pYsCZCztr5+KAjReLyBeGhLV0vaQ2Du/eMe/ux9QAfQl7efiWejM1IWjALh0zHIRYuIbhQ8N2KztZ4ci56pnQ== + version "2.5.1" + resolved "https://registry.yarnpkg.com/listr2/-/listr2-2.5.1.tgz#f265dddf916c8a9b475437b34ae85a7d8f495c7a" + integrity sha512-qkNRW70SwfwWLD/eiaTf2tfgWT/ZvjmMsnEFJOCzac0cjcc8rYHDBr1eQhRxopj6lZO7Oa5sS/pZzS6q+BsX+w== dependencies: chalk "^4.1.0" cli-truncate "^2.1.0" @@ -6944,7 +7030,7 @@ listr2@^2.1.0: indent-string "^4.0.0" log-update "^4.0.0" p-map "^4.0.0" - rxjs "^6.6.0" + rxjs "^6.6.2" through "^2.3.8" load-json-file@^1.0.0: @@ -7091,6 +7177,11 @@ lodash.some@^4.4.0: resolved "https://registry.yarnpkg.com/lodash.some/-/lodash.some-4.6.0.tgz#1bb9f314ef6b8baded13b549169b2a945eb68e4d" integrity sha1-G7nzFO9ri63tE7VJFpsqlF62jk0= +lodash.sortby@^4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" + integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg= + lodash.template@^4.0.2: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.5.0.tgz#f976195cf3f347d0d5f52483569fe8031ccce8ab" @@ -7370,6 +7461,11 @@ markdown@~0.5.0: dependencies: nopt "~2.1.1" +marked@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/marked/-/marked-0.7.0.tgz#b64201f051d271b1edc10a04d1ae9b74bb8e5c0e" + integrity sha512-c+yYdCZJQrsRjTPhUx7VKkApw9bwDkNbHUKo1ovgcfDjb2kc8rLuRbIFyXL5WOEUwzSSKo3IXpph2K6DqB/KZg== + marked@^0.8.2: version "0.8.2" resolved "https://registry.yarnpkg.com/marked/-/marked-0.8.2.tgz#4faad28d26ede351a7a1aaa5fec67915c869e355" @@ -7464,17 +7560,15 @@ meow@^3.7.0: trim-newlines "^1.0.0" meow@^7.0.0, meow@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/meow/-/meow-7.0.1.tgz#1ed4a0a50b3844b451369c48362eb0515f04c1dc" - integrity sha512-tBKIQqVrAHqwit0vfuFPY3LlzJYkEOFyKa3bPgxzNl6q/RtN8KQ+ALYEASYuFayzSAsjlhXj/JZ10rH85Q6TUw== + version "7.1.0" + resolved "https://registry.yarnpkg.com/meow/-/meow-7.1.0.tgz#50ecbcdafa16f8b58fb7eb9675b933f6473b3a59" + integrity sha512-kq5F0KVteskZ3JdfyQFivJEj2RaA8NFsS4+r9DaMKLcUHpk5OcHS3Q0XkCXONB1mZRPsu/Y/qImKri0nwSEZog== dependencies: "@types/minimist" "^1.2.0" - arrify "^2.0.1" - camelcase "^6.0.0" camelcase-keys "^6.2.2" decamelize-keys "^1.1.0" hard-rejection "^2.1.0" - minimist-options "^4.0.2" + minimist-options "4.1.0" normalize-package-data "^2.5.0" read-pkg-up "^7.0.1" redent "^3.0.0" @@ -7610,7 +7704,7 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: dependencies: brace-expansion "^1.1.7" -minimist-options@^4.0.2: +minimist-options@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619" integrity sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A== @@ -7696,7 +7790,7 @@ mkdirp@0.5.5, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.3, mkd dependencies: minimist "^1.2.5" -mkdirp@^1.0.3, mkdirp@^1.0.4, mkdirp@~1.0.3: +mkdirp@^1.0.3, mkdirp@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== @@ -7836,7 +7930,7 @@ nice-try@^1.0.4: resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== -nise@^4.0.1: +nise@^4.0.4: version "4.0.4" resolved "https://registry.yarnpkg.com/nise/-/nise-4.0.4.tgz#d73dea3e5731e6561992b8f570be9e363c4512dd" integrity sha512-bTTRUNlemx6deJa+ZyoCUTRvH3liK5+N6VQZ4NIw90AgDXY6iPnsqplNFf6STcj+ePk0H/xqxnP75Lr0J0Fq3A== @@ -7922,7 +8016,7 @@ node-preload@^0.2.1: dependencies: process-on-spawn "^1.0.0" -node-releases@^1.1.58: +node-releases@^1.1.60: version "1.1.60" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.60.tgz#6948bdfce8286f0b5d0e5a88e8384e954dfe7084" integrity sha512-gsO4vjEdQaTusZAEebUWp2a5d7dF5DYoIpDG7WySnk7BuZDW+GPpHXoXXuYawRBr/9t5q54tirPz79kFIWg4dA== @@ -8078,6 +8172,11 @@ nunjucks@^3.1.3: optionalDependencies: chokidar "^3.3.0" +nwsapi@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7" + integrity sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ== + nyc@^15.0.1: version "15.1.0" resolved "https://registry.yarnpkg.com/nyc/-/nyc-15.1.0.tgz#1335dae12ddc87b6e249d5a1994ca4bdaea75f02" @@ -8210,9 +8309,9 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0: wrappy "1" onetime@^5.1.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.1.tgz#5c8016847b0d67fcedb7eef254751cfcdc7e9418" - integrity sha512-ZpZpjcJeugQfWsfyQlshVoowIIQ1qBGSVll4rfDq6JJVO//fesjoX808hXWfBjY+ROZgpKDI5TRSRBSoJiZ8eg== + version "5.1.2" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== dependencies: mimic-fn "^2.1.0" @@ -8373,13 +8472,12 @@ parent-module@^1.0.0: callsites "^3.0.0" parse-asn1@^5.0.0, parse-asn1@^5.1.5: - version "5.1.5" - resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.5.tgz#003271343da58dc94cace494faef3d2147ecea0e" - integrity sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ== + version "5.1.6" + resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.6.tgz#385080a3ec13cb62a62d39409cb3e88844cdaed4" + integrity sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw== dependencies: - asn1.js "^4.0.0" + asn1.js "^5.2.0" browserify-aes "^1.0.0" - create-hash "^1.1.0" evp_bytestokey "^1.0.0" pbkdf2 "^3.0.3" safe-buffer "^5.1.1" @@ -8446,6 +8544,11 @@ parse5@1.0.0: resolved "https://registry.yarnpkg.com/parse5/-/parse5-1.0.0.tgz#d53ec053a2054e7538424ea9a6eeb9b265261279" integrity sha1-1T7AU6IFTnU4Qk6ppu65smUmEnk= +parse5@5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.1.tgz#f68e4e5ba1852ac2cadc00f4555fff6c2abb6178" + integrity sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug== + parseqs@0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/parseqs/-/parseqs-0.0.5.tgz#d5208a3738e46766e291ba2ea173684921a8b89d" @@ -8647,9 +8750,9 @@ posix-character-classes@^0.1.0: integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= postcss-calc@^7.0.1: - version "7.0.2" - resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-7.0.2.tgz#504efcd008ca0273120568b0792b16cdcde8aac1" - integrity sha512-rofZFHUg6ZIrvRwPeFktv06GdbDYLcGqh9EwiMutZg+a0oePCCw1zHOEiji6LCpyRcjTREtPASuUqeAvYlEVvQ== + version "7.0.3" + resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-7.0.3.tgz#d65cca92a3c52bf27ad37a5f732e0587b74f1623" + integrity sha512-IB/EAEmZhIMEIhG7Ov4x+l47UaXOS1n2f4FBUk/aKllQhtSCxWhTzn0nJgkqN7fo/jcWySvWTSB6Syk9L+31bA== dependencies: postcss "^7.0.27" postcss-selector-parser "^6.0.2" @@ -9111,9 +9214,9 @@ pretty-hrtime@^1.0.3: integrity sha1-t+PqQkNaTJsnWdmeDyAesZWALuE= prismjs@^1.17.1: - version "1.20.0" - resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.20.0.tgz#9b685fc480a3514ee7198eac6a3bf5024319ff03" - integrity sha512-AEDjSrVNkynnw6A+B1DsFkd6AVdTnp+/WoUixFRULlCLZVRZlVQMVWio/16jv7G1FscUxQxOQhWwApgbnxr6kQ== + version "1.21.0" + resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.21.0.tgz#36c086ec36b45319ec4218ee164c110f9fc015a3" + integrity sha512-uGdSIu1nk3kej2iZsLyDoJ7e9bnPzIgY0naW/HdknGj61zScaprVEVGHrPoXqI+M9sP0NDnTK2jpkvmldpuqDw== optionalDependencies: clipboard "^2.0.0" @@ -9875,6 +9978,22 @@ replace-ext@1.0.0: resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb" integrity sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs= +request-promise-core@1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.4.tgz#3eedd4223208d419867b78ce815167d10593a22f" + integrity sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw== + dependencies: + lodash "^4.17.19" + +request-promise-native@^1.0.8: + version "1.0.9" + resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.9.tgz#e407120526a5efdc9a39b28a5679bf47b9d9dc28" + integrity sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g== + dependencies: + request-promise-core "1.1.4" + stealthy-require "^1.1.1" + tough-cookie "^2.3.3" + request@^2.51.0, request@^2.87.0, request@^2.88.0, request@^2.88.2: version "2.88.2" resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" @@ -10063,7 +10182,7 @@ run-queue@^1.0.0, run-queue@^1.0.3: dependencies: aproba "^1.1.1" -rxjs@^6.6.0: +rxjs@^6.6.0, rxjs@^6.6.2: version "6.6.2" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.2.tgz#8096a7ac03f2cc4fe5860ef6e572810d9e01c0d2" integrity sha512-BHdBMVoWC2sL26w//BCu3YzKT4s2jip/WhwsGEDmeKYBhKDZeYezVUnHatYB7L85v5xs0BAQmg6BEYJEKxBabg== @@ -10112,6 +10231,13 @@ sax@^1.2.4, sax@~1.2.4: resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== +saxes@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/saxes/-/saxes-5.0.1.tgz#eebab953fa3b7608dbe94e5dadb15c888fa6696d" + integrity sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw== + dependencies: + xmlchars "^2.2.0" + scheduler@^0.19.1: version "0.19.1" resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.19.1.tgz#4f3e2ed2c1a7d65681f4c854fa8c5a1ccb40f196" @@ -10198,13 +10324,6 @@ semver@~5.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" integrity sha1-myzl094C0XxgEq0yaqa00M9U+U8= -serialize-javascript@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-3.1.0.tgz#8bf3a9170712664ef2561b44b691eafe399214ea" - integrity sha512-JIJT1DGiWmIKhzRsG91aS6Ze4sFUrYbltlkg2onR5OrnNM02Kl/hnY/T4FN2omvyeBbQmMJv+K4cPOpGzOTFBg== - dependencies: - randombytes "^2.1.0" - serialize-javascript@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-4.0.0.tgz#b525e1238489a5ecfc42afacc3fe99e666f4b1aa" @@ -10313,16 +10432,16 @@ sinon-chai@^3.5.0: integrity sha512-IifbusYiQBpUxxFJkR3wTU68xzBN0+bxCScEaKMjBvAQERg6FnTTc1F17rseLb1tjmkJ23730AXpFI0c47FgAg== sinon@^9.0.2: - version "9.0.2" - resolved "https://registry.yarnpkg.com/sinon/-/sinon-9.0.2.tgz#b9017e24633f4b1c98dfb6e784a5f0509f5fd85d" - integrity sha512-0uF8Q/QHkizNUmbK3LRFqx5cpTttEVXudywY9Uwzy8bTfZUhljZ7ARzSxnRHWYWtVTeh4Cw+tTb3iU21FQVO9A== + version "9.0.3" + resolved "https://registry.yarnpkg.com/sinon/-/sinon-9.0.3.tgz#bffc3ec28c936332cd2a41833547b9eed201ecff" + integrity sha512-IKo9MIM111+smz9JGwLmw5U1075n1YXeAq8YeSFlndCLhAL5KGn6bLgu7b/4AYHTV/LcEMcRm2wU2YiL55/6Pg== dependencies: "@sinonjs/commons" "^1.7.2" "@sinonjs/fake-timers" "^6.0.1" "@sinonjs/formatio" "^5.0.1" - "@sinonjs/samsam" "^5.0.3" + "@sinonjs/samsam" "^5.1.0" diff "^4.0.2" - nise "^4.0.1" + nise "^4.0.4" supports-color "^7.1.0" sitemap@^6.1.6: @@ -10663,6 +10782,11 @@ stdout-stream@^1.4.0: dependencies: readable-stream "^2.0.1" +stealthy-require@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" + integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks= + stream-browserify@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b" @@ -11057,6 +11181,11 @@ swig-templates@^2.0.3: optimist "~0.6" uglify-js "2.6.0" +symbol-tree@^3.2.4: + version "3.2.4" + resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" + integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== + table@^5.2.3, table@^5.4.6: version "5.4.6" resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" @@ -11099,15 +11228,15 @@ tar@^6.0.2: yallist "^4.0.0" terser-webpack-plugin@^1.4.3: - version "1.4.4" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.4.tgz#2c63544347324baafa9a56baaddf1634c8abfc2f" - integrity sha512-U4mACBHIegmfoEe5fdongHESNJWqsGU+W0S/9+BmYGVQDw1+c2Ow05TpMhxjPK1sRb7cuYq1BPl1e5YHJMTCqA== + version "1.4.5" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz#a217aefaea330e734ffacb6120ec1fa312d6040b" + integrity sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw== dependencies: cacache "^12.0.2" find-cache-dir "^2.1.0" is-wsl "^1.1.0" schema-utils "^1.0.0" - serialize-javascript "^3.1.0" + serialize-javascript "^4.0.0" source-map "^0.6.1" terser "^4.1.2" webpack-sources "^1.4.0" @@ -11285,7 +11414,7 @@ token-stream@1.0.0: resolved "https://registry.yarnpkg.com/token-stream/-/token-stream-1.0.0.tgz#cc200eab2613f4166d27ff9afc7ca56d49df6eb4" integrity sha1-zCAOqyYT9BZtJ/+a/HylbUnfbrQ= -tough-cookie@~2.5.0: +tough-cookie@^2.3.3, tough-cookie@~2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== @@ -11293,6 +11422,22 @@ tough-cookie@~2.5.0: psl "^1.1.28" punycode "^2.1.1" +tough-cookie@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-3.0.1.tgz#9df4f57e739c26930a018184887f4adb7dca73b2" + integrity sha512-yQyJ0u4pZsv9D4clxO69OEjLWYw+jbgspjTue4lTQZLfV0c5l1VmK2y1JK8E9ahdpltPOaAThPcp5nKPUgSnsg== + dependencies: + ip-regex "^2.1.0" + psl "^1.1.28" + punycode "^2.1.1" + +tr46@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-2.0.2.tgz#03273586def1595ae08fedb38d7733cee91d2479" + integrity sha512-3n1qG+/5kg+jrbTzwAykB5yRYtQCTqOGKq5U5PE3b0a1/mzo6snDhjGS0zJVJunO0NrT3Dg1MLy5TjWP/UJppg== + dependencies: + punycode "^2.1.1" + tree-model@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/tree-model/-/tree-model-1.0.7.tgz#45b2307aa2dfc2da8ceb6a631c1e2b15550dce88" @@ -11360,6 +11505,18 @@ tunnel-agent@^0.6.0: dependencies: safe-buffer "^5.0.1" +turndown-plugin-gfm@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/turndown-plugin-gfm/-/turndown-plugin-gfm-1.0.2.tgz#6f8678a361f35220b2bdf5619e6049add75bf1c7" + integrity sha512-vwz9tfvF7XN/jE0dGoBei3FXWuvll78ohzCZQuOb+ZjWrs3a0XhQVomJEb2Qh4VHTPNRO4GPZh0V7VRbiWwkRg== + +turndown@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/turndown/-/turndown-6.0.0.tgz#c083d6109a9366be1b84b86b20af09140ea4b413" + integrity sha512-UVJBhSyRHCpNKtQ00mNWlYUM/i+tcipkb++F0PrOpt0L7EhNd0AX9mWEpL2dRFBu7LWXMp4HgAMA4OeKKnN7og== + dependencies: + jsdom "^16.2.0" + tweetnacl@^0.14.3, tweetnacl@~0.14.0: version "0.14.5" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" @@ -11852,6 +12009,20 @@ vue-template-compiler@^2.6.11: de-indent "^1.0.2" he "^1.1.0" +w3c-hr-time@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd" + integrity sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ== + dependencies: + browser-process-hrtime "^1.0.0" + +w3c-xmlserializer@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz#3e7104a05b75146cc60f564380b7f683acf1020a" + integrity sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA== + dependencies: + xml-name-validator "^3.0.0" + walkdir@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/walkdir/-/walkdir-0.4.1.tgz#dc119f83f4421df52e3061e514228a2db20afa39" @@ -11887,6 +12058,16 @@ watchpack@^1.7.4: chokidar "^3.4.1" watchpack-chokidar2 "^2.0.0" +webidl-conversions@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-5.0.0.tgz#ae59c8a00b121543a2acc65c0434f57b0fc11aff" + integrity sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA== + +webidl-conversions@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514" + integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w== + webpack-cli@^3.3.11: version "3.3.12" resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.3.12.tgz#94e9ada081453cd0aa609c99e500012fd3ad2d4a" @@ -11960,6 +12141,27 @@ webpack@^4.43.0: watchpack "^1.7.4" webpack-sources "^1.4.1" +whatwg-encoding@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0" + integrity sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw== + dependencies: + iconv-lite "0.4.24" + +whatwg-mimetype@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf" + integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g== + +whatwg-url@^8.0.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-8.1.0.tgz#c628acdcf45b82274ce7281ee31dd3c839791771" + integrity sha512-vEIkwNi9Hqt4TV9RdnaBPNt+E2Sgmo3gePebCRgZ1R7g6d23+53zCTnuB0amKI4AXq6VM8jj2DUAa0S1vjJxkw== + dependencies: + lodash.sortby "^4.7.0" + tr46 "^2.0.2" + webidl-conversions "^5.0.0" + which-module@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" @@ -11997,9 +12199,9 @@ window-size@0.1.0: integrity sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0= windows-release@^3.1.0: - version "3.3.1" - resolved "https://registry.yarnpkg.com/windows-release/-/windows-release-3.3.1.tgz#cb4e80385f8550f709727287bf71035e209c4ace" - integrity sha512-Pngk/RDCaI/DkuHPlGTdIkDiTAnAkyMjoQMZqRsxydNl1qGXNIoZrB7RK8g53F2tEgQBMqQJHQdYZuQEEAu54A== + version "3.3.3" + resolved "https://registry.yarnpkg.com/windows-release/-/windows-release-3.3.3.tgz#1c10027c7225743eec6b89df160d64c2e0293999" + integrity sha512-OSOGH1QYiW5yVor9TtmXKQvt2vjQqbYS+DqmsZw+r7xDwLXEeT3JGW0ZppFmHx4diyXmxt238KFR3N9jzevBRg== dependencies: execa "^1.0.0" @@ -12088,7 +12290,7 @@ write@1.0.3: dependencies: mkdirp "^0.5.1" -ws@^7.1.2: +ws@^7.1.2, ws@^7.2.3: version "7.3.1" resolved "https://registry.yarnpkg.com/ws/-/ws-7.3.1.tgz#d0547bf67f7ce4f12a72dfe31262c68d7dc551c8" integrity sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA== @@ -12100,6 +12302,16 @@ ws@~6.1.0: dependencies: async-limiter "~1.0.0" +xml-name-validator@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" + integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw== + +xmlchars@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" + integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== + xmlcreate@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/xmlcreate/-/xmlcreate-2.0.3.tgz#df9ecd518fd3890ab3548e1b811d040614993497"