slab / quill

Quill is a modern WYSIWYG editor built for compatibility and extensibility
https://quilljs.com
BSD 3-Clause "New" or "Revised" License
43.11k stars 3.35k forks source link

Add support for tables #117

Open jhchen opened 10 years ago

jhchen commented 10 years ago

As an administrative note, I will delete all non-substantive comments from this thread to cut down the clutter and mass emails to everyone. Please use the Reaction feature to show support.

dost commented 7 years ago

We moved forward our work on tables: test editor It does:

If you have a time to look at it, you will find all code for tables in quilljs-extended-toolbar subdirectory of project. It is just one JS file and one HTML file. Public repo is at: https://github.com/dost/quilljs-table. Your input is highly appreciated.

2Pacalypse- commented 7 years ago

I also made my own version of the tables support. You can see the demo here: http://galaxy.fesb.hr/quill/index.html

Source can be found here: https://github.com/2Pacalypse-/quill

For now it inserts a default 3x2 table, with the ability to insert new rows before the one currently selected and it's also possible to insert new columns to the left of the one currently selected. The plan is to work on a better toolbar support for working with tables next. Few notable things that are missing and will hopefully be added soon:

dmitryuv commented 7 years ago

@2Pacalypse- that's pretty clever way, great job! Regarding your question in the code - i don't think merging tables is a good idea, people might not want this to happen especially if there's no way to "unmerge" them. One thought - having all 3 attributes with repeatable values seems excessive, do you think it's possible to roll them up into just plain 3 (cell, row, table)?

dons20 commented 7 years ago

@dost That's a pretty clean table editor. Most of my suggestions are seen within your "Known Issues" on the repo. I think it should also be able to delete a row, or delete a column at the click of a button. I'm pretty interested to see it take off.

2Pacalypse- commented 7 years ago

@dmitryuv

Regarding your question in the code - i don't think merging tables is a good idea, people might not want this to happen especially if there's no way to "unmerge" them.

Yeah, will probably take that out for now. But I do think that in future it might be useful to have an option to merge two tables together (and of course be able to unmerge/undo it).

One thought - having all 3 attributes with repeatable values seems excessive, do you think it's possible to roll them up into just plain 3 (cell, row, table)?

