Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Quill inserts a useless line-break before the <ul> element #2905

Closed
flockisoft opened this issue Jan 16, 2020 · 12 comments
Closed

Quill inserts a useless line-break before the <ul> element #2905

flockisoft opened this issue Jan 16, 2020 · 12 comments

Comments

@flockisoft
Copy link

flockisoft commented Jan 16, 2020

Unfortunately quill insert a line-break if you paste the following html into the editor:

<p>Simple list:</p><ul><li>item one</li><li>item two</li></ul><p><br></p>

The behavior of pasteHTML() or convert(), setContents() is the same.

Steps for Reproduction

  1. Visit https://codepen.io/iice/pen/vQKrWY
  2. change line in js to var html = <p>Simple list:</p><ul><li>item one</li><li>item two</li></ul><p><br></p>;
  3. Watch what happens in the Viewer

Expected behavior:

Quill should not insert an line-break before the <ul> - because this sums up.
The first time it insert a line-break, then we save it, then quill inserts the second line-break, we save again, and so on...

Actual behavior:

Simple list:

  • item one
  • item two

Platforms:

Chrome 79
Windows 10

Version:
1.3.7

Run Quill.version to find out

@flockisoft
Copy link
Author

flockisoft commented Jan 16, 2020

After playing a little bit i found two ways to prevent quill to insert the line-break

  1. prepend the <ul> by an empty paragraph
    <p>Simple list:</p><p></p><ul><li>item one</li><li>item two</li></ul><p><br></p>

  2. wrap the <ul> by a paragraph
    <p>Simple list:</p><p><ul><li>item one</li><li>item two</li></ul></p><p><br></p>

@mtycholaz
Copy link

I'm experiencing the same issue. This is frustrating a client of mine because if they make any change (make a word bold for example), a new empty <p> is added, which pushes down their content. The result is that the space keeps growing bigger every time they save.

@ivangarcia2
Copy link

I'm having the same issue

@codesplode
Copy link

I'm having the same issue as well. Looking through the code.

The problem appears to be that on load, Quill is inserting a Block blot (p) tag before the ul, which by default contains a br as a child. Presumably that is the default behavior so the user can click there and type after creating it. I'm working my way up the chain to see if I can find what is actually making the decision to insert that item.

@deniskabalkin
Copy link

Same problem, please fix =)

@mhdhamouday
Copy link

I fixed it by disabling matchVisual, but I think we should find better solution.

var quill = new Quill('.quill', {
    theme: 'snow',
    modules: {
        toolbar : [...]
        clipboard: {
            matchVisual: false
        }
    }
});

@Triggsy22
Copy link

Triggsy22 commented Mar 9, 2021

I have the same problem and i found another solution. But its not a good one, so i still hope that this Bug got fixed properly.

setContents() wants a delta object. And we just force a linebreak at the end of this delta object. So that not only at the end of our bugy delta object is a linebreak. Its at the end of all of them. And then we hide the linebreak with CSS.

Javascript

addLinebreakToTheEndOfDelta(delta){
    let bugAttributes = ['header', 'align', 'list', 'indent', 'blockquote', 'code-block'];
    let bugInserts = ['video'];
    let ops = delta.ops;
    let opsLast = ops[ops.length - 1];

    //EQUILIZE THE END OF THE OPS
    //remove \n if its the last ops
    if(opsLast.insert === '\n'){
        ops.pop();
        opsLast = ops[ops.length - 1];
    }
    //remove br if its the last ops
    if(typeof opsLast.insert === 'object' && opsLast.insert.break !== undefined){
        ops.pop();
        opsLast = ops[ops.length - 1];
    }
    //remove \n from the end of last ops
    if(typeof opsLast.insert !== 'object' && opsLast.insert.substr(opsLast.insert.length - 2, opsLast.insert.length) === '\n') {
        opsLast.insert = opsLast.insert.substr(0, opsLast.insert.length - 2)
    }

    //FORCE BREAK AT THE END
    //\n for all ops where the insert is not an object and it have no 'bugAttributes' properties in attributes
    //\n for all ops where insert is an object and it have no 'bugInserts' properties in insert
    //info: all that are in bugAttributes are buggy and are setting a linebreak on its own.
    let foundInAttributes = 0;
    let foundInInsert = false;
    if(opsLast.attributes !== undefined){
        for(let attr of bugAttributes){
            if(opsLast.attributes.hasOwnProperty(attr)){
                ++foundInAttributes;
            }
        }
        if(typeof opsLast.insert === 'object') {
            for (let insert of bugInserts) {
                if (opsLast.insert.hasOwnProperty(insert)) {
                    foundInInsert = true;
                    break;
                }
            }
        }
    }
    if(typeof opsLast.insert !== 'object'){
        if(foundInAttributes === 0 || foundInAttributes !== Object.keys(opsLast.attributes).length) {
            opsLast.insert += '\n';
        }
    }else{
        if((foundInAttributes === 0 || foundInAttributes !== Object.keys(opsLast.attributes).length) && foundInInsert === false){
            ops.push({insert: '\n'})
        }else if(foundInAttributes !== 0 && foundInAttributes === Object.keys(opsLast.attributes).length && foundInInsert === false){
            //the \n needs the attributes, so we do a copy of opsLast and overwrite insert. so we still have the attributes
            ops.push(Object.assign({}, opsLast, {insert: '\n'}));
        }
    }

    //and an additional br for all
    ops.push({insert: {break: ""}})

    return delta;
}

SCSS

.ql-editor{
  > p:last-child{
    margin: 0;//we dont want display:none, cause the user can still delete the last p and then the previous is the last one.
    > br{
      display: none;
    }
  }
}

edit: changed the javascript code again. had still a few bugs. but now its working properly i think.

@mtycholaz
Copy link

@Triggsy22 thanks for sharing. I plan to take a look at this further. For my own clarity, where did you implement the addLinebreakToTheEndOfDelta method?

@Triggsy22
Copy link

quillEditorObject.setContent(addLinebreakToTheEndOfDelta(delta))
i have the quillEditorObject and call setContent.
setContent wants a delta object.
and instead of giving it directly to setContent i give it to addLinebreakToTheEndOfDelta and the result to setContent

@dmarsola
Copy link

Recreated the issue with a simple page based on the example usage provided. You can see that the extra line is created if a single paragraph is followed by the bullets. Two consecutive paragraphs will not give the same error.

https://codepen.io/dmarsola/pen/KKWXoVE

@peter-elliott-ms
Copy link

I fixed it by disabling matchVisual, but I think we should find better solution.

var quill = new Quill('.quill', {
    theme: 'snow',
    modules: {
        toolbar : [...]
        clipboard: {
            matchVisual: false
        }
    }
});

it a appears as though that was the ultimate solution in later versions of quill:
3897c98

@quill-bot
Copy link

Quill 2.0 has been released (announcement post) with many changes and fixes. If this is still an issue please create a new issue after reviewing our updated Contributing guide 🙏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants