ueberdosis / tiptap

The headless rich text editor framework for web artisans.
https://tiptap.dev
MIT License
27.7k stars 2.3k forks source link

Ordered lists do not support list types (`a`, `A`, `i` and `I`) #3726

Open ahukkanen opened 1 year ago

ahukkanen commented 1 year ago

What’s the bug you are facing?

When you create an ordered list with some type (alphabet order, roman numerals), these list types are disappearing when this kind of content is entered to Tiptap.

This is typical behavior for example when copying content from a desktop rich text editor program.

For further reference, see the documentation for the type attribute for ordered lists: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ol

This is a valid attribute with one of those values described on that page.

Which browser was this experienced in? Are any special extensions installed?

Chrome 109.0.5414.119

How can we reproduce the bug on our side?

Create the following kind of text in a desktop rich text editor (e.g. LibreOffice, MS Office):

Rich text editor content

When using LibreOffice Writer, this content would produce the following HTML when copied and pasted to a contenteditable area:

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
    <title></title>
    <meta name="generator" content="LibreOffice 7.3.7.2 (Linux)"/>
    <style type="text/css">
        @page { size: 21.59cm 27.94cm; margin: 2cm }
        p { line-height: 115%; margin-bottom: 0.25cm; background: transparent }
    </style>
</head>
<body lang="en-US" link="#000080" vlink="#800000" dir="ltr"><p style="line-height: 100%; margin-bottom: 0cm">
Copy this text from rich text editor</p>
<ol>
    <li><p style="line-height: 100%; margin-bottom: 0cm">Item 1</p>
    <ol type="a">
        <li><p style="line-height: 100%; margin-bottom: 0cm">Subitem 1.1</p>
        <li><p style="line-height: 100%; margin-bottom: 0cm">Subitem 1.2</p>
    </ol>
    <li><p style="line-height: 100%; margin-bottom: 0cm">Item 2</p>
    <ol type="a">
        <li><p style="line-height: 100%; margin-bottom: 0cm">Subitem 2.1</p>
        <li><p style="line-height: 100%; margin-bottom: 0cm">Subitem 2.2</p>
    </ol>
</ol>
</body>
</html>

Copy this content from the rich text editor and paste it to Tiptap.

Can you provide a CodeSandbox?

https://jsfiddle.net/69utomky/

Note that here I am replicating the list content as described above as the initial content for the editor, so that you are able to see the behavior directly.

What did you expect to happen?

I would expect the valid ordered list type attributes to be preserved in the final markup.

As defined by the spec, the valid values are a, A, i and I.

The default type of 1 does not need to be supported as that is the default anyways.

Anything to add? (optional)

I fixed this in our implementation with the following extension to the OrderedList extension: https://github.com/decidim/decidim/blob/e8d1f7eb691b8cb882d345a932d08888a8a6f443/decidim-core/app/packs/src/decidim/editor/extensions/ordered_list/index.js

Did you update your dependencies?

Are you sponsoring us?

ahukkanen commented 1 year ago

Also as an update to this, Google Docs does not carry the ordered list's type attribute so we have to read the style from the first list item in the ordered list.

I have update the link above to our implementation which contains this fix as well.

Here is an example document you can try copying from: https://docs.google.com/document/d/1NmbHtoHRul9P2EgYFJ922-uo6zGoo7l1H0-43uiW5WY/edit

When copied to clipboard, this produces the following HTML:

