diff --git a/packages/blocks/src/code-block/code-block.ts b/packages/blocks/src/code-block/code-block.ts index d4e2a5f21d54..0feab1dad4fa 100644 --- a/packages/blocks/src/code-block/code-block.ts +++ b/packages/blocks/src/code-block/code-block.ts @@ -48,9 +48,6 @@ import { getHighLighter } from './utils/high-lighter.js'; export class CodeBlockComponent extends BlockElement { static override styles = codeBlockStyles; - @state() - private _wrap = false; - @query('.lang-button') private _langButton!: HTMLButtonElement; @@ -176,9 +173,9 @@ export class CodeBlockComponent extends BlockElement { CodeOptionTemplate({ anchor: this, model: this.model, - wrap: this._wrap, - onClickWrap: () => { - this._wrap = !this._wrap; + wrap: this.model.wrap, + toggleWrap: () => { + this.setWrap(!this.model.wrap); updatePortal(); }, abortController, @@ -429,6 +426,10 @@ export class CodeBlockComponent extends BlockElement { }); } + setWrap(wrap: boolean) { + this.doc.updateBlock(this.model, { wrap }); + } + private _onClickLangBtn() { if (this.readonly) return; if (this._langListAbortController) return; @@ -477,7 +478,9 @@ export class CodeBlockComponent extends BlockElement { this.querySelector('#line-numbers'); assertExists(lineNumbersContainer); - const next = this._wrap ? generateLineNumberRender() : lineNumberRender; + const next = this.model.wrap + ? generateLineNumberRender() + : lineNumberRender; render( repeat(Array.from(this.querySelectorAll('v-line')), next), @@ -491,7 +494,7 @@ export class CodeBlockComponent extends BlockElement { ${ref(this._whenHover.setReference)} class=${classMap({ 'affine-code-block-container': true, - wrap: this._wrap, + wrap: this.model.wrap, })} > ${this._curLanguageButtonTemplate()} @@ -507,7 +510,7 @@ export class CodeBlockComponent extends BlockElement { .inlineRangeProvider=${this._inlineRangeProvider} .enableClipboard=${false} .enableUndoRedo=${false} - .wrapText=${this._wrap} + .wrapText=${this.model.wrap} .verticalScrollContainer=${getViewportElement(this.host)} > diff --git a/packages/blocks/src/code-block/code-model.ts b/packages/blocks/src/code-block/code-model.ts index 6a04f07e1d0a..8e2fdf657190 100644 --- a/packages/blocks/src/code-block/code-model.ts +++ b/packages/blocks/src/code-block/code-model.ts @@ -8,6 +8,7 @@ export const CodeBlockSchema = defineBlockSchema({ props: internal => ({ text: internal.Text(), language: FALLBACK_LANG, + wrap: false, }), metadata: { version: 1, diff --git a/packages/blocks/src/code-block/components/code-option.ts b/packages/blocks/src/code-block/components/code-option.ts index e981ff8cf2b0..8a133a669bba 100644 --- a/packages/blocks/src/code-block/components/code-option.ts +++ b/packages/blocks/src/code-block/components/code-option.ts @@ -15,7 +15,7 @@ export function CodeOptionTemplate({ ref: containerRef, model, wrap, - onClickWrap, + toggleWrap, anchor, }: { ref?: RefOrCallback; @@ -23,7 +23,7 @@ export function CodeOptionTemplate({ model: BlockModel; wrap: boolean; abortController: AbortController; - onClickWrap: () => void; + toggleWrap: () => void; }) { const page = model.doc; const readonly = page.readonly; @@ -71,17 +71,19 @@ export function CodeOptionTemplate({ >Copy to Clipboard - - ${wrap ? CancelWrapIcon : WrapIcon} - ${wrap ? 'Cancel wrap' : 'Wrap code'} - + ${readonly + ? nothing + : html` + ${wrap ? CancelWrapIcon : WrapIcon} + ${wrap ? 'Cancel wrap' : 'Wrap code'} + `} ${readonly ? nothing : html` { > { /*xml*/ ` `, codeBlockId ); @@ -286,6 +288,7 @@ test('change code language can work', async ({ page }) => { /*xml*/ ` `, codeBlockId ); @@ -418,10 +421,12 @@ test.skip('use keyboard copy inside code block copy', async ({ page }) => { ` @@ -473,10 +478,12 @@ test.fixme( ` @@ -711,6 +718,89 @@ test('should tab works in code block', async ({ page }) => { await assertRichTexts(page, ['const a = 10;\n \nconst b = "NothingToSay"']); }); +test('toggle code block wrap can work', async ({ page }) => { + await enterPlaygroundRoom(page); + const { codeBlockId } = await initEmptyCodeBlockState(page); + await focusRichText(page); + + const codeBlockController = getCodeBlock(page); + await assertStoreMatchJSX( + page, + /*xml*/ ` +`, + codeBlockId + ); + + await codeBlockController.codeBlock.hover(); + await expect(codeBlockController.wrapButton).toBeVisible(); + await codeBlockController.wrapButton.click(); + await assertStoreMatchJSX( + page, + /*xml*/ ` +`, + codeBlockId + ); + + await codeBlockController.wrapButton.click(); + await assertStoreMatchJSX( + page, + /*xml*/ ` +`, + codeBlockId + ); +}); + +test('undo code block wrap can work', async ({ page }) => { + await enterPlaygroundRoom(page); + const { codeBlockId } = await initEmptyCodeBlockState(page); + await focusRichText(page); + + const codeBlockController = getCodeBlock(page); + await assertStoreMatchJSX( + page, + /*xml*/ ` +`, + codeBlockId + ); + + await codeBlockController.codeBlock.hover(); + await expect(codeBlockController.wrapButton).toBeVisible(); + await codeBlockController.wrapButton.click(); + await assertStoreMatchJSX( + page, + /*xml*/ ` +`, + codeBlockId + ); + + await focusRichText(page); + await undoByKeyboard(page); + await assertStoreMatchJSX( + page, + /*xml*/ ` +`, + codeBlockId + ); +}); + test('should code block wrap active after click', async ({ page }) => { await enterPlaygroundRoom(page); await initEmptyCodeBlockState(page); @@ -734,6 +824,16 @@ test('should code block wrap active after click', async ({ page }) => { ); }); +test('code block wrap icon hidden in read only mode', async ({ page }) => { + await enterPlaygroundRoom(page); + await initEmptyCodeBlockState(page); + await switchReadonly(page); + + const codeBlockController = getCodeBlock(page); + await codeBlockController.codeBlock.hover(); + await expect(codeBlockController.wrapButton).toBeHidden(); +}); + test('should code block works in read only mode', async ({ page }) => { await enterPlaygroundRoom(page); await initEmptyCodeBlockState(page); diff --git a/tests/format-bar.spec.ts b/tests/format-bar.spec.ts index e91a87cfe9f4..9e9667417e60 100644 --- a/tests/format-bar.spec.ts +++ b/tests/format-bar.spec.ts @@ -1318,6 +1318,7 @@ test('should format quick bar show after convert to code block', async ({ `, noteId