Enhancing Quill's capabilities to accommodate soft line breaks

My current challenge involves extending Quill with a custom Blot in order to allow newlines within <p> tags. Following the advice provided by the library author on a recent stackoverflow post, I have come up with the following code:

import * as Quill from 'quill';

const Delta = Quill.import('delta');
const Embed = Quill.import('blots/embed');

export class SoftLineBreakBlot extends Embed {
    static blotName = 'softbreak';
    static tagName = 'br';  
    static className = 'softbreak';
}

export function shiftEnterHandler(this: any, range) {    
    const currentLeaf = this.quill.getLeaf(range.index)[0];
    const nextLeaf = this.quill.getLeaf(range.index + 1)[0];    
    this.quill.insertEmbed(range.index, "softbreak", true, Quill.sources.USER);    
    // Insert a second break if:
    // At the end of the editor, OR next leaf has a different parent (<p>)
    if (nextLeaf === null || currentLeaf.parent !== nextLeaf.parent) {
      this.quill.insertEmbed(range.index, "softbreak", true, Quill.sources.USER);
    }
    // Now that we've inserted a line break, move the cursor forward
    this.quill.setSelection(range.index + 1, Quill.sources.SILENT);    
}

export function brMatcher(node, delta) {
    let newDelta = new Delta();
    newDelta.insert({softbreak: true});
    return newDelta;
}

I am working with the ngx-quill wrapper for Quill in an Angular 10 project. Here is how my Quill module is set up:

QuillModule.forRoot({
      format: 'json',
      modules: {
        keyboard: {
          bindings: {
            "shift enter": {
              key: 13,
              shiftKey: true,
              handler: shiftEnterHandler
            }
          }
        },
        clipboard: {
          matchers: [            
             [ "BR", brMatcher ]
          ],          
        }
      },
    }),

However, despite implementing Shift+Enter functionality, I am encountering an issue where the insertEmbed() call seems to have no effect even though the cursor moves forward. Any insights into what might be going wrong would be appreciated.

Answer №1

It appears that you may have simply overlooked calling

Quill.register(SoftLineBreakBlot)

Therefore:

...
export class SoftLineBreakBlot extends Embed {
    static blotName = 'softbreak';
    static tagName = 'br';  
    static className = 'softbreak';
}
...

This code snippet should now read as follows:

...
export class SoftLineBreakBlot extends Embed {
    static blotName = 'softbreak';
    static tagName = 'br';  
    static className = 'softbreak';
}
Quill.register(SoftLineBreakBlot);
...

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Building a forum using Angular 2+ with blank fields

