Comments (24)
For anyone wondering, in version 4.0.6 the Link
should be lowercase:
<ReactMarkdown
source={source}
renderers={{link: props => <a href={props.href} target="_blank">{props.children}</a>}}
/>
from react-markdown.
I've implemented custom renderers in commonmark-react-renderer
(which powers this component). I'll see if I can get a new release of react-markdown
out quite soon. When that is out it should be as as easy as:
<ReactMarkdown
source="Click [here](https://espen.codes/) to visit external site"
renderers={{Link: props => <a href={props.href} target="_blank">{props.children</a>}}
/>
from react-markdown.
Dont forget to add rel="noopener noreferrer"
(See https://medium.com/@jitbit/target-blank-the-most-underestimated-vulnerability-ever-96e328301f4c)
from react-markdown.
I'm currently using it like so:
<ReactMarkdown
renderers={{ Link: (props: Object) => {
if (props.href.match('http')) {
return <a href={props.href} target="_blank" rel="nofollow noreferrer noopener">{props.children}</a>
}
return <a href={props.href}>{props.children}</a>
} }}
maybe this should be built in?
or passable as a prop?
so we could do something like ...
<ReactMarkdown externalLinksInNewTab />
from react-markdown.
This has now been changed, renderers
attribute is no longer being used. linkTarget
is the attribute, with values like _blank
. More about the APIs can be found in the API Docs https://github.com/remarkjs/react-markdown#api
.
from react-markdown.
Here is how you can add rel="noopener noreferrer"
for target="_blank"
:
<ReactMarkdown
linkTarget={'_blank'}
components={{
a: ({ node, children, ...props}) => {
const linkProps = props;
if (props.target === '_blank') {
linkProps['rel'] = 'noopener noreferrer';
}
return <a {...linkProps}>{children}</a>
}
}}
>
{`[Link with rel="noopener noreferrer"](https://somedomain.com])`}
</ReactMarkdown>
from react-markdown.
shouldn't it be
<ReactMarkdown source="Click [here](https://espen.codes/) to visit external site" renderers={{Link: props => <a href={props.href} target="_blank">{props.children}</a>}}/>
from react-markdown.
having a [legitimate link](http://www.example.com//){name:value}
look easy enough where the {...} is a json with properties added to the link tag. and ignore it if there is a space between ] and { . or maybe go with the {:target="_blank"}
i'd prefer the json solution.
from react-markdown.
In case what I found helps others:
I needed something similar within an Electron app and went with this solution before I found this issue:
var shell = require('electron').shell;
//open links externally by default
$(document).on('click', 'a[href^="http"]', function(event) {
event.preventDefault();
shell.openExternal(this.href);
});
...though this makes all links on the page get opened by the user's default browser, not just links rendered by react-markdown
, which might not quite be what you're looking for.
from react-markdown.
Appreciate all the code snippets everyone's shared above. I wanted to share an improved version that I'm now using, that are more robust than checking whether the URL contains http
(which fails for links like /path/containing/http
and about:blank
):
If you want to check whether the link points to the same domain, regardless of whether it's an absolute URL or not:
<ReactMarkdown
components={{
a({ node, children, ...props }) {
let url = new URL(props.href ?? "", location.href);
if (url.origin !== location.origin) {
props.target = "_blank";
props.rel = "noopener noreferrer";
}
return <a {...props}>{children}</a>;
},
}}
>
{`[External Link](https://example.com)\n\n[Internal Link](#anchor)`}
</ReactMarkdown>
If you just want to check whether the link is an absolute URL:
<ReactMarkdown
components={{
a({ node, children, ...props }) {
try {
new URL(props.href ?? "");
// If we don't get an error, then it's an absolute URL.
props.target = "_blank";
props.rel = "noopener noreferrer";
} catch (e) {}
return <a {...props}>{children}</a>;
},
}}
>
{`[External Link](https://example.com)\n\n[Internal Link](#anchor)`}
</ReactMarkdown>
from react-markdown.
A bit unsure. It's easy enough to add, but I don't know if the API makes sense. I think there are two options:
- Allowing users to pass their own handlers for types, eg
Link: MyCustomLinkComponent
. This would be very flexible and is something I've been wanting to add anyway. - Adding a
linkTarget
prop that can either be a string or a function. The functions could determine the target based on the node, for instance whether it is a relative URL or not.
I'm leaning towards the first, as that will allow all sorts of flexibility to be added without bloating the renderer with options.
from react-markdown.
This method is not a good one because the anchor link will also open in a new tab.
I think the best practice is to identify internal and external links.
<ReactMarkdown
components={{
a: ({ node, children, ...props }) => {
if (props.href?.includes('http')) {
props.target = '_blank'
props.rel = 'noopener noreferrer'
}
return <a {...props}>{children}</a>
},
}}
>
{`[External Link](https://example.com)\n\n[Internal Link](#anchor)`}
</ReactMarkdown>
Rendered as:
<p>
<a href="https://example.com" target="_blank" rel="noopener noreferrer">External Link</a>
</p>
<p>
<a href="#anchor">Internal Link</a>
</p>
from react-markdown.
I agree. The first option you listed sounds the best way to go and would open up the API to be much more flexible.
Do you have any inkling as to when such a feature could be ready?
from react-markdown.
I don't think it should be too much work, so it's more a question of when I'll have the time to prioritize it. I'm hoping it'll be this week, at least.
from react-markdown.
That would be perfect. I really like this package as I don't have to use the dangerouslySetInnerHTML
property!
Keep up the good work on this package 👍
from react-markdown.
Wouldn't the most optimal case be that any valid attribute would be valid and applied? When rendering the container, you could just spread the props with ...this.props
(and handling special cases such as source
like you do now).
Then you could just do <ReactMarkdown containerTagName="a" target="_blank" href="https://foo.com" source={"Link **here** to visit foo.com"}>
from react-markdown.
Version 4 is now out, and the above example should work for this use case.
from react-markdown.
I wonder how to do a paragraph like this? I end up Each child in an array or iterator should have a unique "key" prop. Check the render method of 'Paragraph'
This seems to occur when using the softBreak: 'br'
option.
Update - can be fixed by overriding the softBreak renderer with const SoftBreak = () => (<br/>)
from react-markdown.
Whats the reason you have if (props.href.match('http')) {
check?
What else can it be?
from react-markdown.
Never mind. Just realised that there are a plethora of protocols. That said, I would not recommend blindly constructing a link. A safer option would be:
const renderLink = (props: Object) => {
if (!props.href.startsWith('http')) {
return props.children;
}
return <a href={props.href} rel='nofollow noreferrer noopener' target='_blank'>{props.children}</a>;
};
from react-markdown.
@gajus
that will not work, because [my internal link](/some-internal-path/)
will just render my internal link
as text
from react-markdown.
Sorry, this should have been props.href
, i.e.
const renderLink = (props: Object) => {
if (!props.href.startsWith('http')) {
return props.href;
}
return <a href={props.href} rel='nofollow noreferrer noopener' target='_blank'>{props.children}</a>;
};
And yes, that would just render plain text link.
from react-markdown.
@gajus
yes but we want to render an internal link
from react-markdown.
oh, I see. Forgot about that possibility.
from react-markdown.
Related Issues (20)
- Code highliting with react-syntax-highlighter bug HOT 7
- Unnecessarily narrow range for React peer deps HOT 7
- Support for inapp links HOT 5
- text not created as hyperlink HOT 6
- Possible inconsistency with handling emphasis and strong when immediately followed by emphasis HOT 3
- p component overriding img component HOT 4
- A 11k star makrdown widget can not have a copy button at code block?
- How render image in cneter? HOT 3
- rermarkgfm showing tasklist wrong HOT 21
- \n Doesn't work properly HOT 8
- Tables do not display correctly when they have spaces at the beginning (remark-gfm) HOT 2
- Code is wrapped in an exrea <pre> even with a custom component HOT 9
- Custom Components Always Re-rendered HOT 4
- Not compatible to Chrome 90 or older HOT 9
- How to append content ,not cover? HOT 2
- When using two **enclosed bold texts containing colons, react-markdown fails to correctly parse the bold syntax. HOT 3
- Please add syntax for `{.tabset} ` HOT 2
- Typescript error while using syntax hightlight part code from README.md HOT 4
- sup element rendering with remark-gfm plugin is painfully slow. HOT 7
- React 18.3.0/19.0.0 support for react-markdown ^6.0.0 HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from react-markdown.