lbry-desktop/ui/component/common/markdown-preview-internal.jsx

122 lines
2.9 KiB
React
Raw Normal View History

2019-04-03 07:56:58 +02:00
// @flow
import * as React from 'react';
import remark from 'remark';
2019-06-10 22:16:01 +02:00
import remarkAttr from 'remark-attr';
2019-06-09 08:57:51 +02:00
import remarkStrip from 'strip-markdown';
2019-04-03 07:56:58 +02:00
import remarkEmoji from 'remark-emoji';
2019-05-30 22:51:23 +02:00
import reactRenderer from 'remark-react';
2019-04-03 07:56:58 +02:00
import ExternalLink from 'component/externalLink';
import defaultSchema from 'hast-util-sanitize/lib/github.json';
2019-06-10 08:20:40 +02:00
import { formatedLinks, inlineLinks } from 'util/remark-lbry';
import { Link } from 'react-router-dom';
import { formatLbryUrlForWeb } from 'util/url';
2019-04-03 07:56:58 +02:00
2019-06-09 08:57:51 +02:00
type SimpleTextProps = {
children?: React.Node,
2019-04-03 07:56:58 +02:00
};
type SimpleLinkProps = {
href?: string,
title?: string,
children?: React.Node,
};
2019-06-09 08:57:51 +02:00
type MarkdownProps = {
strip?: boolean,
content: ?string,
promptLinks?: boolean,
};
const SimpleText = (props: SimpleTextProps) => {
return <span>{props.children}</span>;
};
2019-04-03 07:56:58 +02:00
const SimpleLink = (props: SimpleLinkProps) => {
const { title, children } = props;
let { href } = props;
2020-02-03 23:29:22 +01:00
if (IS_WEB && href && href.startsWith('lbry://')) {
href = formatLbryUrlForWeb(href);
2020-01-04 04:36:27 +01:00
// using Link after formatLbryUrl to handle "/" vs "#/"
// for web and desktop scenarios respectively
return (
<Link
title={title}
to={href}
onClick={e => {
e.stopPropagation();
}}
>
{children}
</Link>
);
}
2019-04-03 07:56:58 +02:00
return (
<a href={href} title={title}>
{children}
</a>
);
};
// Use github sanitation schema
const schema = { ...defaultSchema };
// Extend sanitation schema to support lbry protocol
2019-05-30 22:51:23 +02:00
schema.protocols.href.push('lbry');
2019-06-13 09:18:30 +02:00
schema.attributes.a.push('embed');
2019-04-03 07:56:58 +02:00
const MarkdownPreview = (props: MarkdownProps) => {
2019-06-09 08:57:51 +02:00
const { content, strip, promptLinks } = props;
const remarkOptions: Object = {
2019-04-03 07:56:58 +02:00
sanitize: schema,
2019-06-09 08:57:51 +02:00
fragment: React.Fragment,
2019-04-03 07:56:58 +02:00
remarkReactComponents: {
a: promptLinks ? ExternalLink : SimpleLink,
2019-06-09 08:57:51 +02:00
// Workaraund of remarkOptions.Fragment
div: React.Fragment,
2019-04-03 07:56:58 +02:00
},
};
2019-06-09 08:57:51 +02:00
2019-06-10 22:16:01 +02:00
const remarkAttrOpts = {
scope: 'extended',
elements: ['link'],
2019-06-13 09:18:30 +02:00
extend: { link: ['embed'] },
defaultValue: true,
2019-06-10 22:16:01 +02:00
};
2019-06-09 08:57:51 +02:00
// Strip all content and just render text
if (strip) {
// Remove new lines and extra space
remarkOptions.remarkReactComponents.p = SimpleText;
return (
<span className="markdown-preview">
{
remark()
.use(remarkStrip)
.use(reactRenderer, remarkOptions)
.processSync(content).contents
}
</span>
);
}
2019-04-03 07:56:58 +02:00
return (
<div className="markdown-preview">
{
remark()
2019-06-10 22:16:01 +02:00
.use(remarkAttr, remarkAttrOpts)
2019-06-10 08:20:40 +02:00
// Remark plugins for lbry urls
// Note: The order is important
.use(formatedLinks)
.use(inlineLinks)
// Emojis
2019-04-03 07:56:58 +02:00
.use(remarkEmoji)
.use(reactRenderer, remarkOptions)
.processSync(content).contents
}
</div>
);
};
export default MarkdownPreview;