@discord/markdown-react 0.1.1
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/README.md +36 -0
- package/dist/src/index.js +1 -0
- package/package.json +35 -0
- package/src/index.d.ts +116 -0
package/README.md
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# @discord/markdown-react
|
|
2
|
+
|
|
3
|
+
## Prerequisites
|
|
4
|
+
|
|
5
|
+
- Build WASM module
|
|
6
|
+
|
|
7
|
+
## Build
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
pnpm build
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
```js
|
|
16
|
+
import Markdown from '@discord/markdown-react';
|
|
17
|
+
|
|
18
|
+
function Text({ children }) {
|
|
19
|
+
return <span>{children}</span>;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function Paragraph({ children }) {
|
|
23
|
+
return <span>{children}</span>;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const renderers = {
|
|
27
|
+
text: Text,
|
|
28
|
+
paragraph: Paragraph,
|
|
29
|
+
quote: Quote,
|
|
30
|
+
...otherRenderers, // define renderers for other node types
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export function MyMarkdown({ content }) {
|
|
34
|
+
return <Markdown content={content} renderers={renderers} />;
|
|
35
|
+
}
|
|
36
|
+
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{parse as e}from"@discord/markdown-wasm";import*as t from"react";import{memo as r,useMemo as n}from"react";function l(e,t){if(null==e)throw Error(`Attempted to render "${t}" but no renderer was provided`)}export const RULES=new Set(["bold","italic","underline","strikethrough","spoiler","emoji","timestamp","mention","link","code","code_block","heading","list","quote","small"]);export function Node({node:e,renderers:r}){let n=r[e.type];if(l(n,e.type),Array.isArray(e.value))return t.createElement(n,null,t.createElement(NodeList,{nodes:e.value,renderers:r}));switch(e.type){case"mention":case"timestamp":case"emoji":case"code_block":return t.createElement(n,e.value);case"link":let a=e.value,o=null;if("normal"===a.type){let{value:{text:e,url:n}}=a;o=e?t.createElement(NodeList,{nodes:e,renderers:r}):n}return t.createElement(n,e.value,o);case"quote":let s=r.paragraph;return l(s,"paragraph"),t.createElement(n,null,e.value.lines.map((e,n)=>t.createElement(s,{key:n,value:e,renderers:r},t.createElement(NodeList,{nodes:e,renderers:r}))));case"text":case"code":return t.createElement(n,null,e.value);case"heading":return t.createElement(n,{level:e.value.level},t.createElement(NodeList,{nodes:e.value.content,renderers:r}));case"list":let c=r.listItem??"li";return t.createElement(n,e.value,e.value.items.map((e,n)=>t.createElement(c,{key:n},t.createElement(NodeList,{nodes:e.content,renderers:r}))));case"empty":return t.createElement(n,null);case"small":return t.createElement(n,null,t.createElement(NodeList,{nodes:e.value.content,renderers:r}));default:throw TypeError(`Unknown node type "${e.type}"`)}}export const NodeList=r(function({nodes:e,renderers:r}){return t.createElement(t.Fragment,null,e.map((e,n)=>t.createElement(Node,{key:n,node:e,renderers:r})))});export default function a({content:r,renderers:l}){let a=n(()=>{let e=Object.keys(l).filter(e=>RULES.has(e));return e.length>0?e:null},[l]),o=n(()=>e(r,a),[r,a]);return t.createElement(NodeList,{nodes:o,renderers:l})}
|
package/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@discord/markdown-react",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "React library for parsing and rendering Discord Markdown",
|
|
6
|
+
"main": "dist/src/index.js",
|
|
7
|
+
"types": "src/index.d.ts",
|
|
8
|
+
"scripts": {
|
|
9
|
+
"test": "vitest run",
|
|
10
|
+
"build": "swc src/index.jsx -d dist"
|
|
11
|
+
},
|
|
12
|
+
"keywords": [],
|
|
13
|
+
"author": "Will Nelson",
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"files": [
|
|
16
|
+
"dist/src/index.js",
|
|
17
|
+
"src/index.d.ts"
|
|
18
|
+
],
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"@discord/markdown-wasm": "workspace:*",
|
|
21
|
+
"react": "^18.3.1"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@discord/markdown-types": "workspace:*",
|
|
25
|
+
"@swc/cli": "^0.5.2",
|
|
26
|
+
"@swc/core": "^1.10.1",
|
|
27
|
+
"@testing-library/jest-dom": "^6.4.8",
|
|
28
|
+
"@testing-library/react": "^16.0.0",
|
|
29
|
+
"@types/react": "^18",
|
|
30
|
+
"jsdom": "^24.1.1",
|
|
31
|
+
"vite": "^5.4.0",
|
|
32
|
+
"vite-plugin-wasm": "^3.3.0",
|
|
33
|
+
"vitest": "^2.0.3"
|
|
34
|
+
}
|
|
35
|
+
}
|
package/src/index.d.ts
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import {
|
|
3
|
+
Node,
|
|
4
|
+
AnyNode,
|
|
5
|
+
CodeBlock,
|
|
6
|
+
Emoji,
|
|
7
|
+
Timestamp,
|
|
8
|
+
Mention,
|
|
9
|
+
Link,
|
|
10
|
+
List,
|
|
11
|
+
} from "@discord/markdown-types";
|
|
12
|
+
|
|
13
|
+
type NodeRenderProps<P = {}> = React.PropsWithChildren<P>;
|
|
14
|
+
|
|
15
|
+
// inline
|
|
16
|
+
export type BoldProps = NodeRenderProps;
|
|
17
|
+
export type ItalicProps = NodeRenderProps;
|
|
18
|
+
export type UnderlineProps = NodeRenderProps;
|
|
19
|
+
export type StrikethroughProps = NodeRenderProps;
|
|
20
|
+
export type SpoilerProps = NodeRenderProps;
|
|
21
|
+
export type EmojiProps = Emoji["value"];
|
|
22
|
+
export type TimestampProps = Timestamp["value"];
|
|
23
|
+
export type MentionProps = Mention["value"];
|
|
24
|
+
export type LinkProps = NodeRenderProps<Link["value"]>;
|
|
25
|
+
export type CodeProps = NodeRenderProps;
|
|
26
|
+
export type CodeBlockProps = CodeBlock["value"];
|
|
27
|
+
|
|
28
|
+
export type InlineProps =
|
|
29
|
+
| BoldProps
|
|
30
|
+
| ItalicProps
|
|
31
|
+
| UnderlineProps
|
|
32
|
+
| StrikethroughProps
|
|
33
|
+
| SpoilerProps
|
|
34
|
+
| EmojiProps
|
|
35
|
+
| TimestampProps
|
|
36
|
+
| MentionProps
|
|
37
|
+
| LinkProps
|
|
38
|
+
| CodeProps
|
|
39
|
+
| CodeBlockProps;
|
|
40
|
+
|
|
41
|
+
// block
|
|
42
|
+
export type HeadingProps = NodeRenderProps<{ level: 1 | 2 | 3 }>;
|
|
43
|
+
export type ListProps = NodeRenderProps<List["value"]>;
|
|
44
|
+
export type QuoteProps = NodeRenderProps;
|
|
45
|
+
export type SmallProps = NodeRenderProps;
|
|
46
|
+
|
|
47
|
+
export type BlockProps = HeadingProps | ListProps | QuoteProps | SmallProps;
|
|
48
|
+
|
|
49
|
+
// top-level
|
|
50
|
+
export type TextProps = NodeRenderProps;
|
|
51
|
+
export type ParagraphProps = NodeRenderProps;
|
|
52
|
+
export type EmptyProps = {};
|
|
53
|
+
export type ListItemProps = NodeRenderProps;
|
|
54
|
+
|
|
55
|
+
export type TopLevelProps =
|
|
56
|
+
| TextProps
|
|
57
|
+
| ParagraphProps
|
|
58
|
+
| EmptyProps
|
|
59
|
+
| ListItemProps;
|
|
60
|
+
|
|
61
|
+
export type AllProps = InlineProps | BlockProps | TopLevelProps;
|
|
62
|
+
|
|
63
|
+
export type RendererProps = {
|
|
64
|
+
// inline
|
|
65
|
+
bold: BoldProps;
|
|
66
|
+
italic: ItalicProps;
|
|
67
|
+
underline: UnderlineProps;
|
|
68
|
+
strikethrough: StrikethroughProps;
|
|
69
|
+
spoiler: SpoilerProps;
|
|
70
|
+
emoji: EmojiProps;
|
|
71
|
+
timestamp: TimestampProps;
|
|
72
|
+
mention: MentionProps;
|
|
73
|
+
link: LinkProps;
|
|
74
|
+
code: CodeProps;
|
|
75
|
+
code_block: CodeBlockProps;
|
|
76
|
+
|
|
77
|
+
// block
|
|
78
|
+
heading: HeadingProps;
|
|
79
|
+
list: ListProps;
|
|
80
|
+
quote: QuoteProps;
|
|
81
|
+
small: SmallProps;
|
|
82
|
+
|
|
83
|
+
// top-level
|
|
84
|
+
text: TextProps;
|
|
85
|
+
paragraph: ParagraphProps;
|
|
86
|
+
empty: EmptyProps;
|
|
87
|
+
|
|
88
|
+
// pseudo
|
|
89
|
+
listItem: ListItemProps;
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
export type Renderers = {
|
|
93
|
+
readonly [K in keyof RendererProps]?: React.FC<RendererProps[K]>;
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
export type NodeProps = {
|
|
97
|
+
node: AnyNode;
|
|
98
|
+
renderers: Renderers;
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
export type NodeListProps = {
|
|
102
|
+
nodes: AnyNode[];
|
|
103
|
+
renderers: Renderers;
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
export type MarkdownProps = {
|
|
107
|
+
content: string;
|
|
108
|
+
renderers: Renderers;
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
export const INLINE_RULES: string[];
|
|
112
|
+
export const BLOCK_RULES: string[];
|
|
113
|
+
|
|
114
|
+
export function Node(props: NodeProps): React.ReactNode;
|
|
115
|
+
export function NodeList(props: NodeListProps): React.ReactNode;
|
|
116
|
+
export default function Markdown(props: MarkdownProps): React.ReactNode;
|