diff --git a/package-lock.json b/package-lock.json index 1b7b0c7e52..ba554ff58d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -159,6 +159,12 @@ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", "dev": true }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", + "dev": true + }, "brace-expansion": { "version": "1.1.8", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", @@ -198,6 +204,31 @@ "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", "dev": true }, + "cheerio": { + "version": "1.0.0-rc.3", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.3.tgz", + "integrity": "sha512-0td5ijfUPuubwLUu0OBoe98gZj8C/AA+RW3v67GPlGOrvxWjZmBXiBCRU+I8VEiNyJzjth40POfHiz2RB3gImA==", + "dev": true, + "requires": { + "css-select": "~1.2.0", + "dom-serializer": "~0.1.1", + "entities": "~1.1.1", + "htmlparser2": "^3.9.1", + "lodash": "^4.15.0", + "parse5": "^3.0.1" + }, + "dependencies": { + "parse5": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz", + "integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==", + "dev": true, + "requires": { + "@types/node": "*" + } + } + } + }, "cli-cursor": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", @@ -340,6 +371,24 @@ "which": "^1.2.9" } }, + "css-select": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", + "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", + "dev": true, + "requires": { + "boolbase": "~1.0.0", + "css-what": "2.1", + "domutils": "1.5.1", + "nth-check": "~1.0.1" + } + }, + "css-what": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz", + "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==", + "dev": true + }, "debug": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", @@ -376,6 +425,41 @@ "esutils": "^2.0.2" } }, + "dom-serializer": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz", + "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==", + "dev": true, + "requires": { + "domelementtype": "^1.3.0", + "entities": "^1.1.1" + } + }, + "domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", + "dev": true + }, + "domhandler": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", + "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", + "dev": true, + "requires": { + "domelementtype": "1" + } + }, + "domutils": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", + "dev": true, + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, "emoji-regex": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", @@ -860,6 +944,20 @@ "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", "dev": true }, + "htmlparser2": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", + "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", + "dev": true, + "requires": { + "domelementtype": "^1.3.1", + "domhandler": "^2.3.0", + "domutils": "^1.5.1", + "entities": "^1.1.1", + "inherits": "^2.0.1", + "readable-stream": "^3.1.1" + } + }, "http-basic": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/http-basic/-/http-basic-7.0.0.tgz", @@ -1221,6 +1319,15 @@ "validate-npm-package-license": "^3.0.1" } }, + "nth-check": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "dev": true, + "requires": { + "boolbase": "~1.0.0" + } + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -1433,6 +1540,17 @@ "read-pkg": "^2.0.0" } }, + "readable-stream": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.3.0.tgz", + "integrity": "sha512-EsI+s3k3XsW+fU8fQACLN59ky34AZ14LoeVZpYwmZvldCFo0r0gnelwF2TcMjLor/BTL5aDJVBMkss0dthToPw==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, "regexpp": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", @@ -1607,6 +1725,15 @@ "integrity": "sha1-q6Nt4I3O5qWjN9SbLqHaGyj8Ds8=", "dev": true }, + "string_decoder": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.2.0.tgz", + "integrity": "sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", diff --git a/package.json b/package.json index 916f6a177b..43cea559fc 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ ], "devDependencies": { "@markedjs/html-differ": "^2.0.1", + "cheerio": "^1.0.0-rc.3", "commonmark": "0.x", "eslint": "^5.15.1", "eslint-config-standard": "^12.0.0", diff --git a/test/specs/gfm/getSpecs.js b/test/specs/gfm/getSpecs.js new file mode 100644 index 0000000000..2746bdbbcb --- /dev/null +++ b/test/specs/gfm/getSpecs.js @@ -0,0 +1,44 @@ +const fetch = require('node-fetch'); +const cheerio = require('cheerio'); +const marked = require('../../../'); +const htmlDiffer = require('../../helpers/html-differ.js'); +const fs = require('fs'); + +fetch('https://github.github.com/gfm/') + .then(res => res.text()) + .then(html => cheerio.load(html)) + .then($ => { + const version = $('.version').text().match(/\d+\.\d+/)[0]; + if (!version) { + throw new Error('No version found'); + } + const specs = []; + $('.extension').each((i, ext) => { + const section = $('.definition', ext).text().trim().replace(/^\d+\.\d+(.*?) \(extension\)[\s\S]*$/, '$1'); + $('.example', ext).each((j, exa) => { + const example = +$(exa).attr('id').replace(/\D/g, ''); + const markdown = $('.language-markdown', exa).text().trim(); + const html = $('.language-html', exa).text().trim(); + specs.push({ + section, + html, + markdown, + example + }); + }); + }); + + return [version, specs]; + }) + .then(([version, specs]) => { + specs.forEach(spec => { + const html = marked(spec.markdown, {gfm: true}); + if (!htmlDiffer.isEqual(html, spec.html)) { + spec.shouldFail = true; + } + }); + fs.writeFileSync(`gfm.${version}.json`, JSON.stringify(specs, null, 2) + '\n'); + }) + .catch((err) => { + console.error(err); + }); diff --git a/test/specs/gfm/gfm.0.28.json b/test/specs/gfm/gfm.0.29.json similarity index 86% rename from test/specs/gfm/gfm.0.28.json rename to test/specs/gfm/gfm.0.29.json index 75bffc64ce..7d1d43e4b6 100644 --- a/test/specs/gfm/gfm.0.28.json +++ b/test/specs/gfm/gfm.0.29.json @@ -1,153 +1,147 @@ [ { "section": "Tables", - "html": "\n\n\n\n\n\n\n\n\n\n\n
foobar
bazbim
", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n\n
foobar
bazbim
", "markdown": "| foo | bar |\n| --- | --- |\n| baz | bim |", - "example": 191 + "example": 198 }, { "section": "Tables", - "html": "\n\n\n\n\n\n\n\n\n\n\n
abcdefghi
barbaz
", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n\n
abcdefghi
barbaz
", "markdown": "| abc | defghi |\n:-: | -----------:\nbar | baz", - "example": 192 + "example": 199 }, { "section": "Tables", - "html": "\n\n\n\n\n\n\n\n\n\n\n\n
f|oo
b | az
b | im
", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n
f|oo
b | az
b | im
", "markdown": "| f\\|oo |\n| ------ |\n| b `\\|` az |\n| b **\\|** im |", - "example": 193 + "example": 200 }, { "section": "Tables", - "html": "\n\n\n\n\n\n\n\n\n\n\n
abcdef
barbaz
\n
\n

