@pinkpixel/marzipan 1.1.0 → 1.1.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 (130) hide show
  1. package/README.md +72 -37
  2. package/dist/_basePickBy-D4kyG5Tu.js +152 -0
  3. package/dist/_basePickBy-D4kyG5Tu.js.map +1 -0
  4. package/dist/_baseUniq-s5uZhHMt.js +615 -0
  5. package/dist/_baseUniq-s5uZhHMt.js.map +1 -0
  6. package/dist/arc-Cd2Fw3V6.js +84 -0
  7. package/dist/arc-Cd2Fw3V6.js.map +1 -0
  8. package/dist/architectureDiagram-VXUJARFQ-ylT61Lln.js +4663 -0
  9. package/dist/architectureDiagram-VXUJARFQ-ylT61Lln.js.map +1 -0
  10. package/dist/blockDiagram-VD42YOAC-CoIxLSyQ.js +2257 -0
  11. package/dist/blockDiagram-VD42YOAC-CoIxLSyQ.js.map +1 -0
  12. package/dist/c4Diagram-YG6GDRKO-CsQimMM6.js +1581 -0
  13. package/dist/c4Diagram-YG6GDRKO-CsQimMM6.js.map +1 -0
  14. package/dist/channel-0tZUlnqz.js +6 -0
  15. package/dist/channel-0tZUlnqz.js.map +1 -0
  16. package/dist/chunk-4BX2VUAB-DVkBhLxy.js +9 -0
  17. package/dist/chunk-4BX2VUAB-DVkBhLxy.js.map +1 -0
  18. package/dist/chunk-55IACEB6-CVQcegI-.js +9 -0
  19. package/dist/chunk-55IACEB6-CVQcegI-.js.map +1 -0
  20. package/dist/chunk-B4BG7PRW-DPUTNckV.js +1376 -0
  21. package/dist/chunk-B4BG7PRW-DPUTNckV.js.map +1 -0
  22. package/dist/chunk-DI55MBZ5-F7DI2N9R.js +1371 -0
  23. package/dist/chunk-DI55MBZ5-F7DI2N9R.js.map +1 -0
  24. package/dist/chunk-FMBD7UC4-C3wNpU7V.js +20 -0
  25. package/dist/chunk-FMBD7UC4-C3wNpU7V.js.map +1 -0
  26. package/dist/chunk-QN33PNHL-BOdqrixJ.js +20 -0
  27. package/dist/chunk-QN33PNHL-BOdqrixJ.js.map +1 -0
  28. package/dist/chunk-QZHKN3VN-BFPNdgmW.js +16 -0
  29. package/dist/chunk-QZHKN3VN-BFPNdgmW.js.map +1 -0
  30. package/dist/chunk-TZMSLE5B-BZuxNW58.js +65 -0
  31. package/dist/chunk-TZMSLE5B-BZuxNW58.js.map +1 -0
  32. package/dist/classDiagram-2ON5EDUG-CiRjpBEe.js +17 -0
  33. package/dist/classDiagram-2ON5EDUG-CiRjpBEe.js.map +1 -0
  34. package/dist/classDiagram-v2-WZHVMYZB-CiRjpBEe.js +17 -0
  35. package/dist/classDiagram-v2-WZHVMYZB-CiRjpBEe.js.map +1 -0
  36. package/dist/clone-Bm_onhkP.js +9 -0
  37. package/dist/clone-Bm_onhkP.js.map +1 -0
  38. package/dist/cose-bilkent-S5V4N54A-D9xMKgKB.js +2609 -0
  39. package/dist/cose-bilkent-S5V4N54A-D9xMKgKB.js.map +1 -0
  40. package/dist/dagre-6UL2VRFP-BhIQJjaK.js +445 -0
  41. package/dist/dagre-6UL2VRFP-BhIQJjaK.js.map +1 -0
  42. package/dist/diagram-PSM6KHXK-h4YEzD1S.js +532 -0
  43. package/dist/diagram-PSM6KHXK-h4YEzD1S.js.map +1 -0
  44. package/dist/diagram-QEK2KX5R-spuV0akZ.js +218 -0
  45. package/dist/diagram-QEK2KX5R-spuV0akZ.js.map +1 -0
  46. package/dist/diagram-S2PKOQOG-CQx-wsyw.js +143 -0
  47. package/dist/diagram-S2PKOQOG-CQx-wsyw.js.map +1 -0
  48. package/dist/erDiagram-Q2GNP2WA-Cqkjjf2a.js +842 -0
  49. package/dist/erDiagram-Q2GNP2WA-Cqkjjf2a.js.map +1 -0
  50. package/dist/flowDiagram-NV44I4VS-mCXE9u9b.js +1621 -0
  51. package/dist/flowDiagram-NV44I4VS-mCXE9u9b.js.map +1 -0
  52. package/dist/ganttDiagram-JELNMOA3-Bz1GBIHE.js +2671 -0
  53. package/dist/ganttDiagram-JELNMOA3-Bz1GBIHE.js.map +1 -0
  54. package/dist/gitGraphDiagram-V2S2FVAM-Be01Oq15.js +700 -0
  55. package/dist/gitGraphDiagram-V2S2FVAM-Be01Oq15.js.map +1 -0
  56. package/dist/graph-DVWVTM7e.js +248 -0
  57. package/dist/graph-DVWVTM7e.js.map +1 -0
  58. package/dist/index-kKw24iiA.js +34 -0
  59. package/dist/index-kKw24iiA.js.map +1 -0
  60. package/dist/index.d.ts +0 -11
  61. package/dist/index.d.ts.map +1 -1
  62. package/dist/index.js +270 -277
  63. package/dist/index.js.map +1 -1
  64. package/dist/infoDiagram-HS3SLOUP-joTtnw9j.js +25 -0
  65. package/dist/infoDiagram-HS3SLOUP-joTtnw9j.js.map +1 -0
  66. package/dist/journeyDiagram-XKPGCS4Q-CMVu7VEd.js +835 -0
  67. package/dist/journeyDiagram-XKPGCS4Q-CMVu7VEd.js.map +1 -0
  68. package/dist/kanban-definition-3W4ZIXB7-CfanK5Eg.js +720 -0
  69. package/dist/kanban-definition-3W4ZIXB7-CfanK5Eg.js.map +1 -0
  70. package/dist/katex-Cj93GM5Y.js +11605 -0
  71. package/dist/katex-Cj93GM5Y.js.map +1 -0
  72. package/dist/layout-BC8VSiQq.js +1336 -0
  73. package/dist/layout-BC8VSiQq.js.map +1 -0
  74. package/dist/linear-GV5CIa17.js +260 -0
  75. package/dist/linear-GV5CIa17.js.map +1 -0
  76. package/dist/marzipan.d.ts +1 -2
  77. package/dist/marzipan.d.ts.map +1 -1
  78. package/dist/marzipan.js +1 -19
  79. package/dist/marzipan.js.map +1 -1
  80. package/dist/mermaid.core-cSWK5aGH.js +15302 -0
  81. package/dist/mermaid.core-cSWK5aGH.js.map +1 -0
  82. package/dist/mindmap-definition-VGOIOE7T-Vu_RTZar.js +785 -0
  83. package/dist/mindmap-definition-VGOIOE7T-Vu_RTZar.js.map +1 -0
  84. package/dist/parser.d.ts.map +1 -1
  85. package/dist/parser.js +6 -5
  86. package/dist/parser.js.map +1 -1
  87. package/dist/pieDiagram-ADFJNKIX-BUcd1l-6.js +162 -0
  88. package/dist/pieDiagram-ADFJNKIX-BUcd1l-6.js.map +1 -0
  89. package/dist/plugins/accentSwatchPlugin.d.ts +1 -1
  90. package/dist/plugins/accentSwatchPlugin.d.ts.map +1 -1
  91. package/dist/plugins/accentSwatchPlugin.js +162 -81
  92. package/dist/plugins/accentSwatchPlugin.js.map +1 -1
  93. package/dist/plugins/block-handles.d.ts +10 -2
  94. package/dist/plugins/block-handles.d.ts.map +1 -1
  95. package/dist/plugins/block-handles.js +77 -51
  96. package/dist/plugins/block-handles.js.map +1 -1
  97. package/dist/plugins/index.d.ts +0 -2
  98. package/dist/plugins/index.d.ts.map +1 -1
  99. package/dist/plugins/index.js +27 -29
  100. package/dist/plugins/index.js.map +1 -1
  101. package/dist/plugins/mermaidPlugin.js +1 -1
  102. package/dist/plugins/tinyHighlight.d.ts.map +1 -1
  103. package/dist/plugins/tinyHighlight.js +34 -22
  104. package/dist/plugins/tinyHighlight.js.map +1 -1
  105. package/dist/quadrantDiagram-AYHSOK5B-B1ekOH99.js +1023 -0
  106. package/dist/quadrantDiagram-AYHSOK5B-B1ekOH99.js.map +1 -0
  107. package/dist/requirementDiagram-UZGBJVZJ-BNcVcwNf.js +851 -0
  108. package/dist/requirementDiagram-UZGBJVZJ-BNcVcwNf.js.map +1 -0
  109. package/dist/sankeyDiagram-TZEHDZUN-BpHcdj5K.js +811 -0
  110. package/dist/sankeyDiagram-TZEHDZUN-BpHcdj5K.js.map +1 -0
  111. package/dist/sequenceDiagram-WL72ISMW-D5UyNvsv.js +2512 -0
  112. package/dist/sequenceDiagram-WL72ISMW-D5UyNvsv.js.map +1 -0
  113. package/dist/stateDiagram-FKZM4ZOC-C8DBscXu.js +264 -0
  114. package/dist/stateDiagram-FKZM4ZOC-C8DBscXu.js.map +1 -0
  115. package/dist/stateDiagram-v2-4FDKWEC3-CHqwUDPY.js +17 -0
  116. package/dist/stateDiagram-v2-4FDKWEC3-CHqwUDPY.js.map +1 -0
  117. package/dist/timeline-definition-IT6M3QCI-Dtg0oJbr.js +796 -0
  118. package/dist/timeline-definition-IT6M3QCI-Dtg0oJbr.js.map +1 -0
  119. package/dist/treemap-GDKQZRPO-rbQo3Em-.js +17926 -0
  120. package/dist/treemap-GDKQZRPO-rbQo3Em-.js.map +1 -0
  121. package/dist/xychartDiagram-PRI3JC2R-uNpgYSnV.js +1341 -0
  122. package/dist/xychartDiagram-PRI3JC2R-uNpgYSnV.js.map +1 -0
  123. package/docs/.vitepress/config.ts +1 -1
  124. package/docs/README.md +6 -8
  125. package/docs/TABLE_OF_CONTENTS.md +4 -1
  126. package/docs/api.md +262 -202
  127. package/docs/index.md +22 -19
  128. package/docs/plugins.md +27 -23
  129. package/package.json +1 -1
  130. package/docs/block-handles.md +0 -325
