@dxos/react-ui-markdown 0.8.4-main.1068cf700f
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/LICENSE +8 -0
- package/README.md +1 -0
- package/dist/lib/browser/index.mjs +79 -0
- package/dist/lib/browser/index.mjs.map +7 -0
- package/dist/lib/browser/meta.json +1 -0
- package/dist/types/src/MarkdownViewer/MarkdownViewer.d.ts +15 -0
- package/dist/types/src/MarkdownViewer/MarkdownViewer.d.ts.map +1 -0
- package/dist/types/src/MarkdownViewer/MarkdownViewer.stories.d.ts +11 -0
- package/dist/types/src/MarkdownViewer/MarkdownViewer.stories.d.ts.map +1 -0
- package/dist/types/src/MarkdownViewer/index.d.ts +2 -0
- package/dist/types/src/MarkdownViewer/index.d.ts.map +1 -0
- package/dist/types/src/index.d.ts +2 -0
- package/dist/types/src/index.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -0
- package/package.json +78 -0
- package/src/MarkdownViewer/MarkdownViewer.stories.tsx +75 -0
- package/src/MarkdownViewer/MarkdownViewer.tsx +95 -0
- package/src/MarkdownViewer/index.ts +5 -0
- package/src/index.ts +5 -0
- package/src/typings.d.ts +8 -0
package/package.json
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dxos/react-ui-markdown",
|
|
3
|
+
"version": "0.8.4-main.1068cf700f",
|
|
4
|
+
"description": "Markdown components.",
|
|
5
|
+
"homepage": "https://dxos.org",
|
|
6
|
+
"bugs": "https://github.com/dxos/dxos/issues",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/dxos/dxos"
|
|
10
|
+
},
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"author": "DXOS.org",
|
|
13
|
+
"type": "module",
|
|
14
|
+
"exports": {
|
|
15
|
+
".": {
|
|
16
|
+
"source": "./src/index.ts",
|
|
17
|
+
"types": "./dist/types/src/index.d.ts",
|
|
18
|
+
"browser": "./dist/lib/browser/index.mjs"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"types": "dist/types/src/index.d.ts",
|
|
22
|
+
"typesVersions": {
|
|
23
|
+
"*": {}
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"dist",
|
|
27
|
+
"src"
|
|
28
|
+
],
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"@codemirror/autocomplete": "^6.19.0",
|
|
31
|
+
"@codemirror/language": "^6.11.3",
|
|
32
|
+
"@codemirror/state": "^6.5.2",
|
|
33
|
+
"@codemirror/view": "^6.38.4",
|
|
34
|
+
"@lezer/common": "^1.2.2",
|
|
35
|
+
"@lezer/highlight": "^1.2.1",
|
|
36
|
+
"@lezer/markdown": "^1.3.1",
|
|
37
|
+
"@lezer/xml": "^1.0.6",
|
|
38
|
+
"@radix-ui/react-compose-refs": "1.1.1",
|
|
39
|
+
"@radix-ui/react-context": "1.1.1",
|
|
40
|
+
"effect": "3.19.16",
|
|
41
|
+
"json5": "^2.2.3",
|
|
42
|
+
"react-markdown": "^10.1.0",
|
|
43
|
+
"react-resize-detector": "^11.0.1",
|
|
44
|
+
"remark-gfm": "^4.0.1",
|
|
45
|
+
"@dxos/async": "0.8.4-main.1068cf700f",
|
|
46
|
+
"@dxos/echo": "0.8.4-main.1068cf700f",
|
|
47
|
+
"@dxos/invariant": "0.8.4-main.1068cf700f",
|
|
48
|
+
"@dxos/log": "0.8.4-main.1068cf700f",
|
|
49
|
+
"@dxos/react-ui-editor": "0.8.4-main.1068cf700f",
|
|
50
|
+
"@dxos/react-ui-syntax-highlighter": "0.8.4-main.1068cf700f",
|
|
51
|
+
"@dxos/util": "0.8.4-main.1068cf700f"
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@types/react": "~19.2.7",
|
|
55
|
+
"@types/react-dom": "~19.2.3",
|
|
56
|
+
"react": "~19.2.3",
|
|
57
|
+
"react-dom": "~19.2.3",
|
|
58
|
+
"vite": "7.1.9",
|
|
59
|
+
"@dxos/echo": "0.8.4-main.1068cf700f",
|
|
60
|
+
"@dxos/lit-ui": "0.8.4-main.1068cf700f",
|
|
61
|
+
"@dxos/random": "0.8.4-main.1068cf700f",
|
|
62
|
+
"@dxos/react-ui": "0.8.4-main.1068cf700f",
|
|
63
|
+
"@dxos/react-client": "0.8.4-main.1068cf700f",
|
|
64
|
+
"@dxos/schema": "0.8.4-main.1068cf700f",
|
|
65
|
+
"@dxos/storybook-utils": "0.8.4-main.1068cf700f",
|
|
66
|
+
"@dxos/ui-theme": "0.8.4-main.1068cf700f"
|
|
67
|
+
},
|
|
68
|
+
"peerDependencies": {
|
|
69
|
+
"effect": "3.19.16",
|
|
70
|
+
"react": "~19.2.3",
|
|
71
|
+
"react-dom": "~19.2.3",
|
|
72
|
+
"@dxos/react-ui": "0.8.4-main.1068cf700f",
|
|
73
|
+
"@dxos/ui-theme": "0.8.4-main.1068cf700f"
|
|
74
|
+
},
|
|
75
|
+
"publishConfig": {
|
|
76
|
+
"access": "public"
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
6
|
+
|
|
7
|
+
import { faker } from '@dxos/random';
|
|
8
|
+
import { withLayout, withTheme } from '@dxos/react-ui/testing';
|
|
9
|
+
import { trim } from '@dxos/util';
|
|
10
|
+
|
|
11
|
+
import { MarkdownViewer } from './MarkdownViewer';
|
|
12
|
+
|
|
13
|
+
faker.seed(0);
|
|
14
|
+
|
|
15
|
+
const meta = {
|
|
16
|
+
title: 'ui/react-ui-markdown/MarkdownViewer',
|
|
17
|
+
component: MarkdownViewer,
|
|
18
|
+
decorators: [withTheme(), withLayout({ layout: 'column' })],
|
|
19
|
+
} satisfies Meta<typeof MarkdownViewer>;
|
|
20
|
+
|
|
21
|
+
export default meta;
|
|
22
|
+
|
|
23
|
+
type Story = StoryObj<typeof MarkdownViewer>;
|
|
24
|
+
|
|
25
|
+
const content = trim`
|
|
26
|
+
# Hello World!
|
|
27
|
+
|
|
28
|
+
> An example of the MarkdownViewer component.
|
|
29
|
+
|
|
30
|
+
${faker.lorem.paragraphs(1)}
|
|
31
|
+
|
|
32
|
+
Here's a JSON block:
|
|
33
|
+
|
|
34
|
+
~~~json
|
|
35
|
+
{
|
|
36
|
+
"hello": "world"
|
|
37
|
+
}
|
|
38
|
+
~~~
|
|
39
|
+
|
|
40
|
+
And some code:
|
|
41
|
+
|
|
42
|
+
~~~tsx
|
|
43
|
+
import React from 'react'
|
|
44
|
+
|
|
45
|
+
const App = () => {
|
|
46
|
+
const title = 'Hello, world!'
|
|
47
|
+
return <div>{title}</div>
|
|
48
|
+
}
|
|
49
|
+
~~~
|
|
50
|
+
|
|
51
|
+
## Task lists
|
|
52
|
+
|
|
53
|
+
- [ ] Task one
|
|
54
|
+
- [x] Task two
|
|
55
|
+
- [ ] Task three
|
|
56
|
+
|
|
57
|
+
## Tables
|
|
58
|
+
|
|
59
|
+
| Column 1 | Column 2 | Column 3 |
|
|
60
|
+
| -------- | -------- | -------- |
|
|
61
|
+
| Cell 1 | Cell 2 | Cell 3 |
|
|
62
|
+
| Cell 4 | Cell 5 | Cell 6 |
|
|
63
|
+
| Cell 7 | Cell 8 | Cell 9 |
|
|
64
|
+
|
|
65
|
+
## Examples
|
|
66
|
+
|
|
67
|
+
${faker.lorem.paragraphs(1)}
|
|
68
|
+
`;
|
|
69
|
+
|
|
70
|
+
export const Default: Story = {
|
|
71
|
+
args: {
|
|
72
|
+
classNames: 'p-4 border border-border rounded-md overflow-y-auto bg-baseSurface',
|
|
73
|
+
content,
|
|
74
|
+
},
|
|
75
|
+
};
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React, { type PropsWithChildren } from 'react';
|
|
6
|
+
import ReactMarkdown, { type Options as ReactMarkdownOptions } from 'react-markdown';
|
|
7
|
+
import remarkGfm from 'remark-gfm';
|
|
8
|
+
|
|
9
|
+
import { type ThemedClassName } from '@dxos/react-ui';
|
|
10
|
+
import { SyntaxHighlighter } from '@dxos/react-ui-syntax-highlighter';
|
|
11
|
+
import { mx } from '@dxos/ui-theme';
|
|
12
|
+
|
|
13
|
+
export type MarkdownViewerProps = ThemedClassName<
|
|
14
|
+
PropsWithChildren<{
|
|
15
|
+
content?: string;
|
|
16
|
+
components?: ReactMarkdownOptions['components'];
|
|
17
|
+
}>
|
|
18
|
+
>;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Transforms markdown text into react elements.
|
|
22
|
+
* https://github.com/remarkjs/react-markdown
|
|
23
|
+
* markdown -> remark -> [mdast -> remark plugins] -> [hast -> rehype plugins] -> components -> react elements.
|
|
24
|
+
* Consider using @dxos/react-ui-editor.
|
|
25
|
+
*/
|
|
26
|
+
export const MarkdownViewer = ({ classNames, children, components, content = '' }: MarkdownViewerProps) => {
|
|
27
|
+
return (
|
|
28
|
+
<div className={mx(classNames)}>
|
|
29
|
+
<ReactMarkdown remarkPlugins={[remarkGfm]} skipHtml components={{ ...defaultComponents, ...components }}>
|
|
30
|
+
{content}
|
|
31
|
+
</ReactMarkdown>
|
|
32
|
+
{children}
|
|
33
|
+
</div>
|
|
34
|
+
);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const defaultComponents: ReactMarkdownOptions['components'] = {
|
|
38
|
+
h1: ({ children }) => {
|
|
39
|
+
return <h1 className='pbs-1 pbe-1 text-xl'>{children}</h1>;
|
|
40
|
+
},
|
|
41
|
+
h2: ({ children }) => {
|
|
42
|
+
return <h2 className='pbs-1 pbe-1 text-lg'>{children}</h2>;
|
|
43
|
+
},
|
|
44
|
+
h3: ({ children }) => {
|
|
45
|
+
return <h3 className='pbs-1 pbe-1 text-base'>{children}</h3>;
|
|
46
|
+
},
|
|
47
|
+
blockquote: ({ children, ...props }) => (
|
|
48
|
+
<blockquote className='pis-4 mbs-2 mbe-2 pbs-2 pbe-2 border-l-4 border-accentText text-accentText' {...props}>
|
|
49
|
+
{children}
|
|
50
|
+
</blockquote>
|
|
51
|
+
),
|
|
52
|
+
p: ({ children }) => {
|
|
53
|
+
return <div className='pbs-1 pbe-1'>{children}</div>;
|
|
54
|
+
},
|
|
55
|
+
a: ({ children, href, ...props }) => (
|
|
56
|
+
<a
|
|
57
|
+
href={href}
|
|
58
|
+
className='text-primary-500 hover:text-primary-500' // TODO(burdon): Use link token.
|
|
59
|
+
target='_blank'
|
|
60
|
+
rel='noopener noreferrer'
|
|
61
|
+
{...props}
|
|
62
|
+
>
|
|
63
|
+
{children}
|
|
64
|
+
</a>
|
|
65
|
+
),
|
|
66
|
+
ol: ({ children, ...props }) => (
|
|
67
|
+
<ol className='pbs-1 pbe-1 pis-6 leading-tight list-decimal' {...props}>
|
|
68
|
+
{children}
|
|
69
|
+
</ol>
|
|
70
|
+
),
|
|
71
|
+
ul: ({ children, ...props }) => (
|
|
72
|
+
<ul className='pbs-1 pbe-1 pis-6 leading-tight list-disc' {...props}>
|
|
73
|
+
{children}
|
|
74
|
+
</ul>
|
|
75
|
+
),
|
|
76
|
+
li: ({ children, ...props }) => (
|
|
77
|
+
<li className='' {...props}>
|
|
78
|
+
{children}
|
|
79
|
+
</li>
|
|
80
|
+
),
|
|
81
|
+
pre: ({ children }) => children,
|
|
82
|
+
// TODO(burdon): Copy/paste button.
|
|
83
|
+
code: ({ children, className }) => {
|
|
84
|
+
const [, language] = /language-(\w+)/.exec(className || '') || [];
|
|
85
|
+
return (
|
|
86
|
+
<SyntaxHighlighter
|
|
87
|
+
language={language}
|
|
88
|
+
classNames='mbs-2 mbe-2 border border-separator rounded-sm text-sm bg-groupSurface'
|
|
89
|
+
PreTag='pre'
|
|
90
|
+
>
|
|
91
|
+
{children}
|
|
92
|
+
</SyntaxHighlighter>
|
|
93
|
+
);
|
|
94
|
+
},
|
|
95
|
+
};
|
package/src/index.ts
ADDED