markdown-text-editor 1.8.0 → 2.0.0-beta.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.8.0",
3
+ "version": "2.0.0-beta.0",
4
4
  "type": "module",
5
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",
@@ -15,7 +15,10 @@
15
15
  "import": "./dist/markdown-text-editor.es.js",
16
16
  "require": "./dist/markdown-text-editor.umd.js",
17
17
  "default": "./dist/markdown-text-editor.umd.js"
18
- }
18
+ },
19
+ "./style.css": "./dist/markdown-text-editor.css",
20
+ "./dist/*": "./dist/*",
21
+ "./package.json": "./package.json"
19
22
  },
20
23
  "files": [
21
24
  "dist/",
@@ -32,7 +35,8 @@
32
35
  "build": "vite build",
33
36
  "preview": "vite preview",
34
37
  "prepublishOnly": "npm run build",
35
- "postversion": "git push origin main --tags",
38
+ "version": "node scripts/check-changelog.mjs",
39
+ "postversion": "git push origin HEAD --follow-tags",
36
40
  "test": "node test/smoke.mjs",
37
41
  "typecheck": "tsc --noEmit --strict --lib es2020,dom --moduleResolution bundler --module esnext test/types.test.ts"
38
42
  },
@@ -75,20 +79,19 @@
75
79
  },
76
80
  "dependencies": {
77
81
  "dompurify": "^3.4.16",
78
- "marked": "~18.0.14"
82
+ "marked": "~18.1.0"
79
83
  },
80
84
  "devDependencies": {
81
85
  "@tailwindcss/postcss": "^4.3.3",
82
86
  "@tailwindcss/typography": "^0.5.20",
83
87
  "@tailwindcss/vite": "^4.3.3",
84
88
  "diff": "^9.0.0",
85
- "frutjam": "^2.2.6",
86
- "happy-dom": "^20.14.5",
87
- "postcss": "^8.5.28",
89
+ "frutjam": "^2.3.0",
90
+ "happy-dom": "^20.14.6",
91
+ "postcss": "^8.5.29",
88
92
  "tailwindcss": "^4.3.3",
89
93
  "typescript": "^7.0.2",
90
- "vite": "^8.3.1",
91
- "vite-plugin-css-injected-by-js": "^5.0.2"
94
+ "vite": "^8.3.4"
92
95
  },
93
96
  "types": "./types/index.d.ts"
94
97
  }
package/types/index.d.ts CHANGED
@@ -52,6 +52,24 @@ export interface VariablesTool {
52
52
  variables: Array<Variable | VariableGroup>;
53
53
  }
54
54
 
