md-editor-lite 0.1.13 → 0.1.15
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/dist/index.mjs +104 -78
- package/package.json +1 -1
- package/dist/index.js +0 -405
package/dist/index.mjs
CHANGED
|
@@ -1,36 +1,45 @@
|
|
|
1
1
|
// src/components/EditorHeader.tsx
|
|
2
2
|
import "./style.css";
|
|
3
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
4
|
function EditorHeader({
|
|
4
5
|
mode,
|
|
5
6
|
setMode,
|
|
6
7
|
insertMarkdown
|
|
7
8
|
}) {
|
|
8
|
-
return /* @__PURE__ */
|
|
9
|
+
return /* @__PURE__ */ jsxs("header", { className: "editor-header", children: [
|
|
10
|
+
/* @__PURE__ */ jsx(EditorTab, { mode, setMode }),
|
|
11
|
+
mode === "write" && /* @__PURE__ */ jsx(Toolbar, { insertMarkdown })
|
|
12
|
+
] });
|
|
9
13
|
}
|
|
10
14
|
|
|
11
15
|
// src/components/EditorTab.tsx
|
|
12
16
|
import "./style.css";
|
|
17
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
13
18
|
function EditorTab({ mode, setMode }) {
|
|
14
|
-
return /* @__PURE__ */
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
19
|
+
return /* @__PURE__ */ jsxs2("div", { className: "editor-tab-container", children: [
|
|
20
|
+
/* @__PURE__ */ jsx2(
|
|
21
|
+
"div",
|
|
22
|
+
{
|
|
23
|
+
className: `editor-tab ${mode === "write" ? "editor-tab--active" : ""}`,
|
|
24
|
+
onClick: () => setMode("write"),
|
|
25
|
+
children: "Write"
|
|
26
|
+
}
|
|
27
|
+
),
|
|
28
|
+
/* @__PURE__ */ jsx2(
|
|
29
|
+
"div",
|
|
30
|
+
{
|
|
31
|
+
className: `editor-tab ${mode === "preview" ? "editor-tab--active" : ""}`,
|
|
32
|
+
onClick: () => setMode("preview"),
|
|
33
|
+
children: "Preview"
|
|
34
|
+
}
|
|
35
|
+
)
|
|
36
|
+
] });
|
|
29
37
|
}
|
|
30
38
|
|
|
31
39
|
// src/components/EditorTextarea.tsx
|
|
32
40
|
import { forwardRef } from "react";
|
|
33
41
|
import "./style.css";
|
|
42
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
34
43
|
var EditorTextarea = forwardRef(({ value, placeholder, setValue, onImageUpload }, ref) => {
|
|
35
44
|
const handleDrop = async (e) => {
|
|
36
45
|
e.preventDefault();
|
|
@@ -45,7 +54,7 @@ var EditorTextarea = forwardRef(({ value, placeholder, setValue, onImageUpload }
|
|
|
45
54
|
`);
|
|
46
55
|
}
|
|
47
56
|
};
|
|
48
|
-
return /* @__PURE__ */
|
|
57
|
+
return /* @__PURE__ */ jsx3(
|
|
49
58
|
"textarea",
|
|
50
59
|
{
|
|
51
60
|
ref,
|
|
@@ -93,6 +102,7 @@ function useMarkdownEditor({ value, setValue }) {
|
|
|
93
102
|
|
|
94
103
|
// src/components/MarkdownEditor.tsx
|
|
95
104
|
import "./style.css";
|
|
105
|
+
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
96
106
|
function MarkdownEditor({
|
|
97
107
|
value,
|
|
98
108
|
onChange: setValue,
|
|
@@ -103,22 +113,25 @@ function MarkdownEditor({
|
|
|
103
113
|
setValue
|
|
104
114
|
});
|
|
105
115
|
const [mode, setMode] = useState("write");
|
|
106
|
-
return /* @__PURE__ */
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
116
|
+
return /* @__PURE__ */ jsxs3("div", { className: "editor", children: [
|
|
117
|
+
/* @__PURE__ */ jsx4(
|
|
118
|
+
EditorHeader,
|
|
119
|
+
{
|
|
120
|
+
mode,
|
|
121
|
+
setMode,
|
|
122
|
+
insertMarkdown
|
|
123
|
+
}
|
|
124
|
+
),
|
|
125
|
+
mode === "write" ? /* @__PURE__ */ jsx4(
|
|
126
|
+
EditorTextarea,
|
|
127
|
+
{
|
|
128
|
+
ref: textareaRef,
|
|
129
|
+
value,
|
|
130
|
+
setValue,
|
|
131
|
+
onImageUpload
|
|
132
|
+
}
|
|
133
|
+
) : /* @__PURE__ */ jsx4(Preview, { value })
|
|
134
|
+
] });
|
|
122
135
|
}
|
|
123
136
|
|
|
124
137
|
// src/utils/markdown.ts
|
|
@@ -199,8 +212,9 @@ function markdownToHtml(markdown) {
|
|
|
199
212
|
|
|
200
213
|
// src/components/Preview.tsx
|
|
201
214
|
import "./style.css";
|
|
215
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
202
216
|
function Preview({ value }) {
|
|
203
|
-
return /* @__PURE__ */
|
|
217
|
+
return /* @__PURE__ */ jsx5(
|
|
204
218
|
"div",
|
|
205
219
|
{
|
|
206
220
|
className: "preview",
|
|
@@ -248,20 +262,25 @@ var listOptions = [
|
|
|
248
262
|
|
|
249
263
|
// src/components/Toolbar.tsx
|
|
250
264
|
import "./style.css";
|
|
265
|
+
import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
251
266
|
function Toolbar({ insertMarkdown }) {
|
|
252
|
-
return /* @__PURE__ */
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
267
|
+
return /* @__PURE__ */ jsxs4("menu", { className: "toolbar-menu", children: [
|
|
268
|
+
TOOLBAR_BUTTONS.map(({ key, before, after, Icon }) => /* @__PURE__ */ jsx6(
|
|
269
|
+
"button",
|
|
270
|
+
{
|
|
271
|
+
className: "toolbar-button",
|
|
272
|
+
onClick: () => insertMarkdown(before, after),
|
|
273
|
+
children: /* @__PURE__ */ jsx6(Icon, { size: 18 })
|
|
274
|
+
},
|
|
275
|
+
key
|
|
276
|
+
)),
|
|
277
|
+
/* @__PURE__ */ jsx6(ToolbarDropdownHeading, { insertMarkdown }),
|
|
278
|
+
/* @__PURE__ */ jsx6(ToolbarDropdownList, { insertMarkdown })
|
|
279
|
+
] });
|
|
261
280
|
}
|
|
262
281
|
|
|
263
282
|
// src/components/IconDropdown.tsx
|
|
264
|
-
import
|
|
283
|
+
import React from "react";
|
|
265
284
|
|
|
266
285
|
// src/utils/cx.ts
|
|
267
286
|
function cx(...classes) {
|
|
@@ -270,6 +289,7 @@ function cx(...classes) {
|
|
|
270
289
|
|
|
271
290
|
// src/components/IconDropdown.tsx
|
|
272
291
|
import "./style.css";
|
|
292
|
+
import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
273
293
|
function IconDropdown({
|
|
274
294
|
className,
|
|
275
295
|
disabled,
|
|
@@ -278,12 +298,12 @@ function IconDropdown({
|
|
|
278
298
|
triggerIcon,
|
|
279
299
|
onChange
|
|
280
300
|
}) {
|
|
281
|
-
const [isOpen, setIsOpen] =
|
|
282
|
-
const dropdownRef =
|
|
301
|
+
const [isOpen, setIsOpen] = React.useState(false);
|
|
302
|
+
const dropdownRef = React.useRef(null);
|
|
283
303
|
const toggle = () => {
|
|
284
304
|
if (!disabled) setIsOpen((prev) => !prev);
|
|
285
305
|
};
|
|
286
|
-
|
|
306
|
+
React.useEffect(() => {
|
|
287
307
|
const handleClickOutside = (e) => {
|
|
288
308
|
if (dropdownRef.current && !dropdownRef.current.contains(e.target)) {
|
|
289
309
|
setIsOpen(false);
|
|
@@ -292,46 +312,52 @@ function IconDropdown({
|
|
|
292
312
|
document.addEventListener("mousedown", handleClickOutside);
|
|
293
313
|
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
294
314
|
}, []);
|
|
295
|
-
return /* @__PURE__ */
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
), isOpen && /* @__PURE__ */ React2.createElement("ul", { className: "md-dropdown__menu" }, options.map((option) => /* @__PURE__ */ React2.createElement(
|
|
308
|
-
"li",
|
|
309
|
-
{
|
|
310
|
-
key: option.value,
|
|
311
|
-
className: cx(
|
|
312
|
-
"md-dropdown__item",
|
|
313
|
-
selected && "md-dropdown__item--selected"
|
|
314
|
-
),
|
|
315
|
-
onClick: () => {
|
|
316
|
-
onChange(option.value);
|
|
317
|
-
setIsOpen(false);
|
|
315
|
+
return /* @__PURE__ */ jsxs5("div", { ref: dropdownRef, className: cx("md-dropdown", className), children: [
|
|
316
|
+
/* @__PURE__ */ jsx7(
|
|
317
|
+
"button",
|
|
318
|
+
{
|
|
319
|
+
type: "button",
|
|
320
|
+
onClick: toggle,
|
|
321
|
+
disabled,
|
|
322
|
+
className: cx(
|
|
323
|
+
"md-dropdown__trigger",
|
|
324
|
+
disabled && "md-dropdown__trigger--disabled"
|
|
325
|
+
),
|
|
326
|
+
children: triggerIcon
|
|
318
327
|
}
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
328
|
+
),
|
|
329
|
+
isOpen && /* @__PURE__ */ jsx7("ul", { className: "md-dropdown__menu", children: options.map((option) => /* @__PURE__ */ jsxs5(
|
|
330
|
+
"li",
|
|
331
|
+
{
|
|
332
|
+
className: cx(
|
|
333
|
+
"md-dropdown__item",
|
|
334
|
+
selected && "md-dropdown__item--selected"
|
|
335
|
+
),
|
|
336
|
+
onClick: () => {
|
|
337
|
+
onChange(option.value);
|
|
338
|
+
setIsOpen(false);
|
|
339
|
+
},
|
|
340
|
+
children: [
|
|
341
|
+
option.Icon && /* @__PURE__ */ jsx7("span", { className: "md-dropdown__icon", children: /* @__PURE__ */ jsx7(option.Icon, {}) }),
|
|
342
|
+
option.label && /* @__PURE__ */ jsx7("span", { className: "md-dropdown__label", children: option.label })
|
|
343
|
+
]
|
|
344
|
+
},
|
|
345
|
+
option.value
|
|
346
|
+
)) })
|
|
347
|
+
] });
|
|
323
348
|
}
|
|
324
349
|
|
|
325
350
|
// src/components/ToolbarDropdown.tsx
|
|
326
351
|
import { Heading1Icon as Heading1Icon2, ListIcon as ListIcon2 } from "lucide-react";
|
|
352
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
327
353
|
function ToolbarDropdownHeading({
|
|
328
354
|
insertMarkdown
|
|
329
355
|
}) {
|
|
330
|
-
return /* @__PURE__ */
|
|
356
|
+
return /* @__PURE__ */ jsx8(
|
|
331
357
|
IconDropdown,
|
|
332
358
|
{
|
|
333
359
|
options: headingOptions,
|
|
334
|
-
triggerIcon: /* @__PURE__ */
|
|
360
|
+
triggerIcon: /* @__PURE__ */ jsx8(Heading1Icon2, {}),
|
|
335
361
|
onChange: (value) => {
|
|
336
362
|
const option = headingOptions.find((o) => o.value === value);
|
|
337
363
|
if (option) insertMarkdown(option.before);
|
|
@@ -340,11 +366,11 @@ function ToolbarDropdownHeading({
|
|
|
340
366
|
);
|
|
341
367
|
}
|
|
342
368
|
function ToolbarDropdownList({ insertMarkdown }) {
|
|
343
|
-
return /* @__PURE__ */
|
|
369
|
+
return /* @__PURE__ */ jsx8(
|
|
344
370
|
IconDropdown,
|
|
345
371
|
{
|
|
346
372
|
options: listOptions,
|
|
347
|
-
triggerIcon: /* @__PURE__ */
|
|
373
|
+
triggerIcon: /* @__PURE__ */ jsx8(ListIcon2, {}),
|
|
348
374
|
onChange: (value) => {
|
|
349
375
|
const option = listOptions.find((o) => o.value === value);
|
|
350
376
|
if (option) insertMarkdown(option.before);
|
package/package.json
CHANGED
package/dist/index.js
DELETED
|
@@ -1,405 +0,0 @@
|
|
|
1
|
-
var __create = Object.create;
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
-
var __export = (target, all) => {
|
|
8
|
-
for (var name in all)
|
|
9
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
-
};
|
|
11
|
-
var __copyProps = (to, from, except, desc) => {
|
|
12
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
-
for (let key of __getOwnPropNames(from))
|
|
14
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
-
}
|
|
17
|
-
return to;
|
|
18
|
-
};
|
|
19
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
21
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
22
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
23
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
24
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
25
|
-
mod
|
|
26
|
-
));
|
|
27
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
28
|
-
|
|
29
|
-
// src/index.ts
|
|
30
|
-
var index_exports = {};
|
|
31
|
-
__export(index_exports, {
|
|
32
|
-
EditorHeader: () => EditorHeader,
|
|
33
|
-
EditorTab: () => EditorTab,
|
|
34
|
-
EditorTextarea: () => EditorTextarea,
|
|
35
|
-
MarkdownEditor: () => MarkdownEditor,
|
|
36
|
-
Preview: () => Preview,
|
|
37
|
-
TOOLBAR_BUTTONS: () => TOOLBAR_BUTTONS,
|
|
38
|
-
Toolbar: () => Toolbar,
|
|
39
|
-
ToolbarDropdownHeading: () => ToolbarDropdownHeading,
|
|
40
|
-
ToolbarDropdownList: () => ToolbarDropdownList,
|
|
41
|
-
cx: () => cx,
|
|
42
|
-
headingOptions: () => headingOptions,
|
|
43
|
-
listOptions: () => listOptions,
|
|
44
|
-
markdownToHtml: () => markdownToHtml,
|
|
45
|
-
useMarkdownEditor: () => useMarkdownEditor
|
|
46
|
-
});
|
|
47
|
-
module.exports = __toCommonJS(index_exports);
|
|
48
|
-
|
|
49
|
-
// src/components/EditorHeader.tsx
|
|
50
|
-
var import_style = require("./style.css");
|
|
51
|
-
function EditorHeader({
|
|
52
|
-
mode,
|
|
53
|
-
setMode,
|
|
54
|
-
insertMarkdown
|
|
55
|
-
}) {
|
|
56
|
-
return /* @__PURE__ */ React.createElement("header", { className: "editor-header" }, /* @__PURE__ */ React.createElement(EditorTab, { mode, setMode }), mode === "write" && /* @__PURE__ */ React.createElement(Toolbar, { insertMarkdown }));
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// src/components/EditorTab.tsx
|
|
60
|
-
var import_style2 = require("./style.css");
|
|
61
|
-
function EditorTab({ mode, setMode }) {
|
|
62
|
-
return /* @__PURE__ */ React.createElement("div", { className: "editor-tab-container" }, /* @__PURE__ */ React.createElement(
|
|
63
|
-
"div",
|
|
64
|
-
{
|
|
65
|
-
className: `editor-tab ${mode === "write" ? "editor-tab--active" : ""}`,
|
|
66
|
-
onClick: () => setMode("write")
|
|
67
|
-
},
|
|
68
|
-
"Write"
|
|
69
|
-
), /* @__PURE__ */ React.createElement(
|
|
70
|
-
"div",
|
|
71
|
-
{
|
|
72
|
-
className: `editor-tab ${mode === "preview" ? "editor-tab--active" : ""}`,
|
|
73
|
-
onClick: () => setMode("preview")
|
|
74
|
-
},
|
|
75
|
-
"Preview"
|
|
76
|
-
));
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// src/components/EditorTextarea.tsx
|
|
80
|
-
var import_react = require("react");
|
|
81
|
-
var import_style3 = require("./style.css");
|
|
82
|
-
var EditorTextarea = (0, import_react.forwardRef)(({ value, placeholder, setValue, onImageUpload }, ref) => {
|
|
83
|
-
const handleDrop = async (e) => {
|
|
84
|
-
e.preventDefault();
|
|
85
|
-
if (!onImageUpload) return;
|
|
86
|
-
const files = Array.from(e.dataTransfer.files).filter(
|
|
87
|
-
(file) => file.type.startsWith("image/")
|
|
88
|
-
);
|
|
89
|
-
for (const file of files) {
|
|
90
|
-
const url = await onImageUpload(file);
|
|
91
|
-
setValue(value + `
|
|
92
|
-

|
|
93
|
-
`);
|
|
94
|
-
}
|
|
95
|
-
};
|
|
96
|
-
return /* @__PURE__ */ React.createElement(
|
|
97
|
-
"textarea",
|
|
98
|
-
{
|
|
99
|
-
ref,
|
|
100
|
-
value,
|
|
101
|
-
onChange: (e) => setValue(e.target.value),
|
|
102
|
-
onDragOver: (e) => e.preventDefault(),
|
|
103
|
-
onDrop: handleDrop,
|
|
104
|
-
placeholder,
|
|
105
|
-
className: "editor-textarea"
|
|
106
|
-
}
|
|
107
|
-
);
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
// src/components/MarkdownEditor.tsx
|
|
111
|
-
var import_react3 = require("react");
|
|
112
|
-
|
|
113
|
-
// src/hooks/useMarkdownEditor.ts
|
|
114
|
-
var import_react2 = require("react");
|
|
115
|
-
function useMarkdownEditor({ value, setValue }) {
|
|
116
|
-
const textareaRef = (0, import_react2.useRef)(null);
|
|
117
|
-
const insertMarkdown = (0, import_react2.useCallback)(
|
|
118
|
-
(before, after = "") => {
|
|
119
|
-
const textarea = textareaRef.current;
|
|
120
|
-
if (!textarea) return;
|
|
121
|
-
const start = textarea.selectionStart;
|
|
122
|
-
const end = textarea.selectionEnd;
|
|
123
|
-
const selected = value.slice(start, end);
|
|
124
|
-
const replaced = before + (selected || "") + after;
|
|
125
|
-
setValue(value.slice(0, start) + replaced + value.slice(end));
|
|
126
|
-
requestAnimationFrame(() => {
|
|
127
|
-
if (!textareaRef.current) return;
|
|
128
|
-
const next = start + replaced.length;
|
|
129
|
-
textareaRef.current.focus();
|
|
130
|
-
textareaRef.current.selectionStart = next;
|
|
131
|
-
textareaRef.current.selectionEnd = next;
|
|
132
|
-
});
|
|
133
|
-
},
|
|
134
|
-
[value, setValue]
|
|
135
|
-
);
|
|
136
|
-
return {
|
|
137
|
-
textareaRef,
|
|
138
|
-
insertMarkdown
|
|
139
|
-
};
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
// src/components/MarkdownEditor.tsx
|
|
143
|
-
var import_style4 = require("./style.css");
|
|
144
|
-
function MarkdownEditor({
|
|
145
|
-
value,
|
|
146
|
-
onChange: setValue,
|
|
147
|
-
onImageUpload
|
|
148
|
-
}) {
|
|
149
|
-
const { textareaRef, insertMarkdown } = useMarkdownEditor({
|
|
150
|
-
value,
|
|
151
|
-
setValue
|
|
152
|
-
});
|
|
153
|
-
const [mode, setMode] = (0, import_react3.useState)("write");
|
|
154
|
-
return /* @__PURE__ */ React.createElement("div", { className: "editor" }, /* @__PURE__ */ React.createElement(
|
|
155
|
-
EditorHeader,
|
|
156
|
-
{
|
|
157
|
-
mode,
|
|
158
|
-
setMode,
|
|
159
|
-
insertMarkdown
|
|
160
|
-
}
|
|
161
|
-
), mode === "write" ? /* @__PURE__ */ React.createElement(
|
|
162
|
-
EditorTextarea,
|
|
163
|
-
{
|
|
164
|
-
ref: textareaRef,
|
|
165
|
-
value,
|
|
166
|
-
setValue,
|
|
167
|
-
onImageUpload
|
|
168
|
-
}
|
|
169
|
-
) : /* @__PURE__ */ React.createElement(Preview, { value }));
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
// src/utils/markdown.ts
|
|
173
|
-
function parseBold(text) {
|
|
174
|
-
return text.replace(/\*\*(.+?)\*\*/g, "<strong>$1</strong>");
|
|
175
|
-
}
|
|
176
|
-
function parseItalic(text) {
|
|
177
|
-
return text.replace(/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/g, "<em>$1</em>");
|
|
178
|
-
}
|
|
179
|
-
function parseInlineCode(text) {
|
|
180
|
-
return text.replace(/`(.+?)`/g, "<code>$1</code>");
|
|
181
|
-
}
|
|
182
|
-
function parseBlockquote(text) {
|
|
183
|
-
return text.replace(/^> (.+)$/gm, "<blockquote>$1</blockquote>");
|
|
184
|
-
}
|
|
185
|
-
function parseStrikethrough(text) {
|
|
186
|
-
return text.replace(/~~(.+?)~~/g, "<del>$1</del>");
|
|
187
|
-
}
|
|
188
|
-
function parseUnderline(text) {
|
|
189
|
-
return text.replace(/__(.+?)__/g, "<u>$1</u>");
|
|
190
|
-
}
|
|
191
|
-
function parseHr(text) {
|
|
192
|
-
return text.replace(/^---$/gm, "<hr />");
|
|
193
|
-
}
|
|
194
|
-
function parseImages(text) {
|
|
195
|
-
return text.replace(
|
|
196
|
-
/!\[(.*?)\]\(([^)]*?)\)/g,
|
|
197
|
-
(_, alt, url) => `<img src="${url}" alt="${alt || ""}" />`
|
|
198
|
-
);
|
|
199
|
-
}
|
|
200
|
-
function parseLinks(text) {
|
|
201
|
-
return text.replace(/\[(.+?)\]\((.+?)\)/g, '<a href="$2">$1</a>');
|
|
202
|
-
}
|
|
203
|
-
function parseHeadings(text) {
|
|
204
|
-
return text.replace(/^# (.+)$/gm, "<h1>$1</h1>").replace(/^## (.+)$/gm, "<h2>$1</h2>").replace(/^### (.+)$/gm, "<h3>$1</h3>");
|
|
205
|
-
}
|
|
206
|
-
function parseUnorderedList(text) {
|
|
207
|
-
return text.replace(
|
|
208
|
-
/(^|\r?\n)((?:\s*- .+(?:\r?\n|$))+)/g,
|
|
209
|
-
(_, prefix, block) => {
|
|
210
|
-
const items = block.trim().split(/\r?\n/).map((line) => line.replace(/^\s*- /, "").trim()).filter(Boolean).map((item) => `<li>${item}</li>`).join("");
|
|
211
|
-
return `${prefix}<ul>${items}</ul>`;
|
|
212
|
-
}
|
|
213
|
-
);
|
|
214
|
-
}
|
|
215
|
-
function parseOrderedList(text) {
|
|
216
|
-
return text.replace(
|
|
217
|
-
/(^|\r?\n)((?:\d+\. .+(?:\r?\n|$))+)/g,
|
|
218
|
-
(_, prefix, block) => {
|
|
219
|
-
const items = block.trim().split(/\r?\n/).map((line) => line.replace(/^\d+\. /, "").trim()).filter(Boolean).map((item) => `<li>${item}</li>`).join("");
|
|
220
|
-
return `${prefix}<ol>${items}</ol>`;
|
|
221
|
-
}
|
|
222
|
-
);
|
|
223
|
-
}
|
|
224
|
-
function parseLineBreaks(text) {
|
|
225
|
-
return text.replace(
|
|
226
|
-
/(?<!<\/ul>|<\/ol>|<\/li>|<\/h1>|<\/h2>|<\/h3>)\n/g,
|
|
227
|
-
"<br/>"
|
|
228
|
-
);
|
|
229
|
-
}
|
|
230
|
-
function markdownToHtml(markdown) {
|
|
231
|
-
let html = markdown;
|
|
232
|
-
html = parseHr(html);
|
|
233
|
-
html = parseHeadings(html);
|
|
234
|
-
html = parseBlockquote(html);
|
|
235
|
-
html = parseUnorderedList(html);
|
|
236
|
-
html = parseOrderedList(html);
|
|
237
|
-
html = parseBold(html);
|
|
238
|
-
html = parseUnderline(html);
|
|
239
|
-
html = parseStrikethrough(html);
|
|
240
|
-
html = parseItalic(html);
|
|
241
|
-
html = parseInlineCode(html);
|
|
242
|
-
html = parseImages(html);
|
|
243
|
-
html = parseLinks(html);
|
|
244
|
-
html = parseLineBreaks(html);
|
|
245
|
-
return html;
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
// src/components/Preview.tsx
|
|
249
|
-
var import_style5 = require("./style.css");
|
|
250
|
-
function Preview({ value }) {
|
|
251
|
-
return /* @__PURE__ */ React.createElement(
|
|
252
|
-
"div",
|
|
253
|
-
{
|
|
254
|
-
className: "preview",
|
|
255
|
-
dangerouslySetInnerHTML: { __html: markdownToHtml(value) },
|
|
256
|
-
style: { listStyle: "decimal" }
|
|
257
|
-
}
|
|
258
|
-
);
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
// src/constants/toolbar.ts
|
|
262
|
-
var import_lucide_react = require("lucide-react");
|
|
263
|
-
var TOOLBAR_BUTTONS = [
|
|
264
|
-
{ key: "bold", before: "**", after: "**", Icon: import_lucide_react.BoldIcon },
|
|
265
|
-
{ key: "italic", before: "*", after: "*", Icon: import_lucide_react.ItalicIcon },
|
|
266
|
-
{ key: "code", before: "`", after: "`", Icon: import_lucide_react.CodeIcon },
|
|
267
|
-
{ key: "blockquote", before: "> ", after: "", Icon: import_lucide_react.QuoteIcon },
|
|
268
|
-
{ key: "strikethrough", before: "~~", after: "~~", Icon: import_lucide_react.StrikethroughIcon },
|
|
269
|
-
{ key: "underline", before: "__", after: "__", Icon: import_lucide_react.UnderlineIcon },
|
|
270
|
-
{ key: "horizontal rule", before: "\n---\n", after: "", Icon: import_lucide_react.ListEndIcon },
|
|
271
|
-
{ key: "link", before: "[", after: "]()", Icon: import_lucide_react.LinkIcon }
|
|
272
|
-
];
|
|
273
|
-
var headingOptions = [
|
|
274
|
-
{ value: "h1", Icon: import_lucide_react.Heading1Icon, before: "# " },
|
|
275
|
-
{ value: "h2", Icon: import_lucide_react.Heading2Icon, before: "## " },
|
|
276
|
-
{ value: "h3", Icon: import_lucide_react.Heading3Icon, before: "### " }
|
|
277
|
-
];
|
|
278
|
-
var listOptions = [
|
|
279
|
-
{ value: "unordered list", Icon: import_lucide_react.ListIcon, before: "- " },
|
|
280
|
-
{ value: "ordered list", Icon: import_lucide_react.ListOrderedIcon, before: "1. " }
|
|
281
|
-
];
|
|
282
|
-
|
|
283
|
-
// src/components/Toolbar.tsx
|
|
284
|
-
var import_style6 = require("./style.css");
|
|
285
|
-
function Toolbar({ insertMarkdown }) {
|
|
286
|
-
return /* @__PURE__ */ React.createElement("menu", { className: "toolbar-menu" }, TOOLBAR_BUTTONS.map(({ key, before, after, Icon }) => /* @__PURE__ */ React.createElement(
|
|
287
|
-
"button",
|
|
288
|
-
{
|
|
289
|
-
key,
|
|
290
|
-
className: "toolbar-button",
|
|
291
|
-
onClick: () => insertMarkdown(before, after)
|
|
292
|
-
},
|
|
293
|
-
/* @__PURE__ */ React.createElement(Icon, { size: 18 })
|
|
294
|
-
)), /* @__PURE__ */ React.createElement(ToolbarDropdownHeading, { insertMarkdown }), /* @__PURE__ */ React.createElement(ToolbarDropdownList, { insertMarkdown }));
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
// src/components/IconDropdown.tsx
|
|
298
|
-
var import_react4 = __toESM(require("react"));
|
|
299
|
-
|
|
300
|
-
// src/utils/cx.ts
|
|
301
|
-
function cx(...classes) {
|
|
302
|
-
return classes.filter(Boolean).join(" ");
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
// src/components/IconDropdown.tsx
|
|
306
|
-
var import_style7 = require("./style.css");
|
|
307
|
-
function IconDropdown({
|
|
308
|
-
className,
|
|
309
|
-
disabled,
|
|
310
|
-
options,
|
|
311
|
-
selected,
|
|
312
|
-
triggerIcon,
|
|
313
|
-
onChange
|
|
314
|
-
}) {
|
|
315
|
-
const [isOpen, setIsOpen] = import_react4.default.useState(false);
|
|
316
|
-
const dropdownRef = import_react4.default.useRef(null);
|
|
317
|
-
const toggle = () => {
|
|
318
|
-
if (!disabled) setIsOpen((prev) => !prev);
|
|
319
|
-
};
|
|
320
|
-
import_react4.default.useEffect(() => {
|
|
321
|
-
const handleClickOutside = (e) => {
|
|
322
|
-
if (dropdownRef.current && !dropdownRef.current.contains(e.target)) {
|
|
323
|
-
setIsOpen(false);
|
|
324
|
-
}
|
|
325
|
-
};
|
|
326
|
-
document.addEventListener("mousedown", handleClickOutside);
|
|
327
|
-
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
328
|
-
}, []);
|
|
329
|
-
return /* @__PURE__ */ import_react4.default.createElement("div", { ref: dropdownRef, className: cx("md-dropdown", className) }, /* @__PURE__ */ import_react4.default.createElement(
|
|
330
|
-
"button",
|
|
331
|
-
{
|
|
332
|
-
type: "button",
|
|
333
|
-
onClick: toggle,
|
|
334
|
-
disabled,
|
|
335
|
-
className: cx(
|
|
336
|
-
"md-dropdown__trigger",
|
|
337
|
-
disabled && "md-dropdown__trigger--disabled"
|
|
338
|
-
)
|
|
339
|
-
},
|
|
340
|
-
triggerIcon
|
|
341
|
-
), isOpen && /* @__PURE__ */ import_react4.default.createElement("ul", { className: "md-dropdown__menu" }, options.map((option) => /* @__PURE__ */ import_react4.default.createElement(
|
|
342
|
-
"li",
|
|
343
|
-
{
|
|
344
|
-
key: option.value,
|
|
345
|
-
className: cx(
|
|
346
|
-
"md-dropdown__item",
|
|
347
|
-
selected && "md-dropdown__item--selected"
|
|
348
|
-
),
|
|
349
|
-
onClick: () => {
|
|
350
|
-
onChange(option.value);
|
|
351
|
-
setIsOpen(false);
|
|
352
|
-
}
|
|
353
|
-
},
|
|
354
|
-
option.Icon && /* @__PURE__ */ import_react4.default.createElement("span", { className: "md-dropdown__icon" }, /* @__PURE__ */ import_react4.default.createElement(option.Icon, null)),
|
|
355
|
-
option.label && /* @__PURE__ */ import_react4.default.createElement("span", { className: "md-dropdown__label" }, option.label)
|
|
356
|
-
))));
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
// src/components/ToolbarDropdown.tsx
|
|
360
|
-
var import_lucide_react2 = require("lucide-react");
|
|
361
|
-
function ToolbarDropdownHeading({
|
|
362
|
-
insertMarkdown
|
|
363
|
-
}) {
|
|
364
|
-
return /* @__PURE__ */ React.createElement(
|
|
365
|
-
IconDropdown,
|
|
366
|
-
{
|
|
367
|
-
options: headingOptions,
|
|
368
|
-
triggerIcon: /* @__PURE__ */ React.createElement(import_lucide_react2.Heading1Icon, null),
|
|
369
|
-
onChange: (value) => {
|
|
370
|
-
const option = headingOptions.find((o) => o.value === value);
|
|
371
|
-
if (option) insertMarkdown(option.before);
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
);
|
|
375
|
-
}
|
|
376
|
-
function ToolbarDropdownList({ insertMarkdown }) {
|
|
377
|
-
return /* @__PURE__ */ React.createElement(
|
|
378
|
-
IconDropdown,
|
|
379
|
-
{
|
|
380
|
-
options: listOptions,
|
|
381
|
-
triggerIcon: /* @__PURE__ */ React.createElement(import_lucide_react2.ListIcon, null),
|
|
382
|
-
onChange: (value) => {
|
|
383
|
-
const option = listOptions.find((o) => o.value === value);
|
|
384
|
-
if (option) insertMarkdown(option.before);
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
);
|
|
388
|
-
}
|
|
389
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
390
|
-
0 && (module.exports = {
|
|
391
|
-
EditorHeader,
|
|
392
|
-
EditorTab,
|
|
393
|
-
EditorTextarea,
|
|
394
|
-
MarkdownEditor,
|
|
395
|
-
Preview,
|
|
396
|
-
TOOLBAR_BUTTONS,
|
|
397
|
-
Toolbar,
|
|
398
|
-
ToolbarDropdownHeading,
|
|
399
|
-
ToolbarDropdownList,
|
|
400
|
-
cx,
|
|
401
|
-
headingOptions,
|
|
402
|
-
listOptions,
|
|
403
|
-
markdownToHtml,
|
|
404
|
-
useMarkdownEditor
|
|
405
|
-
});
|