<meta charset="utf-8"><b style="font-weight:normal;" id="docs-internal-guid-ea08f363-7fff-0635-f25d-5f6d2ddc7d51"><p dir="ltr" style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;"><span style="font-size:11pt;font-family:Arial;color:#000000;background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre;white-space:pre-wrap;">Pasting list with styles</span></p><ol style="margin-top:0;margin-bottom:0;padding-inline-start:48px;"><li dir="ltr" style="list-style-type:decimal;font-size:11pt;font-family:Arial;color:#000000;background-color:transparent;font-weight:700;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre;" aria-level="1"><p dir="ltr" style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;" role="presentation"><span style="font-size:11pt;font-family:Arial;color:#000000;background-color:transparent;font-weight:700;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre;white-space:pre-wrap;">Item 1</span></p></li><ol style="margin-top:0;margin-bottom:0;padding-inline-start:48px;"><li dir="ltr" style="list-style-type:lower-alpha;font-size:11pt;font-family:Arial;color:#000000;background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre;" aria-level="2"><p dir="ltr" style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;" role="presentation"><span style="font-size:11pt;font-family:Arial;color:#000000;background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre;white-space:pre-wrap;">Subitem 1</span></p></li><li dir="ltr" style="list-style-type:lower-alpha;font-size:11pt;font-family:Arial;color:#000000;background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre;" aria-level="2"><p dir="ltr" style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;" role="presentation"><span style="font-size:11pt;font-family:Arial;color:#000000;background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre;white-space:pre-wrap;">Subitem 2</span></p></li><li dir="ltr" style="list-style-type:lower-alpha;font-size:11pt;font-family:Arial;color:#000000;background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre;" aria-level="2"><p dir="ltr" style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;" role="presentation"><span style="font-size:11pt;font-family:Arial;color:#000000;background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre;white-space:pre-wrap;">Subitem 3</span></p></li></ol><li dir="ltr" style="list-style-type:decimal;font-size:11pt;font-family:Arial;color:#000000;background-color:transparent;font-weight:700;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre;" aria-level="1"><p dir="ltr" style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;" role="presentation"><span style="font-size:11pt;font-family:Arial;color:#000000;background-color:transparent;font-weight:700;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre;white-space:pre-wrap;">Item 2</span></p></li><ol style="margin-top:0;margin-bottom:0;padding-inline-start:48px;"><li dir="ltr" style="list-style-type:lower-alpha;font-size:11pt;font-family:Arial;color:#000000;background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre;" aria-level="2"><p dir="ltr" style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;" role="presentation"><span style="font-size:11pt;font-family:Arial;color:#000000;background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre;white-space:pre-wrap;">Subitem 1</span></p></li><li dir="ltr" style="list-style-type:lower-alpha;font-size:11pt;font-family:Arial;color:#000000;background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre;" aria-level="2"><p dir="ltr" style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;" role="presentation"><span style="font-size:11pt;font-family:Arial;color:#000000;background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre;white-space:pre-wrap;">Subitem 2</span></p></li><li dir="ltr" style="list-style-type:lower-alpha;font-size:11pt;font-family:Arial;color:#000000;background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre;" aria-level="2"><p dir="ltr" style="line-height:1.38;margin-top:0pt;margin-bottom:0pt;" role="presentation"><span style="font-size:11pt;font-family:Arial;color:#000000;background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre;white-space:pre-wrap;">Subitem 3</span></p></li></ol></ol></b>

It carries the list-style-type style definition on the list items but does not define the type for the parent <ol> item.

gethari commented 1 year ago

@ahukkanen but the extension still does not support when the user manually indents the sub items based on the indent level right ?. Do you think we need to take care of it as well ? But this same problem has been solved by czi-prosemirror, in this REPO, but the code is in raw prosemirror

ahukkanen commented 1 year ago

@gethari Yes, that is not supported by the extension currently.

I'm not sure if we want to support that either, there are a bit of differences how different editors work in this regard. For example, LibreOffice does not change the list style automatically for the sub-list items unless the user changes it themselves.

What I'm thinking is that maybe we could provide some keyboard shortcut for changing the list style on the fly. I have to investigate a bit about different editors and if they provide any commonly known shortcut for this.

Or alternatively, we can add a toolbar control to change the list style for ordered lists.

EDIT: The keyboard shortcuts has been added to the extension and the link to the extension is also updated. There did not seem to be a generic convention for this, so we went with ALT+SHIFT+UP and ALT+SHIFT+DOWN for changing through the available list types.

ahukkanen commented 1 year ago

We found out another issue with the ordered lists with a type. If you have customized the list rendering and not relying on the user agent's default styling, you cannot style the upper-* and lower-* list style types based on the type attribute alone because you cannot target that attribute through CSS case sensitively. Apparently it's a limitation in the CSS specification, further details:

This should be eventually fixed as the case sensitive selector modifier was accepted to the CSS specification as per: https://github.com/w3c/csswg-drafts/commit/de57526

As a workaround, we decided to add a secondary data-type attribute to the typed ordered lists in the linked extension above to allow styling these elements through CSS. I have updated the link in the original issue to the customized OrderedList extension that includes this feature as well.

github-actions[bot] commented 1 year ago

This issue is stale because it has been open 45 days with no activity. Remove stale label or comment or this will be closed in 7 days

ahukkanen commented 1 year ago

This is still relevant.

planktonrobo commented 1 year ago

bump

planktonrobo commented 1 year ago

You can edit your css like so if you know you want a nested ordered lists to be letters:

li > ol {
    counter-reset: list;
    margin: 0;
}

li > ol > li {
    list-style: none;
    position: relative;
}

li > ol > li:before {
    counter-increment: list;
    content: counter(list, lower-alpha) ") ";
    position: absolute;
    left: -1.4em;
}

I think type="a" support would be nice though

sangeethkc commented 10 months ago

Bump