diff --git a/blocksuite/playground/apps/_common/components/collab-debug-menu.ts b/blocksuite/playground/apps/_common/components/collab-debug-menu.ts deleted file mode 100644 index 4274fb059b..0000000000 --- a/blocksuite/playground/apps/_common/components/collab-debug-menu.ts +++ /dev/null @@ -1,635 +0,0 @@ -/* eslint-disable @typescript-eslint/no-restricted-imports */ -import '@shoelace-style/shoelace/dist/components/alert/alert.js'; -import '@shoelace-style/shoelace/dist/components/button/button.js'; -import '@shoelace-style/shoelace/dist/components/button-group/button-group.js'; -import '@shoelace-style/shoelace/dist/components/color-picker/color-picker.js'; -import '@shoelace-style/shoelace/dist/components/divider/divider.js'; -import '@shoelace-style/shoelace/dist/components/dropdown/dropdown.js'; -import '@shoelace-style/shoelace/dist/components/icon/icon.js'; -import '@shoelace-style/shoelace/dist/components/icon-button/icon-button.js'; -import '@shoelace-style/shoelace/dist/components/input/input.js'; -import '@shoelace-style/shoelace/dist/components/menu/menu.js'; -import '@shoelace-style/shoelace/dist/components/menu-item/menu-item.js'; -import '@shoelace-style/shoelace/dist/components/select/select.js'; -import '@shoelace-style/shoelace/dist/components/tab/tab.js'; -import '@shoelace-style/shoelace/dist/components/tab-group/tab-group.js'; -import '@shoelace-style/shoelace/dist/components/tooltip/tooltip.js'; -import '@shoelace-style/shoelace/dist/themes/light.css'; -import '@shoelace-style/shoelace/dist/themes/dark.css'; - -import type { AffineTextAttributes } from '@blocksuite/affine-shared/types'; -import { ShadowlessElement } from '@blocksuite/block-std'; -import { - ColorScheme, - type DocMode, - DocModeProvider, - EdgelessRootService, - ExportManager, - printToPdf, -} from '@blocksuite/blocks'; -import { type SerializedXYWH, SignalWatcher } from '@blocksuite/global/utils'; -import type { DeltaInsert } from '@blocksuite/inline'; -import type { AffineEditorContainer } from '@blocksuite/presets'; -import { Text, type Workspace } from '@blocksuite/store'; -import { setBasePath } from '@shoelace-style/shoelace/dist/utilities/base-path.js'; -import { css, html, nothing } from 'lit'; -import { customElement, property, state } from 'lit/decorators.js'; - -import { notify } from '../../default/utils/notify.js'; -import { mockEdgelessTheme } from '../mock-services.js'; -import { generateRoomId } from '../sync/websocket/utils.js'; -import type { DocsPanel } from './docs-panel.js'; -import type { LeftSidePanel } from './left-side-panel.js'; - -const basePath = - 'https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.11.2/dist/'; -setBasePath(basePath); - -@customElement('collab-debug-menu') -export class CollabDebugMenu extends SignalWatcher(ShadowlessElement) { - static override styles = css` - :root { - --sl-font-size-medium: var(--affine-font-xs); - --sl-input-font-size-small: var(--affine-font-xs); - } - - .dg.ac { - z-index: 1001 !important; - } - - .top-container { - display: flex; - align-items: center; - gap: 12px; - font-size: 16px; - } - `; - - private readonly _darkModeChange = (e: MediaQueryListEvent) => { - this._setThemeMode(!!e.matches); - }; - - private readonly _handleDocsPanelClose = () => { - this.leftSidePanel.toggle(this.docsPanel); - }; - - private readonly _keydown = (e: KeyboardEvent) => { - if (e.key === 'F1') { - this._switchEditorMode(); - } - }; - - private readonly _startCollaboration = async () => { - if (window.wsProvider) { - notify('There is already a websocket provider exists', 'neutral').catch( - console.error - ); - return; - } - - const params = new URLSearchParams(location.search); - const id = params.get('room') || (await generateRoomId()); - - params.set('room', id); - const url = new URL(location.href); - url.search = params.toString(); - location.href = url.href; - }; - - get doc() { - return this.editor.doc; - } - - get editorMode() { - return this.editor.mode; - } - - set editorMode(value: DocMode) { - this.editor.mode = value; - } - - get rootService() { - try { - return this.editor.std.getService('affine:page'); - } catch { - return null; - } - } - - private _addNote() { - const rootModel = this.doc.root; - if (!rootModel) return; - const rootId = rootModel.id; - - this.doc.captureSync(); - - const count = rootModel.children.length; - const xywh: SerializedXYWH = `[0,${count * 60},800,95]`; - - const noteId = this.doc.addBlock('affine:note', { xywh }, rootId); - this.doc.addBlock('affine:paragraph', {}, noteId); - } - - private async _clearSiteData() { - await fetch('/Clear-Site-Data'); - window.location.reload(); - } - - private _exportHtml() { - const htmlTransformer = this.rootService?.transformers.html; - htmlTransformer?.exportDoc(this.doc).catch(console.error); - } - - private _exportMarkDown() { - const markdownTransformer = this.rootService?.transformers.markdown; - markdownTransformer?.exportDoc(this.doc).catch(console.error); - } - - private _exportPdf() { - this.editor.std.get(ExportManager).exportPdf().catch(console.error); - } - - private _exportPng() { - this.editor.std.get(ExportManager).exportPng().catch(console.error); - } - - private async _exportSnapshot() { - if (!this.rootService) return; - const zipTransformer = this.rootService.transformers.zip; - await zipTransformer.exportDocs( - this.collection, - Array.from(this.collection.docs.values()).map(collection => - collection.getStore() - ) - ); - } - - private _importSnapshot() { - const input = document.createElement('input'); - input.setAttribute('type', 'file'); - input.setAttribute('accept', '.zip'); - input.multiple = false; - input.onchange = async () => { - const file = input.files?.item(0); - if (!file) return; - if (!this.rootService) return; - try { - const zipTransformer = this.rootService.transformers.zip; - const docs = await zipTransformer.importDocs(this.collection, file); - for (const doc of docs) { - let noteBlockId; - const noteBlocks = window.doc.getBlocksByFlavour('affine:note'); - if (noteBlocks.length) { - noteBlockId = noteBlocks[0].id; - } else { - noteBlockId = this.doc.addBlock( - 'affine:note', - { - xywh: '[-200,-48,400,96]', - }, - this.doc.root?.id - ); - } - - if (!doc) { - break; - } - - window.doc.addBlock( - 'affine:paragraph', - { - type: 'text', - text: new Text([ - { - insert: ' ', - attributes: { - reference: { - type: 'LinkedPage', - pageId: doc.id, - }, - }, - } as DeltaInsert, - ]), - }, - noteBlockId - ); - } - this.requestUpdate(); - } catch (e) { - console.error('Invalid snapshot.'); - console.error(e); - } finally { - input.remove(); - } - }; - input.click(); - } - - private _insertTransitionStyle(classKey: string, duration: number) { - const $html = document.documentElement; - const $style = document.createElement('style'); - const slCSSKeys = ['sl-transition-x-fast']; - $style.innerHTML = `html.${classKey} * { transition: all ${duration}ms 0ms linear !important; } :root { ${slCSSKeys.map( - key => `--${key}: ${duration}ms` - )} }`; - - $html.append($style); - $html.classList.add(classKey); - - setTimeout(() => { - $style.remove(); - $html.classList.remove(classKey); - }, duration); - } - - private _print() { - printToPdf().catch(console.error); - } - - private _setThemeMode(dark: boolean) { - const html = document.querySelector('html'); - - this._dark = dark; - localStorage.setItem('blocksuite:dark', dark ? 'true' : 'false'); - if (!html) return; - html.dataset.theme = dark ? 'dark' : 'light'; - - this._insertTransitionStyle('color-transition', 0); - - if (dark) { - html.classList.add('dark'); - html.classList.add('sl-theme-dark'); - } else { - html.classList.remove('dark'); - html.classList.remove('sl-theme-dark'); - } - - const theme = dark ? ColorScheme.Dark : ColorScheme.Light; - mockEdgelessTheme.setTheme(theme); - } - - private _switchEditorMode() { - if (!this.editor.host) return; - const newMode = this._docMode === 'page' ? 'edgeless' : 'page'; - const docModeService = this.editor.host.std.get(DocModeProvider); - if (docModeService) { - docModeService.setPrimaryMode(newMode, this.editor.doc.id); - } - this._docMode = newMode; - this.editor.mode = newMode; - } - - private _toggleDarkMode() { - this._setThemeMode(!this._dark); - } - - private _toggleDocsPanel() { - this.docsPanel.onClose = this._handleDocsPanelClose; - this.leftSidePanel.toggle(this.docsPanel); - } - - override connectedCallback() { - super.connectedCallback(); - - this._docMode = this.editor.mode; - this.editor.slots.docUpdated.on(({ newDocId }) => { - const newDocMode = this.editor.std - .get(DocModeProvider) - .getPrimaryMode(newDocId); - this._docMode = newDocMode; - }); - - document.body.addEventListener('keydown', this._keydown); - } - - override createRenderRoot() { - const matchMedia = window.matchMedia('(prefers-color-scheme: dark)'); - this._setThemeMode(this._dark && matchMedia.matches); - matchMedia.addEventListener('change', this._darkModeChange); - - return this; - } - - override disconnectedCallback() { - super.disconnectedCallback(); - - const matchMedia = window.matchMedia('(prefers-color-scheme: dark)'); - matchMedia.removeEventListener('change', this._darkModeChange); - document.body.removeEventListener('keydown', this._keydown); - } - - override firstUpdated() { - this.doc.slots.historyUpdated.on(() => { - this._canUndo = this.doc.canUndo; - this._canRedo = this.doc.canRedo; - }); - } - - override render() { - return html` - -
-
-
- - - - - - - - Test operations - - Print - - Add Note - - Export Markdown - - - Export HTML - - - Export PDF - - - Export PNG - - - Export Snapshot - - - Import Snapshot - - - - - Clear Site Data - - - - Toggle ${this._dark ? 'Light' : 'Dark'} Mode - - - - - - - GitHub - - - - - - - - - - { - this.doc.undo(); - }} - > - - - - - - { - this.doc.redo(); - }} - > - - - - - - - - - - - - - - - - - ${new URLSearchParams(location.search).get('room') - ? html` { - if ((e.target as HTMLInputElement).value.length > 0) { - this.collection.awarenessStore.awareness.setLocalStateField( - 'user', - { - name: (e.target as HTMLInputElement).value ?? '', - } - ); - } else { - this.collection.awarenessStore.awareness.setLocalStateField( - 'user', - { - name: 'Unknown', - } - ); - } - }} - >` - : nothing} -
- -
- - ${this._docMode === 'edgeless' - ? html` - mockEdgelessTheme.toggleTheme()} - > - - - ` - : nothing} - - ${this._docMode === 'edgeless' - ? html` - { - if (this.rootService instanceof EdgelessRootService) { - this.rootService.gfx.tool.setTool('frameNavigator', { - mode: 'fit', - }); - } - }} - > - - - ` - : nothing} - - - - - - - - - - - - - - -
-
-
- `; - } - - @state() - private accessor _canRedo = false; - - @state() - private accessor _canUndo = false; - - @state() - private accessor _dark = localStorage.getItem('blocksuite:dark') === 'true'; - - @state() - private accessor _docMode: DocMode = 'page'; - - @property({ attribute: false }) - accessor collection!: Workspace; - - @property({ attribute: false }) - accessor docsPanel!: DocsPanel; - - @property({ attribute: false }) - accessor editor!: AffineEditorContainer; - - @property({ attribute: false }) - accessor leftSidePanel!: LeftSidePanel; - - @property({ attribute: false }) - accessor readonly = false; -} - -declare global { - interface HTMLElementTagNameMap { - 'collab-debug-menu': CollabDebugMenu; - } -} diff --git a/blocksuite/playground/apps/_common/components/pdf/worker.ts b/blocksuite/playground/apps/_common/components/pdf/worker.ts index 648ebe7269..cd46b9fecb 100644 --- a/blocksuite/playground/apps/_common/components/pdf/worker.ts +++ b/blocksuite/playground/apps/_common/components/pdf/worker.ts @@ -35,7 +35,6 @@ function renderToImageData(index: number, scale: number) { bitmap.fill(0, 0, width, height); page.render(bitmap, 0, 0, width, height, 0, flags); - // @ts-expect-error ignore const data = new Uint8ClampedArray(bitmap.toUint8Array()); bitmap.close(); diff --git a/blocksuite/playground/apps/_common/history.ts b/blocksuite/playground/apps/_common/history.ts index a8ee6741a3..51e7b1a27f 100644 --- a/blocksuite/playground/apps/_common/history.ts +++ b/blocksuite/playground/apps/_common/history.ts @@ -1,11 +1,11 @@ import type { DocModeProvider } from '@blocksuite/blocks'; import { assertExists } from '@blocksuite/global/utils'; import type { AffineEditorContainer } from '@blocksuite/presets'; -import type { Blocks, Doc, Workspace } from '@blocksuite/store'; +import type { Doc, Store, Workspace } from '@blocksuite/store'; import type { LitElement } from 'lit'; export function getDocFromUrlParams(collection: Workspace, url: URL) { - let doc: Blocks | null = null; + let doc: Store | null = null; const docId = decodeURIComponent(url.hash.slice(1)); diff --git a/blocksuite/playground/apps/starter/utils/collection.ts b/blocksuite/playground/apps/starter/utils/collection.ts index 2a4fd596eb..3fb4f9aa7e 100644 --- a/blocksuite/playground/apps/starter/utils/collection.ts +++ b/blocksuite/playground/apps/starter/utils/collection.ts @@ -1,5 +1,4 @@ import { AffineSchemas, SpecProvider, TestUtils } from '@blocksuite/blocks'; -import type { BlockSuiteFlags } from '@blocksuite/global/types'; import { nanoid, Schema, Transformer } from '@blocksuite/store'; import { createAutoIncrementIdGenerator, @@ -48,27 +47,10 @@ export function createStarterDocCollection() { blobSources.shadows.push(new IndexedDBBlobSource(collectionId)); } - const flags: Partial = Object.fromEntries( - Array.from(params.entries()) - .filter(([key]) => key.startsWith('enable_')) - .map(([k, v]) => [k, v === 'true']) - ); - const options: DocCollectionOptions = { id: collectionId, schema, idGenerator, - defaultFlags: { - enable_synced_doc_block: true, - enable_pie_menu: true, - enable_lasso_tool: true, - enable_edgeless_text: true, - enable_color_picker: true, - enable_mind_map_import: true, - enable_advanced_block_visibility: true, - enable_shape_shadow_blur: false, - ...flags, - }, awarenessSources: [new BroadcastChannelAwarenessSource(id)], docSources, blobSources, diff --git a/blocksuite/tests-legacy/basic.spec.ts b/blocksuite/tests-legacy/basic.spec.ts index 62f5bae988..55c91fb478 100644 --- a/blocksuite/tests-legacy/basic.spec.ts +++ b/blocksuite/tests-legacy/basic.spec.ts @@ -1,4 +1,4 @@ -import type { DeltaInsert } from '@inline/types.js'; +import type { DeltaInsert } from '@blocksuite/inline'; import { expect } from '@playwright/test'; import { diff --git a/blocksuite/tests-legacy/bookmark.spec.ts b/blocksuite/tests-legacy/bookmark.spec.ts index f7f7909872..8c4d892a97 100644 --- a/blocksuite/tests-legacy/bookmark.spec.ts +++ b/blocksuite/tests-legacy/bookmark.spec.ts @@ -1,8 +1,8 @@ import './utils/declare-test-window.js'; +import type { BlockSnapshot } from '@blocksuite/store'; import type { Page } from '@playwright/test'; import { expect } from '@playwright/test'; -import type { BlockSnapshot } from '@store/index.js'; import { ignoreSnapshotId } from 'utils/ignore.js'; import { getEmbedCardToolbar } from 'utils/query.js'; diff --git a/blocksuite/tests-legacy/clipboard/list.spec.ts b/blocksuite/tests-legacy/clipboard/list.spec.ts index 9abb4092e3..3db626d1e3 100644 --- a/blocksuite/tests-legacy/clipboard/list.spec.ts +++ b/blocksuite/tests-legacy/clipboard/list.spec.ts @@ -1,5 +1,5 @@ +import type { BlockSnapshot } from '@blocksuite/store'; import { expect } from '@playwright/test'; -import type { BlockSnapshot } from '@store/index.js'; import { lightThemeV2 } from '@toeverything/theme/v2'; import { initDatabaseColumn } from '../database/actions.js'; diff --git a/blocksuite/tests-legacy/database/actions.ts b/blocksuite/tests-legacy/database/actions.ts index e78627ad5e..0ca51d25c5 100644 --- a/blocksuite/tests-legacy/database/actions.ts +++ b/blocksuite/tests-legacy/database/actions.ts @@ -1,9 +1,8 @@ import type { RichTextCell, RichTextCellEditing, -} from '@blocks/database-block/properties/rich-text/cell-renderer.js'; -import { press } from '@inline/__tests__/utils.js'; -import { ZERO_WIDTH_SPACE } from '@inline/consts.js'; +} from '@blocksuite/affine-block-database'; +import { ZERO_WIDTH_SPACE } from '@blocksuite/inline'; import { expect, type Locator, type Page } from '@playwright/test'; import { @@ -18,6 +17,11 @@ import { waitNextFrame, } from '../utils/actions/misc.js'; +export async function press(page: Page, content: string) { + await page.keyboard.press(content, { delay: 50 }); + await page.waitForTimeout(50); +} + export async function initDatabaseColumn(page: Page, title = '') { const editor = getEditorLocator(page); await editor.locator('affine-data-view-table-group').first().hover(); @@ -265,7 +269,7 @@ export async function assertDatabaseCellLink( 'affine-database-link-cell-editing' ); if (!richText) throw new Error('Missing database rich text cell'); - return richText.inlineEditor.yText.toString(); + return richText.inlineEditor!.yText.toString(); }, { rowIndex, columnIndex } ); diff --git a/blocksuite/tests-legacy/database/statistics.spec.ts b/blocksuite/tests-legacy/database/statistics.spec.ts index 536db36ca7..c320817d8e 100644 --- a/blocksuite/tests-legacy/database/statistics.spec.ts +++ b/blocksuite/tests-legacy/database/statistics.spec.ts @@ -1,4 +1,3 @@ -import { press } from '@inline/__tests__/utils.js'; import { expect, type Page } from '@playwright/test'; import { type } from '../utils/actions/index.js'; @@ -9,7 +8,12 @@ import { waitNextFrame, } from '../utils/actions/misc.js'; import { test } from '../utils/playwright.js'; -import { changeColumnType, moveToCenterOf, pressKey } from './actions.js'; +import { + changeColumnType, + moveToCenterOf, + press, + pressKey, +} from './actions.js'; const addRow = async (page: Page, count: number = 1) => { await waitNextFrame(page); diff --git a/blocksuite/tests-legacy/database/title.spec.ts b/blocksuite/tests-legacy/database/title.spec.ts index 5c5e684404..c0dbd0726d 100644 --- a/blocksuite/tests-legacy/database/title.spec.ts +++ b/blocksuite/tests-legacy/database/title.spec.ts @@ -1,4 +1,3 @@ -import { press } from '@inline/__tests__/utils.js'; import { expect } from '@playwright/test'; import { @@ -7,6 +6,7 @@ import { initEmptyDatabaseState, } from '../utils/actions/misc.js'; import { test } from '../utils/playwright.js'; +import { press } from './actions.js'; test.describe('title', () => { test('should able to link doc by press @', async ({ page }) => { diff --git a/blocksuite/tests-legacy/edgeless/basic.spec.ts b/blocksuite/tests-legacy/edgeless/basic.spec.ts index 4c73eee5bc..643aeb9e19 100644 --- a/blocksuite/tests-legacy/edgeless/basic.spec.ts +++ b/blocksuite/tests-legacy/edgeless/basic.spec.ts @@ -138,7 +138,9 @@ test('zoom by mouse without ctrl pressed when edgelessScrollZoom is enabled', as // enable edgelessScrollZoom await page.evaluate(() => { + // @ts-expect-error set a setting window.editorSetting$.value = { + // @ts-expect-error set a setting ...window.editorSetting$.value, edgelessScrollZoom: true, }; @@ -153,7 +155,9 @@ test('zoom by mouse without ctrl pressed when edgelessScrollZoom is enabled', as // disable edgelessScrollZoom await page.evaluate(() => { + // @ts-expect-error set a setting window.editorSetting$.value = { + // @ts-expect-error set a setting ...window.editorSetting$.value, edgelessScrollZoom: false, }; diff --git a/blocksuite/tests-legacy/edgeless/edgeless-text.spec.ts b/blocksuite/tests-legacy/edgeless/edgeless-text.spec.ts index 852c47f7aa..8bebce5e6c 100644 --- a/blocksuite/tests-legacy/edgeless/edgeless-text.spec.ts +++ b/blocksuite/tests-legacy/edgeless/edgeless-text.spec.ts @@ -1,4 +1,4 @@ -import type { EdgelessTextBlockComponent } from '@blocks/edgeless-text-block/edgeless-text-block.js'; +import type { EdgelessTextBlockComponent } from '@blocksuite/affine-block-edgeless-text'; import { Bound } from '@blocksuite/global/utils'; import { expect, type Page } from '@playwright/test'; diff --git a/blocksuite/tests-legacy/format-bar.spec.ts b/blocksuite/tests-legacy/format-bar.spec.ts index 7c65b4b7a5..970fc47a55 100644 --- a/blocksuite/tests-legacy/format-bar.spec.ts +++ b/blocksuite/tests-legacy/format-bar.spec.ts @@ -1,4 +1,4 @@ -import type { DeltaInsert } from '@inline/types.js'; +import type { DeltaInsert } from '@blocksuite/inline'; import { expect } from '@playwright/test'; import { diff --git a/blocksuite/tests-legacy/inline/inline-editor.spec.ts b/blocksuite/tests-legacy/inline/inline-editor.spec.ts index 4d74341ba7..1196a2a6b3 100644 --- a/blocksuite/tests-legacy/inline/inline-editor.spec.ts +++ b/blocksuite/tests-legacy/inline/inline-editor.spec.ts @@ -1,17 +1,158 @@ -import { - assertSelection, - enterInlineEditorPlayground, - focusInlineRichText, - getDeltaFromInlineRichText, - getInlineRangeIndexRect, - getInlineRichTextLine, - press, - setInlineRichTextRange, - type, -} from '@inline/__tests__/utils.js'; -import { ZERO_WIDTH_SPACE } from '@inline/consts.js'; -import type { InlineEditor } from '@inline/index.js'; -import { expect, test } from '@playwright/test'; +import type { + DeltaInsert, + InlineEditor, + InlineRange, +} from '@blocksuite/inline'; +import { ZERO_WIDTH_SPACE } from '@blocksuite/inline'; +import { expect, type Page, test } from '@playwright/test'; + +// FIXME(mirone): copy paste from framework/inline/__tests__/utils.ts +const defaultPlaygroundURL = new URL( + `http://localhost:${process.env.CI ? 4173 : 5173}/` +); + +async function type(page: Page, content: string) { + await page.keyboard.type(content, { delay: 50 }); +} + +async function press(page: Page, content: string) { + await page.keyboard.press(content, { delay: 50 }); + await page.waitForTimeout(50); +} + +async function enterInlineEditorPlayground(page: Page) { + const url = new URL('examples/inline/index.html', defaultPlaygroundURL); + await page.goto(url.toString()); +} + +async function focusInlineRichText(page: Page, index = 0): Promise { + await page.evaluate(index => { + const richTexts = document + .querySelector('test-page') + ?.querySelectorAll('test-rich-text'); + + if (!richTexts) { + throw new Error('Cannot find test-rich-text'); + } + + (richTexts[index] as any).inlineEditor.focusEnd(); + }, index); +} + +async function getDeltaFromInlineRichText( + page: Page, + index = 0 +): Promise { + await page.waitForTimeout(100); + return page.evaluate(index => { + const richTexts = document + .querySelector('test-page') + ?.querySelectorAll('test-rich-text'); + + if (!richTexts) { + throw new Error('Cannot find test-rich-text'); + } + + const editor = (richTexts[index] as any).inlineEditor as InlineEditor; + return editor.yText.toDelta(); + }, index); +} + +async function setInlineRichTextRange( + page: Page, + inlineRange: InlineRange, + index = 0 +): Promise { + await page.evaluate( + ([inlineRange, index]) => { + const richTexts = document + .querySelector('test-page') + ?.querySelectorAll('test-rich-text'); + + if (!richTexts) { + throw new Error('Cannot find test-rich-text'); + } + + const editor = (richTexts[index as number] as any) + .inlineEditor as InlineEditor; + editor.setInlineRange(inlineRange as InlineRange); + }, + [inlineRange, index] + ); +} + +async function getInlineRichTextLine( + page: Page, + index: number, + i = 0 +): Promise { + return page.evaluate( + ([index, i]) => { + const richTexts = document.querySelectorAll('test-rich-text'); + + if (!richTexts) { + throw new Error('Cannot find test-rich-text'); + } + + const editor = (richTexts[i] as any).inlineEditor as InlineEditor; + const result = editor.getLine(index); + if (!result) { + throw new Error('Cannot find line'); + } + const { line, rangeIndexRelatedToLine } = result; + return [line.vTextContent, rangeIndexRelatedToLine] as const; + }, + [index, i] + ); +} + +async function getInlineRangeIndexRect( + page: Page, + [richTextIndex, inlineIndex]: [number, number], + coordOffSet: { x: number; y: number } = { x: 0, y: 0 } +) { + const rect = await page.evaluate( + ({ richTextIndex, inlineIndex: vIndex, coordOffSet }) => { + const richText = document.querySelectorAll('test-rich-text')[ + richTextIndex + ] as any; + const domRange = richText.inlineEditor.toDomRange({ + index: vIndex, + length: 0, + }); + const pointBound = domRange.getBoundingClientRect(); + return { + x: pointBound.left + coordOffSet.x, + y: pointBound.top + pointBound.height / 2 + coordOffSet.y, + }; + }, + { + richTextIndex, + inlineIndex, + coordOffSet, + } + ); + return rect; +} + +async function assertSelection( + page: Page, + richTextIndex: number, + rangeIndex: number, + rangeLength = 0 +) { + const actual = await page.evaluate( + ([richTextIndex]) => { + const richText = + document?.querySelectorAll('test-rich-text')[richTextIndex]; + // @ts-expect-error getInlineRange + const inlineEditor = richText.inlineEditor; + return inlineEditor?.getInlineRange(); + }, + [richTextIndex] + ); + expect(actual).toEqual({ index: rangeIndex, length: rangeLength }); +} test('basic input', async ({ page }) => { await enterInlineEditorPlayground(page); diff --git a/blocksuite/tests-legacy/latex/inline.spec.ts b/blocksuite/tests-legacy/latex/inline.spec.ts index 3a987be6e7..a4a013a46b 100644 --- a/blocksuite/tests-legacy/latex/inline.spec.ts +++ b/blocksuite/tests-legacy/latex/inline.spec.ts @@ -1,4 +1,4 @@ -import { ZERO_WIDTH_SPACE } from '@inline/consts.js'; +import { ZERO_WIDTH_SPACE } from '@blocksuite/inline'; import { expect } from '@playwright/test'; import { assertRichTextInlineDeltas, diff --git a/blocksuite/tests-legacy/package.json b/blocksuite/tests-legacy/package.json index 10a08a326a..e658fecce5 100644 --- a/blocksuite/tests-legacy/package.json +++ b/blocksuite/tests-legacy/package.json @@ -12,7 +12,9 @@ "@blocksuite/affine-shared": "workspace:*", "@blocksuite/block-std": "workspace:*", "@blocksuite/global": "workspace:*", + "@blocksuite/inline": "workspace:*", "@blocksuite/presets": "workspace:*", + "@blocksuite/store": "workspace:*", "@playwright/test": "=1.49.1", "@toeverything/theme": "^1.1.7" }, diff --git a/blocksuite/tests-legacy/paragraph.spec.ts b/blocksuite/tests-legacy/paragraph.spec.ts index 20a144d21f..a82dc965e4 100644 --- a/blocksuite/tests-legacy/paragraph.spec.ts +++ b/blocksuite/tests-legacy/paragraph.spec.ts @@ -1,4 +1,4 @@ -import type { DeltaInsert } from '@inline/types.js'; +import type { DeltaInsert } from '@blocksuite/inline'; import { expect } from '@playwright/test'; import { diff --git a/blocksuite/tests-legacy/slash-menu.spec.ts b/blocksuite/tests-legacy/slash-menu.spec.ts index 43cc8b3b13..345f07988c 100644 --- a/blocksuite/tests-legacy/slash-menu.spec.ts +++ b/blocksuite/tests-legacy/slash-menu.spec.ts @@ -835,7 +835,7 @@ test.describe('slash menu with customize menu', () => { const SlashMenuWidget = window.$blocksuite.blocks.AffineSlashMenuWidget; class CustomSlashMenu extends SlashMenuWidget { - config = { + override config = { ...SlashMenuWidget.DEFAULT_CONFIG, items: [ { groupName: 'Custom Menu' }, diff --git a/blocksuite/tests-legacy/tsconfig.json b/blocksuite/tests-legacy/tsconfig.json index aee9dd0c98..7792d712c4 100644 --- a/blocksuite/tests-legacy/tsconfig.json +++ b/blocksuite/tests-legacy/tsconfig.json @@ -2,13 +2,7 @@ "extends": "../tsconfig.json", "compilerOptions": { "baseUrl": ".", - "outDir": "./dist", - "paths": { - "@blocks/*": ["../blocks/src/*"], - "@inline/*": ["../framework/inline/src/*"], - "@store/*": ["../framework/store/src/*"], - "@playground/*": ["../playground/*"] - } + "outDir": "./dist" }, "include": ["**.spec.ts", "**.test.ts", "**/**.ts"], "exclude": ["dist"], @@ -18,6 +12,8 @@ { "path": "../affine/shared" }, { "path": "../framework/block-std" }, { "path": "../framework/global" }, - { "path": "../presets" } + { "path": "../framework/inline" }, + { "path": "../presets" }, + { "path": "../framework/store" } ] } diff --git a/blocksuite/tests-legacy/utils/actions/block.ts b/blocksuite/tests-legacy/utils/actions/block.ts index fe11bde35b..cb1e24243e 100644 --- a/blocksuite/tests-legacy/utils/actions/block.ts +++ b/blocksuite/tests-legacy/utils/actions/block.ts @@ -9,8 +9,7 @@ export async function updateBlockType( ) { await page.evaluate( ([flavour, type]) => { - window.host.std.command - .chain() + (window.host.std.command.chain() as any) .updateBlockType({ flavour, props: { diff --git a/blocksuite/tests-legacy/utils/actions/click.ts b/blocksuite/tests-legacy/utils/actions/click.ts index 101508d7db..c346ed7c73 100644 --- a/blocksuite/tests-legacy/utils/actions/click.ts +++ b/blocksuite/tests-legacy/utils/actions/click.ts @@ -1,6 +1,6 @@ import type { IPoint } from '@blocksuite/global/utils'; +import type { Store } from '@blocksuite/store'; import type { Page } from '@playwright/test'; -import type { Store } from '@store/index.js'; import { toViewCoord } from './edgeless.js'; import { waitNextFrame } from './misc.js'; diff --git a/blocksuite/tests-legacy/utils/actions/edgeless.ts b/blocksuite/tests-legacy/utils/actions/edgeless.ts index 68db1cc06d..2a2bee48be 100644 --- a/blocksuite/tests-legacy/utils/actions/edgeless.ts +++ b/blocksuite/tests-legacy/utils/actions/edgeless.ts @@ -1,6 +1,6 @@ import '../declare-test-window.js'; -import type { NoteBlockModel, NoteDisplayMode } from '@blocks/index.js'; +import type { NoteBlockModel, NoteDisplayMode } from '@blocksuite/affine-model'; import type { IPoint, IVec } from '@blocksuite/global/utils'; import { assertExists, sleep } from '@blocksuite/global/utils'; import type { Locator, Page } from '@playwright/test'; diff --git a/blocksuite/tests-legacy/utils/actions/misc.ts b/blocksuite/tests-legacy/utils/actions/misc.ts index e0002ec774..12690941c7 100644 --- a/blocksuite/tests-legacy/utils/actions/misc.ts +++ b/blocksuite/tests-legacy/utils/actions/misc.ts @@ -1,20 +1,20 @@ import '../declare-test-window.js'; -import type { DatabaseBlockModel, ListType, RichText } from '@blocks/index.js'; -import type { EditorHost, ExtensionType } from '@blocksuite/block-std'; -import type { BlockSuiteFlags } from '@blocksuite/global/types'; +import type { EditorHost } from '@blocksuite/block-std'; +import type { + BlockSuiteFlags, + DatabaseBlockModel, + ListType, + RichText, +} from '@blocksuite/blocks'; +import type { Container } from '@blocksuite/global/di'; import { assertExists } from '@blocksuite/global/utils'; +import type { InlineRange, InlineRootElement } from '@blocksuite/inline'; import type { AffineEditorContainer } from '@blocksuite/presets'; -import type { InlineRange, InlineRootElement } from '@inline/index.js'; -import type { CustomFramePanel } from '@playground/apps/_common/components/custom-frame-panel.js'; -import type { CustomOutlinePanel } from '@playground/apps/_common/components/custom-outline-panel.js'; -import type { CustomOutlineViewer } from '@playground/apps/_common/components/custom-outline-viewer.js'; -import type { DocsPanel } from '@playground/apps/_common/components/docs-panel.js'; -import type { StarterDebugMenu } from '@playground/apps/_common/components/starter-debug-menu.js'; +import type { BlockModel, ExtensionType } from '@blocksuite/store'; +import { uuidv4 } from '@blocksuite/store'; import type { ConsoleMessage, Locator, Page } from '@playwright/test'; import { expect } from '@playwright/test'; -import type { BlockModel } from '@store/schema/index.js'; -import { uuidv4 } from '@store/utils/id-generator.js'; import lz from 'lz-string'; import { currentEditorIndex, multiEditor } from '../multiple-editor.js'; @@ -95,7 +95,7 @@ async function initEmptyEditor({ for (const [key, value] of Object.entries(flags)) { doc .get(window.$blocksuite.blocks.FeatureFlagService) - .setFlag(key, value); + .setFlag(key as keyof BlockSuiteFlags, value); } doc .get(window.$blocksuite.blocks.FeatureFlagService) @@ -105,7 +105,7 @@ async function initEmptyEditor({ const defaultExtensions: ExtensionType[] = [ ...window.$blocksuite.defaultExtensions(), { - setup: di => { + setup: (di: Container) => { di.addImpl(window.$blocksuite.identifiers.ParseDocUrlService, { parseDocUrl() { return undefined; @@ -114,12 +114,13 @@ async function initEmptyEditor({ }, }, { - setup: di => { + setup: (di: Container) => { di.override( window.$blocksuite.identifiers.DocModeProvider, + // @ts-expect-error set mock service window.$blocksuite.mockServices.mockDocModeService( () => editor.mode, - mode => editor.switchEditor(mode) + (mode: 'page' | 'edgeless') => editor.switchEditor(mode) ) ); }, @@ -149,28 +150,35 @@ async function initEmptyEditor({ editor.updateComplete .then(() => { - const debugMenu: StarterDebugMenu = - document.createElement('starter-debug-menu'); - const docsPanel: DocsPanel = document.createElement('docs-panel'); - const framePanel: CustomFramePanel = - document.createElement('custom-frame-panel'); - const outlinePanel: CustomOutlinePanel = document.createElement( - 'custom-outline-panel' - ); - const outlineViewer: CustomOutlineViewer = document.createElement( + const debugMenu = document.createElement('starter-debug-menu'); + const docsPanel = document.createElement('docs-panel'); + const framePanel = document.createElement('custom-frame-panel'); + const outlinePanel = document.createElement('custom-outline-panel'); + const outlineViewer = document.createElement( 'custom-outline-viewer' ); + // @ts-expect-error set test editor docsPanel.editor = editor; + // @ts-expect-error set test editor framePanel.editor = editor; + // @ts-expect-error set test editor outlinePanel.editor = editor; + // @ts-expect-error set test editor outlineViewer.editor = editor; + // @ts-expect-error set test collection debugMenu.collection = collection; + // @ts-expect-error set test editor debugMenu.editor = editor; + // @ts-expect-error set test docsPanel debugMenu.docsPanel = docsPanel; + // @ts-expect-error set test framePanel debugMenu.framePanel = framePanel; + // @ts-expect-error set test outlineViewer debugMenu.outlineViewer = outlineViewer; + // @ts-expect-error set test outlinePanel debugMenu.outlinePanel = outlinePanel; const leftSidePanel = document.createElement('left-side-panel'); + // @ts-expect-error set test leftSidePanel debugMenu.leftSidePanel = leftSidePanel; document.body.append(debugMenu); document.body.append(leftSidePanel); diff --git a/blocksuite/tests-legacy/utils/asserts.ts b/blocksuite/tests-legacy/utils/asserts.ts index bfb7a86f39..856a8da7ce 100644 --- a/blocksuite/tests-legacy/utils/asserts.ts +++ b/blocksuite/tests-legacy/utils/asserts.ts @@ -1,20 +1,20 @@ import './declare-test-window.js'; -import type { - AffineInlineEditor, - NoteBlockModel, - RichText, - RootBlockModel, -} from '@blocks/index.js'; import type { BlockComponent, EditorHost, TextSelection, } from '@blocksuite/block-std'; +import type { + AffineInlineEditor, + NoteBlockModel, + RichText, + RootBlockModel, +} from '@blocksuite/blocks'; import { assertExists } from '@blocksuite/global/utils'; -import type { InlineRootElement } from '@inline/inline-editor.js'; +import type { InlineRootElement } from '@blocksuite/inline'; +import type { BlockModel } from '@blocksuite/store'; import { expect, type Locator, type Page } from '@playwright/test'; -import type { BlockModel } from '@store/index.js'; import { DEFAULT_NOTE_HEIGHT, @@ -462,7 +462,9 @@ export async function assertBlockChildrenFlavours( ) { const actual = await page.evaluate( ({ blockId }) => { - const element = document.querySelector(`[data-block-id="${blockId}"]`); + const element = document.querySelector( + `[data-block-id="${blockId}"]` + ); // @ts-ignore const model = element.model as BlockModel; return model.children.map(child => child.flavour); diff --git a/blocksuite/tests-legacy/utils/declare-test-window.ts b/blocksuite/tests-legacy/utils/declare-test-window.ts index bbe1221b9e..5b37a687ad 100644 --- a/blocksuite/tests-legacy/utils/declare-test-window.ts +++ b/blocksuite/tests-legacy/utils/declare-test-window.ts @@ -1,17 +1,24 @@ -import type { RefNodeSlotsProvider, TestUtils } from '@blocks/index.js'; +import type { + DocModeProvider, + DocModeService, + ParseDocUrlProvider, + QuickSearchProvider, + ThemeProvider, +} from '@blocksuite/affine-shared/services'; import type { EditorHost, - ExtensionType, + WidgetViewMapExtension, WidgetViewMapIdentifier, } from '@blocksuite/block-std'; +import type { RefNodeSlotsProvider, TestUtils } from '@blocksuite/blocks'; import type { AffineEditorContainer } from '@blocksuite/presets'; -import type { StarterDebugMenu } from '@playground/apps/_common/components/starter-debug-menu.js'; import type { BlockModel, - Blocks, + ExtensionType, + Store, Transformer, Workspace, -} from '@store/index.js'; +} from '@blocksuite/store'; declare global { interface Window { @@ -19,32 +26,32 @@ declare global { * the following instance are initialized in `packages/playground/apps/starter/main.ts` */ $blocksuite: { - store: typeof import('../../framework/store/src/index.js'); - blocks: typeof import('../../blocks/src/index.js'); + store: typeof import('@blocksuite/store'); + blocks: typeof import('@blocksuite/blocks'); global: { - utils: typeof import('../../framework/global/src/utils.js'); + utils: typeof import('@blocksuite/global/utils'); }; - editor: typeof import('../../presets/src/index.js'); + editor: typeof import('@blocksuite/presets'); identifiers: { WidgetViewMapIdentifier: typeof WidgetViewMapIdentifier; - QuickSearchProvider: typeof import('../../affine/shared/src/services/quick-search-service.js').QuickSearchProvider; - DocModeProvider: typeof import('../../affine/shared/src/services/doc-mode-service.js').DocModeProvider; - ThemeProvider: typeof import('../../affine/shared/src/services/theme-service.js').ThemeProvider; + QuickSearchProvider: typeof QuickSearchProvider; + DocModeProvider: typeof DocModeProvider; + ThemeProvider: typeof ThemeProvider; RefNodeSlotsProvider: typeof RefNodeSlotsProvider; - ParseDocUrlService: typeof import('../../affine/shared/src/services/parse-url-service.js').ParseDocUrlProvider; + ParseDocUrlService: typeof ParseDocUrlProvider; }; defaultExtensions: () => ExtensionType[]; extensions: { - WidgetViewMapExtension: typeof import('../../framework/block-std/src/extension/widget-view-map.js').WidgetViewMapExtension; + WidgetViewMapExtension: typeof WidgetViewMapExtension; }; mockServices: { - mockDocModeService: typeof import('../../playground/apps/_common/mock-services.js').mockDocModeService; + mockDocModeService: typeof DocModeService; }; }; collection: Workspace; blockSchema: Record; - doc: Blocks; - debugMenu: StarterDebugMenu; + doc: Store; + debugMenu: HTMLElement; editor: AffineEditorContainer; host: EditorHost; testUtils: TestUtils; diff --git a/blocksuite/tests-legacy/utils/ignore.ts b/blocksuite/tests-legacy/utils/ignore.ts index a0859d8b75..cd3a070f5a 100644 --- a/blocksuite/tests-legacy/utils/ignore.ts +++ b/blocksuite/tests-legacy/utils/ignore.ts @@ -1,4 +1,4 @@ -import type { BlockSnapshot } from '@store/index.js'; +import type { BlockSnapshot } from '@blocksuite/store'; export function ignoreFields(target: unknown, keys: string[]): unknown { if (Array.isArray(target)) { diff --git a/tools/cli/src/init.ts b/tools/cli/src/init.ts index 3ae1320bcf..710c6ac4c2 100755 --- a/tools/cli/src/init.ts +++ b/tools/cli/src/init.ts @@ -107,13 +107,6 @@ export class InitCommand extends Command { ['references'], this.workspace.packages .filter(p => p.isTsProject) - .filter( - p => - // NOTE(@forehalo): there two packages including outdated types, will be fixed when merged with affine-e2e - !['@blocksuite/playground', '@blocksuite/legacy-e2e'].includes( - p.name - ) - ) .map(p => ({ path: p.path.relativePath })), {} ) diff --git a/tools/utils/src/workspace.gen.ts b/tools/utils/src/workspace.gen.ts index 0140f38ed1..9ff0a411d6 100644 --- a/tools/utils/src/workspace.gen.ts +++ b/tools/utils/src/workspace.gen.ts @@ -452,7 +452,9 @@ export const PackageList = [ 'blocksuite/affine/shared', 'blocksuite/framework/block-std', 'blocksuite/framework/global', + 'blocksuite/framework/inline', 'blocksuite/presets', + 'blocksuite/framework/store', ], }, { diff --git a/tsconfig.json b/tsconfig.json index ae5f869fe2..49820ba325 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -82,7 +82,9 @@ { "path": "./blocksuite/framework/inline" }, { "path": "./blocksuite/framework/store" }, { "path": "./blocksuite/framework/sync" }, + { "path": "./blocksuite/playground" }, { "path": "./blocksuite/presets" }, + { "path": "./blocksuite/tests-legacy" }, { "path": "./packages/backend/native" }, { "path": "./packages/backend/server" }, { "path": "./packages/common/debug" }, diff --git a/yarn.lock b/yarn.lock index 2eac6d8ab8..9d85a555c7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4011,7 +4011,9 @@ __metadata: "@blocksuite/affine-shared": "workspace:*" "@blocksuite/block-std": "workspace:*" "@blocksuite/global": "workspace:*" + "@blocksuite/inline": "workspace:*" "@blocksuite/presets": "workspace:*" + "@blocksuite/store": "workspace:*" "@playwright/test": "npm:=1.49.1" "@toeverything/theme": "npm:^1.1.7" languageName: unknown