bar

\n
", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n\n
abcdef
barbaz
\n
\n

bar

\n
", "markdown": "| abc | def |\n| --- | --- |\n| bar | baz |\n> bar", - "example": 194 + "example": 201 }, { "section": "Tables", - "html": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
abcdef
barbaz
bar
\n

bar

", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
abcdef
barbaz
bar
\n

bar

", "markdown": "| abc | def |\n| --- | --- |\n| bar | baz |\nbar\n\nbar", - "example": 195 + "example": 202 }, { "section": "Tables", "html": "

| abc | def |\n| --- |\n| bar |

", "markdown": "| abc | def |\n| --- |\n| bar |", - "example": 196 + "example": 203 }, { "section": "Tables", - "html": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
abcdef
bar
barbaz
", + "html": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
abcdef
bar
barbaz
", "markdown": "| abc | def |\n| --- | --- |\n| bar |\n| bar | baz | boo |", - "example": 197 + "example": 204 }, { "section": "Tables", - "html": "\n\n\n\n\n\n
abcdef
", + "html": "\n\n\n\n\n\n\n
abcdef
", "markdown": "| abc | def |\n| --- | --- |", - "example": 198 + "example": 205 }, { "section": "Task list items", "html": "", "markdown": "- [ ] foo\n- [x] bar", - "example": 272 + "example": 279 }, { "section": "Task list items", "html": "", "markdown": "- [x] foo\n - [ ] bar\n - [x] baz\n- [ ] bim", - "example": 273 + "example": 280 }, { "section": "Strikethrough", "html": "

Hi Hello, world!

