From 66e295154b78e3a23bc6f022c2a03e187f18100c Mon Sep 17 00:00:00 2001 From: Ruslan Farkhutdinov Date: Mon, 2 Mar 2026 17:56:25 +0200 Subject: [PATCH 1/2] Parchment: Add tests for Blots custom classes & data attributes --- test/unit.js | 1 + test/unit/formats/custom-class-blot.js | 67 ++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 test/unit/formats/custom-class-blot.js diff --git a/test/unit.js b/test/unit.js index 596da72280..14cf5b6994 100644 --- a/test/unit.js +++ b/test/unit.js @@ -27,6 +27,7 @@ import './unit/formats/indent'; import './unit/formats/list'; import './unit/formats/bold'; import './unit/formats/table'; +import './unit/formats/custom-class-blot'; import './unit/modules/clipboard'; import './unit/modules/history'; diff --git a/test/unit/formats/custom-class-blot.js b/test/unit/formats/custom-class-blot.js new file mode 100644 index 0000000000..f36ba82c3d --- /dev/null +++ b/test/unit/formats/custom-class-blot.js @@ -0,0 +1,67 @@ +import Quill from '../../../core/quill'; + +function createClassDataBlot(BaseBlot, tagName) { + return class ClassDataBlot extends BaseBlot { + static create(value) { + const node = super.create(value); + if (value && value.customClass) node.className = value.customClass; + if (value && value.customData) node.dataset.test = value.customData; + return node; + } + + static formats(node) { + if (node.tagName !== tagName) return false; + + const formats = {}; + if (node.className) formats.customClass = node.className; + if (node.dataset.test) formats.customData = node.dataset.test; + + return formats; + } + }; +} + +describe('Custom class/data blots', function () { + const InlineBlot = Quill.import('blots/inline'); + const BlockBlot = Quill.import('blots/block'); + + const ClassInline = createClassDataBlot(InlineBlot, 'SPAN'); + ClassInline.tagName = 'SPAN'; + + const ClassBlock = createClassDataBlot(BlockBlot, 'P'); + ClassBlock.tagName = 'P'; + + it('Inline: create() applies class and data; formats() extracts them back', function () { + const node = ClassInline.create({ customClass: 'testClass', customData: 'testData' }); + + expect(node.outerHTML).toEqualHTML(''); + expect(ClassInline.formats(node)).toEqual({ customClass: 'testClass', customData: 'testData' }); + }); + + it('Block: create() applies class and data; formats() extracts them back', function () { + const node = ClassBlock.create({ customClass: 'testClass', customData: 'testData' }); + + expect(node.outerHTML).toEqualHTML( + '

', + ); + + expect(ClassBlock.formats(node)).toEqual({ + customClass: 'testClass', + customData: 'testData', + }); + }); + + it('formats() returns false for unexpected tags', function () { + const div = document.createElement('div'); + div.className = 'testClass'; + div.dataset.test = 'testData'; + + expect(ClassInline.formats(div)).toBe(false); + + const span = document.createElement('span'); + span.className = 'testClass'; + span.dataset.test = 'testData'; + + expect(ClassBlock.formats(span)).toBe(false); + }); +}); From 447acd14c4257ab4830846ec6dec03999ee6f620 Mon Sep 17 00:00:00 2001 From: Ruslan Farkhutdinov Date: Tue, 3 Mar 2026 11:29:44 +0200 Subject: [PATCH 2/2] Add custom tag test case --- test/unit/formats/custom-class-blot.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/test/unit/formats/custom-class-blot.js b/test/unit/formats/custom-class-blot.js index f36ba82c3d..54d676a921 100644 --- a/test/unit/formats/custom-class-blot.js +++ b/test/unit/formats/custom-class-blot.js @@ -64,4 +64,23 @@ describe('Custom class/data blots', function () { expect(ClassBlock.formats(span)).toBe(false); }); + + it('Custom inline tag (): create() and formats() work correctly', function () { + const ItalicBlot = createClassDataBlot(InlineBlot, 'I'); + ItalicBlot.tagName = 'I'; + + const node = ItalicBlot.create({ + customClass: 'testClass', + customData: 'testData', + }); + + expect(node.outerHTML).toEqualHTML( + '', + ); + + expect(ItalicBlot.formats(node)).toEqual({ + customClass: 'testClass', + customData: 'testData', + }); + }); });