55
+ export interface HeadingTool {
56
+ heading: {
57
+ /**
58
+ * Which heading levels the dropdown offers, in the order 1-6 regardless
59
+ * of how you list them. Defaults to all six. Useful where H1 belongs to
60
+ * the page rather than the content, e.g. `[2, 3, 4]`.
61
+ *
62
+ * `Ctrl+1`, `Ctrl+2` and `Ctrl+3` follow this list, so a level you leave
63
+ * out cannot be inserted from the keyboard either.
64
+ *
65
+ * This restricts the toolbar, not the document: someone can still type
66
+ * `# Title` by hand and it renders as a heading. Enforce the rule on the
67
+ * server if it has to hold.
68
+ */
69
+ levels?: Array<1 | 2 | 3 | 4 | 5 | 6>;
70
+ };
71
+ }
72
+
55
73
  export interface ImageTool {
56
74
  image: {
57
75
  fileInput?: {
@@ -65,7 +83,59 @@ export interface ImageTool {
65
83
  };
66
84
  }
67
85
 
68
- export type ToolbarEntry = ToolName | VariablesTool | ImageTool;
86
+ /**
87
+ * A tool of your own. Extend `MarkdownEditor.Tool`, set `this.button` in the
88
+ * constructor, and implement `applySyntax()`.
89
+ *
90
+ * @example
91
+ * class ShoutTool extends MarkdownEditor.Tool {
92
+ * constructor(editor) {
93
+ * super(editor, 'Shout');
94
+ * this.button = this.createButton('<svg>…</svg>');
95
+ * }
96
+ * applySyntax() { this.editor.insertText('**LOUD**'); }
97
+ * }
98
+ */
99
+ export type CustomTool = new (editor: MarkdownEditor, config?: any) => {
100
+ /** Appended to the toolbar. Return `null` to render nothing. */
101
+ button: HTMLElement | null;
102
+ };
103
+
104
+ /**
105
+ * A toolbar button described rather than written as a class. The usual way to
106
+ * add your own tool.
107
+ *
108
+ * @example
109
+ * { custom: {
110
+ * title: 'Insert accordion',
111
+ * icon: '<svg>…</svg>',
112
+ * action(editor) { editor.insertText('<div class="accordion">…</div>'); }
113
+ * }}
114
+ */
115
+ export interface DeclarativeTool {
116
+ custom: {
117
+ /** Tooltip, and the source of the button's CSS class. Translatable via `labels`. */
118
+ title: string;
119
+ /** Inline SVG for the button face. */
120
+ icon?: string;
121
+ /** Runs on click. The event is passed on for handing to `MarkdownEditor.modal`. */
122
+ action: (editor: MarkdownEditor, event: Event) => void;
123
+ /**
124
+ * Keyboard shortcut, e.g. `'Ctrl+Shift+K'`. Appended to the tooltip, and
125
+ * takes precedence over a built-in using the same combination.
126
+ */
127
+ shortcut?: string;
128
+ };
129
+ }
130
+
131
+ export type ToolbarEntry =
132
+ | ToolName
133
+ | VariablesTool
134
+ | ImageTool
135
+ | HeadingTool
136
+ | DeclarativeTool
137
+ | CustomTool
138
+ | { tool: CustomTool; config?: any };
69
139
 
70
140
  /** Status bar fields. `false` hides the bar entirely. */
71
141
  export interface FooterOptions {
@@ -147,12 +217,53 @@ export interface MarkdownEditorOptions {
147
217
  sanitizer?: (html: string) => string;
148
218
  }
149
219
 
220
+ /** Base class for toolbar tools. Reach it as `MarkdownEditor.Tool`. */
221
+ export declare class Tool {
222
+ constructor(editor: MarkdownEditor, title: string);
223
+ readonly editor: MarkdownEditor;
224
+ /** The element appended to the toolbar. Set it to `null` to render nothing. */
225
+ button: HTMLElement | null;
226
+ /** Builds the default square icon button. Override for a dropdown or similar. */
227
+ createButton(iconHtml?: string): HTMLElement | null;
228
+ /** Called when the button is clicked, or its shortcut is pressed. */
229
+ applySyntax(event?: Event): void;
230
+ /** Set to e.g. `'Ctrl+Shift+K'` to bind a shortcut. */
231
+ shortcut?: string;
232
+ /** Implement to release anything the tool registered. Called by `destroy()`. */
233
+ destroy?: () => void;
234
+ }
235
+
150
236
  export default class MarkdownEditor {
151
237
  /**
152
238
  * @param selector A CSS selector for a `<textarea>`, or the element itself.
153
239
  */
154
240
  constructor(selector: string | HTMLTextAreaElement, options?: MarkdownEditorOptions);
155
241
 
242
+ /** Base class for writing your own toolbar tool. */
243
+ static Tool: typeof Tool;
244
+
245
+ /** The dialog helper the built-in link and image tools use. */
246
+ static modal: (event: Event, size: string, bodyHTML: string, label?: string) => HTMLDialogElement;
247
+
248
+ /** Returns the translation for a UI string, or the string itself. */
249
+ label(text: string): string;
250
+
251
+ /**
252
+ * Renders markdown to sanitized HTML exactly as the preview does, honouring
253
+ * the configured `renderer` and `sanitizer`. For custom tools that need to
254
+ * embed rendered content, such as a tooltip body.
255
+ */
256
+ renderMarkdown(markdown: string): string;
257
+
258
+ /**
259
+ * Builds a small toolbar bound to another textarea, for a custom tool that
260
+ * collects rich text in its own dialog. The tools are the real ones, and
261
+ * `labels` are inherited. Returns the element; append it where you like.
262
+ *
263
+ * No preview button is added, whatever you pass.
264
+ */
265
+ createToolbar(textarea: HTMLTextAreaElement, tools?: ToolbarEntry[]): HTMLDivElement;
266
+
156
267
  /** The original textarea. Its `.value` is always the current markdown. */
157
268
  readonly usertextarea: HTMLTextAreaElement;
158
269