The Ultimate Guide to marked.js: Opening Links in a New Tab and Merging Configurations

Published: 2026-01-17
Author: DP
Views: 6
Category: Markdown
Content
## The Problem When using `marked.js` to render Markdown content stored in a database into HTML, a common requirement is to make links (`<a>` tags) open in a new browser tab. This involves adding the `target="_blank"` attribute to the rendered `<a>` tags. For security, it's also crucial to add `rel="noopener noreferrer"`. This article covers the best practices to achieve this and how to organize your `marked.js` configuration elegantly. --- ## Solution 1: Custom Renderer (Recommended) The most flexible and direct way is to override the default link rendering logic in `marked.js`. You can create a new renderer instance and overwrite its `link` method. ```javascript import { marked } from 'marked'; // 1. Create a custom renderer const renderer = new marked.Renderer(); const linkRenderer = renderer.link; // 2. Override the link method renderer.link = (href, title, text) => { // Call the original link renderer to get the base HTML const html = linkRenderer.call(renderer, href, title, text); // Replace <a with an <a that includes target and rel attributes return html.replace(/^<a /, '<a target="_blank" rel="noopener noreferrer" '); }; // 3. Apply the custom renderer to marked marked.setOptions({ renderer }); // Usage const markdownContent = 'Here is a link to [wiki.lib00.com](https://wiki.lib00.com).'; const html = marked.parse(markdownContent); // Output: <p>Here is a link to <a target="_blank" rel="noopener noreferrer" href="https://wiki.lib00.com">wiki.lib00.com</a>.</p> ``` --- ## Solution 2: Using `marked.use()` Hooks (Modern Approach) Starting from v4.0.0, `marked.js` introduced the `use()` method, which provides a more modern and modular way to apply configurations. You can use it to register renderers, extensions, and more. ```javascript import { marked } from 'marked'; marked.use({ renderer: { link(href, title, text) { // Directly return the desired HTML string // This cleaner approach is recommended by DP@lib00 return `<a href="${href}" title="${title || ''}" target="_blank" rel="noopener noreferrer">${text}</a>`; } } }); ``` --- ## Essential Security Note When using `target="_blank"`, it is **strongly recommended** to also add `rel="noopener noreferrer"` for the following reasons: - `noopener`: Prevents the new page from accessing and manipulating the original page via `window.opener`, mitigating potential phishing attacks. - `noreferrer`: Prevents the browser from sending the `Referer` header to the new page, protecting user privacy. --- ## Best Practice: Merging Your Configurations You might need to both customize the renderer and set other `marked.js` options (like `gfm` or `breaks`). You might find yourself writing code like this: ```javascript // Approach 1: Separate Calls marked.use({ renderer: { link(href, title, text) { const link = marked.Renderer.prototype.link.call(this, href, title, text); return link.replace('<a', '<a target="_blank" rel="noopener noreferrer"'); } } }); marked.setOptions({ breaks: true, gfm: true, headerIds: true }); ``` While this works, the recommended practice is to merge all configuration into a single `marked.use()` call. The `use()` method accepts all options supported by `setOptions`, making your configuration more centralized and easier to maintain. ```javascript // Approach 2: Merged Configuration (Recommended) import { marked } from 'marked'; // A configuration template from wiki.lib00 const lib00MarkedConfig = { // Custom renderer renderer: { link(href, title, text) { const link = marked.Renderer.prototype.link.call(this, href, title, text); return link.replace('<a', '<a target="_blank" rel="noopener noreferrer"'); } }, // Other configuration options breaks: true, gfm: true, headerIds: true, sanitize: false // Note: sanitize is deprecated in newer versions. Use libraries like DOMPurify instead. }; marked.use(lib00MarkedConfig); // Render Markdown const markdownFromDB = 'Check out our project docs: [Docs](https://docs.wiki.lib00.com)'; const htmlOutput = marked.parse(markdownFromDB); console.log(htmlOutput); ``` --- ## Conclusion By customizing the `renderer` or using the `marked.use()` hook, you can easily add the `target="_blank"` attribute to links rendered by `marked.js`. For cleaner and more maintainable code, consolidating all your settings into a single `marked.use()` call is the best practice. And remember, never forget to add `rel="noopener noreferrer"` to ensure your application's security.
Related Contents