@powerduck/md-editor 0.10.6 → 0.10.8
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 +136 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -22,7 +22,6 @@ High-performance embeddable Markdown editor built on the markdown-it ecosystem.
|
|
|
22
22
|
- **Simple / Complex modes** -- toggle toolbar and status bar at runtime
|
|
23
23
|
- **Light / Dark themes** -- CSS custom properties, inherits host design tokens
|
|
24
24
|
- **React component** -- `forwardRef` with imperative handle
|
|
25
|
-
- **Zero Chinese** -- all code, comments, and UI strings in American English
|
|
26
25
|
|
|
27
26
|
## Installation
|
|
28
27
|
|
|
@@ -245,6 +244,142 @@ npm test # run all tests (vitest + jsdom)
|
|
|
245
244
|
npm run build # vite build + d.ts generation
|
|
246
245
|
```
|
|
247
246
|
|
|
247
|
+
## React Demo
|
|
248
|
+
```jsx
|
|
249
|
+
import { useRef, useCallback } from "react";
|
|
250
|
+
import { type MentionItem, type DocItem } from "@powerduck/md-editor";
|
|
251
|
+
import {
|
|
252
|
+
MarkdownEditorReact,
|
|
253
|
+
type MarkdownEditorHandle,
|
|
254
|
+
} from "@powerduck/md-editor/react";
|
|
255
|
+
import "@powerduck/md-editor/dist/style.css";
|
|
256
|
+
|
|
257
|
+
const USERS: MentionItem[] = [
|
|
258
|
+
{
|
|
259
|
+
id: "1",
|
|
260
|
+
label: "Alice",
|
|
261
|
+
avatar: "https://i.pravatar.cc/40?u=alice",
|
|
262
|
+
description: "alice@example.com",
|
|
263
|
+
},
|
|
264
|
+
{
|
|
265
|
+
id: "2",
|
|
266
|
+
label: "Bob",
|
|
267
|
+
avatar: "https://i.pravatar.cc/40?u=bob",
|
|
268
|
+
description: "bob@example.com",
|
|
269
|
+
},
|
|
270
|
+
{ id: "3", label: "Charlie", description: "charlie@example.com" },
|
|
271
|
+
];
|
|
272
|
+
|
|
273
|
+
const DOCS: DocItem[] = [
|
|
274
|
+
{
|
|
275
|
+
id: "d1",
|
|
276
|
+
title: "Getting Started",
|
|
277
|
+
url: "https://docs.example.com/start",
|
|
278
|
+
description: "Quick start guide",
|
|
279
|
+
thumbnail: "https://picsum.photos/seed/start/96/72",
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
id: "d2",
|
|
283
|
+
title: "API Reference",
|
|
284
|
+
url: "https://docs.example.com/api",
|
|
285
|
+
description: "Full API documentation",
|
|
286
|
+
},
|
|
287
|
+
{
|
|
288
|
+
id: "d3",
|
|
289
|
+
title: "Changelog",
|
|
290
|
+
url: "https://docs.example.com/changelog",
|
|
291
|
+
description: "Release notes",
|
|
292
|
+
},
|
|
293
|
+
];
|
|
294
|
+
|
|
295
|
+
function App() {
|
|
296
|
+
const editorRef = useRef<MarkdownEditorHandle>(null);
|
|
297
|
+
|
|
298
|
+
const handleSave = useCallback(() => {
|
|
299
|
+
const markdown = editorRef.current?.getValue() ?? "";
|
|
300
|
+
console.log("Saving:", markdown);
|
|
301
|
+
}, []);
|
|
302
|
+
|
|
303
|
+
// Stable callbacks so the editor does not recreate on every render
|
|
304
|
+
const searchUsers = useCallback(async (query: string) => {
|
|
305
|
+
return USERS.filter((u) =>
|
|
306
|
+
u.label.toLowerCase().includes(query.toLowerCase()),
|
|
307
|
+
);
|
|
308
|
+
}, []);
|
|
309
|
+
|
|
310
|
+
const searchDocs = useCallback(async (query: string) => {
|
|
311
|
+
return DOCS.filter((d) =>
|
|
312
|
+
d.title.toLowerCase().includes(query.toLowerCase()),
|
|
313
|
+
);
|
|
314
|
+
}, []);
|
|
315
|
+
|
|
316
|
+
const fetchDocMeta = useCallback(async (url: string) => {
|
|
317
|
+
// In production, route through your backend to avoid CORS:
|
|
318
|
+
// const res = await fetch(`/api/og?url=${encodeURIComponent(url)}`);
|
|
319
|
+
// return res.json();
|
|
320
|
+
// For demo: return whatever metadata the item already has
|
|
321
|
+
const doc = DOCS.find((d) => d.url === url);
|
|
322
|
+
return {
|
|
323
|
+
title: doc?.title ?? new URL(url).hostname,
|
|
324
|
+
description: doc?.description,
|
|
325
|
+
thumbnail: doc?.thumbnail,
|
|
326
|
+
url,
|
|
327
|
+
};
|
|
328
|
+
}, []);
|
|
329
|
+
|
|
330
|
+
return (
|
|
331
|
+
<div style={{ padding: 24, maxWidth: 1100, margin: "0 auto" }}>
|
|
332
|
+
<div style={{ marginBottom: 12, display: "flex", gap: 8 }}>
|
|
333
|
+
<button onClick={handleSave}>Save</button>
|
|
334
|
+
<button onClick={() => editorRef.current?.setTheme("dark")}>
|
|
335
|
+
Dark
|
|
336
|
+
</button>
|
|
337
|
+
<button onClick={() => editorRef.current?.setTheme("light")}>
|
|
338
|
+
Light
|
|
339
|
+
</button>
|
|
340
|
+
</div>
|
|
341
|
+
|
|
342
|
+
<MarkdownEditorReact
|
|
343
|
+
ref={editorRef}
|
|
344
|
+
defaultValue={[
|
|
345
|
+
"# Welcome",
|
|
346
|
+
"",
|
|
347
|
+
"Type **@** to mention a user, or **/** to insert a document link.",
|
|
348
|
+
"",
|
|
349
|
+
"## Task list",
|
|
350
|
+
"- [ ] This is checked (green)",
|
|
351
|
+
"- [x] This is unchecked",
|
|
352
|
+
"- [ x] Spaces inside brackets also work",
|
|
353
|
+
"",
|
|
354
|
+
"## Table",
|
|
355
|
+
"| Name | Role |",
|
|
356
|
+
"|------|------|",
|
|
357
|
+
"| Alice | Admin |",
|
|
358
|
+
"| Bob | Editor |",
|
|
359
|
+
].join("\n")}
|
|
360
|
+
mode="complex"
|
|
361
|
+
theme="light"
|
|
362
|
+
onChange={(v) => console.log("auto-save:", v.length)}
|
|
363
|
+
mention={{
|
|
364
|
+
onMentionSearch: searchUsers,
|
|
365
|
+
minChars: 0,
|
|
366
|
+
maxItems: 8,
|
|
367
|
+
}}
|
|
368
|
+
docLink={{
|
|
369
|
+
onDocSearch: searchDocs,
|
|
370
|
+
onFetchDocMeta: fetchDocMeta,
|
|
371
|
+
insertStyle: "auto",
|
|
372
|
+
minChars: 0,
|
|
373
|
+
maxItems: 8,
|
|
374
|
+
}}
|
|
375
|
+
/>
|
|
376
|
+
</div>
|
|
377
|
+
);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
export default App;
|
|
381
|
+
```
|
|
382
|
+
|
|
248
383
|
## Changelog
|
|
249
384
|
|
|
250
385
|
### v0.8.4
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@powerduck/md-editor",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.8",
|
|
4
4
|
"description": "High-performance embeddable Markdown editor: KaTeX math, Markmap mindmaps, highlight.js code blocks with copy button, github-markdown-css preview, admonition blocks, rich toolbar with image/video/YouTube/table popups, keyboard shortcuts, configurable toolbar, image upload hook, standalone renderMarkdown API, React component, block-level incremental rendering. Simple and complex modes, light/dark themes.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.cjs",
|