This is something I was wondering about as well. I was hoping that someone with more experience with Quill and Delta internals would be able to shed some light on. It feels with the approach I took (which is actually @cray0000's approach outlined above ^^), it would be pretty hard to do since we have 3 separate blots all being inserted. And each of them needs to have a way to be able to say where they belong, eg. a cell needs to know which row and table it belongs to.

The way it is now makes it pretty easy to get rowId and tableId for each cell, but thinking about it further, I guess we could make the delta a bit more succinct by only making each blot have their respective id. So it would look something like this:

{
  "attributes": {
    "table-cell": {
      "cellId": "cell-oi1sibyxp4dbl3a1j8v5kx1or"
    },
    "table-row": {
      "rowId": "row-e6jj7821yfms4fn0topskmx6r"
    },
    "table": {
      "tableId": "table-mbgxs12ydrji1bpv1ujl9pb9"
    }
  },
  "insert": "\n"
}

This way, each time you need to get tableId for a particular cell, you would need to do cell.parent.parent and then get the tableId from the table blot. But yeah, I think that's actually the better way to do it and having the delta be as optimal as possible is very important. Thanks for the feedback!

WinstonFassett commented 7 years ago

Here’s an approach that doesn’t require generating IDs, but instead uses embeds for row and cell “breaks” to identify TRs and TDs that need to be rendered as separate elements.

http://jsbin.com/defixum/edit?js,output

The advantage here is that you don’t have mess with ID book-keeping at all.

Conceptually, the structure of a table delta is

insert "Row 1 Col 1"
insert "\n", attributes: { td:true }
insert { tdbr: true }
insert "Row 1 Col 2"
insert "\n", attributes: { td:true }
insert { trbr: true }
insert "Row 2 Col 1"
insert "\n", attributes: { td:true }
insert { tdbr: true }
insert "Row 2 Col 2"
insert "\n", attributes: { td:true }
insert { trbr: true }

Caveats:

It has decent parity with https://github.com/dost/quilljs-table in terms of features and open issues, except that it doesn’t do nested tables as you can do when using explicit table IDs

dmitryuv commented 7 years ago

@WinstonFassett i like it, in my case i don't need nested tables so easier solution is preferable. I'd add problems with lists to the issues, but overall looks good. Do you plan to keep working on this?

WinstonFassett commented 7 years ago

Thanks @dmitryuv,

I will look into the list issues. I did try pasting a list into a cell and it worked but had problems on enter, so perhaps the issue can be fixed with keyboard handlers.

This isn't for my day job and I'm still proving out the approach, so I hesitate to publish in anything more formal than gists/jsbins. However, I'm pretty committed to quill in my side project and am keen on this feature, so I will keep moving it forward as time permits until I settle on an implementation.

WinstonFassett commented 7 years ago

I think I got lists working, although I had to make a small change to bubbleFormats in Quill.js so that attribute ordering is preserved in a top-down manner.

Updated demo: http://jsbin.com/defixum/6/edit?js,output

The attribute ordering matters when you have a block that is both a td and a list. Things work as expected if the td attribute is first. However, the current implementation of bubbleFormats appends things bottom up, so that the TD is always last.

Changing from extend(formats, blot.formats()) to extend(blot.formats(), formats) seemed to fix most of the issues with lists in tables without making any changes to the actual table code.

This might also fix the same list issue in quilljs-table.

ghost commented 7 years ago

啊啊啊,我可以说中文么? 是不是只支持拷贝一个表格过来可以让事情变得简单一点。 这就满足了楼主一旦创建后就不改变的要求。 这样,很多用户的问题就有了个临时解决方案,很多人会很开心!!! 哈哈!

Let me try some english , The first step ,support copying a table from another page ,maybe it make things simple.

jhchen commented on Sep 4, 2016 • edited :"Tables cannot be resized after creation" ,I think it is right . We can edit a table by using another edit tool ,and then copy the table into the quill , We can modify the table again If need ,and now, we have the table , and have the time to discuss the more cormfortable solution.

emmanuelmillionaer commented 7 years ago

Hi! 🙂 @WinstonFassett you made fantastic progress on the Quill-JS table feature. 💯 🥇

Did you further continue on your implementation? 🙂 Could I somehow help within a Git-Repository? because I really like your approach and would like to make an impact 🙂 Above you mentioned, undoing table commands sometimes have messy results. I'm eager to make that work!

Thank you so much, you started something amazing! 🥇 👏

Theopt commented 7 years ago

Impressive work I've seen so far from everyone on the Quill Table support. Is it safe to assume this will not come out of the box from the development team? Last repo I saw was updated 5 months ago now.

jhchen commented 7 years ago

Not sure which repo is being referred to but Quill was updated 4 days ago. But no Quill does plan to add official table support in the future. There is no timeline at the moment but the community can make it faster by contributing and exploring implementation designs which is what is being done here.

seandearnaley commented 7 years ago

@jhchen I think @Theopt is referring to the repos discussed in this thread, work on tables seems to have come to a halt and the solutions here are too half baked to use in production. I do agree that there needs to be more contribution and discussion but IMHO work needs to be done to the core features to make it easier to develop features like tables... there seems to be a reluctance to accept things are actually needed.... maybe we can start with figuring out the roadblocks that preventing this particular feature from moving forward?

I have been working with the quill.js platform for about 2 months, I'm not the greatest coder in the world but have been one for over 20 years, I've read through the quill.js, delta and parchment codebases and I still have trouble with most of my extension efforts... in particular the lack of support for nested blocks(and deltas) and the handling of breaks to be particularly troublesome.... when I originally investigated solutions based on quill.js I was lead to believe extensions would be straightforward, looking at a lot of community code, it's alarming how much of it is incomplete... a lot of devs seem to drop support for the delta format and just use html, which is obviously a step backwards....

There is definitely an issue with guides, the medium guide is good but we need more guides for more complex things involving parchment and delta.... I know guides/docs are on the roadmap, there are apparently no plans for table support, I hope there are plans to make developing tables easier because nobody seems to be having any success with this (solutions are incomplete, and not actively being worked on, there isn't very much community code out there considering this is supposed to be an API driven application). I appreciate everyone's hard work and I hope quill.js has a bright future, as long as I'm working with it, I will help wherever I can but I would like to see some light with several features that have been talked about for several years now.

Theopt commented 7 years ago

@seandearnaley That was exactly what I meant back there. I hope you guys make it because it is so much lighter and easy to use than everything else I've found so far, and to be honest all I need to use it in production is the tables part now : ) Unfortunately I'm trying to replace some parts of a legacy product and I'm on a time schedule. Most likely be using CKEditor for this rollout. Will keep an eye on Quill for sure.

jhchen commented 7 years ago

Tables are a very large feature that will take time and work to add. I have posted a very detailed suggestion on how to start and proceed. If you want to ignore this advice that if your prerogative but the expectation it should be easy or straightforward to add tables from zero represents a gross misunderstanding of the feature.

Alternatively you can just wait for us to add it in core but either way unconstructive complaints are not helpful.

GarrettGeorge commented 7 years ago

I added on some functionality to @WinstonFassett's work on tables.

Here it is in a repo. Just open the body.html to load.

So much thanks to @WinstonFassett because without his work on the actual Parchment objects and low level stuff I wouldn't have been able to add my UI aspects.

I added tab functionality inside tables, so if you're in a cell it'll go to the next one and vice versa for shift+tab. If you're in the last cell of the table and hit tab it'll add a row, so that's fun. The only time it doesn't go to the next cell is when you're in the very first index of the first cell. This is mostly l likely due to my algorithm for finding the next td.

Also added some css to make the table cell's equal width. This is for my planned update where I add some ability to resize akin to Word and Google Docs.

I also made the <p>'s inside table cells vertical-align: top because it made more sense, imo. Feel free to change it.

Most work could be done to the functions to improve them/clean them up. Outside of that from a potential PR perspective lots of work needs to go into figuring out how exactly to make tables work with the stack. undo/redo doesn't work at all really. Redo'ing a row add creates a new table entirely.

StefanNeuser commented 7 years ago

Hi all, what do you think about an modal/dialog to edit a table that becomes inserted as a embeded? If you click into the table within quilljs the dialog gehts open to make content and table/cell property changes? In this way we dont need to enforce quilljs to support table-editing within its canvas. And on the other hand the dialog-table-tool could be an opensource project of its own like https://limonte.github.io/sweetalert2/ with a api with events to pass data onOpen and sends/returns data back onClose.

bubach commented 7 years ago

Great work so far, the last version I looked at from @WinstonFassett seemed pretty damn good to me.

Moving forward I think the Resize-module from kensnyder's image-resize plugin could be useful. The idea of overlay controls inside the editor is also something that could come in handy for adding cols/rows or opening up a settings modal.

https://run.plnkr.co/k0LyTIn6BfFLuemu/

2017-09-02 kl 21 39 56
lucassoamaral commented 6 years ago

The company I work for is using Quill on one of our projects. The table support will be a great improvement for it!

Is there a planned date for 2.0 release?

benbro commented 6 years ago

@lucassoamaral you can read about Quill 2.0 here.

javiercbk commented 6 years ago

I need this feature so badly that I'm going to start working on it, but reading the article that @benbro pointed out I see that table support is coming in version 2, which leaves me with further questions:

I need this feature for my work, so I will be working on supporting tables either on my own branch or collaborating with other developers (probably I will be checking out other repositories to see what has been developed so far), any suggestions or guidance?

Personally I like how summernote handles tables, so I am going to implement something similar.

NoBodyButMe commented 6 years ago

Maybe tell this to potential users immediately on YOUR FRONT PAGE. It took me hours to replace my old editor with Quill.... it looked very promising. And suddenly... you see... no table support?????????? Come on, guys????

danielschwartz commented 6 years ago

I’ve been an avid Quill user for years at this point, and have been following this thread for a while. Table support is important, we all know it, we’ve all been clamoring for it, and yes sometimes it’s been frustrating that it’s not officially supported yet.

However, @KrisMerckx, please rethink your approach to open source projects and how you interface with the implementing team. @jchen and the rest of the contributors of this fine project owe you absolutely nothing, and the fact that we get such an amazing and extensible editor that “just works” out of the box, is nothing short of astounding. No one made you choose Quill. No one made you skip over the Formats section of the website. And certainly no one made you spend hours implementing it without reading the docs thoroughly. It’s replies like yours that make people rethink open sourcing things.

@jhchen and the rest of the contributing team: You make an amazing piece of software. Just know that there are lots of folks (like myself) who love this project, and appreciate all of the effort and work you put into it.

And if you’re ever in NYC, there’s a round of beers for y’all on me 🍻

GarrettGeorge commented 6 years ago

@javiercbk check out my work with some of the UI for tables. Github. I was struggling with the Parchment/DOM based interactions and coding, but I was able to figure out some stuff for navigating them as a user.

javiercbk commented 6 years ago

Hey @jhchen, I've seen this commit you made a while back. I'm using a similar approach.

Would care to comment on that? Is that a good idea?

I'm using another this repo and creating tables in a similar fashion. Any comment on that?

Thanks

EDIT: In on of @jhchen comments he says that he posted something about how to implement tables. Does anybody knows where that post is?

EDIT 2: I'm also taking a look at @2Pacalypse- work

jhchen commented 6 years ago

@javiercbk I think that was something I tried and decided against. I don't remember the reason. This comment is what you are looking for. Subsequent comments by others who tried this approach or took a different one are also useful.

whather commented 6 years ago

@jhchen I think the biggest issue with lack of table support for us is the formatting not being preserved when pasting in content. For example, pasting in a user's email signature with their name on the left, and their logo on the right and a border in between.

Just fixing the pasting issue (and allowing tables in the dom) would be a huge win, versus adding support to insert a new table from the toolbar, etc.

Keep up the good work!

maikdiepenbroek commented 6 years ago

Great work on this so far guys, can i in some way contribute to speed up the release of this feature ?

unstoo commented 6 years ago

I have implemented support of tables using multiple bloats approach. Tables stay consistent after quill.getContents() : delta -> quill.setContents(delta).

I'd appreciate any feedback: https://github.com/unstoo/cpay-wysiwyg/blob/master/src-client/TableBlot.js

The only question I have is regarding pasteHTML of a table. It parses a <table> down to a funny looking delta[ops]. Would the clipboard module be the right place for fixing tables parsing behaviour or should I look elsewhere @jhchen?

Also, can you give me a hint how do I go about disabling enter hits from inserting anything into a table? I've tried to add a blank handler to the bindings module, but as a result the behaviour of enter strokes becomes inconsistent.

key: 'enter',
    format: ['table'],
    handler: function(range, context) {
      return false
    }
ShirlyChan commented 6 years ago

just want to know that when will version 2 publish? I need table support recently. ths~

jhchen commented 6 years ago

The long awaited table support is almost here! You can check out a demo with the latest 2.0 dev build here: https://codepen.io/quill/pen/QxypzX. The UI is not polished of course but the functionality is there. Having multiple editors on the page is meant to test the API and all changes from one should be perfectly produced in the other. I'll be filling out the 2.0 upgrade guide in the next week or two so you can try out tables in your own applications soon. The full 2.0 release will be further out but the dev build is meant to be well documented enough for the brave and eager to try.

In the meantime, help testing and reporting bugs in the demo would be greatly appreciated. Please comment with the bug report (must include your browser/os, steps for reproduction, expected and actual behavior -- there would be too much noise from back and forth otherwise).

The supported features tables features/limitations include:

I will not discuss including additional features here. Please open a separate feature request to request this.

As an administrative note, have marked existing comments as outdated and will also continue to delete all non-substantive comments from this thread to cut down the clutter and mass emails to everyone. Please use the Reaction feature to show support instead of commenting.

dmitryuv commented 6 years ago

great work and happy to see tables are making it into editor core!

Chrome 67 / Mac OS High Sierra

1) Insert table, put cursor into first cell on first row, type and hit Enter. Result: new row inserted BEFORE table. Expected: row should be inserted within cell 2) Insert table, put cursor into first cell on second row, type and hit Enter. Result: new row inserted AFTER table. Expected: row should be inserted within cell 3) Insert table, put cursor into any cell, type then hit Shift+Enter. Result: new cell inserted into the same row on the right, table broken. Expected: row should be inserted within cell.

