neo-md 1.0.0
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 +21 -0
- package/README.md +142 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.js +10910 -0
- package/dist/index.umd.cjs +62 -0
- package/dist/neo-md.css +1 -0
- package/dist/vite.svg +1 -0
- package/package.json +65 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Atharv Dange
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# React Markdown Editor
|
|
2
|
+
|
|
3
|
+
A modern, highly-configurable, and highly-secure React markdown editor component. Built with React and Tailwind CSS, it provides dual-pane live preview capabilities, syntax highlighting, and an extensive Props API for controlled or uncontrolled states.
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **XSS Prevention** - Raw HTML rendering in the editor pane is secured via `isomorphic-dompurify`.
|
|
10
|
+
- **Controlled & Uncontrolled Support** - Plug it into external state naturally like a standard input element, or let it manage its own.
|
|
11
|
+
- **Deep Customizability** - Apply your own `className` structures mapping to the editor pane, preview pane, and toolbar.
|
|
12
|
+
- **Ref Forwarding** - Programmatically trigger focus or grab values using `useImperativeHandle` and `forwardRef`.
|
|
13
|
+
- **Custom Renderers** - Inject your own custom React components directly into the `react-markdown` DOM rendering pipeline.
|
|
14
|
+
- **Live Preview** - Real-time rendering of markdown content with scroll tracking sync.
|
|
15
|
+
- **Dark Mode Support** - Built-in Tailwind themeing compatible with system preferences.
|
|
16
|
+
|
|
17
|
+
## Demo
|
|
18
|
+
|
|
19
|
+
[Live Demo](https://your-demo-link.vercel.app)
|
|
20
|
+
|
|
21
|
+
## Installation
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm install neo-md
|
|
25
|
+
# or
|
|
26
|
+
yarn add neo-md
|
|
27
|
+
# or
|
|
28
|
+
pnpm add neo-md
|
|
29
|
+
# or
|
|
30
|
+
bun add neo-md
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
You must also have `react` and `react-dom` installed as they are peer dependencies.
|
|
34
|
+
|
|
35
|
+
## Usage
|
|
36
|
+
|
|
37
|
+
### Basic Implementation (Uncontrolled)
|
|
38
|
+
|
|
39
|
+
By default, the editor works out of the box with zero configuration necessary.
|
|
40
|
+
|
|
41
|
+
```tsx
|
|
42
|
+
import { MarkdownEditor } from "neo-md";
|
|
43
|
+
|
|
44
|
+
// Important: import the CSS!
|
|
45
|
+
import "neo-md/react-markdown-editor.css";
|
|
46
|
+
|
|
47
|
+
function App() {
|
|
48
|
+
return (
|
|
49
|
+
<div className="h-screen py-8">
|
|
50
|
+
<MarkdownEditor />
|
|
51
|
+
</div>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Advanced Implementation (Controlled)
|
|
57
|
+
|
|
58
|
+
Control the text value, track the current pane view mode, and alter the default toolbar state using the rich Props API.
|
|
59
|
+
|
|
60
|
+
```tsx
|
|
61
|
+
import { useState, useRef } from "react";
|
|
62
|
+
import { MarkdownEditor, MarkdownEditorRef } from "neo-md";
|
|
63
|
+
import "neo-md/react-markdown-editor.css";
|
|
64
|
+
|
|
65
|
+
function App() {
|
|
66
|
+
const [markdown, setMarkdown] = useState("# Initial Text");
|
|
67
|
+
const [view, setView] = useState<"edit" | "preview" | "split">("split");
|
|
68
|
+
const editorRef = useRef<MarkdownEditorRef>(null);
|
|
69
|
+
|
|
70
|
+
const focusEditor = () => editorRef.current?.focus();
|
|
71
|
+
|
|
72
|
+
const customRenderers = {
|
|
73
|
+
h1: ({ children }) => (
|
|
74
|
+
<h1 className="text-4xl text-blue-500">{children}</h1>
|
|
75
|
+
),
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
return (
|
|
79
|
+
<div className="h-screen py-8">
|
|
80
|
+
<button onClick={focusEditor}>Focus Textarea</button>
|
|
81
|
+
|
|
82
|
+
<MarkdownEditor
|
|
83
|
+
ref={editorRef}
|
|
84
|
+
value={markdown}
|
|
85
|
+
onChange={setMarkdown}
|
|
86
|
+
viewMode={view}
|
|
87
|
+
onViewModeChange={setView}
|
|
88
|
+
components={customRenderers}
|
|
89
|
+
hideWordCount={true}
|
|
90
|
+
enableCopy={false}
|
|
91
|
+
className="my-custom-wrapper"
|
|
92
|
+
placeholder="Type something amazing..."
|
|
93
|
+
/>
|
|
94
|
+
</div>
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## API Reference
|
|
100
|
+
|
|
101
|
+
The `MarkdownEditor` component accepts the following props:
|
|
102
|
+
|
|
103
|
+
| Prop | Type | Default | Description |
|
|
104
|
+
| ------------------ | -------------------------------- | -------------------- | -------------------------------------------------- |
|
|
105
|
+
| `value` | `string` | `undefined` | The controlled markdown text. |
|
|
106
|
+
| `defaultValue` | `string` | `(default template)` | Initial text for uncontrolled mode. |
|
|
107
|
+
| `onChange` | `(value: string) => void` | `undefined` | Callback fired when text changes. |
|
|
108
|
+
| `viewMode` | `"edit" \| "preview" \| "split"` | `undefined` | The controlled view mode. |
|
|
109
|
+
| `defaultViewMode` | `"edit" \| "preview" \| "split"` | `"split"` | Initial view mode for uncontrolled mode. |
|
|
110
|
+
| `onViewModeChange` | `(mode) => void` | `undefined` | Callback fired when a toolbar tab is clicked. |
|
|
111
|
+
| `className` | `string` | `""` | Classes applied to the root container. |
|
|
112
|
+
| `editorClassName` | `string` | `""` | Classes applied to the editor pane wrapper. |
|
|
113
|
+
| `previewClassName` | `string` | `""` | Classes applied to the preview pane wrapper. |
|
|
114
|
+
| `hideToolbar` | `boolean` | `false` | Completely removes the top toolbar block. |
|
|
115
|
+
| `hideWordCount` | `boolean` | `false` | Hides the character counter badge. |
|
|
116
|
+
| `enableDownload` | `boolean` | `true` | Toggles the exact "Download" button. |
|
|
117
|
+
| `enableCopy` | `boolean` | `true` | Toggles the exact "Copy" button. |
|
|
118
|
+
| `placeholder` | `string` | `"Start typing..."` | Textbox placeholder text. |
|
|
119
|
+
| `readOnly` | `boolean` | `false` | Disables text input while retaining interactions. |
|
|
120
|
+
| `maxLength` | `number` | `undefined` | Hard cap on textarea character length. |
|
|
121
|
+
| `components` | `Components` | `{}` | Complete `react-markdown` DOM rendering overrides. |
|
|
122
|
+
|
|
123
|
+
## Exposed Methods (`MarkdownEditorRef`)
|
|
124
|
+
|
|
125
|
+
Via `forwardRef`, parents can trigger the following imperatives on the editor:
|
|
126
|
+
|
|
127
|
+
- `focus()`: Forces browser focus onto the underlying `<textarea>`.
|
|
128
|
+
- `getValue()`: Retrieves the current internal markdown string, particularly useful if you run uncontrolled mode and just want the value on submit.
|
|
129
|
+
|
|
130
|
+
## Contributing
|
|
131
|
+
|
|
132
|
+
Contributions are welcome. Please feel free to submit a Pull Request.
|
|
133
|
+
|
|
134
|
+
1. Fork the project
|
|
135
|
+
2. Create your feature branch (`git checkout -b feature/Enhancement`)
|
|
136
|
+
3. Commit your changes (`git commit -m 'Add some Enhancement'`)
|
|
137
|
+
4. Push to the branch (`git push origin feature/Enhancement`)
|
|
138
|
+
5. Open a Pull Request
|
|
139
|
+
|
|
140
|
+
## License
|
|
141
|
+
|
|
142
|
+
This project is licensed under the [MIT License](LICENSE).
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Components } from 'react-markdown';
|
|
2
|
+
import { default as default_2 } from 'react';
|
|
3
|
+
|
|
4
|
+
export declare const MarkdownEditor: default_2.ForwardRefExoticComponent<MarkdownEditorProps & default_2.RefAttributes<MarkdownEditorRef>>;
|
|
5
|
+
|
|
6
|
+
export declare interface MarkdownEditorProps {
|
|
7
|
+
value?: string;
|
|
8
|
+
defaultValue?: string;
|
|
9
|
+
onChange?: (value: string) => void;
|
|
10
|
+
viewMode?: "edit" | "preview" | "split";
|
|
11
|
+
defaultViewMode?: "edit" | "preview" | "split";
|
|
12
|
+
onViewModeChange?: (mode: "edit" | "preview" | "split") => void;
|
|
13
|
+
className?: string;
|
|
14
|
+
editorClassName?: string;
|
|
15
|
+
previewClassName?: string;
|
|
16
|
+
hideToolbar?: boolean;
|
|
17
|
+
hideWordCount?: boolean;
|
|
18
|
+
enableDownload?: boolean;
|
|
19
|
+
enableCopy?: boolean;
|
|
20
|
+
placeholder?: string;
|
|
21
|
+
readOnly?: boolean;
|
|
22
|
+
maxLength?: number;
|
|
23
|
+
components?: Components;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export declare interface MarkdownEditorRef {
|
|
27
|
+
focus: () => void;
|
|
28
|
+
getValue: () => string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export { }
|