package/docs/api.md CHANGED
@@ -20,13 +20,13 @@ A comprehensive guide to the core Marzipan class, bundled action toolkit, and fi
20
20
 
21
21
  ```javascript
22
22
  // Import Marzipan
23
- import { Marzipan } from '@pinkpixel/marzipan';
23
+ import { Marzipan } from "@pinkpixel/marzipan";
24
24
 
25
25
  // Initialize single editor
26
- const [editor] = new Marzipan('#my-editor');
26
+ const [editor] = new Marzipan("#my-editor");
27
27
 
28
28
  // Or use the static helper for multiple elements
29
- const editors = Marzipan.init('.markdown-editor');
29
+ const editors = Marzipan.init(".markdown-editor");
30
30
  ```
31
31
 
32
32
  ## Constructor
@@ -36,28 +36,30 @@ const editors = Marzipan.init('.markdown-editor');
36
36
  Creates one or more Marzipan editor instances.
37
37
 
38
38
  **Parameters:**
39
- - `target` *(string|Element|NodeList|Array)* - Target element(s) to initialize
39
+
40
+ - `target` _(string|Element|NodeList|Array)_ - Target element(s) to initialize
40
41
  - `string` - CSS selector
41
42
  - `Element` - Single DOM element
42
43
  - `NodeList` - Collection of DOM elements
