markdown-text-editor 1.7.0 → 1.9.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,8 +1,8 @@
1
1
  {
2
2
  "name": "markdown-text-editor",
3
- "version": "1.7.0",
3
+ "version": "1.9.0",
4
4
  "type": "module",
5
- "description": "Lightweight Markdown editor with hybrid WYSIWYG mode, real-time preview, and zero-config setup. Works with any backend via native textarea.",
5
+ "description": "A markdown editor that enhances your textarea instead of replacing it, so form submission, validation and required fields keep working. WYSIWYG hybrid mode, live preview, find and replace, RTL, TypeScript types. Works with any backend.",
6
6
  "funding": "https://ko-fi.com/nezanuha",
7
7
  "main": "./dist/markdown-text-editor.umd.js",
8
8
  "module": "./dist/markdown-text-editor.es.js",
@@ -32,7 +32,8 @@
32
32
  "build": "vite build",
33
33
  "preview": "vite preview",
34
34
  "prepublishOnly": "npm run build",
35
- "postversion": "git push origin main --tags",
35
+ "version": "node scripts/check-changelog.mjs",
36
+ "postversion": "git push origin HEAD --follow-tags",
36
37
  "test": "node test/smoke.mjs",
37
38
  "typecheck": "tsc --noEmit --strict --lib es2020,dom --moduleResolution bundler --module esnext test/types.test.ts"
38
39
  },
@@ -60,7 +61,12 @@
60
61
  "csp compatible",
61
62
  "form markdown editor",
62
63
  "live preview",
63
- "mde"
64
+ "mde",
65
+ "typescript",
66
+ "markdown-it",
67
+ "template editor",
68
+ "merge tags",
69
+ "placeholders"
64
70
  ],
65
71
  "author": "Nezanuha",
66
72
  "license": "MIT",
@@ -69,20 +75,20 @@
69
75
  "url": "https://github.com/nezanuha/markdown-text-editor/issues"
70
76
  },
71
77
  "dependencies": {
72
- "dompurify": "^3.4.15",
73
- "marked": "~18.0.12"
78
+ "dompurify": "^3.4.16",
79
+ "marked": "~18.0.14"
74
80
  },
75
81
  "devDependencies": {
76
82
  "@tailwindcss/postcss": "^4.3.3",
77
83
  "@tailwindcss/typography": "^0.5.20",
78
84
  "@tailwindcss/vite": "^4.3.3",
79
85
  "diff": "^9.0.0",
80
- "frutjam": "^2.2.5",
81
- "happy-dom": "^20.14.3",
86
+ "frutjam": "^2.2.6",
87
+ "happy-dom": "^20.14.5",
82
88
  "postcss": "^8.5.28",
83
89
  "tailwindcss": "^4.3.3",
84
90
  "typescript": "^7.0.2",
85
- "vite": "^8.3.0",
91
+ "vite": "^8.3.1",
86
92
  "vite-plugin-css-injected-by-js": "^5.0.2"
87
93
  },
88
94
  "types": "./types/index.d.ts"
package/types/index.d.ts CHANGED
@@ -65,7 +65,58 @@ export interface ImageTool {
65
65
  };
66
66
  }
67
67
 
68
- export type ToolbarEntry = ToolName | VariablesTool | ImageTool;
68
+ /**
69
+ * A tool of your own. Extend `MarkdownEditor.Tool`, set `this.button` in the
70
+ * constructor, and implement `applySyntax()`.
71
+ *
72
+ * @example
73
+ * class ShoutTool extends MarkdownEditor.Tool {
74
+ * constructor(editor) {
75
+ * super(editor, 'Shout');
76
+ * this.button = this.createButton('<svg>…</svg>');
77
+ * }
78
+ * applySyntax() { this.editor.insertText('**LOUD**'); }
79
+ * }
80
+ */
81
+ export type CustomTool = new (editor: MarkdownEditor, config?: any) => {
82
+ /** Appended to the toolbar. Return `null` to render nothing. */
83
+ button: HTMLElement | null;
84
+ };
85
+
86
+ /**
87
+ * A toolbar button described rather than written as a class. The usual way to
88
+ * add your own tool.
89
+ *
90
+ * @example
91
+ * { custom: {
92
+ * title: 'Insert accordion',
93
+ * icon: '<svg>…</svg>',
94
+ * action(editor) { editor.insertText('<div class="accordion">…</div>'); }
95
+ * }}
96
+ */
97
+ export interface DeclarativeTool {
98
+ custom: {
99
+ /** Tooltip, and the source of the button's CSS class. Translatable via `labels`. */
100
+ title: string;
101
+ /** Inline SVG for the button face. */
102
+ icon?: string;
103
+ /** Runs on click. The event is passed on for handing to `MarkdownEditor.modal`. */
104
+ action: (editor: MarkdownEditor, event: Event) => void;
105
+ /**
106
+ * Keyboard shortcut, e.g. `'Ctrl+Shift+K'`. Appended to the tooltip, and
107
+ * takes precedence over a built-in using the same combination.
108
+ */
109
+ shortcut?: string;
110
+ };
111
+ }
112
+
113
+ export type ToolbarEntry =
114
+ | ToolName
115
+ | VariablesTool
116
+ | ImageTool
117
+ | DeclarativeTool
118
+ | CustomTool
119
+ | { tool: CustomTool; config?: any };
69
120
 
