3 horizontal lines, burger
3 horizontal lines, burger
3 horizontal lines, burger
3 horizontal lines, burger

3 horizontal lines, burger
Remove all
LOADING ...

Content



    All about quill blots and blocks, and how to make a custom quill blot, block

    Clock
    24.10.2024
    /
    Clock
    02.10.2025
    /
    Clock
    7 minutes
    An eye
    4813
    Hearts
    0
    Connected dots
    0
    Connected dots
    0
    Connected dots
    0
    Tags:
    JS
    Quilljs

    List of blots and how to get them

    Blot is a building block of document used by parchment. Their various types, examples of useage and implementation can be viewed on my online quill editor.
    As you will see below, there are quite a few of these building blocks. And each of them exists to perform a specific role in the document. I will talk about the role of each blot separately, but before this, let's see what kinds of blots we have in QuillJs::
    1. block
    2. block/embed
    3. break
    4. container
    5. cursor
    6. embed
    7. inline
    8. scroll
    9. text
    To import any blot from this list into a new JS variable, enter the blot name after blots, like this:
    let blot = Quill.imports["blots/block"]
    To see a full list of all available blots, type in the browser console:
    Quill.imports

    About each blot

    Inline blot. Examples of using this block are bold, italic, or anything underlined. This is the simplest block; it simply wraps the selected block in a prespecified tag with prespecified classes. And it can be wrapped around another inline block.
    Block blot. For example, a block of quotes, a block of code, or headings. It is important to understand how this block works. It does not simply wrap a selected block in a certain tag - yes, a block, not text - it just replaces it. That is, block blots cannot be inside each other, as is the case with inline blocks.
    Container blot. They are created in order to overcome the inability of previous blocks to be embedded in one another. In other articles, you will see that we will have to specify in advance the elements that can be inside each other ;) An example of the implementation of such blocks are lists and tables.
    Block/embed and embed. They work the same way as regular blocks, but with the only difference that the content they embed cannot be edited. It can be reloaded or deleted, but not changed. These are videos, formulas, and images.
    Scroll blot. It is the main container for all the others. What is it? By default, it is a DIV element with the ql-editor class. Which can contain the following types of blots:
    1. block
    2. embed
    3. container
    Another important feature of this blot is that the constructor accepts a special object as the first parameter - a register. It is too early to talk about Quill registers, but let's say that each register is a unique set of buttons and formatters for editing text. That is, on one page you can have several text editors with their own unique functionality.
    Break blot. This is a special zero element. In the Parchment library, each container that can have children must have at least one. And this blot was created to play the role of the initial element.
    Text blot. It is a regular wrapper around the text
    Cursor blot. It is a vertical line when editing. And it knows where and on which block it is located.

    All blot methods and members to override

    In this chapter, I have collected all possible methods for overriding and added some comments to them. I did this because the official site does not have such information, although it can still be found through the browser console.

    Block blot

    Methods for overriding and a source code -> https://github.com/slab/parchment/blob/main/src/blot/block.ts
    static create(value?: unknown); static formats(domNode: HTMLElement, scroll: Root): any; constructor(scroll: Root, domNode: Node); format(name: string, value: any): void; formats(): { [index: string]: any }; formatAt( index: number, length: number, name: string, value: any ): void; insertAt(index: number, value: string, def?: any): void; replaceWith(name: string | Blot, value?: any): Blot; deleteAt(index: number, length: number): void; delta(): void; insertBefore(blot: Blot, ref?: Blot | null): void; length(): number; moveChildren(target: Parent, ref?: Blot | null): void; optimize(context: { [key: string]: any }): void; path(index: number) [Blot, number][]; removeChild(child: Blot): void; split(index: number, force: boolean | undefined = false): Blot | null;
    A default members and their values:
    static blotName = 'block'; static scope = Scope.BLOCK_BLOT; static tagName: string | string[] = 'P'; static allowedChildren: BlotConstructor[] = [InlineBlot, BlockBlot, LeafBlot ]; length: number; name: string;

    Inline blot

    Methods for overriding and a source code -> https://github.com/slab/parchment/blob/main/src/blot/inline.ts
    static create(value?: unknown): Node; static formats(domNode: HTMLElement, scroll: Root): any; static compare(self: string, other: string): number; constructor(scroll: Root, domNode: Node); format(name: string, value: any): void; formats(): { [index: string]: any }; formatAt( index: number, length: number, name: string, value: any ): void; optimize(context: { [key: string]: any }): void; replaceWith(name: string | Blot, value?: any): Blot; replaceWith(name: string | Blot, value?: any): Blot; update( mutations: MutationRecord[], context: { [key: string]: any } ): void; public wrap(name: string | Parent, value?: any): Parent;
    A default members and their values:
    static blotName = 'inline'; static order = [ 'cursor', 'inline', 'link', 'underline', 'strike', 'italic', 'bold', 'script', 'code', ]; static scope = Scope.INLINE_BLOT; static tagName: string | string[] = 'SPAN'; static allowedChildren: BlotConstructor[] = [InlineBlot, LeafBlot ]; length: number; name: string;

    Embed blot

    Methods for overriding and a source code -> https://github.com/slab/parchment/blob/main/src/blot/embed.ts
    static create(value?: unknown): Node; static formats(_domNode: HTMLElement, _scroll: Root): any; constructor(scroll: Root, domNode: Node); format(name: string, value: any): void; formatAt( index: number, length: number, name: string, value: any ): void; formats(): { [index: string]: any }; index(node: Node, offset: number): number; restore(node: Text): EmbedContextRange | null; update(mutations: MutationRecord[], context: Record<string, unknown>): void;
    A default members and their values:
    static scope = Scope.INLINE_BLOT; length: number; name: string; contentNode: HTMLSpanElement; leftGuard: Text; rightGuard: Text;

    Cursor blot

    Methods for overriding.
    static create(value?: unknown): Node; static formats(_domNode: HTMLElement, _scroll: Root): any; constructor(scroll: ScrollBlot, domNode: HTMLElement, selection: Selection): void; detach(): void; format(name: string, value: unknown): void; formatAt( index: number, length: number, name: string, value: any ): void; formats(): { [index: string]: any }; index(node: Node, offset: number): number; length(): number; position(): [Text, number]; remove(): void; restore(): EmbedContextRange | null; update(mutations: MutationRecord[], context: Record<string, unknown>): void; optimize(context?: unknown): void; value() string; // Will return ''
    A default members and their values:
    static blotName = 'cursor'; static className = 'ql-cursor'; static tagName = 'span'; static CONTENTS = '\uFEFF'; // Zero width no break space length: number; name: string;

    Text blot

    Methods for overriding and a source code -> https://github.com/slab/parchment/blob/main/src/blot/text.ts
    static create(value: string): Node; static value(domNode: Text): string; constructor(scroll: Root, node: Node); deleteAt(index: number, length: number): void; index(node: Node, offset: number): number; insertAt(index: number, value: string, def?: any): void; length(): number optimize(context: { [key: string]: any }): void; position(index: number, _inclusive = false): [Node, number]; split(index: number, force = false): Blot | null; update( mutations: MutationRecord[], _context: { [key: string]: any } ): void; value(): string;
    A default members and their values:
    static readonly blotName = 'text'; domNode: Text; static scope = Scope.INLINE_BLOT;

    Container blot

    static create(value: string): Node; constructor(scroll: Root, domNode: Node); checkMerge(): boolean; deleteAt(index: number, length: number): void ; formatAt( index: number, length: number, name: string, value: any ): void; optimize(context: { [key: string]: any }): void; insertAt(index: number, value: string, def?: any): void;
    A default members and their values:
    static blotName = 'container'; static scope = Scope.BLOCK_BLOT; static tagName: string | string[]; prev: BlockBlot | ContainerBlot | null; next: BlockBlot | ContainerBlot | null;

    Scroll blot

    Methods for overriding and a source code -> https://github.com/slab/parchment/blob/main/src/blot/scroll.ts
    static create(value: string): Node; constructor( public registry: Registry, node: HTMLDivElement, { emitter }: { emitter: Emitter } ); batchStart(): void; batchEnd(): void; emitMount(blot: Blot): void; emitUnmount(blot: Blot): void; emitEmbedUpdate(blot: Blot, change: unknown): void; deleteAt(index: number, length: number): void; enable(enabled = true): void; formatAt(index: number, length: number, format: string, value: unknown): void; insertAt(index: number, value: string, def?: unknown): void; insertBefore(blot: Blot, ref?: Blot | null): void; insertContents(index: number, delta: Delta): void; isEnabled(): boolean; leaf(index: number): [LeafBlot | null, number]; line(index: number): [Block | BlockEmbed | null, number]; lines(index = 0, length = Number.MAX_VALUE): (Block | BlockEmbed)[] optimize(context?: { [key: string]: any }): void; optimize( mutations?: MutationRecord[], context?: { [key: string]: any }): void; optimize(mutations = [], context = {}): void; path(index: number): number; remove(): void; // Do nothing update(source?: EmitterSource): void; update(mutations?: MutationRecord[]): void; update(mutations?: MutationRecord[] | EmitterSource): void; updateEmbedAt(index: number, key: string, change: unknown): void;
    A default members and their values:
    static blotName = 'scroll'; static className = 'ql-editor'; static tagName = 'DIV'; static defaultChild = Block; static allowedChildren = [Block, BlockEmbed, Container]; emitter: Emitter; batch: false | MutationRecord[];

    How to make a new one blot and override a default one

    For the example of overriding an existing blot, I'll use block blot. Let's start with import.
    let Block = Quill.import('blots/block');
    Next, you need to define new blot functionality. In my case, I want to use <div> instead of <p> tag and add a class named "txt". This is how I will do it:
    Block.tagName = 'div' class TextBlock extends Block{ static create(value){ let node = super.create(value); node.setAttribute('class','txt'); return node; } } // Register (updating block blot) Quill.register(TextBlock, true)
    This is about modifying blots. But how to make a new one? Any quill block has 3 variables that are used to distinguish one block from another. The first is tagName, the second is blotName and the third is className.
    To create a new blot, you need to set a different value for blotName. I will demonstrate this using links as an example. We will create 2 types of links:
    1. Internal links
    2. External links
    // Import inline blot let Inline = Quill.import('blots/inline') // Setting up a new inline blot class InternalLink extends Inline{ constructor(scroll, domNode){ super(scroll, domNode); domNode.addEventListener('click', (ev) => { domNode.setAttribute('ref', 'me') }) } } InternalLink.tagName = 'a' InternalLink.className = 'ref-int' // New blots name InternalLink.blotName = 'internal-link' // Register a new formater Quill.register({'formats/internal-link': InternalLink}) // Setting up a new inline blot class ExternalLink extends Inline{ constructor(scroll, domNode){ super(scroll, domNode); domNode.setAttribute('target', '_blank') domNode.setAttribute('ref', 'noreferrer nofollow external') } } ExternalLink.tagName = 'a' ExternalLink.className = 'ref-ext' // New blots name ExternalLink.blotName = 'external-link' // Register a new formater Quill.register({'formats/external-link': ExternalLink})
    You're probably wondering what this "formater" is. But basically, I just made a button to add and delete this type of blot in the editor.

    Do not forget to share, like and leave a comment :)

    Comments

    (0)

    captcha
    Send
    LOADING ...
    It's empty now. Be the first (o゚v゚)ノ

    Other

    Similar articles


    Quill formats(ql-formats), How to make custom format

    Clock
    24.10.2024
    /
    Clock
    02.10.2025
    An eye
    3883
    Hearts
    0
    Connected dots
    1
    Connected dots
    0
    Connected dots
    0
    In this article, I will analyze the types of quilljs formats and explain some of the nuances of working with tables, fonts, images, and video. I will also show how …

    Quill tooltip, how to make your own. Example on links

    Clock
    25.10.2024
    /
    Clock
    02.10.2025
    An eye
    2275
    Hearts
    0
    Connected dots
    0
    Connected dots
    0
    Connected dots
    0
    In this article, you will find an example of how to implement your own Quill tooltip. And you will get how this even works. As an example, a tooltip will …

    How to make custom quill module – table of content as an example

    Clock
    29.10.2024
    /
    Clock
    02.10.2025
    An eye
    1746
    Hearts
    0
    Connected dots
    0
    Connected dots
    4
    Connected dots
    0
    In this article I will show how to make custom quill module for an editors. This module will generate the table of contents of the article. I will also show …

    Used termins


    Related questions