Repository: zestedesavoir/zmarkdown
Pull request #251 (2018-07-22 21:09:10)

remark-images-download: handle invalid URLs
There are some special malformed URLs like `http://%99:%99@example.com` that `url.parse` can’t decode.


Patch:
diff --git a/packages/remark-images-download/dist/index.js b/packages/remark-images-download/dist/index.js
index 8dc258b9..86783f4d 100644
--- a/packages/remark-images-download/dist/index.js
+++ b/packages/remark-images-download/dist/index.js
@@ -96,7 +96,13 @@ function plugin() {
         var url = node.url,
             position = node.position;
 
-        var parsedURI = URL.parse(url);
+        var parsedURI = void 0;
+        try {
+          parsedURI = URL.parse(url);
+        } catch (error) {
+          vfile.message('Invalid URL: ' + url, position, url);
+          return;
+        }
 
         var extension = path.extname(parsedURI.pathname);
         var filename = '' + shortid.generate() + extension;
diff --git a/packages/remark-images-download/src/index.js b/packages/remark-images-download/src/index.js
index ca568c4e..5d47bd57 100644
--- a/packages/remark-images-download/src/index.js
+++ b/packages/remark-images-download/src/index.js
@@ -78,7 +78,13 @@ function plugin ({
 
         visit(tree, 'image', (node) => {
           const {url, position} = node
-          const parsedURI = URL.parse(url)
+          let parsedURI
+          try {
+            parsedURI = URL.parse(url)
+          } catch (error) {
+            vfile.message(`Invalid URL: ${url}`, position, url)
+            return
+          }
 
           const extension = path.extname(parsedURI.pathname)
           const filename = `${shortid.generate()}${extension}`
diff --git a/packages/zmarkdown/config/remark.js b/packages/zmarkdown/config/remark.js
index 1221089e..1c2302aa 100644
--- a/packages/zmarkdown/config/remark.js
+++ b/packages/zmarkdown/config/remark.js
@@ -313,6 +313,7 @@ const remarkConfig = {
   ping: {
     pingUsername: (_username) => true,
     userURL: (username) => `/membres/voir/${username}/`,
+    usernameRegex: /\B@(?:\*\*([^*]+)\*\*|(\w+))/,
   },
 
   disableTokenizers: {},


Test patch:
diff --git a/packages/remark-images-download/__tests__/index.js b/packages/remark-images-download/__tests__/index.js
index 9b3eaf81..a8bcd4c7 100644
--- a/packages/remark-images-download/__tests__/index.js
+++ b/packages/remark-images-download/__tests__/index.js
@@ -42,6 +42,16 @@ const r = (html) => html.replace(
   'foo/bar')
 
 describe('mock server tests', () => {
+  test('rejects invalid URLs', () => {
+    const file = '![foo](http://%99:%99@example.com)'
+
+    const render = renderFactory()
+
+    return render(file).then(vfile => {
+      expect(firstMsg(vfile)).toBe('Invalid URL: http://%99:%99@example.com')
+    })
+  })
+
   test('downloads image ok', () => {
     const file = dedent`
       ![](http://localhost:27273/test.svg)
diff --git a/packages/zmarkdown/__tests__/new-html-suite.test.js b/packages/zmarkdown/__tests__/new-html-suite.test.js
index 027d5368..1205bc72 100644
--- a/packages/zmarkdown/__tests__/new-html-suite.test.js
+++ b/packages/zmarkdown/__tests__/new-html-suite.test.js
@@ -204,3 +204,19 @@ describe('images become figures:', () => {
     expect(result).toMatchSnapshot()
   })
 })
+
+describe('ping', () => {
+  beforeEach(() => {
+    remarkConfig.ping.pingUsername = () => true
+  })
+
+  it(`does not ping parts of email addresses`, () => {
+    const input = 'My email address is test@test.com.'
+
+    return expect(renderString(input)).resolves.not.toContain('ping')
+  })
+
+  afterEach(() => {
+    remarkConfig.ping.pingUsername = () => false
+  })
+})