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

TINY-10892: Fix deleting from P with IMG into LI would create unwanted font-styles on Chrome #9638

Closed
wants to merge 11 commits into from
Closed
6 changes: 6 additions & 0 deletions .changes/unreleased/tinymce-TINY-10892-2024-05-12.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
project: tinymce
kind: Fixed
body: Deleting into a list from a paragraph that has an `img` tag could cause extra inline styles to be added.
time: 2024-05-12T23:00:56.388965+01:00
custom:
Issue: TINY-10892
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ const isEditable = (blockBoundary: BlockBoundary): boolean =>
NodeType.isContentEditableFalse(blockBoundary.from.block.dom) === false && NodeType.isContentEditableFalse(blockBoundary.to.block.dom) === false;

const hasValidBlocks = (blockBoundary: BlockBoundary): boolean => {
const isValidBlock = (block: SugarElement<Element>) => ElementType.isTextBlock(block) || TransparentElements.hasBlockAttr(block.dom);
const isValidBlock = (block: SugarElement<Element>) => ElementType.isTextBlock(block) || TransparentElements.hasBlockAttr(block.dom) || ElementType.isListItem(block);
return isValidBlock(blockBoundary.from.block) && isValidBlock(blockBoundary.to.block);
};

Expand Down
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's no longer really a chrome test, nor it is a quirks test 🤔

I'm happy to keep the test, just rename it (and remember the describe call includes the name).

Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
import { RealKeys } from '@ephox/agar';
import { describe, it } from '@ephox/bedrock-client';
import { TinyAssertions, TinyHooks } from '@ephox/wrap-mcagar';

import Editor from 'tinymce/core/api/Editor';