After utilizing formBuilder to create a form with select, options, and inputs, I noticed that when I console.log the form variable, I receive: {town: null, subject: ƒ, level: ƒ, priceMin: ƒ, priceMax: ƒ} \/ level: ƒ String() priceMax: ƒ Number( ...

Using webpack to generate sourcemaps for converting Typescript to Babel

Sharing code snippets from ts-loader problems may be more suitable in this context: Is there a way to transfer TypeScript sourcemaps to Babel so that the final sourcemap points to the original file rather than the compiled TypeScript one? Let's take ...

What is the reason behind Jest v24 mocking classes that have a need for private methods

Currently, I am facing a challenge in creating mock implementations of my Typescript classes using Jest v24+. Specifically, I am trying to create a mock class that will be injected into a constructor and mock the functions to return specific responses. My ...

Encountering module not found error in Angular 2 after running npm install

I am facing an issue with my Angular 2 application while trying to integrate the angular2-autosize component following the steps outlined on its GitHub page (https://github.com/stevepapa/angular2-autosize). I executed the command below: npm install angula ...

Tips for setting up a websocket connection between angular-socketio and flask-socketio

As a newcomer to web sockets, I am currently working on implementing a web socket server using flask-socketio for the server and angular-socketio for the client-side. For the server side in Flask, this is the code snippet I am using: application.py @ ...

Error encountered in Angular8 Template Driven Form: TypeError - Attempt to access property 'ProviderName' of undefined resulting in Object.eval throwing an error in updateDirectives

An error has occurred with the template causing an issue. ProviderComponent.html:4 ERROR TypeError: Cannot read property 'ProviderName' of undefined at Object.eval [as updateDirectives] (ProviderComponent.html:4) at... provider.compo ...

React useEffect Hook fails to trigger after redux State update

I recently created a React.FunctionComponent to serve as a wrapper for children and perform certain actions after some redux dispatch operations in Typescript, but I'm facing issues. Here is the code snippet of the wrapper: import React, {useState, us ...

The type declaration for the Storage.prototype.setObject method

I'm facing a challenge in creating a d.ts file for the given DOM feature. Storage.prototype.setObject = function(key:string, value:any) { this.setItem(key, JSON.stringify(value)); } Storage.prototype.getObject = function(key:string) { var va ...

The theming feature in Angular 5 with Bootstrap 4 and Bootswatch seems to be malfunctioning

Having trouble implementing bootswatch themes with angular 5 and bootstrap 4? I've added the following to styles.scss: @import "~bootswatch/dist/cerulean/variables"; @import "~bootstrap/scss/bootstrap"; @import "~bootswatch/dist/cerulean/ ...

Displaying data on a webpage using interpolation in HTML

I'm struggling to display user information on my HTML template. I can't seem to figure out what I'm doing wrong. Essentially, I want to retrieve values from the database and dynamically insert them into the main page for display. My issue li ...

Tips for modifying the width of the mat-header-cell in Angular

Is there a way to customize the mat-header-cell in Angular? I've been trying to change its width without success. Any suggestions would be greatly appreciated. <ng-container cdkColumnDef="name"> <mat-header-cell *cdkHeaderCellDe ...

"Exploring the Concept of Tuple Narrowing and Type

Is there anyone who can assist me in comprehending the scenario below: export function functionThatReturnsTurpleObjects(): | [{ a: number }, undefined] | [undefined, { a: number }] { if (Math.random() > 0.5) { return [undefined, { a: 1 }]; ...

Utilize the variable radius feature on HighCharts for enhanced data visualization

Currently, I'm attempting to incorporate a variable radius pie chart from HighCharts. You can view the demonstration of this feature here: https://www.highcharts.com/demo/variable-radius-pie. It's worth mentioning that I am utilizing HighCharts ...

Typescript: uncertain about the "declaration: true" guideline

Let's say I have a app.ts file: interface IApp {} export class App implements IApp {} If I set declaration to true in tsconfig.json, an error will occur: error TS4019: Implements clause of exported class 'App' has or is using private name ...

Assigning enum type variable using string in TypeScript

How can I dynamically assign a value to a TypeScript enum variable? Given: enum options { 'one' = 'one', 'two' = 'two', 'three' = 'three'} let selected = options.one I want to set the variable " ...

What is the reason behind Flow's reluctance to infer the function type from its return value?

I was anticipating the code to undergo type checking within Flow just like it does within TypeScript: var onClick : (() => void) | (() => boolean); onClick = () => { return true; } However, I encountered this error instead: 4: onClick = () => ...

Using Angular 2 along with SweetAlert2 to display a prompt and receive a response

Currently, I am working on an MVC with Angular2 website. My goal is to implement a sweetalert2 message, prompting the user to confirm their intention to update their data. Upon confirmation, I want the sweetalert2 box to display a loading/waiting animation ...

Troubleshooting Standalone Component Routing Issues in Angular 16

For my Angular 16 project code, visit this link To create the Angular 16 project with routing enabled, I used the following command: ng new myapp --standalone Then, I added other components using: ng g c components/home The boilerplate files are differe ...

You won't find ngModel as a property of "input" in Angular (don't rely on importing FormsModule to fix this)

I've exhausted all options but can't seem to get ngModel working in the component.html file. My form contains the following html: <input [ngModel]="username" type="text" name="username" [placeholder]="'INPUT_USERNAME_HINT' | transl ...

How can I determine if any of the values in the array (both previous and current) are identical?

I am facing a challenge with 3 input fields that could potentially have the same values, but I need to ensure uniqueness for each field. {productFormData.Roles.map((role: string, index: number) => { return ( <div className={`form-group in ...