Ckeditor5: Implement the (block)quote feature

Created on 26 Jan 2017  Â·  24Comments  Â·  Source: ckeditor/ckeditor5

OK, let's bootstrap some discussions around the quote or blockquote feature (actually, name is one of the things we should discuss :D).

Editor recommendations: http://ckeditor.github.io/editor-recommendations/features/quote.html

I've got various doubts regarding this feature. Some of them come the fact that we don't have enough time before 1.0.0 to implement the full captionable version like in editor recommendations (and I wonder how we should implement the subset of the ER spec to be open for the future). Some, from the fact that ER spec considers a "self-contained quote", while I'm not sure how this applies to e.g. quoting the message you reply to. Finally, I have troubles imagining how certain aspect should work in practice – e.g. what kind of formatting should be available in the blockquote, how to make the <cite> optional in <figcaption> and how "widgety" the feature needs to be if we want to ensure that the caption won't be detached from the quote.

So, let's start from the beginning. Issues that we'd need to face now:

  • If we'll implement the simple quotes features, like in CKEditor 4, without a support for captioning, we still need to output <figure><blockquote></blockquote></figure>, right? Just like with the image feature, which, even if without the caption is wrapped with the <figure>.
  • Should we start with an implementation which works exactly like in CKEditor 4 (with the exception of a wrapped output)?
  • How to represent a quote in the model? It's a bit tempting to try with the linear approach which we implemented for lists, but it'd need to work differently here, because we'd be extending existing, other features' elements with new attributes. Which means, for instance, that when turning a paragraph into a heading or inserting a new block somehow, the quote attribute would need to be maintained or added. This may turn to be really tricky. OTOH, wrapping content with a new attribute will not be easy too when it comes to integration with other algorithms. Finally, if we expect to add the caption in the future, wrapping seems to be a safer choice.
  • Do we want to support nested quotes at all? I can't create them in CKEditor 4, but if we consider e.g. email-like replies, then you need them. But perhaps the email-like quotes are a completely different feature anyway? If so, then please keep in mind that our initial implementation won't satisfy use cases like e.g. GitHub issues.

