markdown-text-editor 1.5.4 → 1.7.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "markdown-text-editor",
3
- "version": "1.5.4",
3
+ "version": "1.7.0",
4
4
  "type": "module",
5
5
  "description": "Lightweight Markdown editor with hybrid WYSIWYG mode, real-time preview, and zero-config setup. Works with any backend via native textarea.",
6
6
  "funding": "https://ko-fi.com/nezanuha",
@@ -11,6 +11,7 @@
11
11
  "jsdelivr": "./dist/markdown-text-editor.min.js",
12
12
  "exports": {
13
13
  ".": {
14
+ "types": "./types/index.d.ts",
14
15
  "import": "./dist/markdown-text-editor.es.js",
15
16
  "require": "./dist/markdown-text-editor.umd.js",
16
17
  "default": "./dist/markdown-text-editor.umd.js"
@@ -18,6 +19,7 @@
18
19
  },
19
20
  "files": [
20
21
  "dist/",
22
+ "types/",
21
23
  "README.md",
22
24
  "LICENSE"
23
25
  ],
@@ -30,7 +32,9 @@
30
32
  "build": "vite build",
31
33
  "preview": "vite preview",
32
34
  "prepublishOnly": "npm run build",
33
- "postversion": "git push origin main --tags"
35
+ "postversion": "git push origin main --tags",
36
+ "test": "node test/smoke.mjs",
37
+ "typecheck": "tsc --noEmit --strict --lib es2020,dom --moduleResolution bundler --module esnext test/types.test.ts"
34
38
  },
35
39
  "publishConfig": {
36
40
  "provenance": true,
@@ -65,8 +69,8 @@
65
69
  "url": "https://github.com/nezanuha/markdown-text-editor/issues"
66
70
  },
67
71
  "dependencies": {
68
- "dompurify": "^3.4.12",
69
- "marked": "~18.0.7"
72
+ "dompurify": "^3.4.15",
73
+ "marked": "~18.0.12"
70
74
  },
71
75
  "devDependencies": {
72
76
  "@tailwindcss/postcss": "^4.3.3",
@@ -74,9 +78,12 @@
74
78
  "@tailwindcss/vite": "^4.3.3",
75
79
  "diff": "^9.0.0",
76
80
  "frutjam": "^2.2.5",
77
- "postcss": "^8.5.21",
81
+ "happy-dom": "^20.14.3",
82
+ "postcss": "^8.5.28",
78
83
  "tailwindcss": "^4.3.3",
79
- "vite": "^8.1.5",
84
+ "typescript": "^7.0.2",
85
+ "vite": "^8.3.0",
80
86
  "vite-plugin-css-injected-by-js": "^5.0.2"
81
- }
87
+ },
88
+ "types": "./types/index.d.ts"
82
89
  }
