18
Views
4
Comments
[Markdown Renderer] Markdown update: link open in a new tab (_blank)
markdown-renderer
Reactive icon
Forge asset by Maxime Baracco
Application Type
Reactive

Hello,

First of all this component help us a lot. Thank you for that.

Today, we started to work on a new project and we are redering links in this component. We noticed that when identifies a link it creates an <a> tag, this is fine. But we need to open it in a new tab. So, as a sugestion, could you guys update this behavior? I think it will improve the component.


We fixed this in our side, if you guys are interested let us know.


Thanks a lot.

2024-05-17 04-26-02
Maxime Baracco

Hi Bruno,


As a quick workaround for this kind of problem, you can also insert html instead of Markdown text.

So if you use the text:

... it should open the link in a new tab.


About updating the markdown component for this, I see there are different syntaxes possible for this. What would be your preference? And how did you fix it on your side?

Thank you

2024-03-19 12-46-02
Bruno Gomes

Hello,

We change in the component:

- ConvertAndSetContainerHTML screen action

- JavaScript the "replaceContent()", we identify a link and build it  with "_blank" parameter setted.

Not sure what is the best way to go with that, but that was our change. Please let me know your thoughts.

Thanks.

replaceContent.zip
2024-05-17 04-26-02
Maxime Baracco

Hi Bruno,


Yes, that will work if you want all the links to open in new tabs. I'll check what is the most popular or easiest way to specify this in markdown syntax. Then I'll add this in the conversion, probably using the same solution like you did, but at least it will be something we can activate/deactivate for each link using markdown syntax.

2021-06-21 11-43-23
Carlos César Marques
Staff

Hi everyone,

While post-processing the rendered HTML or manually replacing DOM strings via custom scripts (like doing replaceContent post-render) gets the job done, it can cause performance overhead and layout thrashing in Reactive/Web applications.

There is actually a native, secure, and highly performant way to handle this by hooking directly into the marked.js library's custom Renderer configuration before the HTML is even painted in the DOM.

Additionally, when forcing links to open in a new tab (target="_blank"), it is a critical security best practice to inject rel="noopener noreferrer". This prevents a vulnerability known as Reverse Tabnabbing, where a malicious linked page could gain partial control over your parent application's window.

Here is the native implementation you can use inside your OutSystems JavaScript node.

1. Add a Block Configuration (Optional but Recommended)

Create an input parameter on your Markdown block:

  • Name: OpenLinksInNewTab (Boolean)

  • Default: True

  • Description: If true, links open in a new tab safely.

2. The JavaScript Node Implementation

Pass your ContainerId (Text), MarkdownText (Text), and OpenLinksInNewTab (Boolean) into your JS node, and replace the rendering logic with this:


======================================================================================================================================================================

// 1. Locate the target HTML container

const target = document.getElementById($parameters.ContainerId);


if (target) {

    // 2. Clean input and handle empty state immediately

    const cleanText = ($parameters.MarkdownText || '').trim();


    if (!cleanText) {

        target.innerHTML = '';

        return;

    }


    // 3. Ensure the MarkedJS library is loaded in the global scope

    if (typeof marked !== 'undefined' && typeof marked.parse === 'function') {

        

        // Define native parser options

        const parseOptions = {

            breaks: true // Natively converts single \n to <br> without string hacks

        };


        // 🎯 THE NATIVE HOOK: Intercept link token generation during parsing

        if ($parameters.OpenLinksInNewTab) {

            const customRenderer = new marked.Renderer();

            const originalLink = customRenderer.link.bind(customRenderer);

            

            customRenderer.link = function(token) {

                const html = originalLink(token);

                // Inject target="_blank" and the critical security rel attributes

                if (html.startsWith('

                    return html.replace('

                }

                return html;

            };


            parseOptions.renderer = customRenderer;

        }

        

        // 4. Render and set clean HTML safely in a single pass

        target.innerHTML = marked.parse(cleanText, parseOptions);

        

    } else {

        // Fallback: show plain text if library is missing

        target.textContent = cleanText;

        console.warn('MarkedJS library is not loaded or ready.');

    }

}


====================================================================================================================================================================== 


Why this approach is superior:

  1. Zero DOM Layout Thrashing: It doesn't run regex scans on your DOM after painting. It constructs the correct HTML structure directly during the initial parsing phase.

  2. Hardened Security: Built-in protection against Reverse Tabnabbing using rel="noopener noreferrer".

  3. No Unstructured Hack Files: Avoids the need for custom zip file helpers or complex DOM-traversal scripts.

Hope this helps anyone looking to scale their Markdown implementations in OutSystems!

______________________________________________________________________________________________________________

Disclaimer note: this message was built by AI, but tested by me (a human xD).




Community GuidelinesBe kind and respectful, give credit to the original source of content, and search for duplicates before posting.