markdown-text-editor 2.0.0-beta.0 → 2.0.0-beta.2

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.
Files changed (68) hide show
  1. package/README.md +78 -4
  2. package/dist/markdown-text-editor.css +1 -1
  3. package/dist/markdown-text-editor.es.js +858 -799
  4. package/dist/markdown-text-editor.es.js.map +1 -1
  5. package/dist/markdown-text-editor.min.js +67 -67
  6. package/dist/markdown-text-editor.min.js.map +1 -1
  7. package/dist/markdown-text-editor.umd.js +67 -67
  8. package/dist/markdown-text-editor.umd.js.map +1 -1
  9. package/locale/ar.js +55 -0
  10. package/locale/az.js +55 -0
  11. package/locale/bg.js +55 -0
  12. package/locale/bn.js +55 -0
  13. package/locale/bs.js +55 -0
  14. package/locale/ca.js +55 -0
  15. package/locale/cs.js +55 -0
  16. package/locale/da.js +55 -0
  17. package/locale/de.js +55 -0
  18. package/locale/el.js +55 -0
  19. package/locale/es.js +55 -0
  20. package/locale/et.js +55 -0
  21. package/locale/fa.js +55 -0
  22. package/locale/fi.js +55 -0
  23. package/locale/fil.js +55 -0
  24. package/locale/fr.js +55 -0
  25. package/locale/ga.js +55 -0
  26. package/locale/he.js +55 -0
  27. package/locale/hi.js +55 -0
  28. package/locale/hr.js +55 -0
  29. package/locale/hu.js +55 -0
  30. package/locale/hy.js +55 -0
  31. package/locale/id.js +55 -0
  32. package/locale/is.js +55 -0
  33. package/locale/it.js +55 -0
  34. package/locale/ja.js +55 -0
  35. package/locale/kn.js +55 -0
  36. package/locale/ko.js +55 -0
  37. package/locale/locale.d.ts +10 -0
  38. package/locale/lt.js +55 -0
  39. package/locale/lv.js +55 -0
  40. package/locale/mk.js +55 -0
  41. package/locale/mr.js +55 -0
  42. package/locale/ms.js +55 -0
  43. package/locale/mt.js +55 -0
  44. package/locale/nl.js +55 -0
  45. package/locale/no.js +55 -0
  46. package/locale/pl.js +55 -0
  47. package/locale/pt.js +55 -0
  48. package/locale/ro.js +55 -0
  49. package/locale/ru.js +55 -0
  50. package/locale/sk.js +55 -0
  51. package/locale/sl.js +55 -0
  52. package/locale/sq.js +55 -0
  53. package/locale/sr.js +55 -0
  54. package/locale/sv.js +55 -0
  55. package/locale/sw.js +55 -0
  56. package/locale/ta.js +55 -0
  57. package/locale/te.js +55 -0
  58. package/locale/template.js +62 -0
  59. package/locale/th.js +55 -0
  60. package/locale/tr.js +55 -0
  61. package/locale/uk.js +55 -0
  62. package/locale/ur.js +55 -0
  63. package/locale/uz.js +55 -0
  64. package/locale/vi.js +55 -0
  65. package/locale/zh-hk.js +55 -0
  66. package/locale/zh.js +55 -0
  67. package/package.json +22 -8
  68. package/types/index.d.ts +16 -5
package/README.md CHANGED
@@ -13,7 +13,7 @@ A lightweight, embeddable JavaScript Markdown editor that transforms a standard
13
13
 
14
14
  A native-first Markdown editor built on a standard textarea. No data binding, no API — just drop it in and your forms keep working as-is.
15
15
 
16
- **Works standalone.** No Frutjam, no Tailwind, no framework required, the styles are bundled.
16
+ **Works standalone.** No Frutjam, no Tailwind, no framework required. One script and one stylesheet.
17
17
 
