Skip to content

Commit

Permalink
fix(page): inline format should be extended when range is not collaps…
Browse files Browse the repository at this point in the history
  • Loading branch information
Flrande authored Oct 8, 2023
1 parent 06fc7b7 commit c3aa109
Show file tree
Hide file tree
Showing 5 changed files with 213 additions and 72 deletions.
9 changes: 1 addition & 8 deletions packages/blocks/src/components/rich-text/virgo/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,6 @@ export const onVBeforeinput = (
ctx: VBeforeinputHookCtx<AffineTextAttributes>
) => {
const { vEditor, vRange, data, raw } = ctx;
if (vRange.length !== 0) {
return ctx;
}

const deltas = vEditor.getDeltasByVRange(vRange);

// Overwrite the default behavior (Insert period when consecutive spaces) of IME.
Expand Down Expand Up @@ -152,11 +148,8 @@ export const onVCompositionEnd = (
ctx: VCompositionEndHookCtx<AffineTextAttributes>
) => {
const { vEditor, vRange, data } = ctx;
if (vRange.length !== 0) {
return ctx;
}

const deltas = vEditor.getDeltasByVRange(vRange);

if (data && data.length > 0 && data !== '\n') {
if (deltas.length > 1 || (deltas.length === 1 && vRange.index !== 0)) {
const newAttributes = deltas[0][0].attributes;
Expand Down
138 changes: 138 additions & 0 deletions tests/basic.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
pressShiftEnter,
redoByClick,
redoByKeyboard,
setSelection,
SHORT_KEY,
switchEditorMode,
switchReadonly,
Expand All @@ -38,13 +39,15 @@ import {
assertBlockChildrenIds,
assertEmpty,
assertRichTexts,
assertRichTextVirgoDeltas,
assertStore,
assertStoreMatchJSX,
assertText,
assertTitle,
defaultStore,
} from './utils/asserts.js';
import { scoped, test } from './utils/playwright.js';
import { getFormatBar } from './utils/query.js';

test(scoped`basic input`, async ({ page }) => {
await enterPlaygroundRoom(page);
Expand Down Expand Up @@ -540,3 +543,138 @@ test('ctrl+delete to delete one word forward', async ({ page }) => {
await pressForwardDeleteWord(page);
await assertText(page, 'aaa ccc');
});

test('extended inline format', async ({ page }) => {
await enterPlaygroundRoom(page);
await initEmptyParagraphState(page);
await focusRichText(page);
await type(page, 'aaabbbaaa');

const { boldBtn, italicBtn, underlineBtn, strikeBtn, codeBtn } =
getFormatBar(page);
await setSelection(page, 0, 3, 0, 6);
await boldBtn.click();
await italicBtn.click();
await underlineBtn.click();
await strikeBtn.click();
await codeBtn.click();
await assertRichTextVirgoDeltas(page, [
{
insert: 'aaa',
},
{
insert: 'bbb',
attributes: {
bold: true,
italic: true,
underline: true,
strike: true,
code: true,
},
},
{
insert: 'aaa',
},
]);

// aaa|bbbccc
await setSelection(page, 2, 3, 2, 3);
await captureHistory(page);
await type(page, 'c');
await assertRichTextVirgoDeltas(page, [
{
insert: 'aaac',
},
{
insert: 'bbb',
attributes: {
bold: true,
italic: true,
underline: true,
strike: true,
code: true,
},
},
{
insert: 'aaa',
},
]);
await undoByKeyboard(page);

// aaab|bbccc
await setSelection(page, 2, 4, 2, 4);
await type(page, 'c');
await assertRichTextVirgoDeltas(page, [
{
insert: 'aaa',
},
{
insert: 'bcbb',
attributes: {
bold: true,
italic: true,
underline: true,
strike: true,
code: true,
},
},
{
insert: 'aaa',
},
]);
await undoByKeyboard(page);

// aaab|b|bccc
await setSelection(page, 2, 4, 2, 5);
await type(page, 'c');
await assertRichTextVirgoDeltas(page, [
{
insert: 'aaa',
},
{
insert: 'bcb',
attributes: {
bold: true,
italic: true,
underline: true,
strike: true,
code: true,
},
},
{
insert: 'aaa',
},
]);
await undoByKeyboard(page);

// aaabbb|ccc
await setSelection(page, 2, 6, 2, 6);
await type(page, 'c');
await assertRichTextVirgoDeltas(page, [
{
insert: 'aaa',
},
{
insert: 'bbb',
attributes: {
bold: true,
italic: true,
underline: true,
strike: true,
code: true,
},
},
{
insert: 'c',
attributes: {
bold: true,
italic: true,
underline: true,
strike: true,
},
},
{
insert: 'aaa',
},
]);
});
61 changes: 1 addition & 60 deletions tests/format-bar.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,66 +38,7 @@ import {
assertStoreMatchJSX,
} from './utils/asserts.js';
import { test } from './utils/playwright.js';

function getFormatBar(page: Page) {
const formatBar = page.locator('.affine-format-bar-widget');
const boldBtn = formatBar.getByTestId('bold');
const italicBtn = formatBar.getByTestId('italic');
const underlineBtn = formatBar.getByTestId('underline');
const strikeBtn = formatBar.getByTestId('strike');
const codeBtn = formatBar.getByTestId('code');
const linkBtn = formatBar.getByTestId('link');
const copyBtn = formatBar.getByTestId('copy');
// highlight
const backgroundBtn = formatBar.locator('.background-highlight-icon');
const pinkBtn = formatBar.getByTestId('var(--affine-text-highlight-pink)');
const defaultColorBtn = formatBar.getByTestId('unset');
const highlight = {
backgroundBtn,
pinkBtn,
defaultColorBtn,
};

const paragraphBtn = formatBar.locator(`.paragraph-button`);
const openParagraphMenu = async () => {
await expect(formatBar).toBeVisible();
await paragraphBtn.hover();
};

const textBtn = formatBar.getByTestId('affine:paragraph/text');
const h1Btn = formatBar.getByTestId('affine:paragraph/h1');
const bulletedBtn = formatBar.getByTestId('affine:list/bulleted');
const codeBlockBtn = formatBar.getByTestId('affine:code/');

const assertBoundingBox = async (x: number, y: number) => {
const boundingBox = await formatBar.boundingBox();
if (!boundingBox) {
throw new Error("formatBar doesn't exist");
}
assertAlmostEqual(boundingBox.x, x, 6);
assertAlmostEqual(boundingBox.y, y, 6);
};

return {
formatBar,
boldBtn,
italicBtn,
underlineBtn,
strikeBtn,
codeBtn,
linkBtn,
copyBtn,
highlight,

openParagraphMenu,
textBtn,
h1Btn,
bulletedBtn,
codeBlockBtn,

assertBoundingBox,
};
}
import { getFormatBar } from './utils/query.js';

test('should format quick bar show when select text', async ({ page }) => {
await enterPlaygroundRoom(page);
Expand Down
14 changes: 10 additions & 4 deletions tests/utils/actions/misc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -801,13 +801,19 @@ export async function setSelection(
length: 0,
})!;

/* eslint-enable @typescript-eslint/no-non-null-assertion */
getSelection()?.setBaseAndExtent(
const sl = getSelection();
if (!sl) throw new Error('Cannot get selection');
const range = document.createRange();
range.setStart(
anchorRichTextRange.startContainer,
anchorOffset,
anchorRichTextRange.startOffset
);
range.setEnd(
focusRichTextRange.startContainer,
focusOffset
focusRichTextRange.startOffset
);
sl.removeAllRanges();
sl.addRange(range);
},
{ anchorBlockId, anchorOffset, focusBlockId, focusOffset }
);
Expand Down
63 changes: 63 additions & 0 deletions tests/utils/query.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { expect, type Page } from '@playwright/test';

import { assertAlmostEqual } from './asserts.js';

export function getFormatBar(page: Page) {
const formatBar = page.locator('.affine-format-bar-widget');
const boldBtn = formatBar.getByTestId('bold');
const italicBtn = formatBar.getByTestId('italic');
const underlineBtn = formatBar.getByTestId('underline');
const strikeBtn = formatBar.getByTestId('strike');
const codeBtn = formatBar.getByTestId('code');
const linkBtn = formatBar.getByTestId('link');
const copyBtn = formatBar.getByTestId('copy');
// highlight
const backgroundBtn = formatBar.locator('.background-highlight-icon');
const pinkBtn = formatBar.getByTestId('var(--affine-text-highlight-pink)');
const defaultColorBtn = formatBar.getByTestId('unset');
const highlight = {
backgroundBtn,
pinkBtn,
defaultColorBtn,
};

const paragraphBtn = formatBar.locator(`.paragraph-button`);
const openParagraphMenu = async () => {
await expect(formatBar).toBeVisible();
await paragraphBtn.hover();
};

const textBtn = formatBar.getByTestId('affine:paragraph/text');
const h1Btn = formatBar.getByTestId('affine:paragraph/h1');
const bulletedBtn = formatBar.getByTestId('affine:list/bulleted');
const codeBlockBtn = formatBar.getByTestId('affine:code/');

const assertBoundingBox = async (x: number, y: number) => {
const boundingBox = await formatBar.boundingBox();
if (!boundingBox) {
throw new Error("formatBar doesn't exist");
}
assertAlmostEqual(boundingBox.x, x, 6);
assertAlmostEqual(boundingBox.y, y, 6);
};

return {
formatBar,
boldBtn,
italicBtn,
underlineBtn,
strikeBtn,
codeBtn,
linkBtn,
copyBtn,
highlight,

openParagraphMenu,
textBtn,
h1Btn,
bulletedBtn,
codeBlockBtn,

assertBoundingBox,
};
}

2 comments on commit c3aa109

@github-actions
Copy link

Choose a reason for hiding this comment

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

Size Report

Bundles

Entry Size Gzip Brotli
examples/basic 11 MB (+18.3 kB) 2.16 MB (+5.44 kB) 1.34 MB (+4.25 kB)

Packages

Name Size Gzip Brotli
blocks 1.5 MB (+6.37 kB) 376 kB (+788 B) 284 kB (+956 B)
editor 8.85 kB 3.33 kB 2.92 kB
store 60.3 kB 17.4 kB 15.6 kB
virgo 31.3 kB (+1.11 kB) 8.8 kB (+199 B) 7.88 kB (+179 B)

@github-actions
Copy link

Choose a reason for hiding this comment

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

Size Report

Bundles

Entry Size Gzip Brotli
examples/basic 11 MB 2.16 MB 1.34 MB

Packages

Name Size Gzip Brotli
blocks 1.5 MB 376 kB 284 kB
editor 8.85 kB 3.33 kB 2.92 kB
store 60.3 kB 17.4 kB 15.6 kB
virgo 31.3 kB 8.8 kB 7.88 kB

Please sign in to comment.