@@ -45,7 +45,27 @@ function renderTableClassOptions(editor, item) {
4545 . join ( '' ) ;
4646}
4747
48+ // Schema-based checks: static per editor instance, avoid dry-run transactions
49+ function _hasMark ( editor , name ) {
50+ return ! ! editor . schema . marks [ name ] ;
51+ }
52+
53+ function _hasNode ( editor , name ) {
54+ return ! ! editor . schema . nodes [ name ] ;
55+ }
56+
57+ // Two-phase block action: try toggle first, fall back to insertContent
58+ function _toggleOrInsert ( editor , toggleCmd , nodeType , attrs ) {
59+ if ( editor . can ( ) [ toggleCmd ] ( attrs ) ) {
60+ editor . chain ( ) . focus ( ) [ toggleCmd ] ( attrs ) . run ( ) ;
61+ } else {
62+ const content = attrs ? { type : nodeType , attrs } : { type : nodeType } ;
63+ editor . chain ( ) . focus ( ) . insertContent ( content ) . run ( ) ;
64+ }
65+ }
66+
4867const TiptapToolbar = {
68+ // Undo/Redo: must use can() — depends on history state
4969 Undo : {
5070 action : ( editor ) => editor . chain ( ) . focus ( ) . undo ( ) . run ( ) ,
5171 enabled : ( editor ) => editor . can ( ) . undo ( ) ,
@@ -56,41 +76,42 @@ const TiptapToolbar = {
5676 enabled : ( editor ) => editor . can ( ) . redo ( ) ,
5777 type : 'mark' ,
5878 } ,
79+ // Marks: schema check only — marks can always be toggled on text selections
5980 Bold : {
6081 action : ( editor ) => editor . chain ( ) . focus ( ) . toggleBold ( ) . run ( ) ,
61- enabled : ( editor ) => editor . can ( ) . toggleBold ( ) ,
82+ enabled : ( editor ) => _hasMark ( editor , 'bold' ) ,
6283 active : ( editor ) => editor . isActive ( 'bold' ) ,
6384 type : 'mark' ,
6485 } ,
6586 Italic : {
6687 action : ( editor ) => editor . chain ( ) . focus ( ) . toggleItalic ( ) . run ( ) ,
67- enabled : ( editor ) => editor . can ( ) . toggleItalic ( ) ,
88+ enabled : ( editor ) => _hasMark ( editor , 'italic' ) ,
6889 active : ( editor ) => editor . isActive ( 'italic' ) ,
6990 title : 'Italic' ,
7091 type : 'mark' ,
7192 } ,
7293 Underline : {
7394 action : ( editor ) => editor . chain ( ) . focus ( ) . toggleUnderline ( ) . run ( ) ,
74- enabled : ( editor ) => editor . can ( ) . toggleUnderline ( ) ,
95+ enabled : ( editor ) => _hasMark ( editor , 'underline' ) ,
7596 active : ( editor ) => editor . isActive ( 'underline' ) ,
7697 title : 'Underline' ,
7798 type : 'mark' ,
7899 } ,
79100 Strike : {
80101 action : ( editor ) => editor . chain ( ) . focus ( ) . toggleStrike ( ) . run ( ) ,
81- enabled : ( editor ) => editor . can ( ) . toggleStrike ( ) ,
102+ enabled : ( editor ) => _hasMark ( editor , 'strike' ) ,
82103 active : ( editor ) => editor . isActive ( 'strike' ) ,
83104 type : 'mark' ,
84105 } ,
85106 Subscript : {
86107 action : ( editor ) => editor . chain ( ) . focus ( ) . toggleSubscript ( ) . run ( ) ,
87- enabled : ( editor ) => editor . can ( ) . toggleSubscript ( ) ,
108+ enabled : ( editor ) => _hasMark ( editor , 'subscript' ) ,
88109 active : ( editor ) => editor . isActive ( 'subscript' ) ,
89110 type : 'mark' ,
90111 } ,
91112 Superscript : {
92113 action : ( editor ) => editor . chain ( ) . focus ( ) . toggleSuperscript ( ) . run ( ) ,
93- enabled : ( editor ) => editor . can ( ) . toggleSuperscript ( ) ,
114+ enabled : ( editor ) => _hasMark ( editor , 'superscript' ) ,
94115 active : ( editor ) => editor . isActive ( 'superscript' ) ,
95116 type : 'mark' ,
96117 } ,
@@ -102,7 +123,7 @@ const TiptapToolbar = {
102123 }
103124 editor . chain ( ) . focus ( ) . toggleTextColor ( button ?. dataset ?. class || 'text-primary' ) . run ( ) ;
104125 } ,
105- enabled : ( editor ) => editor . can ( ) . toggleTextColor ( ) ,
126+ enabled : ( editor ) => _hasMark ( editor , 'textcolor' ) ,
106127 active : ( editor , button ) => editor . isActive ( 'textcolor' , { class : button . dataset ?. class } ) ,
107128 icon : '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-fonts" viewBox="0 0 16 16"><path d="M12.258 3h-8.51l-.083 2.46h.479c.26-1.544.758-1.783 2.693-1.845l.424-.013v7.827c0 .663-.144.82-1.3.923v.52h4.082v-.52c-1.162-.103-1.306-.26-1.306-.923V3.602l.431.013c1.934.062 2.434.301 2.693 1.846h.479z"/></svg>' ,
108129 type : 'mark' ,
@@ -116,7 +137,7 @@ const TiptapToolbar = {
116137 editor . chain ( ) . focus ( ) . setMark ( 'Q' ) . run ( ) ;
117138 }
118139 } ,
119- enabled : ( editor ) => editor . can ( ) . toggleMark ( 'Q' ) ,
140+ enabled : ( editor ) => _hasMark ( editor , 'Q' ) ,
120141 active : ( editor ) => editor . isActive ( 'Q' ) ,
121142 icon : '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-quote" viewBox="0 0 16 16">' +
122143 '<path d="M12 12a1 1 0 0 0 1-1V8.558a1 1 0 0 0-1-1h-1.388q0-.527.062-1.054.093-.558.31-.992t.559-.683q.34-.279.868-.279V3q-.868 0-1.52.372a3.3 3.3 0 0 0-1.085.992 4.9 4.9 0 0 0-.62 1.458A7.7 7.7 0 0 0 9 7.558V11a1 1 0 0 0 1 1zm-6 0a1 1 0 0 0 1-1V8.558a1 1 0 0 0-1-1H4.612q0-.527.062-1.054.094-.558.31-.992.217-.434.559-.683.34-.279.868-.279V3q-.868 0-1.52.372a3.3 3.3 0 0 0-1.085.992 4.9 4.9 0 0 0-.62 1.458A7.7 7.7 0 0 0 3 7.558V11a1 1 0 0 0 1 1z"/>' +
@@ -132,7 +153,7 @@ const TiptapToolbar = {
132153 editor . chain ( ) . focus ( ) . setMark ( 'Highlight' ) . run ( ) ;
133154 }
134155 } ,
135- enabled : ( editor ) => editor . can ( ) . toggleMark ( 'Highlight' ) ,
156+ enabled : ( editor ) => _hasMark ( editor , 'Highlight' ) ,
136157 active : ( editor ) => editor . isActive ( 'Highlight' ) ,
137158 icon : '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-highlighter" viewBox="0 0 16 16">\n' +
138159 ' <path fill-rule="evenodd" d="M11.096.644a2 2 0 0 1 2.791.036l1.433 1.433a2 2 0 0 1 .035 2.791l-.413.435-8.07 8.995a.5.5 0 0 1-.372.166h-3a.5.5 0 0 1-.234-.058l-.412.412A.5.5 0 0 1 2.5 15h-2a.5.5 0 0 1-.354-.854l1.412-1.412A.5.5 0 0 1 1.5 12.5v-3a.5.5 0 0 1 .166-.372l8.995-8.07zm-.115 1.47L2.727 9.52l3.753 3.753 7.406-8.254zm3.585 2.17.064-.068a1 1 0 0 0-.017-1.396L13.18 1.387a1 1 0 0 0-1.396-.018l-.068.065zM5.293 13.5 2.5 10.707v1.586L3.707 13.5z"/>\n' +
@@ -147,7 +168,7 @@ const TiptapToolbar = {
147168 } ,
148169 enabled : ( editor , button ) => {
149170 if ( button ?. dataset ?. id !== undefined ) {
150- return editor . can ( ) . toggleInlineStyle ( button . dataset . id ) ;
171+ return _hasMark ( editor , 'inlinestyle' ) ;
151172 }
152173 const ext = editor . extensionManager . extensions . find ( e => e . name === 'inlinestyle' ) ;
153174 const styles = editor . options . inlineStyles || ext ?. options ?. styles || [ ] ;
@@ -162,7 +183,7 @@ const TiptapToolbar = {
162183 action : ( editor , button ) => editor . chain ( ) . focus ( ) . toggleBlockStyle ( button ?. dataset ?. id || 0 ) . run ( ) ,
163184 enabled : ( editor , button ) => {
164185 if ( button ?. dataset ?. id !== undefined ) {
165- return editor . can ( ) . toggleBlockStyle ( button . dataset . id ) ;
186+ return _hasNode ( editor , 'blockstyle' ) || ! ! editor . extensionManager . extensions . find ( e => e . name === 'blockstyle' ) ;
166187 }
167188 const ext = editor . extensionManager . extensions . find ( e => e . name === 'blockstyle' ) ;
168189 const styles = editor . options . blockStyles || ext ?. options ?. styles || [ ] ;
@@ -172,56 +193,65 @@ const TiptapToolbar = {
172193 } ,
173194 RemoveFormat : {
174195 action : ( editor ) => editor . chain ( ) . focus ( ) . unsetAllMarks ( ) . run ( ) ,
175- enabled : ( editor ) => editor . can ( ) . unsetAllMarks ( ) ,
196+ enabled : ( ) => true ,
176197 type : 'mark' ,
177198 } ,
199+ // Text alignment: schema check via extension presence
178200 JustifyLeft : {
179201 action : ( editor ) => editor . chain ( ) . focus ( ) . setTextAlign ( 'left' ) . run ( ) ,
180- enabled : ( editor ) => editor . can ( ) . setTextAlign ( 'left ') ,
202+ enabled : ( editor ) => ! ! editor . extensionManager . extensions . find ( e => e . name === 'textAlign ') ,
181203 active : ( editor ) => editor . isActive ( { textAlign : 'left' } ) ,
182204 type : 'block' ,
183205 } ,
184206 JustifyCenter : {
185207 action : ( editor ) => editor . chain ( ) . focus ( ) . setTextAlign ( 'center' ) . run ( ) ,
186- enabled : ( editor ) => editor . can ( ) . setTextAlign ( 'center ') ,
208+ enabled : ( editor ) => ! ! editor . extensionManager . extensions . find ( e => e . name === 'textAlign ') ,
187209 active : ( editor ) => editor . isActive ( ( { textAlign : 'center' } ) ) ,
188210 type : 'block' ,
189211 } ,
190212 JustifyRight : {
191213 action : ( editor ) => editor . chain ( ) . focus ( ) . setTextAlign ( 'right' ) . run ( ) ,
192- enabled : ( editor ) => editor . can ( ) . setTextAlign ( 'right ') ,
214+ enabled : ( editor ) => ! ! editor . extensionManager . extensions . find ( e => e . name === 'textAlign ') ,
193215 active : ( editor ) => editor . isActive ( { textAlign : 'right' } ) ,
194216 type : 'block' ,
195217 } ,
196218 JustifyBlock : {
197219 action : ( editor ) => editor . chain ( ) . focus ( ) . setTextAlign ( 'justify' ) . run ( ) ,
198- enabled : ( editor ) => editor . can ( ) . setTextAlign ( 'justify ') ,
220+ enabled : ( editor ) => ! ! editor . extensionManager . extensions . find ( e => e . name === 'textAlign ') ,
199221 active : ( editor ) => editor . isActive ( { textAlign : 'justify' } ) ,
200222 type : 'block' ,
201223 } ,
224+ // Block nodes: schema check + toggle-or-insert actions
202225 HorizontalRule : {
203- action : ( editor ) => editor . chain ( ) . focus ( ) . setHorizontalRule ( ) . run ( ) ,
204- enabled : ( editor ) => editor . can ( ) . setHorizontalRule ( ) ,
226+ action : ( editor ) => {
227+ if ( editor . can ( ) . setHorizontalRule ( ) ) {
228+ editor . chain ( ) . focus ( ) . setHorizontalRule ( ) . run ( ) ;
229+ } else {
230+ editor . chain ( ) . focus ( ) . insertContent ( { type : 'horizontalRule' } ) . run ( ) ;
231+ }
232+ } ,
233+ enabled : ( editor ) => _hasNode ( editor , 'horizontalRule' ) ,
205234 type : 'block' ,
206235 } ,
207236 NumberedList : {
208237 action : ( editor ) => editor . chain ( ) . focus ( ) . toggleOrderedList ( ) . run ( ) ,
209- enabled : ( editor ) => editor . can ( ) . toggleOrderedList ( ) ,
238+ enabled : ( editor ) => _hasNode ( editor , 'orderedList' ) ,
210239 active : ( editor ) => editor . isActive ( 'orderedList' ) ,
211240 type : 'block' ,
212241 } ,
213242 BulletedList : {
214243 action : ( editor ) => editor . chain ( ) . focus ( ) . toggleBulletList ( ) . run ( ) ,
215- enabled : ( editor ) => editor . can ( ) . toggleBulletList ( ) ,
244+ enabled : ( editor ) => _hasNode ( editor , 'bulletList' ) ,
216245 active : ( editor ) => editor . isActive ( 'bulletList' ) ,
217246 type : 'block' ,
218247 } ,
219248 Blockquote : {
220- action : ( editor ) => editor . chain ( ) . focus ( ) . toggleBlockquote ( ) . run ( ) ,
221- enabled : ( editor ) => editor . can ( ) . toggleBlockquote ( ) ,
249+ action : ( editor ) => _toggleOrInsert ( editor , ' toggleBlockquote' , 'blockquote' ) ,
250+ enabled : ( editor ) => _hasNode ( editor , 'blockquote' ) ,
222251 active : ( editor ) => editor . isActive ( 'blockquote' ) ,
223252 type : 'block' ,
224253 } ,
254+ // Link/Unlink: link uses schema check, unlink checks if link is active
225255 Link : {
226256 action : ( editor ) => {
227257 if ( editor . isActive ( 'link' ) ) {
@@ -240,7 +270,7 @@ const TiptapToolbar = {
240270 editor . chain ( ) . focus ( ) . setLink ( link ) . run ( ) ;
241271 }
242272 } ,
243- enabled : ( editor ) => editor . can ( ) . setLink ( { href : '#' } ) ,
273+ enabled : ( editor ) => _hasMark ( editor , 'link' ) ,
244274 active : ( editor ) => editor . isActive ( 'link' ) ,
245275 attributes : ( editor ) => {
246276 let attrs = editor . getAttributes ( 'link' ) ;
@@ -252,74 +282,75 @@ const TiptapToolbar = {
252282 } ,
253283 Unlink : {
254284 action : ( editor ) => editor . chain ( ) . focus ( ) . unsetLink ( ) . run ( ) ,
255- enabled : ( editor ) => editor . can ( ) . unsetLink ( ) ,
285+ enabled : ( editor ) => editor . isActive ( 'link' ) ,
256286 type : 'mark' ,
257287 } ,
288+ // Table: schema check for insert, isActive('table') for sub-commands
258289 Table : {
259290 action : ( editor , button ) => {
260291 const rows = parseInt ( button ?. dataset ?. rows || 3 ) ;
261292 const cols = parseInt ( button ?. dataset ?. cols || 3 ) ;
262293 const classes = button ?. dataset ?. attr || getDefaultTableClass ( editor . options . tableClasses ) ;
263294 editor . chain ( ) . focus ( ) . insertTable ( { rows : rows , cols : cols } ) . updateAttributes ( 'table' , { addClasses : classes } ) . run ( ) ;
264295 } ,
265- enabled : ( editor ) => editor . can ( ) . insertTable ( { rows : 3 , cols : 3 } ) ,
296+ enabled : ( editor ) => _hasNode ( editor , 'table' ) ,
266297 type : 'mark' ,
267298 items : generateTableMenu ,
268299 class : 'tt-table' ,
269300 } ,
270301 toggleHeaderColumn : {
271302 action : ( editor , button ) => editor . chain ( ) . focus ( ) . toggleHeaderColumn ( ) . run ( ) ,
272- enabled : ( editor ) => editor . can ( ) . toggleHeaderColumn ( ) ,
303+ enabled : ( editor ) => editor . isActive ( 'table' ) ,
273304 active : ( editor ) => editor . isActive ( 'headerColumn' ) ,
274305 type : 'mark' ,
275306 } ,
276307 toggleHeaderRow : {
277308 action : ( editor , button ) => editor . chain ( ) . focus ( ) . toggleHeaderRow ( ) . run ( ) ,
278- enabled : ( editor ) => editor . can ( ) . toggleHeaderRow ( ) ,
309+ enabled : ( editor ) => editor . isActive ( 'table' ) ,
279310 active : ( editor ) => editor . isActive ( 'headerRow' ) ,
280311 type : 'mark' ,
281312 } ,
282313 addColumnBefore : {
283314 action : ( editor , button ) => editor . chain ( ) . focus ( ) . addColumnBefore ( ) . run ( ) ,
284- enabled : ( editor ) => editor . can ( ) . addColumnBefore ( ) ,
315+ enabled : ( editor ) => editor . isActive ( 'table' ) ,
285316 type : 'mark' ,
286317 } ,
287318 addColumnAfter : {
288319 action : ( editor , button ) => editor . chain ( ) . focus ( ) . addColumnAfter ( ) . run ( ) ,
289- enabled : ( editor ) => editor . can ( ) . addColumnAfter ( ) ,
320+ enabled : ( editor ) => editor . isActive ( 'table' ) ,
290321 type : 'mark' ,
291322 } ,
292323 deleteColumn : {
293324 action : ( editor , button ) => editor . chain ( ) . focus ( ) . deleteColumn ( ) . run ( ) ,
294- enabled : ( editor ) => editor . can ( ) . deleteColumn ( ) ,
325+ enabled : ( editor ) => editor . isActive ( 'table' ) ,
295326 type : 'mark' ,
296327 } ,
297328 addRowBefore : {
298329 action : ( editor , button ) => editor . chain ( ) . focus ( ) . addRowBefore ( ) . run ( ) ,
299- enabled : ( editor ) => editor . can ( ) . addRowBefore ( ) ,
330+ enabled : ( editor ) => editor . isActive ( 'table' ) ,
300331 type : 'mark' ,
301332 } ,
302333 addRowAfter : {
303334 action : ( editor , button ) => editor . chain ( ) . focus ( ) . addRowAfter ( ) . run ( ) ,
304- enabled : ( editor ) => editor . can ( ) . addRowAfter ( ) ,
335+ enabled : ( editor ) => editor . isActive ( 'table' ) ,
305336 type : 'mark' ,
306337 } ,
307338 deleteRow : {
308339 action : ( editor , button ) => editor . chain ( ) . focus ( ) . deleteRow ( ) . run ( ) ,
309- enabled : ( editor ) => editor . can ( ) . deleteRow ( ) ,
340+ enabled : ( editor ) => editor . isActive ( 'table' ) ,
310341 type : 'mark' ,
311342 } ,
312343 mergeOrSplit : {
313344 action : ( editor , button ) => editor . chain ( ) . focus ( ) . mergeOrSplit ( ) . run ( ) ,
314- enabled : ( editor ) => editor . can ( ) . mergeOrSplit ( ) ,
345+ enabled : ( editor ) => editor . isActive ( 'table' ) ,
315346 type : 'mark' ,
316347 } ,
317348 tableClass : {
318349 action : ( editor , button ) => {
319350 const classes = button ?. dataset . attr || getDefaultTableClass ( editor . options . tableClasses ) ;
320351 editor . chain ( ) . focus ( ) . updateAttributes ( 'table' , { addClasses : classes } ) . run ( ) ;
321352 } ,
322- enabled : ( editor , button ) => editor . can ( ) . updateAttributes ( 'table' , { addClasses : button ?. dataset . attr || '' } ) ,
353+ enabled : ( editor ) => editor . isActive ( 'table' ) ,
323354 active : ( editor , button ) => {
324355 const classes = editor . getAttributes ( 'table' ) . addClasses ;
325356 return classes && classes === button . dataset . attr ;
@@ -328,20 +359,21 @@ const TiptapToolbar = {
328359 } ,
329360 Code : {
330361 action : ( editor ) => editor . chain ( ) . focus ( ) . toggleCode ( ) . run ( ) ,
331- enabled : ( editor ) => editor . can ( ) . toggleCode ( ) ,
362+ enabled : ( editor ) => _hasMark ( editor , 'code' ) ,
332363 active : ( editor ) => editor . isActive ( 'code' ) ,
333364 type : 'mark' ,
334365 } ,
335366 CodeBlock : {
336- action : ( editor ) => editor . chain ( ) . focus ( ) . toggleCodeBlock ( ) . run ( ) ,
337- enabled : ( editor ) => editor . can ( ) . toggleCodeBlock ( ) ,
367+ action : ( editor ) => _toggleOrInsert ( editor , ' toggleCodeBlock' , 'codeBlock' ) ,
368+ enabled : ( editor ) => _hasNode ( editor , 'codeBlock' ) ,
338369 active : ( editor ) => editor . isActive ( 'codeBlock' ) ,
339370 type : 'block' ,
340371 } ,
341372 HardBreak : {
342373 action : ( editor ) => editor . chain ( ) . focus ( ) . setHardBreak ( ) . run ( ) ,
343- enabled : ( editor ) => editor . can ( ) . setHardBreak ( ) ,
374+ enabled : ( editor ) => _hasNode ( editor , 'hardBreak' ) ,
344375 } ,
376+ // Format dropdown and headings: toggle-or-insert
345377 Format : {
346378 insitu : [ 'Paragraph' , 'Heading1' , 'Heading2' , 'Heading3' , 'Heading4' , 'Heading5' , 'Heading6' , '|' ] ,
347379 iconx : '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-type" viewBox="0 0 16 16">\n' +
@@ -350,48 +382,54 @@ const TiptapToolbar = {
350382 type : 'block' ,
351383 } ,
352384 Heading1 : {
353- action : ( editor ) => editor . chain ( ) . focus ( ) . setHeading ( { level : 1 } ) . run ( ) ,
354- enabled : ( editor ) => editor . can ( ) . setHeading ( { level : 1 } ) ,
385+ action : ( editor ) => _toggleOrInsert ( editor , 'toggleHeading' , 'heading' , { level : 1 } ) ,
386+ enabled : ( editor ) => _hasNode ( editor , 'heading' ) ,
355387 active : ( editor ) => editor . isActive ( 'heading' , { level : 1 } ) ,
356388 type : 'block' ,
357389 } ,
358390 Heading2 : {
359- action : ( editor ) => editor . chain ( ) . focus ( ) . setHeading ( { level : 2 } ) . run ( ) ,
360- enabled : ( editor ) => editor . can ( ) . setHeading ( { level : 2 } ) ,
391+ action : ( editor ) => _toggleOrInsert ( editor , 'toggleHeading' , 'heading' , { level : 2 } ) ,
392+ enabled : ( editor ) => _hasNode ( editor , 'heading' ) ,
361393 active : ( editor ) => editor . isActive ( 'heading' , { level : 2 } ) ,
362394 type : 'block' ,
363395 } ,
364396 Heading3 : {
365- action : ( editor ) => editor . chain ( ) . focus ( ) . setHeading ( { level : 3 } ) . run ( ) ,
366- enabled : ( editor ) => editor . can ( ) . setHeading ( { level : 3 } ) ,
397+ action : ( editor ) => _toggleOrInsert ( editor , 'toggleHeading' , 'heading' , { level : 3 } ) ,
398+ enabled : ( editor ) => _hasNode ( editor , 'heading' ) ,
367399 active : ( editor ) => editor . isActive ( 'heading' , { level : 3 } ) ,
368400 title : 'Heading 3' ,
369401 type : 'block' ,
370402 } ,
371403 Heading4 : {
372- action : ( editor ) => editor . chain ( ) . focus ( ) . setHeading ( { level : 4 } ) . run ( ) ,
373- enabled : ( editor ) => editor . can ( ) . setHeading ( { level : 4 } ) ,
404+ action : ( editor ) => _toggleOrInsert ( editor , 'toggleHeading' , 'heading' , { level : 4 } ) ,
405+ enabled : ( editor ) => _hasNode ( editor , 'heading' ) ,
374406 active : ( editor ) => editor . isActive ( 'heading' , { level : 4 } ) ,
375407 title : 'Heading 4' ,
376408 type : 'block' ,
377409 } ,
378410 Heading5 : {
379- action : ( editor ) => editor . chain ( ) . focus ( ) . setHeading ( { level : 5 } ) . run ( ) ,
380- enabled : ( editor ) => editor . can ( ) . setHeading ( { level : 5 } ) ,
411+ action : ( editor ) => _toggleOrInsert ( editor , 'toggleHeading' , 'heading' , { level : 5 } ) ,
412+ enabled : ( editor ) => _hasNode ( editor , 'heading' ) ,
381413 active : ( editor ) => editor . isActive ( 'heading' , { level : 5 } ) ,
382414 title : 'Heading 5' ,
383415 type : 'block' ,
384416 } ,
385417 Heading6 : {
386- action : ( editor ) => editor . chain ( ) . focus ( ) . setHeading ( { level : 6 } ) . run ( ) ,
387- enabled : ( editor ) => editor . can ( ) . setHeading ( { level : 6 } ) ,
418+ action : ( editor ) => _toggleOrInsert ( editor , 'toggleHeading' , 'heading' , { level : 6 } ) ,
419+ enabled : ( editor ) => _hasNode ( editor , 'heading' ) ,
388420 active : ( editor ) => editor . isActive ( 'heading' , { level : 6 } ) ,
389421 title : 'Heading 6' ,
390422 type : 'block' ,
391423 } ,
392424 Paragraph : {
393- action : ( editor ) => editor . chain ( ) . focus ( ) . setParagraph ( ) . run ( ) ,
394- enabled : ( editor ) => editor . can ( ) . setParagraph ( ) ,
425+ action : ( editor ) => {
426+ if ( editor . can ( ) . setParagraph ( ) ) {
427+ editor . chain ( ) . focus ( ) . setParagraph ( ) . run ( ) ;
428+ } else {
429+ editor . chain ( ) . focus ( ) . insertContent ( { type : 'paragraph' } ) . run ( ) ;
430+ }
431+ } ,
432+ enabled : ( editor ) => _hasNode ( editor , 'paragraph' ) ,
395433 active : ( editor ) => editor . isActive ( 'paragraph' ) ,
396434 title : 'Paragraph' ,
397435 type : 'block' ,
0 commit comments