jhchen commented 6 years ago

Thanks for the notes @dmitryuv. I've fixed 3 and updated the codepen with the new dev build however the expected behavior around the first and last row is inserting a newline outside of the table. Otherwise a table at the edges of the document would prevent any entry before/after it. Also this tables implementation does not allow newlines inside cells. Feel free to open a separate feature request for this.

dmitryuv commented 6 years ago

@jhchen thanks for the update. I see you point regarding newlines, however it's a bit unexpected behaviour comparing to other products. I would agree on having Enter to move cursor below table, but naturally hitting "Enter" after filling column on the first row results in bad UX. Solution? Right now if you create new row above table, there's no way later to remove it (try yourself). Could it be a solution if you automatically create the same editor state when first inserting table into the topmost position?

Regarding multiline - i think this should be fundamental decision and not a separate feature request. For example if you decide to NOT support it, all line-based formats should be automatically disabled once you're in a table. Also any copy&paste should be properly sanitized

Bug or not-fixable?: You can create wrapped line by typing too many text, but it's hard to navigate it for edit. "Down" key moves you to the cell below instead of one wrapped line below. I've seen such behaviours in other editors before if navigation on wrapped text is not explicitly supported.

Bug or intent?: if you apply any row-level format to the cell, it breaks table into separate tables. Any combination of copy&paste of selection that includes tables and row formats create unexpected results. I could get the pattern after few samples but for end user that could be unexpected.