@@ -0,0 +1,176 @@
1
+ /**
2
+ * Type definitions for markdown-text-editor.
3
+ *
4
+ * Options are read once, when the editor is constructed. Changing them afterwards
5
+ * has no effect; call destroy() and construct a new editor instead.
6
+ */
7
+
8
+ /** Tools that take no configuration, referenced by name in `toolbar`. */
9
+ export type ToolName =
10
+ | 'heading'
11
+ | 'bold'
12
+ | 'italic'
13
+ | 'strikethrough'
14
+ | 'blockquote'
15
+ | 'ul'
16
+ | 'ol'
17
+ | 'checklist'
18
+ | 'indent'
19
+ | 'outdent'
20
+ | 'code'
21
+ | 'codeblock'
22
+ | 'hr'
23
+ | 'table'
24
+ | 'link'
25
+ | 'image'
26
+ | 'undo'
27
+ | 'redo'
28
+ | 'preview';
29
+
30
+ /** A single entry in the variables dropdown. */
31
+ export interface Variable {
32
+ /** Text shown in the dropdown. Rendered as plain text, never as markup. */
33
+ label: string;
34
+ /** Inserted at the cursor when the entry is clicked. */
35
+ value: string;
36
+ /**
37
+ * Shown in place of `value` in the preview. The textarea keeps the real
38
+ * placeholder. Entries without a sample appear as written.
39
+ */
40
+ sample?: string;
41
+ }
42
+
43
+ /** A headed section of variables. Groups and flat entries can be mixed. */
44
+ export interface VariableGroup {
45
+ /** Heading shown above the group. Not clickable. */
46
+ label: string;
47
+ items: Variable[];
48
+ }
49
+
50
+ /** Toolbar entries that carry their own configuration. */
51
+ export interface VariablesTool {
52
+ variables: Array<Variable | VariableGroup>;
53
+ }
54
+
55
+ export interface ImageTool {
56
+ image: {
57
+ fileInput?: {
58
+ /** Allowed extensions, e.g. `['webp', 'avif', 'png']`. */
59
+ accept?: string[];
60
+ /** Endpoint the `File` is POSTed to. */
61
+ uploadUrl?: string;
62
+ };
63
+ /** `false` disables alt text validation. */
64
+ altInput?: boolean | { required?: boolean };
65
+ };
66
+ }
67
+
68
+ export type ToolbarEntry = ToolName | VariablesTool | ImageTool;
69
+
70
+ /** Status bar fields. `false` hides the bar entirely. */
71
+ export interface FooterOptions {
72
+ /** Default `true`. */
73
+ line?: boolean;
74
+ /** Default `true`. */
75
+ col?: boolean;
76
+ /** Default `true`. */
77
+ chars?: boolean;
78
+ /** Default `false`. */
79
+ words?: boolean;
80
+ }
81
+
82
+ export interface MarkdownEditorOptions {
83
+ /**
84
+ * `'hybrid'` renders formatting live as you type, `'plain'` shows raw
85
+ * markdown. Default `'plain'`.
86
+ */
87
+ mode?: 'plain' | 'hybrid';
88
+
89
+ /** Text shown when the editor is empty. */
90
+ placeholder?: string;
91
+
92
+ /**
93
+ * Which tools appear and in what order. Omit for the default toolbar.
94
+ * Note that `preview` must be present for the preview pane to exist.
95
+ */
96
+ toolbar?: ToolbarEntry[];
97
+
98
+ /** Status bar configuration, or `false` to hide it. */
99
+ footer?: false | FooterOptions;
100
+
101
+ /**
102
+ * Overrides the theme. Without it the editor inherits `data-theme` from the
103
+ * nearest ancestor, or from the textarea itself.
104
+ */
105
+ theme?: 'light' | 'dark' | 'snowberry' | 'darkberry' | (string & {});
106
+
107
+ /** Minimum height in pixels. Default `200`. */
108
+ minHeight?: number;
109
+
110
+ /** Maximum height in pixels before the editor scrolls. Default `500`. */
111
+ maxHeight?: number;
112
+
113
+ /** Called on every content change with the current markdown. */
114
+ onChange?: (value: string) => void;
115
+
116
+ /**
117
+ * Replaces the markdown parser used for the preview. Must be synchronous and
118
+ * return an HTML string. Affects the preview pane only; hybrid mode's live
119
+ * formatting uses a separate internal renderer.
120
+ *
121
+ * Clickable task list checkboxes are found by looking for
122
+ * `input[type="checkbox"]` in the output, so a renderer without task list
123
+ * support will break them.
124
+ *
125
+ * @example renderer: markdown => markdownIt.render(markdown)
126
+ */
127
+ renderer?: (markdown: string) => string;
128
+
129
+ /**
130
+ * Replaces the HTML sanitizer. Must be synchronous and return an HTML string.
131
+ * Defaults to DOMPurify, which still runs when only `renderer` is given.
132
+ *
133
+ * Replacing this replaces your XSS protection. A pass-through such as
134
+ * `html => html` disables sanitizing entirely.
135
+ *
136
+ * @example sanitizer: html => DOMPurify.sanitize(html, { ADD_TAGS: ['iframe'] })
137
+ */
138
+ sanitizer?: (html: string) => string;
139
+ }
140
+
141
+ export default class MarkdownEditor {
142
+ /**
143
+ * @param selector A CSS selector for a `<textarea>`, or the element itself.
144
+ */
145
+ constructor(selector: string | HTMLTextAreaElement, options?: MarkdownEditorOptions);
146
+
147
+ /** The original textarea. Its `.value` is always the current markdown. */
148
+ readonly usertextarea: HTMLTextAreaElement;
149
+
150
+ /** The wrapper the editor builds around the textarea. */
151
+ readonly editorContainer: HTMLDivElement;
152
+
153
+ /** Options exactly as passed in. */
154
+ readonly options: MarkdownEditorOptions;
155
+
156
+ /** Variables parsed out of the toolbar configuration. */
157
+ readonly variables: Array<Variable | VariableGroup>;
158
+
159
+ /**
160
+ * Inserts text at the cursor, replacing any selection, then restores focus,
161
+ * scrolls the insertion into view, re-renders and fires `onChange`.
162
+ *
163
+ * @param selectionOffset Where the caret lands, measured from the insertion point.
164
+ * @param trailingLength Characters at the end to leave outside the selection.
165
+ */
166
+ insertText(text: string, selectionOffset?: number, trailingLength?: number): void;
167
+
168
+ /** Re-renders the preview and the hybrid display layer from the textarea. */
169
+ render(): void;
170
+
171
+ /**
172
+ * Removes the editor UI, restores the original textarea and detaches every
173
+ * listener. Call this on unmount in single page applications.
174
+ */
175
+ destroy(): void;
176
+ }