43
44
  - `Array` - Array of DOM elements
44
- - `options` *(Object)* - Configuration options (see [Options](#options))
45
+ - `options` _(Object)_ - Configuration options (see [Options](#options))
45
46
 
46
47
  **Returns:** `Array<Marzipan>` - Array of Marzipan instances
47
48
 
48
49
  **Example:**
50
+
49
51
  ```javascript
50
52
  // Single element by selector
51
- const editors = new Marzipan('#editor');
53
+ const editors = new Marzipan("#editor");
52
54
 
53
55
  // Multiple elements
54
- const editors = new Marzipan('.markdown-editor');
56
+ const editors = new Marzipan(".markdown-editor");
55
57
 
56
58
  // With options
57
- const editors = new Marzipan('#editor', {
58
- fontSize: '16px',
59
+ const editors = new Marzipan("#editor", {
60
+ fontSize: "16px",
59
61
  toolbar: true,
60
- showStats: true
62
+ showStats: true,
61
63
  });
62
64
  ```
63
65
 
@@ -66,6 +68,7 @@ const editors = new Marzipan('#editor', {
66
68
  ### Content Management
67
69
 
68
70
  #### `getValue()`
71
+
69
72
  Get the current markdown content from the editor.
70
73
 
71
74
  **Returns:** `string` - Current markdown content
@@ -76,16 +79,19 @@ console.log(content); // "# Hello World\n\nThis is markdown content"
76
79
  ```
77
80
 
78
81
  #### `setValue(value)`
82
+
79
83
  Set the markdown content in the editor.
80
84
 
81
85
  **Parameters:**
82
- - `value` *(string)* - Markdown content to set
86
+
87
+ - `value` _(string)_ - Markdown content to set
83
88
 
84
89
  ```javascript
85
- editor.setValue('# New Content\n\nThis replaces the existing content.');
90
+ editor.setValue("# New Content\n\nThis replaces the existing content.");
86
91
  ```
87
92
 
88
93
  #### `getStats()`
94
+
89
95
  Return live statistics for the current document.
90
96
 
91
97
  **Returns:** `{ chars: number, words: number, lines: number, line: number, column: number }`
@@ -96,11 +102,13 @@ console.log(`${stats.words} words • line ${stats.line}:${stats.column}`);
96
102
  ```
97
103
 
98
104
  #### `getRenderedHTML(options)`
105
+
99
106
  Get the rendered HTML of the current content.
100
107
 
101
108
  **Parameters:**
102
- - `options` *(Object)* - Rendering options
103
- - `cleanHTML` *(boolean)* - Remove syntax markers and Marzipan-specific classes
109
+
110
+ - `options` _(Object)_ - Rendering options
111
+ - `cleanHTML` _(boolean)_ - Remove syntax markers and Marzipan-specific classes
104
112
 
105
113
  **Returns:** `string` - Rendered HTML
106
114
 
@@ -113,11 +121,13 @@ const cleanHtml = editor.getRenderedHTML({ cleanHTML: true });
113
121
  ```
114
122
 
115
123
  #### `getPreviewHTML()`
124
+
116
125
  Get the current preview element's HTML (includes all syntax markers).
117
126
 
118
127
  **Returns:** `string` - Current preview HTML as displayed
119
128
 
120
129
  #### `getCleanHTML()`
130
+
121
131
  Get clean HTML without any Marzipan-specific markup. Shorthand for `getRenderedHTML({ cleanHTML: true })`.
122
132
 
123
133
  **Returns:** `string` - Clean HTML suitable for export
@@ -125,6 +135,7 @@ Get clean HTML without any Marzipan-specific markup. Shorthand for `getRenderedH
125
135
  ### Focus Management
126
136
 
127
137
  #### `focus()`
138
+
128
139
  Focus the editor textarea.
129
140
 
130
141
  ```javascript
@@ -132,6 +143,7 @@ editor.focus();
132
143
  ```
133
144
 
134
145
  #### `blur()`
146
+
135
147
  Blur the editor textarea.
136
148
 
137
149
  ```javascript
@@ -141,20 +153,23 @@ editor.blur();
141
153
  ### DOM Helpers
142
154
 
143
155
  #### `getContainer()`
156
+
144
157
  Return the root container element that wraps the toolbar, textarea, and preview.
145
158
 
146
159
  ```javascript
147
160
  const container = editor.getContainer();
148
- container.classList.add('rounded');
161
+ container.classList.add("rounded");
149
162
  ```
150
163
 
151
164
  ### Display Modes
152
165
 
153
166
  #### `showPlainTextarea(show?)`
167
+
154
168
  Toggle between plain textarea and overlay markdown preview.
155
169
 
156
170
  **Parameters:**
157
- - `show` *(boolean | undefined)* - `true` to show plain textarea, `false` to show overlay. Call without arguments to read the current state.
171
+
172
+ - `show` _(boolean | undefined)_ - `true` to show plain textarea, `false` to show overlay. Call without arguments to read the current state.
158
173
 
159
174
  **Returns:** `boolean` - Current plain textarea state
160
175
 
@@ -170,10 +185,12 @@ const isPlain = editor.showPlainTextarea();
170
185
  ```
171
186
 
172
187
  #### `showPreviewMode(show)`
188
+
173
189
  Toggle between edit and preview-only modes.
174
190
 
175
191
  **Parameters:**
176
- - `show` *(boolean)* - `true` for preview mode, `false` for edit mode
192
+
193
+ - `show` _(boolean)_ - `true` for preview mode, `false` for edit mode
177
194
 
178
195
  **Returns:** `boolean` - Current preview mode state
179
196
 
@@ -186,19 +203,22 @@ editor.showPreviewMode(false);
186
203
  ```
187
204
 
188
205
  #### `showStats(show)`
206
+
189
207
  Show or hide the statistics bar.
190
208
 
191
209
  **Parameters:**
192
- - `show` *(boolean)* - Whether to show statistics
210
+
211
+ - `show` _(boolean)_ - Whether to show statistics
193
212
 
194
213
  ```javascript
195
- editor.showStats(true); // Show character/word/line counts
214
+ editor.showStats(true); // Show character/word/line counts
196
215
  editor.showStats(false); // Hide statistics
197
216
  ```
198
217
 
199
218
  ### Editor State
200
219
 
201
220
  #### `updatePreview()`
221
+
202
222
  Manually update the markdown preview. Usually called automatically.
203
223
 
204
224
  ```javascript
@@ -206,30 +226,34 @@ editor.updatePreview();
206
226
  ```
207
227
 
208
228
  #### `isInitialized()`
229
+
209
230
  Check if the editor is fully initialized.
210
231
 
211
232
  **Returns:** `boolean` - Initialization status
212
233
 
213
234
  ```javascript
214
235
  if (editor.isInitialized()) {
215
- console.log('Editor is ready!');
236
+ console.log("Editor is ready!");
216
237
  }
217
238
  ```
218
239
 
219
240
  #### `reinit(options)`
241
+
220
242
  Re-initialize the editor with new options.
221
243
 
222
244
  **Parameters:**
223
- - `options` *(Object)* - New options to apply (merged with existing options)
245
+
246
+ - `options` _(Object)_ - New options to apply (merged with existing options)
224
247
 
225
248
  ```javascript
226
249
  editor.reinit({
227
- fontSize: '18px',
228
- toolbar: false
250
+ fontSize: "18px",
251
+ toolbar: false,
229
252
  });
230
253
  ```
231
254
 
232
255
  #### `destroy()`
256
+
233
257
  Destroy the editor instance and cleanup resources.
234
258
 
235
259
  ```javascript
@@ -239,28 +263,33 @@ editor.destroy();
239
263
  ## Static Methods
240
264
 
241
265
  ### `Marzipan.init(target, options)`
266
+
242
267
  Convenience method to create new instances. Equivalent to `new Marzipan()`.
243
268
 
244
269
  **Parameters:**
245
- - `target` *(string|Element|NodeList|Array)* - Target element(s)
246
- - `options` *(Object)* - Configuration options
270
+
271
+ - `target` _(string|Element|NodeList|Array)_ - Target element(s)
272
+ - `options` _(Object)_ - Configuration options
247
273
 
248
274
  **Returns:** `Array<Marzipan>` - Array of instances
249
275
 
250
276
  ### `Marzipan.getInstance(element)`
277
+
251
278
  Get existing Marzipan instance from a DOM element.
252
279
 
253
280
  **Parameters:**
254
- - `element` *(Element)* - DOM element
281
+
282
+ - `element` _(Element)_ - DOM element
255
283
 
256
284
  **Returns:** `Marzipan|null` - Instance or null if not found
257
285
 
258
286
  ```javascript
259
- const element = document.getElementById('my-editor');
287
+ const element = document.getElementById("my-editor");
260
288
  const instance = Marzipan.getInstance(element);
261
289
  ```
262
290
 
263
291
  ### `Marzipan.destroyAll()`
292
+
264
293
  Destroy all existing Marzipan instances.
265
294
 
266
295
  ```javascript
@@ -268,38 +297,42 @@ Marzipan.destroyAll();
268
297
  ```
269
298
 
270
299
  ### `Marzipan.setTheme(theme, customColors)`
300
+
271
301
  Set global theme for all Marzipan instances.
272
302
 
273
303
  **Parameters:**
274
- - `theme` *(string|Object)* - Theme name or custom theme object
275
- - `customColors` *(Object)* - Optional color overrides
304
+
305
+ - `theme` _(string|Object)_ - Theme name or custom theme object
306
+ - `customColors` _(Object)_ - Optional color overrides
276
307
 
277
308
  ```javascript
278
309
  // Use built-in theme
279
- Marzipan.setTheme('cave');
310
+ Marzipan.setTheme("cave");
280
311
 
281
312
  // Use custom theme
282
313
  Marzipan.setTheme({
283
- name: 'custom',
314
+ name: "custom",
284
315
  colors: {
285
- bgPrimary: '#1a1a1a',
286
- bgSecondary: '#121212',
287
- text: '#ffffff',
288
- toolbarBg: '#141414'
289
- }
316
+ bgPrimary: "#1a1a1a",
317
+ bgSecondary: "#121212",
318
+ text: "#ffffff",
319
+ toolbarBg: "#141414",
320
+ },
290
321
  });
291
322
 
292
323
  // Override colors
293
- Marzipan.setTheme('solar', {
294
- bgPrimary: '#002b36'
324
+ Marzipan.setTheme("solar", {
325
+ bgPrimary: "#002b36",
295
326
  });
296
327
  ```
297
328
 
298
329
  ### `Marzipan.injectStyles(force)`
330
+
299
331
  Manually inject Marzipan styles into the document.
300
332
 
301
333
  **Parameters:**
302
- - `force` *(boolean)* - Force re-injection even if already injected
334
+
335
+ - `force` _(boolean)_ - Force re-injection even if already injected
303
336
 
304
337
  ```javascript
305
338
  Marzipan.injectStyles(true); // Force style re-injection
@@ -310,15 +343,16 @@ Marzipan.injectStyles(true); // Force style re-injection
310
343
  Marzipan ships a zero-dependency markdown action toolkit alongside the core class. Import the helpers from `@pinkpixel/marzipan` and pass the target `HTMLTextAreaElement`.
311
344
 
312
345
  ```ts
313
- import { actions } from '@pinkpixel/marzipan';
346
+ import { actions } from "@pinkpixel/marzipan";
314
347
 
315
- const textarea = document.querySelector('textarea');
348
+ const textarea = document.querySelector("textarea");
316
349
  if (textarea) {
317
350
  actions.toggleBold(textarea);
318
351
  }
319
352
  ```
320
353
 
321
354
  Available helpers include:
355
+
322
356
  - `toggleBold(textarea)`
323
357
  - `toggleItalic(textarea)`
324
358
  - `toggleCode(textarea)`
@@ -342,7 +376,7 @@ These functions mirror the toolbar and keyboard shortcut behaviour, making it ea
342
376
  ### Strikethrough
343
377
 
344
378
  ```ts
345
- import { actions } from '@pinkpixel/marzipan';
379
+ import { actions } from "@pinkpixel/marzipan";
346
380
 
347
381
  // Wraps selection in ~~…~~ or ~…~
348
382
  actions.toggleStrikethrough(textarea);
@@ -351,7 +385,7 @@ actions.toggleStrikethrough(textarea);
351
385
  ### Horizontal Rule
352
386
 
353
387
  ```ts
354
- import { actions } from '@pinkpixel/marzipan';
388
+ import { actions } from "@pinkpixel/marzipan";
355
389
 
356
390
  // Inserts --- at the cursor with surrounding newlines
357
391
  actions.insertHorizontalRule(textarea);
@@ -367,6 +401,7 @@ Marzipan automatically shows a floating URL tooltip whenever the cursor moves in
367
401
  ```
368
402
 
369
403
  **Implementation details:**
404
+
370
405
  - Uses the CSS Anchor Positioning API (`position-anchor` / `position-area`) for pixel-accurate placement below the link.
371
406
  - Gracefully degrades — in browsers that do not support CSS anchor positioning the tooltip is silently disabled.
372
407
  - Managed by the `LinkTooltip` class, which is instantiated automatically by every editor and cleaned up on `destroy()`.
@@ -380,122 +415,142 @@ Default options and their descriptions:
380
415
  ```javascript
381
416
  const defaultOptions = {
382
417
  // Typography
383
- fontSize: '14px', // Font size
384
- lineHeight: 1.6, // Line height multiplier
385
- fontFamily: '...', // Monospace font stack
386
- padding: '16px', // Internal padding
387
-
418
+ fontSize: "14px", // Font size
419
+ lineHeight: 1.6, // Line height multiplier
420
+ fontFamily: "...", // Monospace font stack
421
+ padding: "16px", // Internal padding
422
+
388
423
  // Mobile-specific styles
389
424
  mobile: {
390
- fontSize: '16px', // Font size on mobile (prevents zoom)
391
- padding: '12px', // Reduced padding on mobile
392
- lineHeight: 1.5 // Adjusted line height
425
+ fontSize: "16px", // Font size on mobile (prevents zoom)
426
+ padding: "12px", // Reduced padding on mobile
427
+ lineHeight: 1.5, // Adjusted line height
393
428
  },
394
-
429
+
395
430
  // Textarea properties
396
- textareaProps: {}, // Native textarea attributes
397
-
431
+ textareaProps: {}, // Native textarea attributes
432
+
398
433
  // Behavior
399
- autofocus: false, // Auto-focus on initialization
400
- autoResize: false, // Auto-expand height with content
401
- minHeight: '100px', // Minimum height (autoResize mode)
402
- maxHeight: null, // Maximum height (autoResize mode)
403
- placeholder: 'Start typing...', // Placeholder text
404
- value: '', // Initial content
405
-
434
+ autofocus: false, // Auto-focus on initialization
435
+ autoResize: false, // Auto-expand height with content
436
+ minHeight: "100px", // Minimum height (autoResize mode)
437
+ maxHeight: null, // Maximum height (autoResize mode)
438
+ placeholder: "Start typing...", // Placeholder text
439
+ value: "", // Initial content
440
+
406
441
  // Callbacks
407
- onChange: null, // Content change callback
408
- onKeydown: null, // Keydown event callback
409
-
442
+ onChange: null, // Content change callback
443
+ onKeydown: null, // Keydown event callback
444
+
410
445
  // Features
411
- showActiveLineRaw: false, // Show active line without markdown rendering
412
- showStats: false, // Show statistics bar
413
- toolbar: false, // Show toolbar (true/false or config object)
414
- statsFormatter: null, // Custom stats formatter function
415
- smartLists: true, // Enable smart list continuation
416
-
446
+ showActiveLineRaw: false, // Show active line without markdown rendering
447
+ showStats: false, // Show statistics bar
448
+ toolbar: false, // Show toolbar (true/false or config object)
449
+ statsFormatter: null, // Custom stats formatter function
450
+ smartLists: true, // Enable smart list continuation
451
+
417
452
  // Themes (applied per-instance)
418
- theme: null // Instance-specific theme override
453
+ theme: null, // Instance-specific theme override
419
454
  };
420
455
  ```
421
456
 
422
457
  ### Option Details
423
458
 
424
459
  #### `textareaProps`
460
+
425
461
  Apply native textarea attributes:
426
462
 
427
463
  ```javascript
428
- new Marzipan('#editor', {
464
+ new Marzipan("#editor", {
429
465
  textareaProps: {
430
- 'data-testid': 'markdown-input',
431
- 'aria-label': 'Markdown editor',
466
+ "data-testid": "markdown-input",
467
+ "aria-label": "Markdown editor",
432
468
  maxlength: 5000,
433
- style: { border: '2px solid blue' }
434
- }
469
+ style: { border: "2px solid blue" },
470
+ },
435
471
  });
436
472
  ```
437
473
 
438
474
  #### `onChange(value, instance)`
475
+
439
476
  Called when content changes:
440
477
 
441
478
  ```javascript
442
- new Marzipan('#editor', {
479
+ new Marzipan("#editor", {
443
480
  onChange: (value, instance) => {
444
- console.log('Content changed:', value.length, 'characters');
481
+ console.log("Content changed:", value.length, "characters");
445
482
  // Save to localStorage, send to server, etc.
446
- }
483
+ },
447
484
  });
448
485
  ```
449
486
 
450
487
  #### `onKeydown(event, instance)`
488
+
451
489
  Called for keydown events:
452
490
 
453
491
  ```javascript
454
- new Marzipan('#editor', {
492
+ new Marzipan("#editor", {
455
493
  onKeydown: (event, instance) => {
456
- if (event.key === 'Enter' && event.ctrlKey) {
457
- console.log('Ctrl+Enter pressed');
494
+ if (event.key === "Enter" && event.ctrlKey) {
495
+ console.log("Ctrl+Enter pressed");
458
496
  // Custom save logic
459
497
  }
460
- }
498
+ },
461
499
  });
462
500
  ```
463
501
 
464
502
  #### `statsFormatter(stats)`
503
+
465
504
  Custom statistics display:
466
505
 
467
506
  ```javascript
468
- new Marzipan('#editor', {
507
+ new Marzipan("#editor", {
469
508
  showStats: true,
470
509
  statsFormatter: (stats) => {
471
510
  return `📝 ${stats.words} words • 📏 ${stats.chars} chars • 📄 ${stats.lines} lines`;
472
- }
511
+ },
473
512
  });
474
513
  ```
475
514
 
476
515
  Stats object contains:
477
- - `chars` *(number)* - Character count
478
- - `words` *(number)* - Word count
479
- - `lines` *(number)* - Line count
480
- - `line` *(number)* - Current line number
481
- - `column` *(number)* - Current column number
516
+
517
+ - `chars` _(number)_ - Character count
518
+ - `words` _(number)_ - Word count
519
+ - `lines` _(number)_ - Line count
520
+ - `line` _(number)_ - Current line number
521
+ - `column` _(number)_ - Current column number
482
522
 
483
523
  #### `toolbar`
524
+
484
525
  Enable toolbar with default buttons:
485
526
 
486
527
  ```javascript
487
528
  // Enable with defaults
488
- new Marzipan('#editor', { toolbar: true });
529
+ new Marzipan("#editor", { toolbar: true });
489
530
 
490
531
  // Custom button configuration
491
- new Marzipan('#editor', {
532
+ new Marzipan("#editor", {
492
533
  toolbar: {
493
- buttons: ['bold', 'italic', 'code', '|', 'link', 'quote', '|', 'bulletList', 'orderedList', '|', 'plain', 'view']
494
- }
534
+ buttons: [
535
+ "bold",
536
+ "italic",
537
+ "code",
538
+ "|",
539
+ "link",
540
+ "quote",
541
+ "|",
542
+ "bulletList",
543
+ "orderedList",
544
+ "|",
545
+ "plain",
546
+ "view",
547
+ ],
548
+ },
495
549
  });
496
550
  ```
497
551
 
498
552
  Available button shorthands:
553
+
499
554
  - `bold`, `italic`, `code`
500
555
  - `link`, `quote`
501
556
  - `h1`, `h2`, `h3`
@@ -519,39 +574,39 @@ Marzipan includes built-in themes and supports custom themes.
519
574
 
520
575
  ```javascript
521
576
  // Global theme (affects all instances)
522
- Marzipan.setTheme('cave');
577
+ Marzipan.setTheme("cave");
523
578
 
524
579
  // Instance-specific theme
525
- new Marzipan('#editor', {
526
- theme: 'cave' // Only this instance uses cave theme
580
+ new Marzipan("#editor", {
581
+ theme: "cave", // Only this instance uses cave theme
527
582
  });
528
583
 
529
584
  // Custom theme
530
585
  const myTheme = {
531
- name: 'purple',
586
+ name: "purple",
532
587
  colors: {
533
- bgPrimary: '#2d1b69',
534
- bgSecondary: '#24124f',
535
- text: '#e1d5f7',
536
- textSecondary: '#c9b4e8',
537
- h1: '#bb9af7',
538
- h2: '#9ece6a',
539
- h3: '#ff9e64',
540
- link: '#a1c4ff',
541
- codeBg: 'rgba(155, 136, 196, 0.2)',
542
- toolbarBg: '#1b0f47'
543
- }
588
+ bgPrimary: "#2d1b69",
589
+ bgSecondary: "#24124f",
590
+ text: "#e1d5f7",
591
+ textSecondary: "#c9b4e8",
592
+ h1: "#bb9af7",
593
+ h2: "#9ece6a",
594
+ h3: "#ff9e64",
595
+ link: "#a1c4ff",
596
+ codeBg: "rgba(155, 136, 196, 0.2)",
597
+ toolbarBg: "#1b0f47",
598
+ },
544
599
  };
545
600
 
546
601
  Marzipan.setTheme(myTheme);
547
602
 
548
603
  // Per-instance tweaks can also be merged with the `colors` option
549
- new Marzipan('#editor', {
550
- theme: 'solar',
604
+ new Marzipan("#editor", {
605
+ theme: "solar",
551
606
  colors: {
552
- toolbarActive: '#ffe066',
553
- cursor: '#ff8c00'
554
- }
607
+ toolbarActive: "#ffe066",
608
+ cursor: "#ff8c00",
609
+ },
555
610
  });
556
611
  ```
557
612
 
@@ -560,38 +615,38 @@ new Marzipan('#editor', {
560
615
  ```javascript
561
616
  const themeColors = {
562
617
  // Base appearance
563
- bgPrimary: '#ffffff',
564
- bgSecondary: '#f8f9fa',
565
- text: '#333333',
566
- textSecondary: '#666666',
618
+ bgPrimary: "#ffffff",
619
+ bgSecondary: "#f8f9fa",
620
+ text: "#333333",
621
+ textSecondary: "#666666",
567
622
 
568
623
  // Typography accents
569
- h1: '#1a73e8',
570
- h2: '#0f9d58',
571
- h3: '#fbbc05',
572
- strong: '#1a73e8',
573
- em: '#d93025',
574
- link: '#1a73e8',
575
- code: '#d93025',
576
- codeBg: 'rgba(26, 115, 232, 0.1)',
624
+ h1: "#1a73e8",
625
+ h2: "#0f9d58",
626
+ h3: "#fbbc05",
627
+ strong: "#1a73e8",
628
+ em: "#d93025",
629
+ link: "#1a73e8",
630
+ code: "#d93025",
631
+ codeBg: "rgba(26, 115, 232, 0.1)",
577
632
 
578
633
  // Block elements
579
- blockquote: '#5f6368',
580
- hr: '#dadce0',
581
- syntaxMarker: 'rgba(95, 99, 104, 0.5)',
582
- listMarker: '#1a73e8',
634
+ blockquote: "#5f6368",
635
+ hr: "#dadce0",
636
+ syntaxMarker: "rgba(95, 99, 104, 0.5)",
637
+ listMarker: "#1a73e8",
583
638
 
584
639
  // Caret & selection
585
- cursor: '#1a73e8',
586
- selection: 'rgba(26, 115, 232, 0.2)',
640
+ cursor: "#1a73e8",
641
+ selection: "rgba(26, 115, 232, 0.2)",
587
642
 
588
643
  // Toolbar styling
589
- toolbarBg: '#ffffff',
590
- toolbarBorder: 'rgba(0, 0, 0, 0.08)',
591
- toolbarIcon: '#1a73e8',
592
- toolbarHover: '#f1f3f4',
593
- toolbarActive: '#e8f0fe',
594
- border: '#dadce0'
644
+ toolbarBg: "#ffffff",
645
+ toolbarBorder: "rgba(0, 0, 0, 0.08)",
646
+ toolbarIcon: "#1a73e8",
647
+ toolbarHover: "#f1f3f4",
648
+ toolbarActive: "#e8f0fe",
649
+ border: "#dadce0",
595
650
  };
596
651
  ```
597
652
 
@@ -600,50 +655,54 @@ const themeColors = {
600
655
  ### Content Events
601
656
 
602
657
  #### Change Event
658
+
603
659
  Triggered when content changes via the `onChange` callback:
604
660
 
605
661
  ```javascript
606
- new Marzipan('#editor', {
662
+ new Marzipan("#editor", {
607
663
  onChange: (value, instance) => {
608
- console.log('Content:', value);
609
- console.log('Instance ID:', instance.instanceId);
610
- }
664
+ console.log("Content:", value);
665
+ console.log("Instance ID:", instance.instanceId);
666
+ },
611
667
  });
612
668
  ```
613
669
 
614
670
  #### Input Events
671
+
615
672
  Access native textarea events through the `textarea` property:
616
673
 
617
674
  ```javascript
618
- const editor = new Marzipan('#editor')[0];
675
+ const editor = new Marzipan("#editor")[0];
619
676
 
620
- editor.textarea.addEventListener('focus', () => {
621
- console.log('Editor focused');
677
+ editor.textarea.addEventListener("focus", () => {
678
+ console.log("Editor focused");
622
679
  });
623
680
 
624
- editor.textarea.addEventListener('blur', () => {
625
- console.log('Editor blurred');
681
+ editor.textarea.addEventListener("blur", () => {
682
+ console.log("Editor blurred");
626
683
  });
627
684
  ```
628
685
 
629
686
  ### Keyboard Events
630
687
 
631
688
  #### Global Keyboard Handler
689
+
632
690
  Use the `onKeydown` callback:
633
691
 
634
692
  ```javascript
635
- new Marzipan('#editor', {
693
+ new Marzipan("#editor", {
636
694
  onKeydown: (event, instance) => {
637
695
  // Handle custom shortcuts
638
- if (event.ctrlKey && event.key === 's') {
696
+ if (event.ctrlKey && event.key === "s") {
639
697
  event.preventDefault();
640
698
  saveContent(instance.getValue());
641
699
  }
642
- }
700
+ },
643
701
  });
644
702
  ```
645
703
 
646
704
  #### Built-in Shortcuts
705
+
647
706
  Marzipan includes built-in keyboard shortcuts:
648
707
 
649
708
  - `Tab` / `Shift+Tab` - Indent/outdent text
@@ -658,9 +717,9 @@ Marzipan includes built-in keyboard shortcuts:
658
717
 
659
718
  ```javascript
660
719
  // Simple editor
661
- const editors = new Marzipan('#editor', {
662
- placeholder: 'Write your markdown here...',
663
- value: '# Hello World\n\nStart writing!'
720
+ const editors = new Marzipan("#editor", {
721
+ placeholder: "Write your markdown here...",
722
+ value: "# Hello World\n\nStart writing!",
664
723
  });
665
724
  ```
666
725
 
@@ -668,34 +727,34 @@ const editors = new Marzipan('#editor', {
668
727
 
669
728
  ```javascript
670
729
  // Editor with all features
671
- const editors = new Marzipan('#advanced-editor', {
730
+ const editors = new Marzipan("#advanced-editor", {
672
731
  // Appearance
673
- fontSize: '16px',
732
+ fontSize: "16px",
674
733
  lineHeight: 1.7,
675
- theme: 'cave',
676
-
734
+ theme: "cave",
735
+
677
736
  // Features
678
737
  toolbar: true,
679
738
  showStats: true,
680
739
  autoResize: true,
681
- minHeight: '200px',
682
- maxHeight: '600px',
683
-
740
+ minHeight: "200px",
741
+ maxHeight: "600px",
742
+
684
743
  // Behavior
685
744
  autofocus: true,
686
745
  smartLists: true,
687
746
  showActiveLineRaw: true,
688
-
747
+
689
748
  // Events
690
749
  onChange: (value, instance) => {
691
- localStorage.setItem('markdown-content', value);
750
+ localStorage.setItem("markdown-content", value);
692
751
  },
693
-
752
+
694
753
  // Custom stats
695
754
  statsFormatter: ({ words, chars, lines, line, column }) => {
696
755
  const readingTime = Math.ceil(words / 200);
697
756
  return `${words} words (${readingTime} min read) • Line ${line}:${column}`;
698
- }
757
+ },
699
758
  });
700
759
 
701
760
  const editor = editors[0];
@@ -705,14 +764,14 @@ const editor = editors[0];
705
764
 
706
765
  ```javascript
707
766
  // Initialize multiple editors with different configs
708
- const editors = Marzipan.init('.editor', {
767
+ const editors = Marzipan.init(".editor", {
709
768
  toolbar: true,
710
- showStats: true
769
+ showStats: true,
711
770
  });
712
771
 
713
772
  // Customize individual editors
714
- editors[0].reinit({ theme: 'solar' });
715
- editors[1].reinit({ theme: 'cave' });
773
+ editors[0].reinit({ theme: "solar" });
774
+ editors[1].reinit({ theme: "cave" });
716
775
 
717
776
  // Handle all editors
718
777
  editors.forEach((editor, index) => {
@@ -725,26 +784,26 @@ editors.forEach((editor, index) => {
725
784
  ```javascript
726
785
  // Create custom theme
727
786
  const darkTheme = {
728
- name: 'dark-purple',
787
+ name: "dark-purple",
729
788
  colors: {
730
- background: '#1a1a2e',
731
- text: '#eee',
732
- comment: '#888',
733
- keyword: '#9d65ff',
734
- string: '#5fb3d4',
735
- number: '#f093a3',
736
- selection: '#2d2d4d',
737
- border: '#333',
738
- toolbar: '#16213e'
739
- }
789
+ background: "#1a1a2e",
790
+ text: "#eee",
791
+ comment: "#888",
792
+ keyword: "#9d65ff",
793
+ string: "#5fb3d4",
794
+ number: "#f093a3",
795
+ selection: "#2d2d4d",
796
+ border: "#333",
797
+ toolbar: "#16213e",
798
+ },
740
799
  };
741
800
 
742
801
  // Apply globally
743
802
  Marzipan.setTheme(darkTheme);
744
803
 
745
804
  // Or per instance
746
- new Marzipan('#editor', {
747
- theme: darkTheme
805
+ new Marzipan("#editor", {
806
+ theme: darkTheme,
748
807
  });
749
808
  ```
750
809
 
@@ -754,48 +813,48 @@ new Marzipan('#editor', {
754
813
  // Complete integration example
755
814
  class MarkdownApp {
756
815
  constructor() {
757
- this.editors = new Marzipan('.markdown-editor', {
816
+ this.editors = new Marzipan(".markdown-editor", {
758
817
  toolbar: true,
759
818
  showStats: true,
760
819
  autoResize: true,
761
- onChange: this.handleChange.bind(this)
820
+ onChange: this.handleChange.bind(this),
762
821
  });
763
-
822
+
764
823
  this.editor = this.editors[0];
765
824
  this.setupCustomButtons();
766
825
  }
767
-
826
+
768
827
  handleChange(value, instance) {
769
828
  // Auto-save
770
829
  clearTimeout(this.saveTimeout);
771
830
  this.saveTimeout = setTimeout(() => {
772
831
  this.saveToServer(value);
773
832
  }, 1000);
774
-
833
+
775
834
  // Update word count display
776
835
  this.updateWordCount(value);
777
836
  }
778
-
837
+
779
838
  setupCustomButtons() {
780
839
  // Add custom save button
781
- const toolbar = this.editor.container.querySelector('.marzipan-toolbar');
782
- const saveBtn = document.createElement('button');
783
- saveBtn.textContent = '💾 Save';
840
+ const toolbar = this.editor.container.querySelector(".marzipan-toolbar");
841
+ const saveBtn = document.createElement("button");
842
+ saveBtn.textContent = "💾 Save";
784
843
  saveBtn.onclick = () => this.saveToServer(this.editor.getValue());
785
844
  toolbar.appendChild(saveBtn);
786
845
  }
787
-
846
+
788
847
  saveToServer(content) {
789
- fetch('/api/save', {
790
- method: 'POST',
791
- headers: { 'Content-Type': 'application/json' },
792
- body: JSON.stringify({ content })
848
+ fetch("/api/save", {
849
+ method: "POST",
850
+ headers: { "Content-Type": "application/json" },
851
+ body: JSON.stringify({ content }),
793
852
  });
794
853
  }
795
-
854
+
796
855
  updateWordCount(content) {
797
- const words = content.split(/\s+/).filter(w => w.length > 0).length;
798
- document.getElementById('word-count').textContent = `${words} words`;
856
+ const words = content.split(/\s+/).filter((w) => w.length > 0).length;
857
+ document.getElementById("word-count").textContent = `${words} words`;
799
858
  }
800
859
  }
801
860
 
@@ -808,11 +867,11 @@ const app = new MarkdownApp();
808
867
  Every plugin located in `src/plugins` publishes as `@pinkpixel/marzipan/plugins/<name>`. Each export is a factory so you can configure behaviour before passing it to the editor:
809
868
 
810
869
  ```ts
811
- import { tablePlugin } from '@pinkpixel/marzipan/plugins/tablePlugin';
812
- import { mermaidPlugin } from '@pinkpixel/marzipan/plugins/mermaidPlugin';
870
+ import { tablePlugin } from "@pinkpixel/marzipan/plugins/tablePlugin";
871
+ import { mermaidPlugin } from "@pinkpixel/marzipan/plugins/mermaidPlugin";
813
872
 
814
- new Marzipan('#editor', {
815
- plugins: [tablePlugin(), mermaidPlugin({ theme: 'dark' })],
873
+ new Marzipan("#editor", {
874
+ plugins: [tablePlugin(), mermaidPlugin({ theme: "dark" })],
816
875
  });
817
876
  ```
818
877
 
@@ -828,6 +887,7 @@ Marzipan supports modern browsers:
828
887
  - Edge 79+
829
888
 
830
889
  Key requirements:
890
+
831
891
  - CSS Custom Properties (CSS Variables)
832
892
  - ES6 Classes
833
893
  - Template Literals