Automatically use gatsby-link for internal links in markdown
2019-02-16Gatsby
In Gatsby: Semantic UI in Markdown posts we set up Semantic UI components in Markdown. Another use of custom components in Markdown is to give “smart” links, so we can use gatsby-link for internal (relative) links to work nicely with the Gatsby router, or an appropriate <a>
for external links.
First we need to distinguish relative and absolute URLs - there are libraries to do this, but they tend to do a lot more than we need, so we’ll start with some regex:
/**
* Case-insensitive regex to identify absolute URLs
* Matches start of line, then either:
* a) a letter, then zero or more letters or
* numbers, then a colon (a protocol)
* b) a double forward slash (start of a
* protocol-relative path)
*/
const absoluteRegex = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;
Next we define a component to render as either an <a>
set up to open safely in a new tab, or a Link
:
const RelativeOrAbsoluteLink = ({href, children}) => {
if (absoluteRegex.test(href)) {
return <a href={href} target='_blank' rel='noopener noreferrer'>{children}</a>
} else {
return <Link to={href}>{children}</Link>
}
}
Note that for different applications and site layouts you might need to tweak the logic above - for example when working with Gatsby: Images in Markdown you will need to add some exceptions for static and image links.
Finally we need to add this as a custom component for rehype, standing in for <a>
. You can see here the semantic components from before, and some other useful mappings:
const renderAst = new rehypeReact({
createElement: React.createElement,
components: {
'ul': SemanticUL,
'ol': SemanticOL,
'li': SemanticLI,
'hr': Divider,
'icon': Icon,
'label': Label,
'a': RelativeOrAbsoluteLink // Our new smart link
},
}).Compiler
2020-04-19
2020-04-18
2019-04-21
2019-03-24
2019-02-26
2019-02-20
2019-02-16
2019-02-15
2019-02-02