@readme/markdown 6.75.0-beta.4 → 6.75.0-beta.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/Anchor.jsx +14 -25
- package/components/Callout/index.tsx +41 -0
- package/components/Code/index.tsx +75 -0
- package/components/CodeTabs/{index.jsx → index.tsx} +8 -19
- package/components/Embed/index.tsx +68 -0
- package/components/Glossary/index.tsx +37 -0
- package/components/Glossary/style.scss +69 -0
- package/components/HTMLBlock/index.tsx +36 -0
- package/components/Image/index.tsx +110 -0
- package/components/Table/index.tsx +19 -0
- package/components/TableOfContents/index.jsx +4 -4
- package/components/{index.js → index.ts} +1 -1
- package/dist/components/Callout/index.d.ts +9 -0
- package/dist/components/Code/index.d.ts +11 -0
- package/dist/components/CodeTabs/index.d.ts +3 -0
- package/dist/components/Embed/index.d.ts +13 -0
- package/dist/components/Glossary/index.d.ts +10 -0
- package/dist/components/HTMLBlock/index.d.ts +7 -0
- package/dist/components/Image/index.d.ts +15 -0
- package/dist/components/Table/index.d.ts +6 -0
- package/dist/components/index.d.ts +12 -0
- package/dist/contexts/GlossaryTerms.d.ts +7 -0
- package/dist/contexts/index.d.ts +5 -0
- package/dist/enums.d.ts +12 -0
- package/dist/errors/mdx-syntax-error.d.ts +5 -0
- package/dist/example/App.d.ts +4 -0
- package/dist/example/Doc.d.ts +3 -0
- package/dist/example/Form.d.ts +3 -0
- package/dist/example/Header.d.ts +3 -0
- package/dist/example/RenderError.d.ts +23 -0
- package/dist/example/Root.d.ts +3 -0
- package/dist/example/docs.d.ts +2 -0
- package/dist/example/index.d.ts +1 -0
- package/dist/index.d.ts +35 -0
- package/dist/lib/owlmoji.d.ts +4 -0
- package/dist/main.js +78869 -2
- package/dist/main.node.js +81008 -2
- package/dist/processor/compile/callout.d.ts +3 -0
- package/dist/processor/compile/code-tabs.d.ts +3 -0
- package/dist/processor/compile/compatibility.d.ts +18 -0
- package/dist/processor/compile/embed.d.ts +3 -0
- package/dist/processor/compile/gemoji.d.ts +3 -0
- package/dist/processor/compile/html-block.d.ts +3 -0
- package/dist/processor/compile/image.d.ts +3 -0
- package/dist/processor/compile/index.d.ts +2 -0
- package/dist/processor/compile/table.d.ts +0 -0
- package/dist/processor/transform/callouts.d.ts +2 -0
- package/dist/processor/transform/code-tabs.d.ts +2 -0
- package/dist/processor/transform/embeds.d.ts +2 -0
- package/dist/processor/transform/gemoji+.d.ts +3 -0
- package/dist/processor/transform/index.d.ts +4 -0
- package/dist/processor/transform/readme-components.d.ts +6 -0
- package/package.json +41 -22
- package/styles/components.scss +1 -1
- package/components/Callout/index.jsx +0 -42
- package/components/Code/index.jsx +0 -101
- package/components/Embed/index.jsx +0 -89
- package/components/GlossaryItem/index.jsx +0 -44
- package/components/GlossaryItem/style.scss +0 -60
- package/components/HTMLBlock/index.jsx +0 -69
- package/components/Image/index.jsx +0 -111
- package/components/Table/index.jsx +0 -19
- package/dist/main.css +0 -399
- package/dist/main.js.LICENSE.txt +0 -17
- package/dist/main.node.js.LICENSE.txt +0 -50
package/components/Anchor.jsx
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { string, node } from 'prop-types';
|
|
2
|
+
import React from 'react';
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
import BaseUrlContext from '../contexts/BaseUrl';
|
|
5
5
|
|
|
6
6
|
// Nabbed from here:
|
|
7
7
|
// https://github.com/readmeio/api-explorer/blob/0dedafcf71102feedaa4145040d3f57d79d95752/packages/api-explorer/src/lib/markdown/renderer.js#L52
|
|
8
|
-
function getHref(href, baseUrl) {
|
|
8
|
+
export function getHref(href, baseUrl) {
|
|
9
9
|
const [path, hash] = href.split('#');
|
|
10
10
|
const hashStr = hash ? `#${hash}` : '';
|
|
11
11
|
|
|
@@ -49,7 +49,9 @@ function docLink(href) {
|
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
function Anchor(props) {
|
|
52
|
-
const {
|
|
52
|
+
const { children, href, target, title, ...attrs } = props;
|
|
53
|
+
const baseUrl = useContext(BaseUrlContext);
|
|
54
|
+
|
|
53
55
|
return (
|
|
54
56
|
// eslint-disable-next-line react/jsx-props-no-spreading
|
|
55
57
|
<a {...attrs} href={getHref(href, baseUrl)} target={target} title={title} {...docLink(href)}>
|
|
@@ -59,12 +61,12 @@ function Anchor(props) {
|
|
|
59
61
|
}
|
|
60
62
|
|
|
61
63
|
Anchor.propTypes = {
|
|
62
|
-
baseUrl:
|
|
63
|
-
children:
|
|
64
|
-
download:
|
|
65
|
-
href:
|
|
66
|
-
target:
|
|
67
|
-
title:
|
|
64
|
+
baseUrl: string,
|
|
65
|
+
children: node.isRequired,
|
|
66
|
+
download: string,
|
|
67
|
+
href: string,
|
|
68
|
+
target: string,
|
|
69
|
+
title: string,
|
|
68
70
|
};
|
|
69
71
|
|
|
70
72
|
Anchor.defaultProps = {
|
|
@@ -74,17 +76,4 @@ Anchor.defaultProps = {
|
|
|
74
76
|
title: '',
|
|
75
77
|
};
|
|
76
78
|
|
|
77
|
-
|
|
78
|
-
<BaseUrlContext.Consumer>{baseUrl => <Anchor baseUrl={baseUrl} {...props} />}</BaseUrlContext.Consumer>
|
|
79
|
-
);
|
|
80
|
-
|
|
81
|
-
AnchorWithContext.sanitize = sanitizeSchema => {
|
|
82
|
-
// This is for our custom link formats
|
|
83
|
-
sanitizeSchema.protocols.href.push('doc', 'target', 'ref', 'blog', 'changelog', 'page');
|
|
84
|
-
|
|
85
|
-
return sanitizeSchema;
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
module.exports = AnchorWithContext;
|
|
89
|
-
|
|
90
|
-
AnchorWithContext.getHref = getHref;
|
|
79
|
+
export default Anchor;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
|
|
3
|
+
interface Props extends React.PropsWithChildren<React.HTMLAttributes<HTMLQuoteElement>> {
|
|
4
|
+
attributes?: {};
|
|
5
|
+
icon: string;
|
|
6
|
+
theme?: string;
|
|
7
|
+
empty?: boolean;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const themes: Record<string, string> = {
|
|
11
|
+
'\uD83D\uDCD8': 'info',
|
|
12
|
+
'\uD83D\uDEA7': 'warn',
|
|
13
|
+
'\u26A0\uFE0F': 'warn',
|
|
14
|
+
'\uD83D\uDC4D': 'okay',
|
|
15
|
+
'\u2705': 'okay',
|
|
16
|
+
'\u2757\uFE0F': 'error',
|
|
17
|
+
'\u2757': 'error',
|
|
18
|
+
'\uD83D\uDED1': 'error',
|
|
19
|
+
'\u2049\uFE0F': 'error',
|
|
20
|
+
'\u203C\uFE0F': 'error',
|
|
21
|
+
'\u2139\uFE0F': 'info',
|
|
22
|
+
'\u26A0': 'warn',
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const Callout = (props: Props) => {
|
|
26
|
+
const { attributes, children, icon, empty } = props;
|
|
27
|
+
let theme = props.theme || themes[icon] || 'default';
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
// @ts-ignore
|
|
31
|
+
<blockquote {...attributes} className={`callout callout_${theme}`} theme={icon}>
|
|
32
|
+
<h3 className={`callout-heading${empty ? ' empty' : ''}`}>
|
|
33
|
+
<span className="callout-icon">{icon}</span>
|
|
34
|
+
{empty || children[0]}
|
|
35
|
+
</h3>
|
|
36
|
+
{empty ? children : React.Children.toArray(children).slice(1)}
|
|
37
|
+
</blockquote>
|
|
38
|
+
);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export default Callout;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import copy from 'copy-to-clipboard';
|
|
2
|
+
import React, { createRef } from 'react';
|
|
3
|
+
|
|
4
|
+
// Only load CodeMirror in the browser, for SSR
|
|
5
|
+
// apps. Necessary because of people like this:
|
|
6
|
+
// https://github.com/codemirror/CodeMirror/issues/3701#issuecomment-164904534
|
|
7
|
+
let syntaxHighlighter;
|
|
8
|
+
let canonicalLanguage = _ => '';
|
|
9
|
+
|
|
10
|
+
if (typeof window !== 'undefined') {
|
|
11
|
+
import('@readme/syntax-highlighter').then(module => {
|
|
12
|
+
syntaxHighlighter = module.default;
|
|
13
|
+
canonicalLanguage = module.canonical;
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function CopyCode({ codeRef, rootClass = 'rdmd-code-copy', className = '' }) {
|
|
18
|
+
const copyClass = `${rootClass}_copied`;
|
|
19
|
+
const button = createRef<HTMLButtonElement>();
|
|
20
|
+
|
|
21
|
+
const copier = () => {
|
|
22
|
+
const code = codeRef.current.textContent;
|
|
23
|
+
|
|
24
|
+
if (copy(code)) {
|
|
25
|
+
const el = button.current;
|
|
26
|
+
el.classList.add(copyClass);
|
|
27
|
+
|
|
28
|
+
setTimeout(() => el.classList.remove(copyClass), 1500);
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
return <button ref={button} aria-label="Copy Code" className={`${rootClass} ${className}`} onClick={copier} />;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
interface CodeProps {
|
|
36
|
+
children?: string[] | string;
|
|
37
|
+
copyButtons?: boolean;
|
|
38
|
+
lang?: string;
|
|
39
|
+
meta?: string;
|
|
40
|
+
theme?: string;
|
|
41
|
+
value?: string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const Code = (props: CodeProps) => {
|
|
45
|
+
const { children, copyButtons, lang, theme, value } = props;
|
|
46
|
+
|
|
47
|
+
const language = canonicalLanguage(lang);
|
|
48
|
+
|
|
49
|
+
const codeRef = createRef<HTMLElement>();
|
|
50
|
+
|
|
51
|
+
const codeOpts = {
|
|
52
|
+
inline: !lang,
|
|
53
|
+
tokenizeVariables: true,
|
|
54
|
+
dark: theme === 'dark',
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const code = value ?? (Array.isArray(children) ? children[0] : children) ?? '';
|
|
58
|
+
const highlightedCode = syntaxHighlighter && code ? syntaxHighlighter(code, language, codeOpts) : code;
|
|
59
|
+
|
|
60
|
+
return (
|
|
61
|
+
<>
|
|
62
|
+
{copyButtons && <CopyCode className="fa" codeRef={codeRef} />}
|
|
63
|
+
<code
|
|
64
|
+
ref={codeRef}
|
|
65
|
+
className={['rdmd-code', `lang-${language}`, `theme-${theme}`].join(' ')}
|
|
66
|
+
data-lang={language}
|
|
67
|
+
suppressHydrationWarning={true}
|
|
68
|
+
>
|
|
69
|
+
{highlightedCode}
|
|
70
|
+
</code>
|
|
71
|
+
</>
|
|
72
|
+
);
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
export default Code;
|
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const React = require('react');
|
|
1
|
+
import { uppercase } from '@readme/syntax-highlighter';
|
|
2
|
+
import React from 'react';
|
|
4
3
|
|
|
5
4
|
const CodeTabs = props => {
|
|
6
5
|
const { children, theme } = props;
|
|
7
6
|
|
|
8
|
-
function handleClick({ target }, index) {
|
|
7
|
+
function handleClick({ target }, index: number) {
|
|
9
8
|
const $wrap = target.parentElement.parentElement;
|
|
10
9
|
const $open = [].slice.call($wrap.querySelectorAll('.CodeTabs_active'));
|
|
11
|
-
$open.forEach(el => el.classList.remove('CodeTabs_active'));
|
|
10
|
+
$open.forEach((el: Element) => el.classList.remove('CodeTabs_active'));
|
|
12
11
|
$wrap.classList.remove('CodeTabs_initial');
|
|
13
12
|
|
|
14
13
|
const codeblocks = $wrap.querySelectorAll('pre');
|
|
@@ -20,8 +19,9 @@ const CodeTabs = props => {
|
|
|
20
19
|
return (
|
|
21
20
|
<div className={`CodeTabs CodeTabs_initial theme-${theme}`}>
|
|
22
21
|
<div className="CodeTabs-toolbar">
|
|
23
|
-
{children.map((
|
|
24
|
-
const { meta, lang } = pre.children
|
|
22
|
+
{(Array.isArray(children) ? children : [children]).map((pre, i) => {
|
|
23
|
+
const { meta, lang } = pre.props.children.props;
|
|
24
|
+
|
|
25
25
|
/* istanbul ignore next */
|
|
26
26
|
return (
|
|
27
27
|
<button key={i} onClick={e => handleClick(e, i)} type="button">
|
|
@@ -35,15 +35,4 @@ const CodeTabs = props => {
|
|
|
35
35
|
);
|
|
36
36
|
};
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
children: PropTypes.arrayOf(PropTypes.any).isRequired,
|
|
40
|
-
theme: PropTypes.string,
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
function CreateCodeTabs({ theme }) {
|
|
44
|
-
// eslint-disable-next-line react/display-name
|
|
45
|
-
return props => <CodeTabs {...props} theme={theme} />;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
module.exports = CreateCodeTabs;
|
|
49
|
-
module.exports.CodeTabs = CodeTabs;
|
|
38
|
+
export default CodeTabs;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
interface FaviconProps {
|
|
4
|
+
src: string;
|
|
5
|
+
alt?: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const Favicon = ({ src, alt = 'favicon', ...attr }: FaviconProps) => (
|
|
9
|
+
<img {...attr} alt={alt} height="14" src={src} width="14" />
|
|
10
|
+
);
|
|
11
|
+
|
|
12
|
+
interface EmbedProps {
|
|
13
|
+
lazy?: boolean;
|
|
14
|
+
url: string;
|
|
15
|
+
title: string;
|
|
16
|
+
provider?: string;
|
|
17
|
+
html?: string;
|
|
18
|
+
iframe?: boolean;
|
|
19
|
+
image?: string;
|
|
20
|
+
favicon?: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const Embed = ({ lazy = true, url, provider, title, html, iframe, image, favicon, ...attrs }: EmbedProps) => {
|
|
24
|
+
if (iframe) {
|
|
25
|
+
return <iframe {...attrs} src={url} style={{ border: 'none', display: 'flex', margin: 'auto' }} />;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (!provider)
|
|
29
|
+
provider = new URL(url).hostname
|
|
30
|
+
.split(/(?:www)?\./)
|
|
31
|
+
.filter(i => i)
|
|
32
|
+
.join('.');
|
|
33
|
+
|
|
34
|
+
const classes = ['embed', image ? 'embed_hasImg' : ''];
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
<div className={classes.join(' ')}>
|
|
38
|
+
{html ? (
|
|
39
|
+
<div className="embed-media" dangerouslySetInnerHTML={{ __html: html }} />
|
|
40
|
+
) : (
|
|
41
|
+
<a className="embed-link" href={url} rel="noopener noreferrer" target="_blank">
|
|
42
|
+
{!image || <img alt={title} className="embed-img" loading={lazy ? 'lazy' : undefined} src={image} />}
|
|
43
|
+
{title ? (
|
|
44
|
+
<div className="embed-body">
|
|
45
|
+
{!favicon || <Favicon alt={provider} src={favicon} />}
|
|
46
|
+
{provider && (
|
|
47
|
+
<small className="embed-provider">
|
|
48
|
+
{provider.search(/^@{1}/) < 0 ? (
|
|
49
|
+
provider
|
|
50
|
+
) : (
|
|
51
|
+
<code style={{ fontFamily: 'var(--md-code-font, monospace)' }}>{url}</code>
|
|
52
|
+
)}
|
|
53
|
+
</small>
|
|
54
|
+
)}
|
|
55
|
+
<div className="embed-title">{title}</div>
|
|
56
|
+
</div>
|
|
57
|
+
) : (
|
|
58
|
+
<div className="embed-body">
|
|
59
|
+
<b>View</b>: <span className="embed-body-url">{url}</span>
|
|
60
|
+
</div>
|
|
61
|
+
)}
|
|
62
|
+
</a>
|
|
63
|
+
)}
|
|
64
|
+
</div>
|
|
65
|
+
);
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export default Embed;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import React, { useContext } from 'react';
|
|
2
|
+
import Tooltip from '@tippyjs/react';
|
|
3
|
+
import GlossaryContext from '../../contexts/GlossaryTerms';
|
|
4
|
+
import type { GlossaryTerm } from '../../contexts/GlossaryTerms';
|
|
5
|
+
|
|
6
|
+
interface Props extends React.PropsWithChildren {
|
|
7
|
+
term?: string;
|
|
8
|
+
terms: GlossaryTerm[];
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const Glossary = ({ children, term: termProp, terms }: Props) => {
|
|
12
|
+
const term = (Array.isArray(children) ? children[0] : children) || termProp;
|
|
13
|
+
const foundTerm = terms.find(i => term.toLowerCase() === i?.term?.toLowerCase());
|
|
14
|
+
|
|
15
|
+
if (!foundTerm) return <span>{term}</span>;
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
<Tooltip
|
|
19
|
+
content={
|
|
20
|
+
<div className="Glossary-tooltip-content">
|
|
21
|
+
<strong className="Glossary-term">{foundTerm.term}</strong> - {foundTerm.definition}
|
|
22
|
+
</div>
|
|
23
|
+
}
|
|
24
|
+
offset={[-5, 5]}
|
|
25
|
+
placement="bottom-start"
|
|
26
|
+
>
|
|
27
|
+
<span className="Glossary-trigger">{term}</span>
|
|
28
|
+
</Tooltip>
|
|
29
|
+
);
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const GlossaryWithContext = props => {
|
|
33
|
+
const terms = useContext(GlossaryContext);
|
|
34
|
+
return terms ? <Glossary {...props} terms={terms} /> : <span>{props.term}</span>;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export { Glossary, GlossaryWithContext as default, GlossaryContext };
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
.Glossary {
|
|
2
|
+
&-trigger {
|
|
3
|
+
border-bottom: 1px solid #737c83;
|
|
4
|
+
border-style: dotted;
|
|
5
|
+
border-top: none;
|
|
6
|
+
border-left: none;
|
|
7
|
+
border-right: none;
|
|
8
|
+
cursor: pointer;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
&-tooltip-content {
|
|
12
|
+
--Glossary-bg: var(--color-bg-page, var(--white));
|
|
13
|
+
--Glossary-color: var(--color-text-default, var(--gray20));
|
|
14
|
+
--Glossary-shadow: var(
|
|
15
|
+
--box-shadow-menu-light,
|
|
16
|
+
0 5px 10px rgba(0, 0, 0, 0.05),
|
|
17
|
+
0 2px 6px rgba(0, 0, 0, 0.025),
|
|
18
|
+
0 1px 3px rgba(0, 0, 0, 0.025)
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
/* what the dark-mode mixin does in the readme project */
|
|
22
|
+
[data-color-mode='dark'] & {
|
|
23
|
+
--Glossary-bg: var(--gray15);
|
|
24
|
+
--Glossary-color: var(--color-text-default, var(--white));
|
|
25
|
+
--Glossary-shadow: var(
|
|
26
|
+
--box-shadow-menu-dark,
|
|
27
|
+
0 1px 3px rgba(0, 0, 0, 0.025),
|
|
28
|
+
0 2px 6px rgba(0, 0, 0, 0.025),
|
|
29
|
+
0 5px 10px rgba(0, 0, 0, 0.05)
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@media (prefers-color-scheme: dark) {
|
|
34
|
+
[data-color-mode='auto'] & {
|
|
35
|
+
--Glossary-bg: var(--Tooltip-bg, var(--gray0));
|
|
36
|
+
--Glossary-color: var(--color-text-default, var(--white));
|
|
37
|
+
--Glossary-shadow: var(
|
|
38
|
+
--box-shadow-menu-dark,
|
|
39
|
+
0 1px 3px rgba(0, 0, 0, 0.025),
|
|
40
|
+
0 2px 6px rgba(0, 0, 0, 0.025),
|
|
41
|
+
0 5px 10px rgba(0, 0, 0, 0.05)
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
background-color: var(--Glossary-bg);
|
|
47
|
+
border: 1px solid #{var(--color-border-default, rgba(black, 0.1))};
|
|
48
|
+
border-radius: var(--border-radius);
|
|
49
|
+
box-shadow: var(--Glossary-shadow);
|
|
50
|
+
color: var(--Glossary-color);
|
|
51
|
+
font-size: 15px;
|
|
52
|
+
font-weight: 400;
|
|
53
|
+
line-height: 1.5;
|
|
54
|
+
padding: 15px;
|
|
55
|
+
text-align: left;
|
|
56
|
+
width: 350px;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
&-term {
|
|
60
|
+
font-style: italic;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.tippy-box {
|
|
65
|
+
// needed for tippy's default animation
|
|
66
|
+
&[data-animation='fade'][data-state='hidden'] {
|
|
67
|
+
opacity: 0;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import React, { useEffect } from 'react';
|
|
2
|
+
import { renderToStaticMarkup } from 'react-dom/server';
|
|
3
|
+
|
|
4
|
+
const MATCH_SCRIPT_TAGS = /<script\b[^>]*>([\s\S]*?)<\/script *>\n?/gim;
|
|
5
|
+
|
|
6
|
+
const extractScripts = (html: string = ''): [string, () => void] => {
|
|
7
|
+
const scripts: string[] = [];
|
|
8
|
+
let match: RegExpExecArray | null;
|
|
9
|
+
while ((match = MATCH_SCRIPT_TAGS.exec(html)) !== null) {
|
|
10
|
+
scripts.push(match[1]);
|
|
11
|
+
}
|
|
12
|
+
const cleaned = html.replace(MATCH_SCRIPT_TAGS, '');
|
|
13
|
+
return [cleaned, () => scripts.map(js => window.eval(js))];
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const HTMLBlock = ({ children = '', runScripts = false, safeMode = false }) => {
|
|
17
|
+
let html = children;
|
|
18
|
+
if (typeof html !== 'string') html = renderToStaticMarkup(html);
|
|
19
|
+
const [cleanedHtml, exec] = extractScripts(html);
|
|
20
|
+
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
if (typeof window !== 'undefined' && typeof runScripts === 'boolean' && runScripts) exec();
|
|
23
|
+
}, [runScripts, exec]);
|
|
24
|
+
|
|
25
|
+
if (safeMode) {
|
|
26
|
+
return (
|
|
27
|
+
<pre className="html-unsafe">
|
|
28
|
+
<code>{html}</code>
|
|
29
|
+
</pre>
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return <div className="rdmd-html" dangerouslySetInnerHTML={{ __html: cleanedHtml }} />;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export default HTMLBlock;
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
|
|
3
|
+
interface ImageProps {
|
|
4
|
+
align?: string;
|
|
5
|
+
alt?: string;
|
|
6
|
+
border?: boolean;
|
|
7
|
+
caption?: string;
|
|
8
|
+
className?: string;
|
|
9
|
+
height?: string;
|
|
10
|
+
src: string;
|
|
11
|
+
title?: string;
|
|
12
|
+
width?: string;
|
|
13
|
+
lazy?: boolean;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const Image = (Props: ImageProps) => {
|
|
17
|
+
const [lightbox, setLightbox] = React.useState(false);
|
|
18
|
+
const {
|
|
19
|
+
align = '',
|
|
20
|
+
alt = '',
|
|
21
|
+
border = false,
|
|
22
|
+
caption,
|
|
23
|
+
className = '',
|
|
24
|
+
height = 'auto',
|
|
25
|
+
src,
|
|
26
|
+
title = '',
|
|
27
|
+
width = 'auto',
|
|
28
|
+
lazy = false,
|
|
29
|
+
} = Props;
|
|
30
|
+
|
|
31
|
+
if (className === 'emoji') {
|
|
32
|
+
return <img src={src} width={width} height={height} title={title} alt={alt} loading={lazy ? 'lazy' : 'eager'} />;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const handleKeyDown = ({ key, metaKey: cmd }: React.KeyboardEvent<HTMLImageElement>) => {
|
|
36
|
+
const cmdKey = cmd ? 'cmd+' : '';
|
|
37
|
+
key = `${cmdKey}${key.toLowerCase()}`;
|
|
38
|
+
|
|
39
|
+
switch (key) {
|
|
40
|
+
case 'cmd+.':
|
|
41
|
+
case 'escape':
|
|
42
|
+
// CLOSE
|
|
43
|
+
setLightbox(false);
|
|
44
|
+
break;
|
|
45
|
+
case ' ':
|
|
46
|
+
case 'enter':
|
|
47
|
+
// OPEN
|
|
48
|
+
if (!lightbox) setLightbox(true);
|
|
49
|
+
default:
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const toggle = () => {
|
|
54
|
+
if (className === 'emoji') return;
|
|
55
|
+
setLightbox(!lightbox);
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
if (caption) {
|
|
59
|
+
return (
|
|
60
|
+
<figure>
|
|
61
|
+
<span
|
|
62
|
+
aria-label={alt}
|
|
63
|
+
className={`img lightbox ${lightbox ? 'open' : 'closed'}`}
|
|
64
|
+
onClick={toggle}
|
|
65
|
+
onKeyDown={handleKeyDown}
|
|
66
|
+
role={'button'}
|
|
67
|
+
tabIndex={0}
|
|
68
|
+
>
|
|
69
|
+
<span className="lightbox-inner">
|
|
70
|
+
<img
|
|
71
|
+
src={src}
|
|
72
|
+
width={width}
|
|
73
|
+
height={height}
|
|
74
|
+
title={title}
|
|
75
|
+
className={`img img-align-center ${border ? 'border' : ''}`}
|
|
76
|
+
alt={alt}
|
|
77
|
+
loading={lazy ? 'lazy' : 'eager'}
|
|
78
|
+
/>
|
|
79
|
+
</span>
|
|
80
|
+
</span>
|
|
81
|
+
<figcaption>{caption}</figcaption>
|
|
82
|
+
</figure>
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return (
|
|
87
|
+
<span
|
|
88
|
+
aria-label={alt}
|
|
89
|
+
className={`img lightbox ${lightbox ? 'open' : 'closed'}`}
|
|
90
|
+
onClick={toggle}
|
|
91
|
+
onKeyDown={handleKeyDown}
|
|
92
|
+
role={'button'}
|
|
93
|
+
tabIndex={0}
|
|
94
|
+
>
|
|
95
|
+
<span className="lightbox-inner">
|
|
96
|
+
<img
|
|
97
|
+
src={src}
|
|
98
|
+
width={width}
|
|
99
|
+
height={height}
|
|
100
|
+
title={title}
|
|
101
|
+
className={`img img-align-${align} ${border ? 'border' : ''}`}
|
|
102
|
+
alt={alt}
|
|
103
|
+
loading={lazy ? 'lazy' : 'eager'}
|
|
104
|
+
/>
|
|
105
|
+
</span>
|
|
106
|
+
</span>
|
|
107
|
+
);
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
export default Image;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
interface Props extends JSX.IntrinsicAttributes {
|
|
4
|
+
children: [React.ReactElement<HTMLTableCaptionElement | HTMLTableSectionElement | HTMLTableRowElement>];
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
const Table = (props: Props) => {
|
|
8
|
+
const { children } = props;
|
|
9
|
+
|
|
10
|
+
return (
|
|
11
|
+
<div className="rdmd-table">
|
|
12
|
+
<div className="rdmd-table-inner">
|
|
13
|
+
<table>{children}</table>
|
|
14
|
+
</div>
|
|
15
|
+
</div>
|
|
16
|
+
);
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export default Table;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { element } from 'prop-types';
|
|
2
|
+
import React from 'react';
|
|
3
3
|
|
|
4
4
|
function TableOfContents({ children }) {
|
|
5
5
|
return (
|
|
@@ -19,7 +19,7 @@ function TableOfContents({ children }) {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
TableOfContents.propTypes = {
|
|
22
|
-
children:
|
|
22
|
+
children: element,
|
|
23
23
|
};
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
export default TableOfContents;
|
|
@@ -3,7 +3,7 @@ export { default as Callout } from './Callout';
|
|
|
3
3
|
export { default as Code } from './Code';
|
|
4
4
|
export { default as CodeTabs } from './CodeTabs';
|
|
5
5
|
export { default as Embed } from './Embed';
|
|
6
|
-
export { default as
|
|
6
|
+
export { default as Glossary } from './Glossary';
|
|
7
7
|
export { default as HTMLBlock } from './HTMLBlock';
|
|
8
8
|
export { default as Heading } from './Heading';
|
|
9
9
|
export { default as Image } from './Image';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
interface Props extends React.PropsWithChildren<React.HTMLAttributes<HTMLQuoteElement>> {
|
|
3
|
+
attributes?: {};
|
|
4
|
+
icon: string;
|
|
5
|
+
theme?: string;
|
|
6
|
+
empty?: boolean;
|
|
7
|
+
}
|
|
8
|
+
declare const Callout: (props: Props) => React.JSX.Element;
|
|
9
|
+
export default Callout;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
interface CodeProps {
|
|
3
|
+
children?: string[] | string;
|
|
4
|
+
copyButtons?: boolean;
|
|
5
|
+
lang?: string;
|
|
6
|
+
meta?: string;
|
|
7
|
+
theme?: string;
|
|
8
|
+
value?: string;
|
|
9
|
+
}
|
|
10
|
+
declare const Code: (props: CodeProps) => React.JSX.Element;
|
|
11
|
+
export default Code;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
interface EmbedProps {
|
|
3
|
+
lazy?: boolean;
|
|
4
|
+
url: string;
|
|
5
|
+
title: string;
|
|
6
|
+
provider?: string;
|
|
7
|
+
html?: string;
|
|
8
|
+
iframe?: boolean;
|
|
9
|
+
image?: string;
|
|
10
|
+
favicon?: string;
|
|
11
|
+
}
|
|
12
|
+
declare const Embed: ({ lazy, url, provider, title, html, iframe, image, favicon, ...attrs }: EmbedProps) => React.JSX.Element;
|
|
13
|
+
export default Embed;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import GlossaryContext from '../../contexts/GlossaryTerms';
|
|
3
|
+
import type { GlossaryTerm } from '../../contexts/GlossaryTerms';
|
|
4
|
+
interface Props extends React.PropsWithChildren {
|
|
5
|
+
term?: string;
|
|
6
|
+
terms: GlossaryTerm[];
|
|
7
|
+
}
|
|
8
|
+
declare const Glossary: ({ children, term: termProp, terms }: Props) => React.JSX.Element;
|
|
9
|
+
declare const GlossaryWithContext: (props: any) => React.JSX.Element;
|
|
10
|
+
export { Glossary, GlossaryWithContext as default, GlossaryContext };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
interface ImageProps {
|
|
3
|
+
align?: string;
|
|
4
|
+
alt?: string;
|
|
5
|
+
border?: boolean;
|
|
6
|
+
caption?: string;
|
|
7
|
+
className?: string;
|
|
8
|
+
height?: string;
|
|
9
|
+
src: string;
|
|
10
|
+
title?: string;
|
|
11
|
+
width?: string;
|
|
12
|
+
lazy?: boolean;
|
|
13
|
+
}
|
|
14
|
+
declare const Image: (Props: ImageProps) => React.JSX.Element;
|
|
15
|
+
export default Image;
|