70
121
  /** Status bar fields. `false` hides the bar entirely. */
71
122
  export interface FooterOptions {
@@ -113,6 +164,15 @@ export interface MarkdownEditorOptions {
113
164
  /** Called on every content change with the current markdown. */
114
165
  onChange?: (value: string) => void;
115
166
 
167
+ /**
168
+ * Translations for the editor's own interface, keyed by the English text:
169
+ * tooltips, menu items, modal fields and buttons. Anything not listed stays
170
+ * in English. CSS class names are unaffected.
171
+ *
172
+ * @example labels: { Bold: 'Negrita', 'Insert variable': 'Insertar variable' }
173
+ */
174
+ labels?: Record<string, string>;
175
+
116
176
  /**
117
177
  * Replaces the markdown parser used for the preview. Must be synchronous and
118
178
  * return an HTML string. Affects the preview pane only; hybrid mode's live
@@ -138,12 +198,53 @@ export interface MarkdownEditorOptions {
138
198
  sanitizer?: (html: string) => string;
139
199
  }
140
200
 
201
+ /** Base class for toolbar tools. Reach it as `MarkdownEditor.Tool`. */
202
+ export declare class Tool {
203
+ constructor(editor: MarkdownEditor, title: string);
204
+ readonly editor: MarkdownEditor;
205
+ /** The element appended to the toolbar. Set it to `null` to render nothing. */
206
+ button: HTMLElement | null;
207
+ /** Builds the default square icon button. Override for a dropdown or similar. */
208
+ createButton(iconHtml?: string): HTMLElement | null;
209
+ /** Called when the button is clicked, or its shortcut is pressed. */
210
+ applySyntax(event?: Event): void;
211
+ /** Set to e.g. `'Ctrl+Shift+K'` to bind a shortcut. */
212
+ shortcut?: string;
213
+ /** Implement to release anything the tool registered. Called by `destroy()`. */
214
+ destroy?: () => void;
215
+ }
216
+
141
217
  export default class MarkdownEditor {
142
218
  /**
143
219
  * @param selector A CSS selector for a `<textarea>`, or the element itself.
144
220
  */
145
221
  constructor(selector: string | HTMLTextAreaElement, options?: MarkdownEditorOptions);
146
222
 
223
+ /** Base class for writing your own toolbar tool. */
224
+ static Tool: typeof Tool;
225
+
226
+ /** The dialog helper the built-in link and image tools use. */
227
+ static modal: (event: Event, size: string, bodyHTML: string, label?: string) => HTMLDialogElement;
228
+
229
+ /** Returns the translation for a UI string, or the string itself. */
230
+ label(text: string): string;
231
+
232
+ /**
233
+ * Renders markdown to sanitized HTML exactly as the preview does, honouring
234
+ * the configured `renderer` and `sanitizer`. For custom tools that need to
235
+ * embed rendered content, such as a tooltip body.
236
+ */
237
+ renderMarkdown(markdown: string): string;
238
+
239
+ /**
240
+ * Builds a small toolbar bound to another textarea, for a custom tool that
241
+ * collects rich text in its own dialog. The tools are the real ones, and
242
+ * `labels` are inherited. Returns the element; append it where you like.
243
+ *
244
+ * No preview button is added, whatever you pass.
245
+ */
246
+ createToolbar(textarea: HTMLTextAreaElement, tools?: ToolbarEntry[]): HTMLDivElement;
247
+
147
248
  /** The original textarea. Its `.value` is always the current markdown. */
148
249
  readonly usertextarea: HTMLTextAreaElement;
149
250