diff --git a/.playwright/screenshots/alignment-mixed.png b/.playwright/screenshots/alignment-mixed.png index c4177a5a6..32dfb4888 100644 Binary files a/.playwright/screenshots/alignment-mixed.png and b/.playwright/screenshots/alignment-mixed.png differ diff --git a/.playwright/screenshots/display-alignment-checkbox.png b/.playwright/screenshots/display-alignment-checkbox.png index 16a347cfa..953b4c05d 100644 Binary files a/.playwright/screenshots/display-alignment-checkbox.png and b/.playwright/screenshots/display-alignment-checkbox.png differ diff --git a/.playwright/screenshots/display-alignment-mixed-lists.png b/.playwright/screenshots/display-alignment-mixed-lists.png index 3d28fd05e..3a9874e6e 100644 Binary files a/.playwright/screenshots/display-alignment-mixed-lists.png and b/.playwright/screenshots/display-alignment-mixed-lists.png differ diff --git a/.playwright/screenshots/display-alignment-ol.png b/.playwright/screenshots/display-alignment-ol.png index dab2f7ee2..e28ae905d 100644 Binary files a/.playwright/screenshots/display-alignment-ol.png and b/.playwright/screenshots/display-alignment-ol.png differ diff --git a/.playwright/screenshots/display-alignment-ul.png b/.playwright/screenshots/display-alignment-ul.png index 1f46b8269..c1f667e87 100644 Binary files a/.playwright/screenshots/display-alignment-ul.png and b/.playwright/screenshots/display-alignment-ul.png differ diff --git a/.playwright/screenshots/enriched-text-all-list-types.png b/.playwright/screenshots/enriched-text-all-list-types.png index a7628b235..a10a8fde5 100644 Binary files a/.playwright/screenshots/enriched-text-all-list-types.png and b/.playwright/screenshots/enriched-text-all-list-types.png differ diff --git a/.playwright/screenshots/enriched-text-checkbox-list-checked.png b/.playwright/screenshots/enriched-text-checkbox-list-checked.png index 69d805957..ba23f891f 100644 Binary files a/.playwright/screenshots/enriched-text-checkbox-list-checked.png and b/.playwright/screenshots/enriched-text-checkbox-list-checked.png differ diff --git a/.playwright/screenshots/enriched-text-checkbox-list-empty-items.png b/.playwright/screenshots/enriched-text-checkbox-list-empty-items.png index fc5b56589..40c593608 100644 Binary files a/.playwright/screenshots/enriched-text-checkbox-list-empty-items.png and b/.playwright/screenshots/enriched-text-checkbox-list-empty-items.png differ diff --git a/.playwright/screenshots/enriched-text-checkbox-list-unchecked.png b/.playwright/screenshots/enriched-text-checkbox-list-unchecked.png index fce7f975e..295f26f61 100644 Binary files a/.playwright/screenshots/enriched-text-checkbox-list-unchecked.png and b/.playwright/screenshots/enriched-text-checkbox-list-unchecked.png differ diff --git a/.playwright/screenshots/enriched-text-checkbox-list-wrapped.png b/.playwright/screenshots/enriched-text-checkbox-list-wrapped.png index 27d2ef38c..acc0ea524 100644 Binary files a/.playwright/screenshots/enriched-text-checkbox-list-wrapped.png and b/.playwright/screenshots/enriched-text-checkbox-list-wrapped.png differ diff --git a/.playwright/screenshots/enriched-text-images-inside-list.png b/.playwright/screenshots/enriched-text-images-inside-list.png index 40eb481ee..c8505081f 100644 Binary files a/.playwright/screenshots/enriched-text-images-inside-list.png and b/.playwright/screenshots/enriched-text-images-inside-list.png differ diff --git a/.playwright/screenshots/enriched-text-images-placeholder-list.png b/.playwright/screenshots/enriched-text-images-placeholder-list.png index dd9e372db..4c32283da 100644 Binary files a/.playwright/screenshots/enriched-text-images-placeholder-list.png and b/.playwright/screenshots/enriched-text-images-placeholder-list.png differ diff --git a/.playwright/screenshots/enriched-text-ordered-list-empty-items.png b/.playwright/screenshots/enriched-text-ordered-list-empty-items.png index dd41cd530..2019cc9b0 100644 Binary files a/.playwright/screenshots/enriched-text-ordered-list-empty-items.png and b/.playwright/screenshots/enriched-text-ordered-list-empty-items.png differ diff --git a/.playwright/screenshots/enriched-text-ordered-list-extended-margin-after.png b/.playwright/screenshots/enriched-text-ordered-list-extended-margin-after.png new file mode 100644 index 000000000..a14301aef Binary files /dev/null and b/.playwright/screenshots/enriched-text-ordered-list-extended-margin-after.png differ diff --git a/.playwright/screenshots/enriched-text-ordered-list-extended-margin-before.png b/.playwright/screenshots/enriched-text-ordered-list-extended-margin-before.png new file mode 100644 index 000000000..053f4b714 Binary files /dev/null and b/.playwright/screenshots/enriched-text-ordered-list-extended-margin-before.png differ diff --git a/.playwright/screenshots/enriched-text-ordered-list-wrapped.png b/.playwright/screenshots/enriched-text-ordered-list-wrapped.png index 0939b509d..55ae3652f 100644 Binary files a/.playwright/screenshots/enriched-text-ordered-list-wrapped.png and b/.playwright/screenshots/enriched-text-ordered-list-wrapped.png differ diff --git a/.playwright/screenshots/enriched-text-ordered-list.png b/.playwright/screenshots/enriched-text-ordered-list.png index 8aa698c69..164425475 100644 Binary files a/.playwright/screenshots/enriched-text-ordered-list.png and b/.playwright/screenshots/enriched-text-ordered-list.png differ diff --git a/.playwright/screenshots/enriched-text-unordered-list-empty-items.png b/.playwright/screenshots/enriched-text-unordered-list-empty-items.png index e1b9a06db..509cf2501 100644 Binary files a/.playwright/screenshots/enriched-text-unordered-list-empty-items.png and b/.playwright/screenshots/enriched-text-unordered-list-empty-items.png differ diff --git a/.playwright/screenshots/enriched-text-unordered-list-wrapped.png b/.playwright/screenshots/enriched-text-unordered-list-wrapped.png index 918add414..9f85e6c01 100644 Binary files a/.playwright/screenshots/enriched-text-unordered-list-wrapped.png and b/.playwright/screenshots/enriched-text-unordered-list-wrapped.png differ diff --git a/.playwright/screenshots/enriched-text-unordered-list.png b/.playwright/screenshots/enriched-text-unordered-list.png index 5f98bdc97..6d948c649 100644 Binary files a/.playwright/screenshots/enriched-text-unordered-list.png and b/.playwright/screenshots/enriched-text-unordered-list.png differ diff --git a/.playwright/screenshots/images-checkbox-list-placeholder.png b/.playwright/screenshots/images-checkbox-list-placeholder.png index d0f5fe7d7..e9ec213c1 100644 Binary files a/.playwright/screenshots/images-checkbox-list-placeholder.png and b/.playwright/screenshots/images-checkbox-list-placeholder.png differ diff --git a/.playwright/screenshots/images-loaded-in-list.png b/.playwright/screenshots/images-loaded-in-list.png index b75a46c71..0f7c10887 100644 Binary files a/.playwright/screenshots/images-loaded-in-list.png and b/.playwright/screenshots/images-loaded-in-list.png differ diff --git a/.playwright/screenshots/images-ol-placeholder.png b/.playwright/screenshots/images-ol-placeholder.png index cf170fb65..f092035f2 100644 Binary files a/.playwright/screenshots/images-ol-placeholder.png and b/.playwright/screenshots/images-ol-placeholder.png differ diff --git a/.playwright/screenshots/images-ul-placeholder.png b/.playwright/screenshots/images-ul-placeholder.png index 69c010bae..d26c58919 100644 Binary files a/.playwright/screenshots/images-ul-placeholder.png and b/.playwright/screenshots/images-ul-placeholder.png differ diff --git a/.playwright/screenshots/list-keyboard-backspace-after-lift-bullet.png b/.playwright/screenshots/list-keyboard-backspace-after-lift-bullet.png index 2cd7ec9a4..ddeb3436b 100644 Binary files a/.playwright/screenshots/list-keyboard-backspace-after-lift-bullet.png and b/.playwright/screenshots/list-keyboard-backspace-after-lift-bullet.png differ diff --git a/.playwright/screenshots/list-keyboard-backspace-after-lift-checkbox.png b/.playwright/screenshots/list-keyboard-backspace-after-lift-checkbox.png index b012fd9b2..0df2d6fb8 100644 Binary files a/.playwright/screenshots/list-keyboard-backspace-after-lift-checkbox.png and b/.playwright/screenshots/list-keyboard-backspace-after-lift-checkbox.png differ diff --git a/.playwright/screenshots/list-keyboard-backspace-after-lift-ordered.png b/.playwright/screenshots/list-keyboard-backspace-after-lift-ordered.png index d5f942ede..6dc870c51 100644 Binary files a/.playwright/screenshots/list-keyboard-backspace-after-lift-ordered.png and b/.playwright/screenshots/list-keyboard-backspace-after-lift-ordered.png differ diff --git a/.playwright/screenshots/list-keyboard-backspace-after-merge-bullet.png b/.playwright/screenshots/list-keyboard-backspace-after-merge-bullet.png index fffab7a47..e6f5816b5 100644 Binary files a/.playwright/screenshots/list-keyboard-backspace-after-merge-bullet.png and b/.playwright/screenshots/list-keyboard-backspace-after-merge-bullet.png differ diff --git a/.playwright/screenshots/list-keyboard-backspace-after-merge-checkbox.png b/.playwright/screenshots/list-keyboard-backspace-after-merge-checkbox.png index 0d67e85bf..1747824b6 100644 Binary files a/.playwright/screenshots/list-keyboard-backspace-after-merge-checkbox.png and b/.playwright/screenshots/list-keyboard-backspace-after-merge-checkbox.png differ diff --git a/.playwright/screenshots/list-keyboard-backspace-after-merge-ordered.png b/.playwright/screenshots/list-keyboard-backspace-after-merge-ordered.png index 5189ac0a7..9e8a61243 100644 Binary files a/.playwright/screenshots/list-keyboard-backspace-after-merge-ordered.png and b/.playwright/screenshots/list-keyboard-backspace-after-merge-ordered.png differ diff --git a/.playwright/screenshots/list-keyboard-enter-bullet.png b/.playwright/screenshots/list-keyboard-enter-bullet.png index 729777807..5870498a1 100644 Binary files a/.playwright/screenshots/list-keyboard-enter-bullet.png and b/.playwright/screenshots/list-keyboard-enter-bullet.png differ diff --git a/.playwright/screenshots/list-keyboard-enter-causes-scrolling-bullet.png b/.playwright/screenshots/list-keyboard-enter-causes-scrolling-bullet.png index 745b3f299..012dd8c67 100644 Binary files a/.playwright/screenshots/list-keyboard-enter-causes-scrolling-bullet.png and b/.playwright/screenshots/list-keyboard-enter-causes-scrolling-bullet.png differ diff --git a/.playwright/screenshots/list-keyboard-enter-causes-scrolling-checkbox.png b/.playwright/screenshots/list-keyboard-enter-causes-scrolling-checkbox.png index 923a321c1..f1efdb12f 100644 Binary files a/.playwright/screenshots/list-keyboard-enter-causes-scrolling-checkbox.png and b/.playwright/screenshots/list-keyboard-enter-causes-scrolling-checkbox.png differ diff --git a/.playwright/screenshots/list-keyboard-enter-causes-scrolling-ordered.png b/.playwright/screenshots/list-keyboard-enter-causes-scrolling-ordered.png index 408fe7031..602284858 100644 Binary files a/.playwright/screenshots/list-keyboard-enter-causes-scrolling-ordered.png and b/.playwright/screenshots/list-keyboard-enter-causes-scrolling-ordered.png differ diff --git a/.playwright/screenshots/list-keyboard-enter-checkbox.png b/.playwright/screenshots/list-keyboard-enter-checkbox.png index c2f0c16e9..0d1511c3d 100644 Binary files a/.playwright/screenshots/list-keyboard-enter-checkbox.png and b/.playwright/screenshots/list-keyboard-enter-checkbox.png differ diff --git a/.playwright/screenshots/list-keyboard-enter-ordered.png b/.playwright/screenshots/list-keyboard-enter-ordered.png index d8aaacd37..268e4fa7e 100644 Binary files a/.playwright/screenshots/list-keyboard-enter-ordered.png and b/.playwright/screenshots/list-keyboard-enter-ordered.png differ diff --git a/.playwright/screenshots/list-nested-html-ol-in-ul.png b/.playwright/screenshots/list-nested-html-ol-in-ul.png index b14d475ec..38f2bd273 100644 Binary files a/.playwright/screenshots/list-nested-html-ol-in-ul.png and b/.playwright/screenshots/list-nested-html-ol-in-ul.png differ diff --git a/.playwright/screenshots/list-nested-html-triple-nested-ul.png b/.playwright/screenshots/list-nested-html-triple-nested-ul.png index 7ceb3c7d2..76186d563 100644 Binary files a/.playwright/screenshots/list-nested-html-triple-nested-ul.png and b/.playwright/screenshots/list-nested-html-triple-nested-ul.png differ diff --git a/.playwright/screenshots/list-nested-html-ul-in-ol.png b/.playwright/screenshots/list-nested-html-ul-in-ol.png index 246c6eadd..1e38b3ccd 100644 Binary files a/.playwright/screenshots/list-nested-html-ul-in-ol.png and b/.playwright/screenshots/list-nested-html-ul-in-ol.png differ diff --git a/.playwright/screenshots/list-nested-html-ul-in-ul.png b/.playwright/screenshots/list-nested-html-ul-in-ul.png index 5369c0be1..35f341a6b 100644 Binary files a/.playwright/screenshots/list-nested-html-ul-in-ul.png and b/.playwright/screenshots/list-nested-html-ul-in-ul.png differ diff --git a/.playwright/screenshots/paragraph-styles-visual-checkbox-list-wrapped.png b/.playwright/screenshots/paragraph-styles-visual-checkbox-list-wrapped.png index d23bb7ab9..7ae56add0 100644 Binary files a/.playwright/screenshots/paragraph-styles-visual-checkbox-list-wrapped.png and b/.playwright/screenshots/paragraph-styles-visual-checkbox-list-wrapped.png differ diff --git a/.playwright/screenshots/paragraph-styles-visual-checkbox-list.png b/.playwright/screenshots/paragraph-styles-visual-checkbox-list.png index 856ad1599..769e37a94 100644 Binary files a/.playwright/screenshots/paragraph-styles-visual-checkbox-list.png and b/.playwright/screenshots/paragraph-styles-visual-checkbox-list.png differ diff --git a/.playwright/screenshots/paragraph-styles-visual-ordered-list-extended-margin-after.png b/.playwright/screenshots/paragraph-styles-visual-ordered-list-extended-margin-after.png new file mode 100644 index 000000000..0da7c3ecd Binary files /dev/null and b/.playwright/screenshots/paragraph-styles-visual-ordered-list-extended-margin-after.png differ diff --git a/.playwright/screenshots/paragraph-styles-visual-ordered-list-extended-margin-before.png b/.playwright/screenshots/paragraph-styles-visual-ordered-list-extended-margin-before.png new file mode 100644 index 000000000..7ffd6e6c2 Binary files /dev/null and b/.playwright/screenshots/paragraph-styles-visual-ordered-list-extended-margin-before.png differ diff --git a/.playwright/screenshots/paragraph-styles-visual-ordered-list-wrapped.png b/.playwright/screenshots/paragraph-styles-visual-ordered-list-wrapped.png index 5f8313ec0..d5c73e198 100644 Binary files a/.playwright/screenshots/paragraph-styles-visual-ordered-list-wrapped.png and b/.playwright/screenshots/paragraph-styles-visual-ordered-list-wrapped.png differ diff --git a/.playwright/screenshots/paragraph-styles-visual-ordered-list.png b/.playwright/screenshots/paragraph-styles-visual-ordered-list.png index 329fdf435..3a125b8ff 100644 Binary files a/.playwright/screenshots/paragraph-styles-visual-ordered-list.png and b/.playwright/screenshots/paragraph-styles-visual-ordered-list.png differ diff --git a/.playwright/screenshots/paragraph-styles-visual-unordered-list-wrapped.png b/.playwright/screenshots/paragraph-styles-visual-unordered-list-wrapped.png index e12b822fc..5b5a837bb 100644 Binary files a/.playwright/screenshots/paragraph-styles-visual-unordered-list-wrapped.png and b/.playwright/screenshots/paragraph-styles-visual-unordered-list-wrapped.png differ diff --git a/.playwright/screenshots/paragraph-styles-visual-unordered-list.png b/.playwright/screenshots/paragraph-styles-visual-unordered-list.png index 9315b1dfc..84a373c79 100644 Binary files a/.playwright/screenshots/paragraph-styles-visual-unordered-list.png and b/.playwright/screenshots/paragraph-styles-visual-unordered-list.png differ diff --git a/.playwright/tests/enrichedTextVisual.spec.ts b/.playwright/tests/enrichedTextVisual.spec.ts index c1be2ea1e..9eb288b59 100644 --- a/.playwright/tests/enrichedTextVisual.spec.ts +++ b/.playwright/tests/enrichedTextVisual.spec.ts @@ -124,6 +124,27 @@ test.describe('visual: complex lists and layouts', () => { }); }); +test.describe('visual: extended ordered list margin', () => { + test('ordered list adds a necessary margin to fit larger marker values', async ({ + page, + }) => { + const htmlBefore = `
    ${'
  1. *
  2. '.repeat(9)}
`; + + await gotoTestEnrichedText(page); + await setEnrichedTextValue(page, htmlBefore); + await expect(displayLocator(page)).toHaveScreenshot( + 'enriched-text-ordered-list-extended-margin-before.png' + ); + + const htmlAfter = `
    ${'
  1. *
  2. '.repeat(10)}
`; + + await setEnrichedTextValue(page, htmlAfter); + await expect(displayLocator(page)).toHaveScreenshot( + 'enriched-text-ordered-list-extended-margin-after.png' + ); + }); +}); + test.describe('visual: typography, blocks, and wrapping', () => { const cases = [ { diff --git a/.playwright/tests/paragraphStylesVisual.spec.ts b/.playwright/tests/paragraphStylesVisual.spec.ts index 72a27acc6..539f2325b 100644 --- a/.playwright/tests/paragraphStylesVisual.spec.ts +++ b/.playwright/tests/paragraphStylesVisual.spec.ts @@ -134,4 +134,24 @@ test.describe('paragraph styles visual', () => { 'paragraph-styles-visual-checkbox-list-wrapped.png' ); }); + + test('ordered list adds a necessary margin to fit larger marker values', async ({ + page, + }) => { + const htmlBefore = `
    ${'
  1. *
  2. '.repeat(9)}
`; + await setEditorHtml(page, htmlBefore); + + const editor = editorLocator(page); + + await expect(editor).toHaveScreenshot( + 'paragraph-styles-visual-ordered-list-extended-margin-before.png' + ); + + const htmlAfter = `
    ${'
  1. *
  2. '.repeat(10)}
`; + await setEditorHtml(page, htmlAfter); + + await expect(editor).toHaveScreenshot( + 'paragraph-styles-visual-ordered-list-extended-margin-after.png' + ); + }); }); diff --git a/src/web/EnrichedText.css b/src/web/EnrichedText.css index 706b8a02e..75d6c4454 100644 --- a/src/web/EnrichedText.css +++ b/src/web/EnrichedText.css @@ -156,7 +156,11 @@ .et-view ul:not([data-type]) { margin: 0; list-style: none; - padding-left: calc(var(--et-ul-margin-left, 16px) + var(--et-ul-gap-width, 16px)); + padding-left: calc( + var(--et-ul-margin-left, 16px) + + var(--et-ul-bullet-size, 8px) + + var(--et-ul-gap-width, 16px) + ); } .eti-editor ul:not([data-type]) > li, @@ -179,14 +183,20 @@ margin-right: var(--et-ul-gap-width, 16px); position: relative; - top: -0.1em; + top: calc(var(--et-ul-bullet-size, 8px) * 0.5 - 0.35em); } .eti-editor ol, .et-view ol { margin: 0; list-style: none; - padding-left: calc(var(--et-ol-margin-left, 16px) + var(--et-ol-gap-width, 16px)); + /* marker column grows to fit the widest counter ("N."), floored at the + configured margin. */ + --et-ol-marker-col: max( + var(--et-ol-margin-left, 16px), + calc((var(--et-ol-digits, 1) + 1) * 1ch) + ); + padding-left: calc(var(--et-ol-marker-col) + var(--et-ol-gap-width, 16px)); counter-reset: et-ol; } @@ -202,10 +212,10 @@ .et-view ol > li::before { content: counter(et-ol) '.'; flex-shrink: 0; - width: var(--et-ol-margin-left, 16px); + width: var(--et-ol-marker-col, var(--et-ol-margin-left, 16px)); text-align: right; - margin-right: calc(var(--et-ol-gap-width, 16px) / 2); - margin-left: calc(-1 * (var(--et-ol-margin-left, 16px) + (var(--et-ol-gap-width, 16px) / 2))); + margin-right: calc(var(--et-ol-gap-width, 16px)); + margin-left: calc(-1 * (var(--et-ol-marker-col, var(--et-ol-margin-left, 16px)) + var(--et-ol-gap-width, 16px))); color: var(--et-ol-marker-color, currentColor); font-weight: var(--et-ol-marker-font-weight, inherit); @@ -258,7 +268,11 @@ .eti-editor ul[data-type='checkboxList'] { margin: 0; list-style: none; - padding-left: calc(var(--et-checkbox-margin-left, 16px) + var(--et-checkbox-gap-width, 16px)); + padding-left: calc( + var(--et-checkbox-margin-left, 16px) + + var(--et-checkbox-box-size, 24px) + + var(--et-checkbox-gap-width, 16px) + ); } .eti-editor ul[data-type='checkboxList'] > li { @@ -279,7 +293,7 @@ margin-top: 0; position: relative; - top: 0.15em; + top: calc(var(--et-checkbox-box-size, 24px) * 0.5 - 0.35em); } .eti-editor ul[data-type='checkboxList'] > li > label input[type='checkbox'] { @@ -301,7 +315,9 @@ margin: 0; list-style: none; padding-left: calc( - var(--et-checkbox-margin-left, 16px) + var(--et-checkbox-gap-width, 16px) + var(--et-checkbox-margin-left, 16px) + + var(--et-checkbox-box-size, 24px) + + var(--et-checkbox-gap-width, 16px) ); } @@ -328,7 +344,7 @@ margin-top: 0; position: relative; - top: 0.15em; + top: calc(var(--et-checkbox-box-size, 24px) * 0.5 - 0.35em); } .et-view ul[data-type="checkbox"] > li > label { diff --git a/src/web/EnrichedText.tsx b/src/web/EnrichedText.tsx index 8ec916cc5..05aedeba1 100644 --- a/src/web/EnrichedText.tsx +++ b/src/web/EnrichedText.tsx @@ -21,6 +21,7 @@ import { usePressInteractions } from './usePressInteractions'; import { adaptWebToNativeEvent } from './adaptWebToNativeEvent'; import { useStableRef } from './useStableRef'; import { assertBrowserEnvironment } from './assertBrowserEnvironment'; +import { useOrderedListMarkerWidth } from './useOrderedListMarkerWidth'; export const EnrichedText = memo( ({ @@ -105,6 +106,8 @@ export const EnrichedText = memo( const onLinkPressRef = useStableRef(onLinkPress); const onMentionPressRef = useStableRef(onMentionPress); + useOrderedListMarkerWidth(containerRef, finalHtml); + useImageErrorFallback(containerRef); usePressInteractions(containerRef, onLinkPressRef, onMentionPressRef); diff --git a/src/web/EnrichedTextInput.tsx b/src/web/EnrichedTextInput.tsx index 87fa483b2..8482f5873 100644 --- a/src/web/EnrichedTextInput.tsx +++ b/src/web/EnrichedTextInput.tsx @@ -66,6 +66,7 @@ import { EnrichedTextAlign } from './formats/EnrichedTextAlign'; import { StripBoldInStyledHeadingsPlugin } from './pmPlugins/StripBoldInStyledHeadingsPlugin'; import { StrictMarksPlugin } from './pmPlugins/StrictMarksPlugin'; import { MergeAdjacentSameKindBlocksPlugin } from './pmPlugins/MergeAdjacentSameKindBlocksPlugin'; +import { OrderedListMarkerWidthPlugin } from './pmPlugins/OrderedListMarkerWidthPlugin'; import { StripMarksInCodeBlockPlugin } from './pmPlugins/StripMarksInCodeBlockPlugin'; import { handleClipboardPasteImages } from './pasteImages'; import { @@ -228,6 +229,7 @@ export const EnrichedTextInput = ({ getHtmlStyle: () => htmlStyleRef.current, }), MergeAdjacentSameKindBlocksPlugin, + OrderedListMarkerWidthPlugin, StrictMarksPlugin, MentionPlugin.configure({ getIndicators: () => mentionIndicatorsRef.current, diff --git a/src/web/pmPlugins/OrderedListMarkerWidthPlugin.ts b/src/web/pmPlugins/OrderedListMarkerWidthPlugin.ts new file mode 100644 index 000000000..8a994cb38 --- /dev/null +++ b/src/web/pmPlugins/OrderedListMarkerWidthPlugin.ts @@ -0,0 +1,43 @@ +import { Extension } from '@tiptap/core'; +import { Plugin, PluginKey } from '@tiptap/pm/state'; +import { Decoration, DecorationSet } from '@tiptap/pm/view'; + +// Finds the ordered list markers with the largest values, +// exposing the digit count as --et-ol-digits per
    . +export const OrderedListMarkerWidthPlugin = Extension.create({ + name: 'orderedListMarkerWidth', + + addProseMirrorPlugins() { + return [ + new Plugin({ + key: new PluginKey('orderedListMarkerWidth'), + props: { + decorations: (state) => { + const decorations: Decoration[] = []; + + state.doc.descendants((node, pos) => { + if (node.type.name !== 'orderedList') { + return true; + } + + const start = + typeof node.attrs.start === 'number' ? node.attrs.start : 1; + const maxNumber = start + Math.max(0, node.childCount - 1); + const digits = String(maxNumber).length; + + decorations.push( + Decoration.node(pos, pos + node.nodeSize, { + style: `--et-ol-digits:${digits}`, + }) + ); + + return false; + }); + + return DecorationSet.create(state.doc, decorations); + }, + }, + }), + ]; + }, +}); diff --git a/src/web/useOrderedListMarkerWidth.ts b/src/web/useOrderedListMarkerWidth.ts new file mode 100644 index 000000000..0bfd599bb --- /dev/null +++ b/src/web/useOrderedListMarkerWidth.ts @@ -0,0 +1,20 @@ +import { useLayoutEffect, type RefObject } from 'react'; + +// Finds the ordered list markers with the largest values, +// exposing the digit count as --et-ol-digits per
      . +export function useOrderedListMarkerWidth( + containerRef: RefObject, + finalHtml: string +) { + useLayoutEffect(() => { + const root = containerRef.current; + if (!root) return; + + root.querySelectorAll('ol').forEach((ol) => { + const startAttr = Number(ol.getAttribute('start')); + const start = Number.isFinite(startAttr) && startAttr > 0 ? startAttr : 1; + const maxNumber = start + Math.max(0, ol.children.length - 1); + ol.style.setProperty('--et-ol-digits', String(String(maxNumber).length)); + }); + }, [containerRef, finalHtml]); +}