myst-to-react 0.1.16 → 0.1.18
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/package.json +21 -9
- package/src/basic.tsx +18 -6
- package/src/card.tsx +15 -3
- package/src/cite.tsx +0 -51
- package/src/index.tsx +1 -1
- package/src/myst.tsx +6 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "myst-to-react",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.18",
|
|
4
4
|
"main": "./src/index.tsx",
|
|
5
5
|
"types": "./src/index.tsx",
|
|
6
6
|
"files": [
|
|
@@ -8,43 +8,55 @@
|
|
|
8
8
|
],
|
|
9
9
|
"license": "MIT",
|
|
10
10
|
"scripts": {
|
|
11
|
+
"compile": "tsc",
|
|
11
12
|
"lint": "eslint \"src/**/*.ts*\" \"src/**/*.tsx\" -c ./.eslintrc.js",
|
|
12
13
|
"lint:format": "prettier --check \"src/**/*.{ts,tsx,md}\""
|
|
13
14
|
},
|
|
14
15
|
"dependencies": {
|
|
15
|
-
"@curvenote/blocks": "
|
|
16
|
+
"@curvenote/blocks": "^1.5.15",
|
|
16
17
|
"@curvenote/connect": "^0.0.6",
|
|
17
18
|
"@curvenote/nbtx": "^0.1.11",
|
|
18
19
|
"@curvenote/ui-providers": "*",
|
|
19
20
|
"@headlessui/react": "^1.6.5",
|
|
20
21
|
"@heroicons/react": "^1.0.6",
|
|
21
22
|
"@popperjs/core": "^2.11.5",
|
|
22
|
-
"@remix-run/react": "^1.6.3",
|
|
23
23
|
"ansi-to-react": "^6.1.6",
|
|
24
24
|
"buffer": "^6.0.3",
|
|
25
25
|
"classnames": "^2.3.1",
|
|
26
|
-
"mermaid": "^9.1.
|
|
26
|
+
"mermaid": "^9.1.7",
|
|
27
27
|
"myst-spec": "^0.0.4",
|
|
28
28
|
"myst-to-docx": "*",
|
|
29
29
|
"myst-to-tex": "*",
|
|
30
30
|
"myst-transforms": "*",
|
|
31
31
|
"mystjs": "^0.0.13",
|
|
32
32
|
"nanoid": "^4.0.0",
|
|
33
|
-
"react-dom": "^17.0.2",
|
|
34
33
|
"react-popper": "^2.3.0",
|
|
35
|
-
"react-redux": "^8.0.2",
|
|
36
34
|
"react-syntax-highlighter": "^15.5.0",
|
|
37
35
|
"swr": "^1.3.0",
|
|
38
36
|
"unist-util-select": "^4.0.1"
|
|
39
37
|
},
|
|
38
|
+
"peerDependencies": {
|
|
39
|
+
"@remix-run/node": "^1.7.2",
|
|
40
|
+
"@remix-run/react": "^1.7.2",
|
|
41
|
+
"@types/react": "^16.8 || ^17.0 || ^18.0",
|
|
42
|
+
"@types/react-dom": "^16.8 || ^17.0 || ^18.0",
|
|
43
|
+
"react": "^16.8 || ^17.0 || ^18.0",
|
|
44
|
+
"react-dom": "^16.8 || ^17.0 || ^18.0",
|
|
45
|
+
"react-redux": "^7.2.1 || ^8.0.2"
|
|
46
|
+
},
|
|
40
47
|
"devDependencies": {
|
|
48
|
+
"@types/js-yaml": "^4.0.5",
|
|
41
49
|
"@types/mermaid": "^8.2.9",
|
|
42
|
-
"@types/react": "^
|
|
43
|
-
"@types/react-dom": "^17.0.11",
|
|
50
|
+
"@types/react-syntax-highlighter": "^15.5.5",
|
|
44
51
|
"eslint": "^8.21.0",
|
|
45
52
|
"eslint-config-curvenote": "*",
|
|
46
|
-
"react": "^17.0.2",
|
|
47
53
|
"tsconfig": "*",
|
|
48
54
|
"typescript": "latest"
|
|
55
|
+
},
|
|
56
|
+
"overrides": {
|
|
57
|
+
"ansi-to-react": {
|
|
58
|
+
"react": "^16.8 || ^17.0 || ^18.0",
|
|
59
|
+
"react-dom": "^16.8 || ^17.0 || ^18.0"
|
|
60
|
+
}
|
|
49
61
|
}
|
|
50
62
|
}
|
package/src/basic.tsx
CHANGED
|
@@ -165,7 +165,12 @@ const BASIC_RENDERERS: BasicNodeRenderers = {
|
|
|
165
165
|
);
|
|
166
166
|
},
|
|
167
167
|
table(node, children) {
|
|
168
|
-
|
|
168
|
+
// TODO: actually render the tbody on the server if it isn't included here.
|
|
169
|
+
return (
|
|
170
|
+
<table key={node.key}>
|
|
171
|
+
<tbody>{children}</tbody>
|
|
172
|
+
</table>
|
|
173
|
+
);
|
|
169
174
|
},
|
|
170
175
|
tableRow(node, children) {
|
|
171
176
|
return <tr key={node.key}>{children}</tr>;
|
|
@@ -203,11 +208,18 @@ const BASIC_RENDERERS: BasicNodeRenderers = {
|
|
|
203
208
|
return <dl key={node.key}>{children}</dl>;
|
|
204
209
|
},
|
|
205
210
|
definitionTerm(node, children) {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
+
let strongChildren: React.ReactNode = children;
|
|
212
|
+
if (Array.isArray(children)) {
|
|
213
|
+
const allowedStrongTypes = new Set(['emphasis']);
|
|
214
|
+
strongChildren = children.map((child, i) => {
|
|
215
|
+
if (typeof child === 'string') return <strong key={node.key + i}>{child}</strong>;
|
|
216
|
+
if (allowedStrongTypes.has(child?.type)) return <strong key={node.key + i}>{child}</strong>;
|
|
217
|
+
return child;
|
|
218
|
+
});
|
|
219
|
+
} else if (typeof children === 'string') {
|
|
220
|
+
strongChildren = <strong key={node.key + '0'}>{children}</strong>;
|
|
221
|
+
}
|
|
222
|
+
return <dt key={node.key}>{strongChildren}</dt>;
|
|
211
223
|
},
|
|
212
224
|
definitionDescription(node, children) {
|
|
213
225
|
return <dd key={node.key}>{children}</dd>;
|
package/src/card.tsx
CHANGED
|
@@ -7,6 +7,7 @@ import { Link } from '@remix-run/react';
|
|
|
7
7
|
type CardSpec = {
|
|
8
8
|
type: 'card';
|
|
9
9
|
url?: string;
|
|
10
|
+
static?: boolean;
|
|
10
11
|
};
|
|
11
12
|
type CardTitleSpec = {
|
|
12
13
|
type: 'cardTitle';
|
|
@@ -71,15 +72,17 @@ function getParts(children: React.ReactNode): Parts {
|
|
|
71
72
|
function ExternalOrInternalLink({
|
|
72
73
|
to,
|
|
73
74
|
className,
|
|
75
|
+
isStatic,
|
|
74
76
|
prefetch = 'intent',
|
|
75
77
|
children,
|
|
76
78
|
}: {
|
|
77
79
|
to: string;
|
|
78
80
|
className?: string;
|
|
81
|
+
isStatic?: boolean;
|
|
79
82
|
prefetch?: 'intent' | 'render' | 'none';
|
|
80
83
|
children: React.ReactNode;
|
|
81
84
|
}) {
|
|
82
|
-
if (to.startsWith('http')) {
|
|
85
|
+
if (to.startsWith('http') || isStatic) {
|
|
83
86
|
return (
|
|
84
87
|
<a href={to} className={className} target="_blank" rel="noopener noreferrer">
|
|
85
88
|
{children}
|
|
@@ -93,7 +96,15 @@ function ExternalOrInternalLink({
|
|
|
93
96
|
);
|
|
94
97
|
}
|
|
95
98
|
|
|
96
|
-
function Card({
|
|
99
|
+
function Card({
|
|
100
|
+
children,
|
|
101
|
+
url,
|
|
102
|
+
isStatic,
|
|
103
|
+
}: {
|
|
104
|
+
children: React.ReactNode;
|
|
105
|
+
url?: string;
|
|
106
|
+
isStatic?: boolean;
|
|
107
|
+
}) {
|
|
97
108
|
const parts = getParts(children);
|
|
98
109
|
const link = !!url;
|
|
99
110
|
const sharedStyle =
|
|
@@ -102,6 +113,7 @@ function Card({ children, url }: { children: React.ReactNode; url?: string }) {
|
|
|
102
113
|
return (
|
|
103
114
|
<ExternalOrInternalLink
|
|
104
115
|
to={url}
|
|
116
|
+
isStatic={isStatic}
|
|
105
117
|
className={classNames(
|
|
106
118
|
sharedStyle,
|
|
107
119
|
'block font-normal no-underline cursor-pointer group',
|
|
@@ -125,7 +137,7 @@ function Card({ children, url }: { children: React.ReactNode; url?: string }) {
|
|
|
125
137
|
|
|
126
138
|
export const CardRenderer: NodeRenderer<CardSpec> = (node, children) => {
|
|
127
139
|
return (
|
|
128
|
-
<Card key={node.key} url={node.url}>
|
|
140
|
+
<Card key={node.key} url={node.url} isStatic={node.static || false}>
|
|
129
141
|
{children}
|
|
130
142
|
</Card>
|
|
131
143
|
);
|
package/src/cite.tsx
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import classNames from 'classnames';
|
|
2
2
|
import { useReferences } from '@curvenote/ui-providers';
|
|
3
3
|
import type { NodeRenderer } from './types';
|
|
4
|
-
import { useState } from 'react';
|
|
5
4
|
import { ClickPopover } from './components/ClickPopover';
|
|
6
5
|
import { InlineError } from './inlineError';
|
|
7
6
|
|
|
@@ -36,59 +35,9 @@ export const Cite: NodeRenderer = (node, children) => {
|
|
|
36
35
|
);
|
|
37
36
|
};
|
|
38
37
|
|
|
39
|
-
const HIDE_OVER_N_REFERENCES = 5;
|
|
40
|
-
|
|
41
|
-
export function Bibliography() {
|
|
42
|
-
const references = useReferences();
|
|
43
|
-
const { order, data } = references?.cite ?? {};
|
|
44
|
-
const filtered = order?.filter((l) => l);
|
|
45
|
-
const [hidden, setHidden] = useState(true);
|
|
46
|
-
if (!filtered || !data || filtered.length === 0) return null;
|
|
47
|
-
const refs = hidden ? filtered.slice(0, HIDE_OVER_N_REFERENCES) : filtered;
|
|
48
|
-
return (
|
|
49
|
-
<section>
|
|
50
|
-
{filtered.length > HIDE_OVER_N_REFERENCES && (
|
|
51
|
-
<button
|
|
52
|
-
onClick={() => setHidden(!hidden)}
|
|
53
|
-
className="float-right text-xs p-1 px-2 border rounded hover:border-blue-500 dark:hover:border-blue-400"
|
|
54
|
-
>
|
|
55
|
-
{hidden ? 'Show All' : 'Collapse'}
|
|
56
|
-
</button>
|
|
57
|
-
)}
|
|
58
|
-
<header className="text-lg font-semibold text-stone-900 dark:text-white">References</header>
|
|
59
|
-
<div className="text-xs mb-8 pl-3 text-stone-500 dark:text-stone-300">
|
|
60
|
-
<ol>
|
|
61
|
-
{refs.map((label) => {
|
|
62
|
-
const { html } = data[label];
|
|
63
|
-
return (
|
|
64
|
-
<li
|
|
65
|
-
key={label}
|
|
66
|
-
className="break-words"
|
|
67
|
-
id={`cite-${label}`}
|
|
68
|
-
dangerouslySetInnerHTML={{ __html: html || '' }}
|
|
69
|
-
/>
|
|
70
|
-
);
|
|
71
|
-
})}
|
|
72
|
-
{filtered.length > HIDE_OVER_N_REFERENCES && (
|
|
73
|
-
<li className="list-none text-center">
|
|
74
|
-
<button
|
|
75
|
-
onClick={() => setHidden(!hidden)}
|
|
76
|
-
className="p-2 border rounded hover:border-blue-500 dark:hover:border-blue-400"
|
|
77
|
-
>
|
|
78
|
-
{hidden ? `Show all ${filtered.length} references` : 'Collapse references'}
|
|
79
|
-
</button>
|
|
80
|
-
</li>
|
|
81
|
-
)}
|
|
82
|
-
</ol>
|
|
83
|
-
</div>
|
|
84
|
-
</section>
|
|
85
|
-
);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
38
|
const CITE_RENDERERS: Record<string, NodeRenderer> = {
|
|
89
39
|
citeGroup: CiteGroup,
|
|
90
40
|
cite: Cite,
|
|
91
|
-
bibliography: (node) => <Bibliography key={node.key}></Bibliography>,
|
|
92
41
|
};
|
|
93
42
|
|
|
94
43
|
export default CITE_RENDERERS;
|
package/src/index.tsx
CHANGED
|
@@ -24,8 +24,8 @@ export { MySTRenderer } from './myst';
|
|
|
24
24
|
import EXT_RENDERERS from './extensions';
|
|
25
25
|
|
|
26
26
|
export type { NodeRenderer } from './types';
|
|
27
|
-
export { Bibliography } from './cite';
|
|
28
27
|
export { CopyIcon } from './components/CopyIcon';
|
|
28
|
+
export { CodeBlock } from './code';
|
|
29
29
|
|
|
30
30
|
export const DEFAULT_RENDERERS: Record<string, NodeRenderer> = {
|
|
31
31
|
...BASIC_RENDERERS,
|
package/src/myst.tsx
CHANGED
|
@@ -92,6 +92,7 @@ async function parse(text: string, defaultFrontmatter?: PageFrontmatter) {
|
|
|
92
92
|
.stringify(mdast as any).result as LatexResult;
|
|
93
93
|
const content = useParse(mdast as any);
|
|
94
94
|
return {
|
|
95
|
+
frontmatter,
|
|
95
96
|
yaml: mdastString,
|
|
96
97
|
references: { ...references, article: mdast } as References,
|
|
97
98
|
html: htmlString,
|
|
@@ -105,6 +106,7 @@ export function MySTRenderer({ value, numbering }: { value: string; numbering: a
|
|
|
105
106
|
const area = useRef<HTMLTextAreaElement | null>(null);
|
|
106
107
|
const [text, setText] = useState<string>(value.trim());
|
|
107
108
|
const [references, setReferences] = useState<References>({});
|
|
109
|
+
const [frontmatter, setFrontmatter] = useState<PageFrontmatter>({});
|
|
108
110
|
const [mdastYaml, setYaml] = useState<string>('Loading...');
|
|
109
111
|
const [html, setHtml] = useState<string>('Loading...');
|
|
110
112
|
const [tex, setTex] = useState<string>('Loading...');
|
|
@@ -116,6 +118,7 @@ export function MySTRenderer({ value, numbering }: { value: string; numbering: a
|
|
|
116
118
|
const ref = { current: true };
|
|
117
119
|
parse(text, { numbering }).then((result) => {
|
|
118
120
|
if (!ref.current) return;
|
|
121
|
+
setFrontmatter(result.frontmatter);
|
|
119
122
|
setYaml(result.yaml);
|
|
120
123
|
setReferences(result.references);
|
|
121
124
|
setHtml(result.html);
|
|
@@ -182,7 +185,9 @@ export function MySTRenderer({ value, numbering }: { value: string; numbering: a
|
|
|
182
185
|
</button>
|
|
183
186
|
</div>
|
|
184
187
|
{previewType === 'DEMO' && (
|
|
185
|
-
<ReferencesProvider references={references}
|
|
188
|
+
<ReferencesProvider references={references} frontmatter={frontmatter}>
|
|
189
|
+
{content}
|
|
190
|
+
</ReferencesProvider>
|
|
186
191
|
)}
|
|
187
192
|
{previewType === 'AST' && <CodeBlock lang="yaml" value={mdastYaml} showCopy={false} />}
|
|
188
193
|
{previewType === 'HTML' && <CodeBlock lang="xml" value={html} showCopy={false} />}
|