", - "markdown": "~Hi~ Hello, world!", - "example": 469 - }, - { - "section": "Strikethrough", - "html": "

This text is curious.

", - "markdown": "This ~text~~~~ is ~~~~curious~.", - "example": 470 + "markdown": "~~Hi~~ Hello, world!", + "example": 491 }, { "section": "Strikethrough", "html": "

This ~~has a

\n

new paragraph~~.

", "markdown": "This ~~has a\n\nnew paragraph~~.", - "example": 471 + "example": 492 }, { "section": "Autolinks", "html": "

www.commonmark.org

", "markdown": "www.commonmark.org", - "example": 597 + "example": 621 }, { "section": "Autolinks", "html": "

Visit www.commonmark.org/help for more information.

", "markdown": "Visit www.commonmark.org/help for more information.", - "example": 598 + "example": 622 }, { "section": "Autolinks", "html": "

Visit www.commonmark.org.

\n

Visit www.commonmark.org/a.b.

", "markdown": "Visit www.commonmark.org.\n\nVisit www.commonmark.org/a.b.", - "example": 599 + "example": 623 }, { "section": "Autolinks", "html": "

www.google.com/search?q=Markup+(business)

\n

(www.google.com/search?q=Markup+(business))

", "markdown": "www.google.com/search?q=Markup+(business)\n\n(www.google.com/search?q=Markup+(business))", - "example": 600 + "example": 624 }, { "section": "Autolinks", "html": "

www.google.com/search?q=(business))+ok

", "markdown": "www.google.com/search?q=(business))+ok", - "example": 601 + "example": 625 }, { "section": "Autolinks", "html": "

www.google.com/search?q=commonmark&hl=en

\n

www.google.com/search?q=commonmark&hl;

", "markdown": "www.google.com/search?q=commonmark&hl=en\n\nwww.google.com/search?q=commonmark&hl;", - "example": 602 + "example": 626 }, { "section": "Autolinks", "html": "

www.commonmark.org/he<lp

", "markdown": "www.commonmark.org/hehttp://commonmark.org

\n

(Visit https://encrypted.google.com/search?q=Markup+(business))

\n

Anonymous FTP is available at ftp://foo.bar.baz.

", "markdown": "http://commonmark.org\n\n(Visit https://encrypted.google.com/search?q=Markup+(business))\n\nAnonymous FTP is available at ftp://foo.bar.baz.", - "example": 604 + "example": 628 }, { "section": "Autolinks", "html": "

foo@bar.baz

", "markdown": "foo@bar.baz", - "example": 605 + "example": 629 }, { "section": "Autolinks", "html": "

hello@mail+xyz.example isn't valid, but hello+xyz@mail.example is.

", "markdown": "hello@mail+xyz.example isn't valid, but hello+xyz@mail.example is.", - "example": 606 + "example": 630 }, { "section": "Autolinks", "html": "

a.b-c_d@a.b

\n

a.b-c_d@a.b.

\n

a.b-c_d@a.b-

\n

a.b-c_d@a.b_

", "markdown": "a.b-c_d@a.b\n\na.b-c_d@a.b.\n\na.b-c_d@a.b-\n\na.b-c_d@a.b_", - "example": 607 + "example": 631 }, { "section": "Disallowed Raw HTML", "html": "

<title> <style>

\n
\n <xmp> is disallowed. <XMP> is also disallowed.\n
", "markdown": " <style> <em>\n\n<blockquote>\n <xmp> is disallowed. <XMP> is also disallowed.\n</blockquote>", - "example": 629, + "example": 653, "shouldFail": true } ] diff --git a/test/specs/run-spec.js b/test/specs/run-spec.js index 56a3f70a49..3af0aa4565 100644 --- a/test/specs/run-spec.js +++ b/test/specs/run-spec.js @@ -48,5 +48,5 @@ function runSpecs(title, file, options) { }); }; -runSpecs('GFM 0.28', './gfm/gfm.0.28.json', {gfm: true}); +runSpecs('GFM 0.29', './gfm/gfm.0.29.json', {gfm: true}); runSpecs('CommonMark 0.29', './commonmark/commonmark.0.29.json', {headerIds: false});