18
18
  ![Hybrid mode: headings, bold text and list markers styled live inside the textarea while the Markdown syntax stays visible](https://cdn.frutjam.com/media/plugins/hybrid-mode-markdown-editor.webp)
19
19
 
@@ -40,7 +40,7 @@ Most JavaScript markdown editors (EasyMDE, SimpleMDE, CodeMirror-based editors)
40
40
  | Swap the markdown parser | ✅ | ❌ |
41
41
  | Keyboard shortcuts | ✅ | Partial |
42
42
  | Dark mode / theming | ✅ | Limited |
43
- | Bundle size, gzipped | 54 KB | 107 KB (JS + CSS) |
43
+ | Bundle size, gzipped | 57 KB (JS + CSS) | 107 KB (JS + CSS) |
44
44
 
45
45
  ## 🚀 Quick Start
46
46
 
@@ -90,6 +90,22 @@ Import the stylesheet **or** link it, never both. If you forget it entirely the
90
90
 
91
91
  That's it. Form submission, `.value` access, and all native textarea behaviour work exactly as before.
92
92
 
93
+ ### Upgrading from 1.x
94
+
95
+ **Add the stylesheet.** It used to be carried inside the JavaScript and injected as a `<style>` element. It is now a real file, so an existing setup keeps working but renders unstyled until you link or import it. The editor says so in the console rather than leaving you to guess.
96
+
97
+ ```javascript
98
+ import 'markdown-text-editor/style.css'; // bundlers
99
+ ```
100
+
101
+ ```html
102
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/markdown-text-editor/dist/markdown-text-editor.css">
103
+ ```
104
+
105
+ If you load the editor from an unpinned CDN URL, this reaches you the moment 2.0.0 publishes. Pin a version if you are not ready.
106
+
107
+ That is the whole breaking change. `labels` was renamed to `locale` and still works under the old name, so nothing else needs touching.
108
+
93
109
  ## ✨ Features
94
110
 
95
111
  - 🔌 **Native Form Integration** — Works exactly like a standard `<textarea>`. No complex APIs — just use `.value` or the `name` attribute. Compatible with Django, Laravel, PHP, Rails, Node.js, and with React or Vue via a ref and `destroy()` on unmount
@@ -106,12 +122,14 @@ That's it. Form submission, `.value` access, and all native textarea behaviour w
106
122
  - 🛡️ **XSS Safe** — Preview output sanitized via [DOMPurify](https://github.com/cure53/DOMPurify) before rendering, including the output of a custom renderer
107
123
  - 🛡️ **CSP Compatible** — No inline event handlers, no `eval`, and no injected `<style>` element. The stylesheet is a real file you link, so a strict policy needs no `'unsafe-inline'` exception for either `script-src` or `style-src` ([#42](https://github.com/nezanuha/markdown-text-editor/issues/42))
108
124
  - 🌍 **RTL Support** — Native Right-to-Left support for Arabic, Urdu, Farsi, and other RTL languages
125
+ - 🗣️ **Translatable Interface** — Every tooltip, menu item, dialog field and screen reader name goes through the `locale` option, keyed by the English string. `locale/template.js` lists all 45 of them so you don't have to go looking. Fifty-six languages ship with the package; you import the one you need
109
126
  - 🌙 **Dark Mode & Theming** — Inherits `data-theme` from any ancestor element. Built-in light, dark, snowberry, and darkberry themes. Fully customizable via CSS variables
110
127
  - 🧩 **Custom Tools** — Add your own toolbar button with `{ custom: { title, icon, action } }`, or extend `MarkdownEditor.Tool` when it builds its own markup. Keyboard shortcuts, translation and teardown work exactly as they do for the built-ins. No fork, no patching
111
128
  - 🎛️ **Modular Toolbar** — Pick exactly which tools appear and in what order
112
129
  - 🟦 **TypeScript Ready** — Definitions ship with the package. Options, toolbar entries and variable shapes are all checked, so a mistyped tool name is a compile error rather than a silently missing button
130
+ - 🖥️ **SSR Safe** — Importing it on the server doesn't throw, so Next.js, Remix and Nuxt need no `dynamic(..., { ssr: false })` wrapper. The `<textarea>` is in the server HTML with its content, and the editor enhances it after hydration, so there's no markup mismatch and nothing pops in
113
131
  - 📦 **Universal Module Support** — ESM, CommonJS, UMD, and IIFE. Works with Vite, webpack, Rollup, or directly via `<script src>` CDN — no configuration needed
114
- - 🚀 **High Performance** — ~40KB gzipped JS plus ~13KB gzipped CSS, cached separately. Debounced preview, cached layout calculations, conflict-free Tab/Enter handling for large documents
132
+ - 🚀 **High Performance** — ~43KB gzipped JS plus ~14KB gzipped CSS, cached separately. Debounced preview, cached layout calculations, conflict-free Tab/Enter handling for large documents
115
133
 
116
134
  ## 🛠 Developer Workflow
117
135
 
@@ -189,6 +207,53 @@ new MarkdownEditor('#markdown-editor', { toolbar: ['bold', EmbedTool, 'preview']
189
207
 
190
208
  Two helpers exist for tools that need them: `editor.renderMarkdown(md)` returns sanitized HTML exactly as the preview does, and `editor.createToolbar(textarea, ['bold', 'italic'])` builds a real toolbar bound to another textarea, for a tool collecting rich text in its own dialog.
191
209
 
210
+ ### Translate the interface
211
+
212
+ Every tooltip, menu item, dialog field and screen reader name goes through the `locale` option, keyed by the English string. Anything you leave out stays in English.
213
+
214
+ ```javascript
215
+ import fr from 'markdown-text-editor/locale/fr.js';
216
+
217
+ new MarkdownEditor('#markdown-editor', { locale: fr });
218
+ ```
219
+
220
+ `locale` takes the strings, not a language code. `locale: 'fr'` is a compile error in TypeScript and logs what to write instead in JavaScript. Importing the one language you want is why nobody downloads the other fifty-five.
221
+
222
+ <details>
223
+ <summary><strong>56 languages ship with the package</strong></summary>
224
+
225
+ `ar` Arabic · `az` Azerbaijani · `bg` Bulgarian · `bn` Bengali · `bs` Bosnian · `ca` Catalan · `cs` Czech · `da` Danish · `de` German · `el` Greek · `es` Spanish · `et` Estonian · `fa` Persian · `fi` Finnish · `fil` Filipino · `fr` French · `ga` Irish · `he` Hebrew · `hi` Hindi · `hr` Croatian · `hu` Hungarian · `hy` Armenian · `id` Indonesian · `is` Icelandic · `it` Italian · `ja` Japanese · `kn` Kannada · `ko` Korean · `lt` Lithuanian · `lv` Latvian · `mk` Macedonian · `mr` Marathi · `ms` Malay · `mt` Maltese · `nl` Dutch · `no` Norwegian · `pl` Polish · `pt` Portuguese · `ro` Romanian · `ru` Russian · `sk` Slovak · `sl` Slovenian · `sq` Albanian · `sr` Serbian · `sv` Swedish · `sw` Swahili · `ta` Tamil · `te` Telugu · `th` Thai · `tr` Turkish · `uk` Ukrainian · `ur` Urdu · `uz` Uzbek · `vi` Vietnamese · `zh` Chinese (Simplified) · `zh-hk` Chinese (Hong Kong)
226
+
227
+ English needs no file; it is what the editor falls back to.
228
+
229
+ None of these has been checked by a native speaker yet, so each file exports `reviewed = false` and says so in its header. If one reads wrong to you, [a pull request](https://github.com/nezanuha/markdown-text-editor/issues) correcting a single line is welcome and genuinely useful. Languages with more than one plural form, such as Polish and Arabic, currently get one wording that reads correctly for most counts but not all.
230
+
231
+ </details>
232
+
233
+ Partial is fine, and you can override a shipped translation without forking it:
234
+
235
+ ```javascript
236
+ import fr from 'markdown-text-editor/locale/fr.js';
237
+
238
+ new MarkdownEditor('#markdown-editor', {
239
+ locale: { ...fr, 'Image': 'Photo' } // your wording wins
240
+ });
241
+ ```
242
+
243
+ **`locale/template.js` lists every string**, English on both sides. Copy it to add a language, or map it through a translation system you already have, which keeps the editor's wording consistent with the rest of your interface:
244
+
245
+ ```javascript
246
+ import template from 'markdown-text-editor/locale/template.js';
247
+
248
+ const locale = Object.fromEntries(
249
+ Object.keys(template).map(key => [key, i18n.t(`editor.${key}`)])
250
+ );
251
+
252
+ new MarkdownEditor('#markdown-editor', { locale });
253
+ ```
254
+
255
+ Counts carry a `{n}` placeholder, so `'{n} words'` can become `'{n} mots'` or `'mots : {n}'` and the number lands where that language wants it. CSS class names never change, so `.bold-btn` stays `.bold-btn` in every language.
256
+
192
257
  ### Tear down in SPAs
193
258
 
194
259
  ```javascript
@@ -199,8 +264,15 @@ editor.destroy();
199
264
  In React, create the editor in an effect and return `destroy` as the cleanup — that also covers StrictMode running effects twice in development:
200
265
 
201
266
  ```jsx
267
+ // Options are read once, so reach the latest onChange through a ref rather
268
+ // than rebuilding the editor whenever the parent re-renders
269
+ const onChangeRef = useRef(onChange);
270
+ onChangeRef.current = onChange;
271
+
202
272
  useEffect(() => {
203
- const editor = new MarkdownEditor(ref.current, { onChange });
273
+ const editor = new MarkdownEditor(ref.current, {
274
+ onChange: (value) => onChangeRef.current?.(value),
275
+ });
204
276
  return () => editor.destroy();
205
277
  }, []);
206
278
  ```
@@ -209,6 +281,8 @@ Use `defaultValue`, not `value`. The editor writes to the textarea directly, so
209
281
 
210
282
  The same two rules cover Svelte, Angular and anything else: don't bind the value, and call `destroy()` on unmount. In Angular, `onChange` fires outside the zone, so wrap it in `zone.run()` for change detection to notice.
211
283
 
284
+ This is also all you need for server-side rendering. `useEffect`, `onMounted` and `onMount` never run on the server, so the DOM work stays in the browser and importing the package server-side is safe. Next.js, Remix and Nuxt need no `ssr: false` wrapper, and the `<textarea>` ships in the server HTML with its content already in it.
285
+
212
286
  Options are read once when the editor is constructed. Changing them later has no effect — destroy the editor and create a new one instead.
213
287
 
214
288
  ## 📖 Documentation