diff --git a/utils/markdown/index.test.js b/utils/markdown/index.test.js index 6adca2e68e64..a309968b077a 100644 --- a/utils/markdown/index.test.js +++ b/utils/markdown/index.test.js @@ -144,6 +144,12 @@ this is long text this is long text this is long text this is long text this is expect(output).toContain('internal_link'); }); + test(' should contain target=_blank for internal links that live under /plugins', () => { + const output = format('[internal_link](http://localhost/plugins/example)', {siteURL: 'http://localhost'}); + + expect(output).toContain('internal_link'); + }); + test(' should not contain target=_blank for pl|channels|messages links', () => { const pl = format('[thread](/reiciendis-0/pl/b3hrs3brjjn7fk4kge3xmeuffc))', {siteURL: 'http://localhost'}); expect(pl).toContain('thread'); @@ -153,5 +159,8 @@ this is long text this is long text this is long text this is long text this is const messages = format('[thread](/reiciendis-0/messages/b3hrs3brjjn7fk4kge3xmeuffc))', {siteURL: 'http://localhost'}); expect(messages).toContain('thread'); + + const plugin = format('[plugin](/reiciendis-0/plugins/example))', {siteURL: 'http://localhost'}); + expect(plugin).toContain('plugin'); }); }); diff --git a/utils/markdown/renderer.tsx b/utils/markdown/renderer.tsx index ee982115380f..dce48c27741c 100644 --- a/utils/markdown/renderer.tsx +++ b/utils/markdown/renderer.tsx @@ -207,14 +207,17 @@ export default class Renderer extends marked.Renderer { output += `" href="${outHref}" rel="noreferrer"`; - // Any link that begins with siteURL should be opened inside the app - let internalLink = outHref.startsWith(this.formattingOptions.siteURL || ''); + const pluginURL = `${this.formattingOptions.siteURL}/plugins`; + + // Any link that begins with siteURL should be opened inside the app, except when rooted + // at /plugins, which is logically "outside the app" despite being hosted by a plugin. + let internalLink = outHref.startsWith(this.formattingOptions.siteURL || '') && (!outHref.startsWith(pluginURL)); // special case for team invite links, channel links, and permalinks that are inside the app const pattern = new RegExp( '^(' + TextFormatting.escapeRegex(this.formattingOptions.siteURL) + - ')?\\/(?:signup_user_complete|admin_console|[^\\/]+\\/(?:pl|channels|messages))\\/', + ')?\\/(?:signup_user_complete|admin_console|[^\\/]+\\/(?:pl|channels|messages|plugins))\\/', ); internalLink = internalLink || pattern.test(outHref);