I'm creating a custom inline blot. I want to use span and style it with css. I read in the: "Cloning Medium with Parchment" tutorial the following:
Note Inline blots use
<span>and Block Blots use<p>by default, so if you would like to use these tags for your custom Blots, you will have to specify a className in addition to a tagName.
And I'm creating this:
class TestBlot extends Inline { }
TestBlot.blotName = 'thick';
TestBlot.tagName = 'span';
TestBlot.className = 'test-class';
Quill.register(TestBlot);
And it's not working. But if I change the tagName to spann it does work! What am I missing here?! What's the right way of doing this?
Thanks!
Please follow the issue template and include all the requested info.
Also, fork the CodePen show what you tried to do and what doesn't work.
Thanks @benbro! Here is the template!
Steps for Reproduction
Expected behavior:
A new <span class="test-class">selected text</span> is created in the html editor.
Actual behavior:
Nothing happens.
Platforms:
Chrome, Safari, Firefox (and I think all the others but those are the ones I have)
Version:
Version: 1.3.4
Hi @benbro,
That link doesn't resolve anymore. Is it possible for someone to repeat the information? I'm interested in how to get around this too.
@benbro. I am experiencing the same issue, and finding that the link is now a dead end.
@dannyrb, @chrisronline : Take a look at https://github.com/quilljs/parchment/blob/master/src/blot/inline.ts#L23
There you will see this:
if (domNode.tagName === InlineBlot.tagName) return undefined;
It's not clear why this line is there or why it should return undefined, but if that line is commented out, you then invoke FormatBlot.formats(domNode) (https://github.com/quilljs/parchment/blob/master/src/blot/abstract/format.ts#L11-L18)
static formats(domNode: HTMLElement): any {
if (typeof this.tagName === 'string') {
return true;
} else if (Array.isArray(this.tagName)) {
return domNode.tagName.toLowerCase();
}
return undefined;
}
On a whim, I simply did this:
export default MyCustomInline extends Inline {
static tagName = 'span'
formats() {
return MyCustomInline.tagName
}
}
...and that got things working for me.
I have no idea what side effects my "solution" will have, as I'm still learning my way about the API, and the documentation only says:
// Returns format values represented by domNode if it is this Blot's type
// No checking that domNode is this Blot's type is required.
static formats(domNode: Node);
...which seems rather arcane and unhelpful.
When I set a breakpoint inside InlineBlot#parchment() (https://github.com/quilljs/parchment/blob/master/src/blot/inline.ts#L50-L61), I can see that other inline elements (e.g. <b> and <i>) return an object from .formats():
{
bold: true
}
But it really doesn't seem to matter (as far as I've cared to dig) whether you return a mapping of tags to truthy values or if you simply return a string...though I am assuming that the mapping is more correct...again, for reasons that do not appear to be documented.
It probably goes without saying that It's very disappointing to have this issue unceremoniously closed by @benbro with nothing more than a link to SO (which has been noted already, is dead), and then pretty much ignored as others have expressed a desire for a real resolution. This does not reflect well on the project.
@dkreft completely forgot about this issue. I had a similar experience. I kept playing and landed on something that looked like this:
// https://github.com/quilljs/parchment/#blots
import Quill from 'quill'
let Inline = Quill.import('blots/inline')
class SpellingBlot extends Inline {
static create(value) {
let node = super.create(value)
node.setAttribute('data-invalid-spelling', '')
node.setAttribute('data-alternative-spellings', [])
return node
}
static formats(domNode) {
return {
isInvalidSpelling: domNode.hasAttribute('data-invalid-spelling'),
alternativeSpellings: domNode.getAttribute('data-alternative-spellings'),
}
}
}
SpellingBlot.blotName = 'spelling'
SpellingBlot.className = 'spelling'
SpellingBlot.tagName = 'SPAN'
export default SpellingBlot
Originally, I only wanted the spelling class applied to the formatted section. When I couldn't get that to work, I began looking at code that would allow me to set a custom data-* annotation. After adding the create and formats methods, the spelling class appeared.
This seems to imply that there is more required to creating an extended Inline Blot than suggested in the documentation. 🤷♂️
I'm having the same issue. Any updates here? I'm unable to figure out Inline with span and class.
Adding to what @dkreft said (which completely fixed my same issue):
Looking at that codeblock (from https://github.com/quilljs/parchment/blob/master/src/blot/abstract/format.ts#L11-L18)
static formats(domNode: HTMLElement): any {
if (typeof this.tagName === 'string') {
return true;
} else if (Array.isArray(this.tagName)) {
return domNode.tagName.toLowerCase();
}
return undefined;
}
Because the first check in formats is to determine if tagName is a string, and thus returns true, then since my tagName = 'span', then I just added my own formats function like this:
static formats(): boolean {
return true;
}
Still seems silly for this to be required, but until there's a legit fix internally, this seems to be working properly. I can't think of any possible side effects this would have since in my case (with tagName = 'span') this function should've normally returned true. Only thing I don't quite understand why the InlineBlot would first do this if (domNode.tagName === InlineBlot.tagName) return undefined; in its formats function.
So, my stripped down blot class looks like this:
export class TagBlot extends Inline {
static blotName = 'tag';
static className = 'aur-tag';
static tagName = 'span';
static formats(): boolean {
return true;
}
}
And it's finally appending the span.aur-tag element to the selection in my editor
Most helpful comment
Adding to what @dkreft said (which completely fixed my same issue):
Looking at that codeblock (from https://github.com/quilljs/parchment/blob/master/src/blot/abstract/format.ts#L11-L18)
Because the first check in
formatsis to determine iftagNameis a string, and thus returnstrue, then since mytagName = 'span', then I just added my ownformatsfunction like this:Still seems silly for this to be required, but until there's a legit fix internally, this seems to be working properly. I can't think of any possible side effects this would have since in my case (with
tagName = 'span') this function should've normally returnedtrue. Only thing I don't quite understand why the InlineBlot would first do thisif (domNode.tagName === InlineBlot.tagName) return undefined;in itsformatsfunction.So, my stripped down blot class looks like this:
And it's finally appending the span.aur-tag element to the selection in my editor