UNPKG

2.13 kBJSXView Raw
1const React = require('react');
2const PropTypes = require('prop-types');
3
4const BaseUrlContext = require('../contexts/BaseUrl');
5
6// Nabbed from here:
7// https://github.com/readmeio/api-explorer/blob/0dedafcf71102feedaa4145040d3f57d79d95752/packages/api-explorer/src/lib/markdown/renderer.js#L52
8function getHref(href, baseUrl) {
9 const base = baseUrl === '/' ? '' : baseUrl;
10 const doc = href.match(/^doc:([-_a-zA-Z0-9#]*)$/);
11 if (doc) {
12 return `${base}/docs/${doc[1]}`;
13 }
14
15 const ref = href.match(/^ref:([-_a-zA-Z0-9#]*)$/);
16 if (ref) {
17 return `${base}/reference-link/${ref[1]}`;
18 }
19
20 // we need to perform two matches for changelogs in case
21 // of legacy links that use 'blog' instead of 'changelog'
22 const blog = href.match(/^blog:([-_a-zA-Z0-9#]*)$/);
23 const changelog = href.match(/^changelog:([-_a-zA-Z0-9#]*)$/);
24 const changelogMatch = blog || changelog;
25 if (changelogMatch) {
26 return `${base}/changelog/${changelogMatch[1]}`;
27 }
28
29 const custompage = href.match(/^page:([-_a-zA-Z0-9#]*)$/);
30 if (custompage) {
31 return `${base}/page/${custompage[1]}`;
32 }
33
34 return href;
35}
36
37function docLink(href) {
38 const doc = href.match(/^doc:([-_a-zA-Z0-9#]*)$/);
39 if (!doc) return false;
40
41 return {
42 className: 'doc-link',
43 'data-sidebar': doc[1],
44 };
45}
46
47function Anchor(props) {
48 const { href, target, baseUrl, children } = props;
49 return (
50 // eslint-disable-next-line react/jsx-props-no-spreading
51 <a href={getHref(href, baseUrl)} target={target} {...docLink(href)}>
52 {children}
53 </a>
54 );
55}
56
57Anchor.propTypes = {
58 baseUrl: PropTypes.string,
59 children: PropTypes.node.isRequired,
60 href: PropTypes.string,
61 target: PropTypes.string,
62};
63
64Anchor.defaultProps = {
65 baseUrl: '/',
66 href: '',
67 target: '_self',
68};
69
70module.exports = sanitizeSchema => {
71 // This is for our custom link formats
72 sanitizeSchema.protocols.href.push('doc', 'target', 'ref', 'blog', 'changelog', 'page');
73
74 // eslint-disable-next-line react/display-name
75 return props => (
76 <BaseUrlContext.Consumer>{baseUrl => <Anchor baseUrl={baseUrl} {...props} />}</BaseUrlContext.Consumer>
77 );
78};