However, if split table behaviour is by design, i can see it might be a good enough solution with proper UX feedback.

jhchen commented 6 years ago

I should clarify the supported features (which I'll edit my original comment for visibility).

These decisions have been made deliberately with consideration of many factors but the biggest is the complexity (both implementation and UX) to utility ratio.

The unable to delete the row above/below the table has been fixed in the develop branch.

I had to overwrite up/down because the native behavior is advancing to the next cell (not the next row) which I thought was unexpected. I did not consider wrapped text though. It would probably have to be one or the other but maybe the next cell is not so strange.

It should also be said Quill is built for customization and all of the keyboard interactions can be changed or removed.

At this point as well I am most concerned about correctness and robustness.

saralnigam commented 6 years ago

@jhchen Great work on tables, there were some table layouts which I don't think are valid as per current description. Sharing details for them.

Browser: Chrome Version 67.0.3396.87 (Official Build) (64-bit)
OS: Linux(Ubuntu 16.04)

Inconsistencies in table layout.

Steps to Reproduce:

1. Insert Table
2. Insert Row Above
3. Insert Column Left
4. Delete Row
5. Insert Table

Output:

image

Some other outputs. Repro steps not available for below cases

Case 1

image Bubble Delta

{
  "ops": [
    {
      "attributes": {
        "table": "row-dpl2"
      },
      "insert": "\n\n\n"
    },
    {
      "attributes": {
        "table": "row-vtlg"
      },
      "insert": "\n\n\n"
    },
    {
      "attributes": {
        "table": "row-7bij"
      },
      "insert": "\n\n\n"
    },
    {
      "attributes": {
        "table": "row-w7z7"
      },
      "insert": "\n\n\n"
    },
    {
      "attributes": {
        "table": "row-b1pp"
      },
      "insert": "\n\n\n"
    },
    {
      "attributes": {
        "table": "row-7bij"
      },
      "insert": "\n\n\n"
    },
    {
      "attributes": {
        "table": "row-b9gy"
      },
      "insert": "\n\n\n"
    },
    {
      "insert": "\n"
    }
  ]
}

Snow Themed Editor Delta

{
  "ops": [
    {
      "attributes": {
        "table": "row-dpl2"
      },
      "insert": "\n\n\n"
    },
    {
      "attributes": {
        "table": "row-vtlg"
      },
      "insert": "\n\n\n"
    },
    {
      "attributes": {
        "table": "row-7bij"
      },
      "insert": "\n\n\n"
    },
    {
      "attributes": {
        "table": "row-w7z7"
      },
      "insert": "\n\n\n"
    },
    {
      "attributes": {
        "table": "row-b1pp"
      },
      "insert": "\n\n\n"
    },
    {
      "attributes": {
        "table": "row-7bij"
      },
      "insert": "\n\n\n"
    },
    {
      "attributes": {
        "table": "row-b9gy"
      },
      "insert": "\n\n\n"
    },
    {
      "insert": "\n"
    }
  ]
}

Case 2

image

Bubble Editor Delta

{
  "ops": [
    {
      "attributes": {
        "table": "row-o4bv"
      },
      "insert": "\n\n\n\n\n"
    },
    {
      "attributes": {
        "table": "row-2yy5"
      },
      "insert": "\n\n"
    },
    {
      "attributes": {
        "table": "row-mb38"
      },
      "insert": "\n\n"
    },
    {
      "attributes": {
        "table": "row-ye3v"
      },
      "insert": "\n\n"
    },
    {
      "attributes": {
        "table": "row-bafm"
      },
      "insert": "\n\n"
    },
    {
      "attributes": {
        "table": "row-omgi"
      },
      "insert": "\n\n\n\n\n"
    },
    {
      "attributes": {
        "table": "row-sx8i"
      },
      "insert": "\n\n\n\n\n"
    },
    {
      "insert": "\n"
    }
  ]
}

Snow Editor Delta

{
  "ops": [
    {
      "attributes": {
        "table": "row-o4bv"
      },
      "insert": "\n\n\n\n\n"
    },
    {
      "attributes": {
        "table": "row-2yy5"
      },
      "insert": "\n\n"
    },
    {
      "attributes": {
        "table": "row-mb38"
      },
      "insert": "\n\n"
    },
    {
      "attributes": {
        "table": "row-ye3v"
      },
      "insert": "\n\n"
    },
    {
      "attributes": {
        "table": "row-bafm"
      },
      "insert": "\n\n"
    },
    {
      "attributes": {
        "table": "row-omgi"
      },
      "insert": "\n\n\n\n\n"
    },
    {
      "attributes": {
        "table": "row-sx8i"
      },
      "insert": "\n\n\n\n\n"
    },
    {
      "insert": "\n"
    }
  ]
}
jhchen commented 6 years ago

Thanks @saralnigam -- should be fixed now and updated the demo

KindBear commented 6 years ago

Who can say how to use it with npm and React?

irowbin commented 6 years ago

@KindBear v2.0 isn't available on npm yet. You've to wait until it officially release to the npm or use dev build at your own risk from https://cdn.quilljs.com/2.0.0-dev.2/quill.js.

jhchen commented 6 years ago

You can do npm install quill@2.0.0-dev.2 but yes use at your own risk.

AdriVanHoudt commented 6 years ago

Hi @jhchen,

We are looking forward to the release of v2 and the ability to use tables ✨ Do you have a (rough) eta on when it will be there?

dearsina commented 6 years ago

If you (force) feed an editor a table within a table by manipulating myQuill.root.innerHTML, it doesn't like it.

<table>
 <tr>
  <td>
   <table>
    <tr>
     <td>
      A table within a table fails.
     </td>
    </tr>
   </table>
  </td>
 </tr>
</table>

Otherwise, force feeding works well and I am very excited about the prospects of using tables with Quill. Tables are big part of HTML. Thank you for your hard work, let us know when you're done!

jhchen commented 6 years ago

pasteHTML was deprecated in favor of dangerouslyPasteHTML and now removed in 2.0. Please keep this thread to table stuff only as you are notifying dozens of people. As I stated above I will remove irrelevant comments.

KindBear commented 6 years ago

I tried to use the quill-table module, but I want to use the built-in module. How do I add options for the toolbar? I could not find how

earshinov commented 6 years ago

Is colspan/rowspan support in the pipeline?

sgiulians commented 6 years ago

Hey hello, First of all thank you for developing quill.js, it's a great library. At the moment I am using the https://cdn.quilljs.com/2.0.0-dev.2/quill.js as I need the table support. It works well so far but I have another question: is it possible to graphically resize the columns by any chance? Thank you very much Simo

Bob343 commented 6 years ago

The current dev version posted uses a lot of lambda functions, can there be a transpiled version uploaded? Current version does not support IE :(

Jvanbeek commented 5 years ago

Hi everyone, For some time now I have been experimenting with Quilljs and I think it works like a charm. For my usecase of the Quill editor I'm in need of the table module that is still in the development branch. Now I was wondering if there is any estimate on when this is going to be officially released. A release window would already be very helpfull. If there is a place where I can find the schedule for the quill editor it would be great if someone could point me in the right direction. If the release of the table module is not somewhere in the near future, is it possible to only add the table module from the development branch or do I have to adopt the development branch as a whole? I'm excited to see what's comming to quill in the future. In any case, thanks in advance and great work on Quill, Jeroen

malek-itani commented 5 years ago

hello @jhchen , how can i add table feature to toolbar using toolbarOptions, not as external buttons as specified in the demo https://codepen.io/quill/pen/QxypzX