diff --git a/src/config.ts b/src/config.ts index eb2b17a..3fb938c 100644 --- a/src/config.ts +++ b/src/config.ts @@ -291,11 +291,31 @@ export const defaultTranslators: TranslatorConfigObject = { const src = node.getAttribute('src') || ''; if (!src || (!options.keepDataImages && /^data:/i.test(src))) return { ignore: true }; + let encodedSrc = ''; + for (const chr of src) { + switch (chr) { + case '(': + encodedSrc += '%28'; + break; + case ')': + encodedSrc += '%29'; + break; + case '_': + encodedSrc += '%5F'; + break; + case '*': + encodedSrc += '%2A'; + break; + default: + encodedSrc += chr; + } + } + const alt = node.getAttribute('alt') || ''; const title = node.getAttribute('title') || ''; return { - content: `![${alt}](${src}${title && ` "${title}"`})`, + content: `![${alt}](${encodedSrc}${title && ` "${title}"`})`, recurse: false } }, diff --git a/test/options.test.ts b/test/options.test.ts index 7174a4c..3c1ae54 100644 --- a/test/options.test.ts +++ b/test/options.test.ts @@ -277,12 +277,12 @@ text`); instance.options.keepDataImages = true; const resKeep = translate(`normal `); - expect(resKeep).toBe(`![normal](normal_img.jpg) ![](data:image/gif;base64,R0lGODlhEA)`); + expect(resKeep).toBe(`![normal](normal%5Fimg.jpg) ![](data:image/gif;base64,R0lGODlhEA)`); instance.options.keepDataImages = false; const resNoKeep = translate(`normal `); - expect(resNoKeep).toBe(`![normal](normal_img.jpg)`); + expect(resNoKeep).toBe(`![normal](normal%5Fimg.jpg)`); instance.options.keepDataImages = originalKeepDataImages; }); diff --git a/test/special-cases.test.ts b/test/special-cases.test.ts index bf52f3b..642226e 100644 --- a/test/special-cases.test.ts +++ b/test/special-cases.test.ts @@ -164,4 +164,16 @@ describe(`Special Cases`, () => { expect(res).toBe('Paragraph 1\n\n \nParagraph 2'); }); }); + + describe(`handles parenthesis within an URL correctly`, () => { + test(`handles parenthesis within an anchor href`, () => { + const res = translate(`My cool article`); + expect(res).toBe("[My cool article](http://example.com/my-cool-article%282%29.png)"); + }); + + test(`handles parenthesis within an img src`, () => { + const res = translate(``); + expect(res).toBe("![](http://example.com/some-selfie%282%29.png)"); + }); + }); });