Skip to content

Commit 901d531

Browse files
committed
fix: custom styles were always disabled
1 parent 55a217a commit 901d531

File tree

4 files changed

+87
-16
lines changed

4 files changed

+87
-16
lines changed

private/js/cms.tiptap.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import Placeholder from '@tiptap/extension-placeholder';
1212
import Subscript from '@tiptap/extension-subscript';
1313
import Superscript from '@tiptap/extension-superscript';
1414
import {TableCell, TableHeader, TableRow} from '@tiptap/extension-table';
15-
import {TextAlign, TextAlignOptions} from '@tiptap/extension-text-align';
15+
import {TextAlign} from '@tiptap/extension-text-align';
1616
import TiptapToolbar from "./tiptap_plugins/cms.tiptap.toolbar";
1717

1818
import {TextColor, Highlight, InlineQuote, InlineStyle, BlockStyle} from "./tiptap_plugins/cms.styles";

private/js/tiptap_plugins/cms.styles.js

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,17 @@ function validateAttributes(node, styleAttributes) {
210210
* Renders the HTML by merging provided attributes with the default ones. Outputs
211211
* a structured array containing the tag, merged attributes, and content placeholder.
212212
*/
213+
/**
214+
* Returns the resolved styles for an extension. Editor options take
215+
* precedence over extension defaults.
216+
*/
217+
function resolveStyles(ext) {
218+
const editorStyles = ext.name === 'blockstyle' ?
219+
ext.editor.options.blockStyles :
220+
ext.editor.options.inlineStyles;
221+
return editorStyles || ext.options.styles || [];
222+
}
223+
213224
const Style = {
214225
addOptions() {
215226
return { styles: [] };
@@ -223,14 +234,9 @@ const Style = {
223234
},
224235

225236
parseHTML() {
226-
const styles = this.name === 'blockstyle' ?
227-
this.editor.options.blockStyles :
228-
this.editor.options.inlineStyles;
229-
if (styles) {
230-
this.options.styles = styles;
231-
}
237+
const styles = resolveStyles(this);
232238

233-
return (this.options.styles || []).map(style => {
239+
return styles.map(style => {
234240
return {
235241
tag: style.element || '*',
236242
getAttrs: node => validateAttributes(node, style.attributes) && (
@@ -275,14 +281,19 @@ const InlineStyle = Mark.create({
275281

276282
addOptions() {
277283
return {
278-
styles: [],
284+
styles: [
285+
{ name: 'Small', element: 'small' },
286+
{ name: 'Kbd', element: 'kbd' },
287+
{ name: 'Var', element: 'var' },
288+
{ name: 'Samp', element: 'samp' },
289+
],
279290
};
280291
},
281292

282293
addCommands() {
283294
return {
284295
toggleInlineStyle: (id) => ({commands}) => {
285-
const style = this.options.styles[id];
296+
const style = resolveStyles(this)[id];
286297
if (!style) {
287298
return false;
288299
}
@@ -296,7 +307,7 @@ const InlineStyle = Mark.create({
296307
});
297308
},
298309
activeInlineStyle: (id) => ({editor}) => {
299-
const style = this.options.styles[id];
310+
const style = resolveStyles(this)[id];
300311
if (!style || !editor.isActive(this.name)) {
301312
return false;
302313
}
@@ -348,14 +359,17 @@ const BlockStyle = Node.create({
348359
addCommands() {
349360
return {
350361
toggleBlockStyle: (id) => ({commands}) => {
351-
const style = this.options.styles[id];
352-
return style && commands.toggleWrap(this.name, {
362+
const style = resolveStyles(this)[id];
363+
if (!style) {
364+
return false;
365+
}
366+
return commands.toggleWrap(this.name, {
353367
tag: style.element,
354368
attributes: style.attributes,
355369
});
356370
},
357371
activeBlockStyle: (id) => ({editor}) => {
358-
const style = this.options.styles[id];
372+
const style = resolveStyles(this)[id];
359373
return style && editor.isActive(this.name, {
360374
tag: style.element,
361375
attributes: style.attributes,

private/js/tiptap_plugins/cms.tiptap.toolbar.js

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,15 +145,29 @@ const TiptapToolbar = {
145145
action: (editor, button) => {
146146
editor.chain().focus().toggleInlineStyle(button?.dataset?.id ||0).run();
147147
},
148-
enabled: (editor, button) => editor.can().toggleInlineStyle(button?.dataset?.id || 0),
148+
enabled: (editor, button) => {
149+
if (button?.dataset?.id !== undefined) {
150+
return editor.can().toggleInlineStyle(button.dataset.id);
151+
}
152+
const ext = editor.extensionManager.extensions.find(e => e.name === 'inlinestyle');
153+
const styles = editor.options.inlineStyles || ext?.options?.styles || [];
154+
return styles.length > 0;
155+
},
149156
active: (editor, button) => editor.commands.activeInlineStyle(button?.dataset?.id || 0),
150157

151158
},
152159
BlockStyles: {
153160
type: 'mark',
154161
class: 'vertical js-set-active-text',
155162
action: (editor, button) => editor.chain().focus().toggleBlockStyle(button?.dataset?.id || 0).run(),
156-
enabled: (editor, button) => editor.can().toggleBlockStyle(button?.dataset?.id || 0),
163+
enabled: (editor, button) => {
164+
if (button?.dataset?.id !== undefined) {
165+
return editor.can().toggleBlockStyle(button.dataset.id);
166+
}
167+
const ext = editor.extensionManager.extensions.find(e => e.name === 'blockstyle');
168+
const styles = editor.options.blockStyles || ext?.options?.styles || [];
169+
return styles.length > 0;
170+
},
157171
active: (editor, button) => editor.commands.activeBlockStyle(button?.dataset?.id || 0),
158172
},
159173
RemoveFormat: {

tests/js/cms.styles.test.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,26 @@ describe('Tiptap style extensions', () => {
8787
expect(html).not.toContain('<samp>');
8888
});
8989

90+
it('enables InlineStyles when styles are configured', () => {
91+
const editor = createEditorWithContent('test-inline-enabled', '<p>test</p>', {
92+
toolbar: [['Bold', 'InlineStyles']],
93+
inlineStyles: [
94+
{ name: 'Small', element: 'small' },
95+
],
96+
});
97+
98+
expect(editor.can().toggleInlineStyle(0)).toBe(true);
99+
});
100+
101+
it('enables InlineStyles with default styles when no inlineStyles option given', () => {
102+
const editor = createEditorWithContent('test-inline-defaults', '<p>test</p>', {
103+
toolbar: [['Bold', 'InlineStyles']],
104+
});
105+
106+
// Default styles include Small, Kbd, Var, Samp
107+
expect(editor.can().toggleInlineStyle(0)).toBe(true);
108+
});
109+
90110
it('handles inline styles with class attributes', () => {
91111
const content = '<p>Normal <span class="lead">lead text</span> and <span class="other">other text</span></p>';
92112
const editor = createEditorWithContent('test-inline-4', content, {
@@ -125,6 +145,29 @@ describe('Tiptap style extensions', () => {
125145
expect(html).toContain('normal');
126146
});
127147

148+
it('enables BlockStyles when styles are configured', () => {
149+
const editor = createEditorWithContent('test-block-enabled', '<p>test</p>', {
150+
toolbar: [['Bold', 'BlockStyles']],
151+
blockStyles: [
152+
{ name: 'Container', element: 'div', attributes: { class: 'container' } },
153+
],
154+
});
155+
156+
expect(editor.options.blockStyles).toEqual([
157+
{ name: 'Container', element: 'div', attributes: { class: 'container' } },
158+
]);
159+
expect(editor.can().toggleBlockStyle(0)).toBe(true);
160+
});
161+
162+
it('disables BlockStyles when no styles are configured', () => {
163+
const editor = createEditorWithContent('test-block-disabled', '<p>test</p>', {
164+
toolbar: [['Bold', 'BlockStyles']],
165+
// no blockStyles
166+
});
167+
168+
expect(editor.can().toggleBlockStyle(0)).toBe(false);
169+
});
170+
128171
it('strips all block styles when none are configured', () => {
129172
const content = '<div class="special"><p>wrapped</p></div><p>normal</p>';
130173
const editor = createEditorWithContent('test-block-2', content, {

0 commit comments

Comments
 (0)