Issues for the future (just to paint some picture, not to actually work too much on them now):

  • The image feature keeps its caption in place by making the <figure> a widget. This ensures that the caption cannot be separated from the image. However, the quote feature should not behave like a widget (with two nested editables – quote content and quote caption), because it prevents making cross-editable selections and easy keyboard navigation. For instance, you wouldn't be able to select a piece of the quote and text outside or get out from the quote by keeping the left arrow key pressed. Quote is not that self-contained to implement it like the simple-box widget.
  • So, the caption will be a normal element within the quote and we'll need to ensure that it cannot be detached from the quote and that it disappears or turns into a paragraph when the quote is removed in some way. There are a lot of use cases to consider like:

    • Pressing enter in an empty paragraph inside quote escaped the quote... what should happen if that paragraph was followed by a caption or if that paragraph was 2nd out of 3 paragraphs in that quote?

    • What should happen with a pasted content which might split the quote? Should pasting a content be able to split a quote? If so, then what about the caption?

  • How to solve the issue that we had with the empty image quotes (when to turn them on visually (https://github.com/ckeditor/ckeditor5-image/issues/6#issuecomment-260944117) and when to add them to the model (https://github.com/ckeditor/ckeditor5-image/issues/28))

Let's say this is all for now. RFC, all!

Related ticket in the engine: https://github.com/ckeditor/ckeditor5-engine/issues/710.

discussion feature

Most helpful comment

First implementation of block quotes is already available in https://github.com/ckeditor/ckeditor5-block-quote. I opened #419 to continue there discussions regarding other types of quotes.

Thanks to all of you for your contributions. It's interesting to see how many circles we've made before coming to the final conclusions. Good that we haven't stopped somewhere in the midway.

All 24 comments

I think we must definitely see two separate features here:

  • Quote (Q): used for external quotation. That's the usual case when writing articles.
  • Message Quote (MQ): used for referencing pieces of text in replies.

We were used to see the above as one single feature because we've been always seeing features as HTML. So, because in both cases we use the <blockquote> element, we had one feature. But the fact is that the use case is totally different, so these features are styles/presented differently, have different feature and different behavior and UX.

Some of the possible differences:

  • Caption: should be in Q only.
  • Enter: should add new paragraph inside Q. Should break Q on empty paragraph. Should break MQ up to the root always.
  • Nesting: not for Q but required for MQ.

Some of the things in common:

  • Pasting: should stay inside Q and MQ (current level).
  • Keyboard navigation must definitely cross along it.
  • Should use <figure> + <blockquote>.

When it comes to captions in Q, I think that doing like we do it for images is the way to go (show of focus, remove if empty). In any case, caption in Q is definitely not a requirement for version 1.

In the model, I would represent them as elements containing paragraphs.

In my opinion blockquote should be implemented as a single ModelElement that will be wrapping it's content. The problem here is, as you stated, the caption. It could be an attribute but we want to format it, so it would have to have it's own element.

Extra wrapping ViewElements are not a problem at all for converters and mappings. We can easily output <figure><blockqoute></blockqoute></figure>.

Regarding captions, do we want/need to have a caption always at the end of <blockquote> element? I think that with mapping we will be able to force this, especially if <caption> is created/removed by some kind of UI element. Worst comes worst, we will have model structure like this:

<blockquote>
<content>
<p>Lorem ipsum.</p>
<p>Foo bar.</p>
</content>
<caption>Caption</caption>
</blockqoute>

But I'd rather avoid this solution, if possible.

Another issue you touched is breaking elements on Enter. I hold an opinion that Enter at the end of non-empty paragraph should break paragraph. Then another Enter should break also the quote. This will be better from UX point of view. It will be easier to edit content without needing to use mouse.

We already changed how Enter works for lists so we have some experience doing this. However we might think about changing default algorithm. I was about to propose something but it wasn't working perfectly, so maybe we should just overwrite behavior for blockquote, but, in fact, this behavior should be same for all blockquote-like features (that is block features that can have another blocks inside -- this is contrary to list items or paragraphs).

BTW. I think it would be better not to "break" blockquote but just insert paragraph (so it's more, as you said, "escaping" blockquote, not "breaking" it). I assume it's very rare that a user inserts two blockquotes one after anohter. This also resolves one issue I had - what happens to <caption> when blockquote is broken?

Nested quotes - from model point of view I think that we are safe. I think this is more of an UX issue.


The only real issue I see is cut/copy-pasting <caption> element. This could be solved by Schema checks, especially after we rewrite it.

<caption> could be allowed only in <blockquote>, <image>, etc. When it is pasted/inserted it will be stripped so only it's content will be pasted. This is super fine and probably how we want it to work.

The problem starts when you insert <caption> into where it is allowed. Do we want to restrict blockquote to have only one <caption>? I think that these are the more difficult problems to solve, other are easy.

BTW. If we go with the structure that I proposed above this problem would be even easier to solve. <caption> would be allowed only just inside <blockquote> but it would be impossible to place selection there so you would not be able to insert it there (unless you do it from code).


BTW. I don't have a feeling that "blockquote" should be "more flexible" or "less self-contained than image". The only problem may be navigating, for example if you have have caret before quote, when clicking right arrow you should first select whole quote, then get to its inside. I don't think it would be disturbing that you can't make cross selection.

Edit: OK it may be cumbersome for MQ but it is totally fine for Q. I like what Fred proposed -- Q can have captions and be more self-contained, while MQ are something like styled div.

Thanks guys.

So, now we'll focus on Message Quote. It's simpler and requires less magic.

Things to define:

  • Feature name?

    • I guess that we agree that "Message Quote" is not an option. It's our term, but we need something simpler. I'll start with just "Block quote" (MQ) and the other feature can be called "External Quote" or something like that.

  • Model element name?

    • Just blockQuote? Or blockquote? Or quote?

I would call these features "Message Quote" and "Quote", with their element names matching their names.

Alternative names for Message Quote: Reply Quote, InReply Quote.

Defitely not Blockquote, to not HTMLize it.

Hm... I don't know if naming this plugin and feature "message quote" makes sense because it will be confusing. The "message" adjective makes it very narrow, while the feature makes sense in a lot more cases.

Another thing – what should be the output HTML? <figure class=quote><blockquote>...</blockquote> will be reserved for normal quotes, so we need to use a different class or an additional class allowing us to differentiate between these two quote types.

Besides, I'm unsure if a message quote needs to be wrapped with <figure>. What's the point of that? Isn't this the situation when <blocquote> can be used alone? If not in this case, then in what case?

In terms of semantics, figure is a little bit tricky. If the quote could be moved into other place (makes sense without the original context), then figure is totally fine. If quote is context-dependent (which is probably a case in MQ), then figure could (or even should) be omitted, as I mentioned earlier.

As far as name is concerned, I thought maybe Quote vs Citation, but they are synonymous, aren't they?

_Howdy, I‘ve been following CK5 progress since you all started (very excited for the direction and dedication you've all shown, so thank you!). This is the first time I felt I might be able to contribute a meaningful thought to your copious deliberations._

FWIW and following on @fredck's comment about thinking of use-cases, you might consider having three features instead of two. This is how I'd name them, and my reasoning:

Block Quotation would include an option for a citation.

I get the aversion to reinforcing bad habits and assumptions around \

Pull Quote would lack a citation and use an \

In practice it seems to me that on the web, users of RTE's avail themselves of the "blockquote" to create _pull-quotes_ more than anything else, and in HTML5 it isn't really the best tag to use semantically. (1) (2) My thinking is that by providing a distinct feature, it would short-circuit this tendency and reinforce the proper use of _Block Quotation_.

Quoted Text for "Message Quote"

This is the language used by most email clients to describe the feature you're looking to create. Go with convention here, I say.

Just my 2¢. 😄

Cheers,
David

Block Quotation
Setting a large block of quoted text apart from the surrounding text is literally called a "Block Quotation"

OMG, how could have we missed this? :(

Pull Quote

That's a very good addition and it indeed makes a lot of sense.

Quoted Text for "Message Quote"

It makes total sense as well, although it sounds a bit weird as a feature name because it is usually referring to text which has already been (usually automatically) quoted.

If we would see this as a button in the toolbar, would simply "Quote" be a good label for it instead?

Summing up... well said @dtwist (David) ;)

Hmm... I wonder how far is a message quote from a block quotation semantically. It seems to me that MQ is just a special case of BQ. Would you agree?

I think the most relevant differences reside on the use cases, purpose, UX and UI. In fact, you'll rarely have an application using both at the same time.

In the other hand, it may be common to see applications using Block Quotation and Pull Quotes at the same time.

I think the most relevant differences reside on the use cases, purpose, UX and UI. In fact, you'll rarely have an application using both at the same time.

But I don't see much of a difference between them – that's what I'm trying to say. If you're quoting someone's message it's pretty much the same as trying to quote someone's words or article in your article. You need to be able to paste/write that text and mark it as a quote – that's the bare minimum in both cases.

However, for the message quote you may also need to be able to easily insert such a text programmatically (like here in GitHub, when you press R) and to be able to nest quotes inside each other. So, unless BQ has some special needs, it seems to me that MQ is a more advanced use case ~than~ of BQ, but the basics are the same. BQ will satisfy simple MQ's use cases.

Also, I can see that the feature we're working on right now (so the feature that we had in CKE4) is exactly BQ. It doesn't satisfy MQ needs because, at least for now, we don't expect to work on nesting quotes.

So I'm starting to feel that calling it MQ was overengineering. It's a BQ and we're only confusing potential users. At the same time, it's not really useful for more advanced MQ use cases because we don't support nesting.

Therefore, I'd start with providing BQ, which is the most general and the widest use case. Later on, we should work on PQs and think on providing special flavours of BQs which will serve MQs better (e.g. add some UI for nesting).

But I don't see much of a difference between them

Hum... I think you're considering just the implementation. All the aspects I've listed are different:

  • Message Quote (Quoted Text):

    • Use cases: usually message/thread systems - e-mail, forum-like systems (like GH).
    • Purpose: comment on previous messages to give context on the text you're writing.
    • UX:

      • in many cases, such quotes are created by the application either when starting editing (like and e-mail reply) or by a comment to inject quote.

      • In some applications one may wish to paste the text to the quoted.

      • The Enter key breaks the quote immediately.

    • UI: usually represented by grayed out text with a bar as the left margin
  • Block Quoting:

    • Use cases: articles, documents.
    • Purpose: enrich the content with a third-party quote.
    • UX:

      • Definitely a button to create it.

      • Text is pasted or typed.

      • The Enter key doesn't break the quote immediately, just on empty line.

    • UI: usually represented by a differently styled block of text with quotes around it.

The above shows that we have two totally different features and it is indeed less likely to have both available at the same time, because the use cases are different.

So I'm starting to feel that calling it MQ was overengineering. It's a BQ and we're only confusing potential users.

Although the implementation may be very similar, separating them will actually make it less confusing. There would be no css, options or configurations to make it work in one way or the other. Each of the features will be focused on solving one problem only in the most optimal and easy to understand way.

OK, I agree – there are some details which make them different. Especially if we want to differentiate styling, because the enter key is something that the users wouldn't mind, I think. It can be easily "workarounded" by pressing the Enter multiple times. And let's be honest – having too many similar features may be as confusing as having one which is less specialised and requires some more actions from the user. We should keep this in mind too.

But, as I said, I generally agree that enter + styling + nesting differentiate significantly (enough) these two features. However, the feature I'm now working on in ckeditor5-message-quote is definitely far closer to BQ than MQ. MQ requires far more work like nesting, proper classes (and perhaps some attributes identifying the author and different styling). The nesting aspect means a lot of work.

Hence, I'd propose to just work on BQ now. Is it ok?

Hence, I'd propose to just work on BQ now. Is it ok?

If that's what we can have now, it's fine.

I think that the most critical thing about MQ is the nesting. Therefore, we may think about an initial proposal that has no support for it, if it would be easier.

In any case, having BQ only is also acceptable for now.

Quoted Text for "Message Quote"

It makes total sense as well, although it sounds a bit weird as a feature name because it is usually referring to text which has already been (usually automatically) quoted.

Maybe "Quote Level" makes more sense? Especially if nesting is the defining characteristic.

If we would see this as a button in the toolbar, would simply "Quote" be a good label for it instead?

In the toolbar, I'd propose a dropdown button with "Increase Quote Level" and "Decrease Quote Level"—similar to "Indent/Outdent".

BTW, I think@fredck summed up the differences between BQ and MQ quite well. Glad you all are agreeing they are separate features. :)

In the toolbar, I'd propose a dropdown button with "Increase Quote Level" and "Decrease Quote Level"—similar to "Indent/Outdent".

I was initially thinking about something like a split button. You click the left part to apply the quote or remove the quote, but you can also click the arrow (the right part) to open a panel with two options – "increase QL" and "decrease QL". So this would be a combination of a dropdown and a button to apply the quote.

We could also try to be smarter and have just the increase and decrease level buttons. First click on the increase option would apply the first level of quotation and so on. I'm thinking though how to squeeze those two options in the toolbar without taking too much space. The first disadvantage of this option is that we lose the ability to indicate that the caret is inside a quote (in the first solution we can do that by changing the state of the "left" part).

The third option is the good old combination of the quote button and indent/outdent buttons. Then, the indent/outdent buttons can be shared with the list feature.

Anyway, there should be even more options. Also, we need to figure out how to show MQ buttons next to BQ and potentially PQ too :D. Perhaps a split button will be able to accommodate that. OTOH, perhaps initially we can assume that no one will use just more than one of these features at the same time. This will be fun... (cc @oleq)

In any case, having BQ only is also acceptable for now.

I'll go this way then – I'll just rename ckeditor5-message-quote to ckeditor5-block-quote. I feel that with BQ we can go with a bare <blockquote> in the data (no classes – just like in the current implementation in ckeditor5-message-quote), while MQ should be somehow marked. Plus, I'm sure the discussion about MQ's UI will take a while so it'd block us from releasing anything.

I was initially thinking about something like a split button.
We could also try to be smarter and have just the increase and decrease level buttons.

+1 for any of the above options.

The third option is the good old combination of the quote button and indent/outdent buttons.

-1 for this.

I was initially thinking about something like a split button. You click the left part to apply the quote or remove the quote, but you can also click the arrow (the right part) to open a panel with two options – "increase QL" and "decrease QL". So this would be a combination of a dropdown and a button to apply the quote.

This idea makes sense,

We could also try to be smarter and have just the increase and decrease level buttons. First click on the increase option would apply the first level of quotation and so on.

...while this one doesn't. For one thing, the buttons wouldn't be able to reflect the state of the feature. Another thing is that to remove the quote which is nested, you got to click the "outdent" many times, e.g. 3 clicks for a short "quote-reply" e-mail conversation.

The third option is the good old combination of the quote button and indent/outdent buttons. Then, the indent/outdent buttons can be shared with the list feature.

Is not a good idea either because the content of the quotation could be a list and sometimes you might want to indent the list and sometimes nest the quotation, which is not quite possible with a single set of UI controls.

Anyway, we have lots of options to implement it in the UI and save precious toolbar space. Some raw ideas:

image

image

image

I don't think we should unify all 3 kinds of quote into a single UI button. As said earlier, there are rare cases where "Quoted Text" will be used together with the "Block Quotation" and "Pull Quote" pair. Additionally, these are features with different purposes.

I would, therefore, propose different solutions for each case, although we may consider a combined approach for "Block Quotation" and "Pull Quote" (maybe a balloon toolbar for it?).

What I meant by these mockups is that we can aggregate things. But we don't have to.

I agree that it's unlikely all of them will be enabled in a single editor instance. E.g. in such case, when just one of them is enabled, the button in the toolbar will activate it and the dropdown will provide quote level functionality, if necessary for that type of quote.

So when just block quote is enabled, it would be
image

and for text quote only
image

If more that one type of quote is enabled, the split-dropdown button will gather them. It would be an UI complement that first quote plugin to be loaded would register and the following quote plugins would just use it to show up in the editor.

That's an idea, although having two different buttons in such case would work for me as well. Also because we may think about a different icon for Quoted Text, maybe.

And what about the following, which I mentioned earlier?

"Block Quotation" and "Pull Quote" (maybe a balloon toolbar for it?)

A toolbar much similar to the image styles toolbar.

First implementation of block quotes is already available in https://github.com/ckeditor/ckeditor5-block-quote. I opened #419 to continue there discussions regarding other types of quotes.

Thanks to all of you for your contributions. It's interesting to see how many circles we've made before coming to the final conclusions. Good that we haven't stopped somewhere in the midway.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

PaulParker picture PaulParker  Â·  3Comments

wwalc picture wwalc  Â·  3Comments

benjismith picture benjismith  Â·  3Comments

hamenon picture hamenon  Â·  3Comments

pandora-iuz picture pandora-iuz  Â·  3Comments