describe('webdriver.tinymce.core.delete.QuirksChromeTest', () => {

const hook = TinyHooks.bddSetupLight<Editor>({
base_url: '/project/tinymce/js/tinymce'
}, [], true);

it('TINY-10892: Backspace from beginning of P that contains IMG into OL when the LI does NOT end with an inline element', async () => {
const editor = hook.editor();
editor.setContent(
`<ol>
<li>sdadsa</li>
</ol>
<p><em>sdada</em><img src="#" alt="" width="24" height="24"> dsada </p>`);
editor.selection.setCursorLocation(editor.getDoc().querySelector('em') as HTMLElement, 0);
await RealKeys.pSendKeysOn('iframe => body => em', [ RealKeys.backspace() ]);
TinyAssertions.assertContent(editor,
`<ol>
<li>sdadsa<em>sdada</em><img src="#" alt="" width="24" height="24"> dsada</li>
</ol>`
);
});

it('TINY-10892: Backspace from beginning of P that contains IMG into OL when the LI DOES end with an inline element', async () => {
const editor = hook.editor();
editor.setContent(
`<ol>
<li>sdadsa <strong>a</strong></li>
</ol>
<p><em>sdada</em><img src="#" alt="" width="24" height="24"> dsada </p>`);
editor.selection.setCursorLocation(editor.getDoc().querySelector('em') as HTMLElement, 0);
await RealKeys.pSendKeysOn('iframe => body => em', [ RealKeys.backspace() ]);
TinyAssertions.assertContent(editor,
`<ol>
<li>sdadsa <strong>a</strong><em>sdada</em><img src="#" alt="" width="24" height="24"> dsada</li>
</ol>`
);
});

it('TINY-10892: Delete from end of OL when the LI does NOT end with an inline element and has nextSibling P that contains IMG', async () => {
const editor = hook.editor();
editor.setContent(
`<ol>
<li>a</li>
</ol>
<p><em>sdada</em><img src="#" alt="" width="24" height="24"> dsada </p>`);
editor.selection.setCursorLocation(editor.getDoc().querySelector('li') as HTMLElement, 1);
await RealKeys.pSendKeysOn('iframe => body => li', [ RealKeys.text('\uE017') /* unicode for Delete key */]);
TinyAssertions.assertContent(editor,
`<ol>
<li>a<em>sdada</em><img src="#" alt="" width="24" height="24"> dsada</li>
</ol>`
);
});

it('TINY-10892: Delete from end of OL when the LI DOES end with an inline element and has nextSibling P that contains IMG', async () => {
const editor = hook.editor();
editor.setContent(
`<ol>
<li>a <strong>a</strong></li>
</ol>
<p><em>sdada</em><img src="#" alt="" width="24" height="24"> dsada </p>`);
editor.selection.setCursorLocation(editor.getDoc().querySelector('strong') as HTMLElement, 1);
await RealKeys.pSendKeysOn('iframe => body => strong', [ RealKeys.text('\uE017') /* unicode for Delete key */]);
TinyAssertions.assertContent(editor,
`<ol>
<li>a <strong>a</strong><em>sdada</em><img src="#" alt="" width="24" height="24"> dsada</li>
</ol>`
);
});

it('TINY-10892: Backspace from beginning of P that contains IMG into UL when the LI does NOT end with an inline element', async () => {
const editor = hook.editor();
editor.setContent(
`<ul>
<li>sdadsa</li>
</ul>
<p><em>sdada</em><img src="#" alt="" width="24" height="24"> dsada </p>`);
editor.selection.setCursorLocation(editor.getDoc().querySelector('em') as HTMLElement, 0);
await RealKeys.pSendKeysOn('iframe => body => em', [ RealKeys.backspace() ]);
TinyAssertions.assertContent(editor,
`<ul>
<li>sdadsa<em>sdada</em><img src="#" alt="" width="24" height="24"> dsada</li>
</ul>`
);
});

it('TINY-10892: Backspace from beginning of P that contains IMG into UL when the LI DOES end with an inline element', async () => {
const editor = hook.editor();
editor.setContent(
`<ul>
<li>sdadsa <strong>a</strong></li>
</ul>
<p><em>sdada</em><img src="#" alt="" width="24" height="24"> dsada </p>`);
editor.selection.setCursorLocation(editor.getDoc().querySelector('em') as HTMLElement, 0);
await RealKeys.pSendKeysOn('iframe => body => em', [ RealKeys.backspace() ]);
TinyAssertions.assertContent(editor,
`<ul>
<li>sdadsa <strong>a</strong><em>sdada</em><img src="#" alt="" width="24" height="24"> dsada</li>
</ul>`
);
});

it('TINY-10892: Delete from end of UL when the LI does NOT end with an inline element and has nextSibling P that contains IMG', async () => {
const editor = hook.editor();
editor.setContent(
`<ul>
<li>a</li>
</ul>
<p><em>sdada</em><img src="#" alt="" width="24" height="24"> dsada </p>`);
editor.selection.setCursorLocation(editor.getDoc().querySelector('li') as HTMLElement, 1);
await RealKeys.pSendKeysOn('iframe => body => li', [ RealKeys.text('\uE017') /* unicode for Delete key */]);
TinyAssertions.assertContent(editor,
`<ul>
<li>a<em>sdada</em><img src="#" alt="" width="24" height="24"> dsada</li>
</ul>`
);
});

it('TINY-10892: Delete from end of UL when the LI DOES end with an inline element and has nextSibling P that contains IMG', async () => {
const editor = hook.editor();
editor.setContent(
`<ul>
<li>a <strong>a</strong></li>
</ul>
<p><em>sdada</em><img src="#" alt="" width="24" height="24"> dsada </p>`);
editor.selection.setCursorLocation(editor.getDoc().querySelector('strong') as HTMLElement, 1);
await RealKeys.pSendKeysOn('iframe => body => strong', [ RealKeys.text('\uE017') /* unicode for Delete key */]);
TinyAssertions.assertContent(editor,
`<ul>
<li>a <strong>a</strong><em>sdada</em><img src="#" alt="" width="24" height="24"> dsada</li>
</ul>`
);
});

});