refactor(editor): extract code block (#9397)

This commit is contained in:
Saul-Mirone
2024-12-27 14:45:11 +00:00
parent 5e1d936c2e
commit 6ebefbbf2b
42 changed files with 177 additions and 52 deletions
+43
View File
@@ -0,0 +1,43 @@
{
"name": "@blocksuite/affine-block-code",
"description": "Code block for BlockSuite.",
"type": "module",
"scripts": {
"build": "tsc",
"test:unit": "nx vite:test --run --passWithNoTests",
"test:unit:coverage": "nx vite:test --run --coverage",
"test:e2e": "playwright test"
},
"sideEffects": false,
"keywords": [],
"author": "toeverything",
"license": "MIT",
"dependencies": {
"@blocksuite/affine-components": "workspace:*",
"@blocksuite/affine-model": "workspace:*",
"@blocksuite/affine-shared": "workspace:*",
"@blocksuite/block-std": "workspace:*",
"@blocksuite/global": "workspace:*",
"@blocksuite/inline": "workspace:*",
"@blocksuite/store": "workspace:*",
"@floating-ui/dom": "^1.6.10",
"@lit/context": "^1.1.2",
"@preact/signals-core": "^1.8.0",
"@toeverything/theme": "^1.1.1",
"@types/mdast": "^4.0.4",
"lit": "^3.2.0",
"minimatch": "^10.0.1",
"shiki": "^1.14.1",
"zod": "^3.23.8"
},
"exports": {
".": "./src/index.ts",
"./effects": "./src/effects.ts"
},
"files": [
"src",
"dist",
"!src/__tests__",
"!dist/__tests__"
]
}
@@ -8,7 +8,7 @@ import {
Clipboard,
type UIEventHandler,
} from '@blocksuite/block-std';
import { assertExists, DisposableGroup } from '@blocksuite/global/utils';
import { DisposableGroup } from '@blocksuite/global/utils';
export class CodeClipboardController {
private _clipboard!: Clipboard;
@@ -42,17 +42,15 @@ export class CodeClipboardController {
.try(cmd => [
cmd.getTextSelection().inline<'currentSelectionPath'>((ctx, next) => {
const textSelection = ctx.currentTextSelection;
assertExists(textSelection);
if (!textSelection) return;
const end = textSelection.to ?? textSelection.from;
next({ currentSelectionPath: end.blockId });
}),
cmd.getBlockSelections().inline<'currentSelectionPath'>((ctx, next) => {
const currentBlockSelections = ctx.currentBlockSelections;
assertExists(currentBlockSelections);
if (!currentBlockSelections) return;
const blockSelection = currentBlockSelections.at(-1);
if (!blockSelection) {
return;
}
if (!blockSelection) return;
next({ currentSelectionPath: blockSelection.blockId });
}),
])
@@ -6,13 +6,13 @@ import {
} from '@blocksuite/block-std';
import { literal, unsafeStatic } from 'lit/static-html.js';
import { AFFINE_CODE_TOOLBAR_WIDGET } from '../root-block/widgets/code-toolbar/index.js';
import { CodeBlockAdapterExtensions } from './adapters/extension.js';
import {
CodeBlockInlineManagerExtension,
CodeBlockUnitSpecExtension,
} from './code-block-inline.js';
import { CodeBlockService } from './code-block-service.js';
import { AFFINE_CODE_TOOLBAR_WIDGET } from './code-toolbar/index.js';
export const CodeBlockSpec: ExtensionType[] = [
FlavourExtension('affine:code'),
@@ -11,7 +11,7 @@ import { property, query } from 'lit/decorators.js';
import { styleMap } from 'lit/directives/style-map.js';
import { html } from 'lit/static-html.js';
import type { CodeBlockComponent } from '../../../../code-block/code-block.js';
import type { CodeBlockComponent } from '../..';
export class LanguageListButton extends WithDisposable(
SignalWatcher(LitElement)
@@ -1,6 +1,6 @@
import { MenuContext } from '@blocksuite/affine-components/toolbar';
import type { CodeBlockComponent } from '../../../code-block/code-block.js';
import type { CodeBlockComponent } from '../code-block';
export class CodeBlockToolbarContext extends MenuContext {
override close = () => {
@@ -13,7 +13,7 @@ import { WidgetComponent } from '@blocksuite/block-std';
import { limitShift, shift } from '@floating-ui/dom';
import { html } from 'lit';
import type { CodeBlockComponent } from '../../../code-block/code-block.js';
import type { CodeBlockComponent } from '../code-block.js';
import { MORE_GROUPS, PRIMARY_GROUPS } from './config.js';
import { CodeBlockToolbarContext } from './context.js';
@@ -0,0 +1,35 @@
import type * as CommandsType from '@blocksuite/affine-shared/commands';
import { CodeBlockComponent } from './code-block';
import type { CodeBlockConfig } from './code-block-config';
import {
AFFINE_CODE_TOOLBAR_WIDGET,
AffineCodeToolbarWidget,
} from './code-toolbar';
import { AffineCodeToolbar } from './code-toolbar/components/code-toolbar';
import { LanguageListButton } from './code-toolbar/components/lang-button';
import { AffineCodeUnit } from './highlight/affine-code-unit';
export function effects() {
customElements.define('language-list-button', LanguageListButton);
customElements.define('affine-code-toolbar', AffineCodeToolbar);
customElements.define(AFFINE_CODE_TOOLBAR_WIDGET, AffineCodeToolbarWidget);
customElements.define('affine-code-unit', AffineCodeUnit);
customElements.define('affine-code', CodeBlockComponent);
}
declare type _GLOBAL_ = typeof CommandsType;
declare global {
namespace BlockSuite {
interface BlockConfigs {
'affine:code': CodeBlockConfig;
}
}
interface HTMLElementTagNameMap {
'language-list-button': LanguageListButton;
'affine-code-toolbar': AffineCodeToolbar;
[AFFINE_CODE_TOOLBAR_WIDGET]: AffineCodeToolbarWidget;
}
}
@@ -0,0 +1,5 @@
export * from './adapters';
export * from './code-block';
export * from './code-block-config';
export * from './code-block-spec';
export * from './code-toolbar';
@@ -0,0 +1,32 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"rootDir": "./src/",
"outDir": "./dist/",
"noEmit": false
},
"include": ["./src"],
"references": [
{
"path": "../../framework/global"
},
{
"path": "../../framework/store"
},
{
"path": "../../framework/block-std"
},
{
"path": "../../framework/inline"
},
{
"path": "../model"
},
{
"path": "../components"
},
{
"path": "../shared"
}
]
}
+1
View File
@@ -16,6 +16,7 @@
"dependencies": {
"@blocksuite/affine-block-attachment": "workspace:*",
"@blocksuite/affine-block-bookmark": "workspace:*",
"@blocksuite/affine-block-code": "workspace:*",
"@blocksuite/affine-block-divider": "workspace:*",
"@blocksuite/affine-block-edgeless-text": "workspace:*",
"@blocksuite/affine-block-embed": "workspace:*",
@@ -1,4 +1,5 @@
import { BookmarkBlockHtmlAdapterExtension } from '@blocksuite/affine-block-bookmark';
import { CodeBlockHtmlAdapterExtension } from '@blocksuite/affine-block-code';
import { DividerBlockHtmlAdapterExtension } from '@blocksuite/affine-block-divider';
import {
EmbedFigmaBlockHtmlAdapterExtension,
@@ -12,7 +13,6 @@ import { ImageBlockHtmlAdapterExtension } from '@blocksuite/affine-block-image';
import { ListBlockHtmlAdapterExtension } from '@blocksuite/affine-block-list';
import { ParagraphBlockHtmlAdapterExtension } from '@blocksuite/affine-block-paragraph';
import { CodeBlockHtmlAdapterExtension } from '../../../code-block/adapters/html.js';
import { DatabaseBlockHtmlAdapterExtension } from '../../../database-block/adapters/html.js';
import { RootBlockHtmlAdapterExtension } from '../../../root-block/adapters/html.js';
@@ -1,4 +1,5 @@
import { bookmarkBlockMarkdownAdapterMatcher } from '@blocksuite/affine-block-bookmark';
import { codeBlockMarkdownAdapterMatcher } from '@blocksuite/affine-block-code';
import { dividerBlockMarkdownAdapterMatcher } from '@blocksuite/affine-block-divider';
import {
embedFigmaBlockMarkdownAdapterMatcher,
@@ -13,7 +14,6 @@ import { latexBlockMarkdownAdapterMatcher } from '@blocksuite/affine-block-latex
import { listBlockMarkdownAdapterMatcher } from '@blocksuite/affine-block-list';
import { paragraphBlockMarkdownAdapterMatcher } from '@blocksuite/affine-block-paragraph';
import { codeBlockMarkdownAdapterMatcher } from '../../../code-block/adapters/markdown.js';
import { databaseBlockMarkdownAdapterMatcher } from '../../../database-block/adapters/markdown.js';
import { rootBlockMarkdownAdapterMatcher } from '../../../root-block/adapters/markdown.js';
@@ -1,5 +1,6 @@
import { AttachmentBlockNotionHtmlAdapterExtension } from '@blocksuite/affine-block-attachment';
import { BookmarkBlockNotionHtmlAdapterExtension } from '@blocksuite/affine-block-bookmark';
import { CodeBlockNotionHtmlAdapterExtension } from '@blocksuite/affine-block-code';
import { DividerBlockNotionHtmlAdapterExtension } from '@blocksuite/affine-block-divider';
import {
EmbedFigmaBlockNotionHtmlAdapterExtension,
@@ -13,7 +14,6 @@ import { ListBlockNotionHtmlAdapterExtension } from '@blocksuite/affine-block-li
import { ParagraphBlockNotionHtmlAdapterExtension } from '@blocksuite/affine-block-paragraph';
import type { ExtensionType } from '@blocksuite/block-std';
import { CodeBlockNotionHtmlAdapterExtension } from '../../../code-block/adapters/notion-html.js';
import { DatabaseBlockNotionHtmlAdapterExtension } from '../../../database-block/adapters/notion-html.js';
import { RootBlockNotionHtmlAdapterExtension } from '../../../root-block/adapters/notion-html.js';
@@ -1,4 +1,5 @@
import { BookmarkBlockPlainTextAdapterExtension } from '@blocksuite/affine-block-bookmark';
import { CodeBlockPlainTextAdapterExtension } from '@blocksuite/affine-block-code';
import { DividerBlockPlainTextAdapterExtension } from '@blocksuite/affine-block-divider';
import {
EmbedFigmaBlockPlainTextAdapterExtension,
@@ -13,7 +14,6 @@ import { ListBlockPlainTextAdapterExtension } from '@blocksuite/affine-block-lis
import { ParagraphBlockPlainTextAdapterExtension } from '@blocksuite/affine-block-paragraph';
import type { ExtensionType } from '@blocksuite/block-std';
import { CodeBlockPlainTextAdapterExtension } from '../../../code-block/adapters/plain-text.js';
import { DatabaseBlockPlainTextAdapterExtension } from '../../../database-block/adapters/plain-text.js';
export const defaultBlockPlainTextAdapterMatchers: ExtensionType[] = [
+1 -1
View File
@@ -1,5 +1,6 @@
import { AttachmentBlockSpec } from '@blocksuite/affine-block-attachment';
import { BookmarkBlockSpec } from '@blocksuite/affine-block-bookmark';
import { CodeBlockSpec } from '@blocksuite/affine-block-code';
import { DividerBlockSpec } from '@blocksuite/affine-block-divider';
import { EmbedExtensions } from '@blocksuite/affine-block-embed';
import { ImageBlockSpec } from '@blocksuite/affine-block-image';
@@ -14,7 +15,6 @@ import { EditPropsStore } from '@blocksuite/affine-shared/services';
import type { ExtensionType } from '@blocksuite/block-std';
import { AdapterFactoryExtensions } from '../_common/adapters/extension.js';
import { CodeBlockSpec } from '../code-block/code-block-spec.js';
import { DataViewBlockSpec } from '../data-view-block/data-view-spec.js';
import { DatabaseBlockSpec } from '../database-block/database-spec.js';
+1 -1
View File
@@ -1,5 +1,6 @@
import { AttachmentBlockSpec } from '@blocksuite/affine-block-attachment';
import { BookmarkBlockSpec } from '@blocksuite/affine-block-bookmark';
import { CodeBlockSpec } from '@blocksuite/affine-block-code';
import { DividerBlockSpec } from '@blocksuite/affine-block-divider';
import {
EmbedFigmaBlockSpec,
@@ -18,7 +19,6 @@ import {
} from '@blocksuite/affine-block-note';
import { ParagraphBlockSpec } from '@blocksuite/affine-block-paragraph';
import { CodeBlockSpec } from '../../code-block/code-block-spec.js';
import { DataViewBlockSpec } from '../../data-view-block/data-view-spec.js';
import { DatabaseBlockSpec } from '../../database-block/database-spec.js';
@@ -1,3 +1,4 @@
import type { CodeBlockConfig } from '@blocksuite/affine-block-code';
import {
type ReferenceNodeConfig,
ReferenceNodeConfigIdentifier,
@@ -11,7 +12,6 @@ import {
} from '@blocksuite/block-std';
import type { Container } from '@blocksuite/global/di';
import type { CodeBlockConfig } from '../../code-block/code-block-config.js';
import { AFFINE_EMBED_CARD_TOOLBAR_WIDGET } from '../../root-block/widgets/embed-card-toolbar/embed-card-toolbar.js';
import { AFFINE_FORMAT_BAR_WIDGET } from '../../root-block/widgets/format-bar/format-bar.js';
import { AFFINE_SLASH_MENU_WIDGET } from '../../root-block/widgets/slash-menu/index.js';
@@ -1,3 +0,0 @@
export * from './adapters/markdown.js';
export * from './code-block.js';
export * from './code-block-config.js';
+2 -10
View File
@@ -1,5 +1,6 @@
import { effects as blockAttachmentEffects } from '@blocksuite/affine-block-attachment/effects';
import { effects as blockBookmarkEffects } from '@blocksuite/affine-block-bookmark/effects';
import { effects as blockCodeEffects } from '@blocksuite/affine-block-code/effects';
import { effects as blockDividerEffects } from '@blocksuite/affine-block-divider/effects';
import { effects as blockEdgelessTextEffects } from '@blocksuite/affine-block-edgeless-text/effects';
import { effects as blockEmbedEffects } from '@blocksuite/affine-block-embed/effects';
@@ -36,11 +37,6 @@ import { EmbedCardEditCaptionEditModal } from './_common/components/embed-card/m
import { EmbedCardCreateModal } from './_common/components/embed-card/modal/embed-card-create-modal.js';
import { EmbedCardEditModal } from './_common/components/embed-card/modal/embed-card-edit-modal.js';
import { registerSpecs } from './_specs/register-specs.js';
import { AffineCodeUnit } from './code-block/highlight/affine-code-unit.js';
import {
CodeBlockComponent,
type CodeBlockConfig,
} from './code-block/index.js';
import { DataViewBlockComponent } from './data-view-block/index.js';
import { CenterPeek } from './database-block/components/layout.js';
import { DatabaseTitle } from './database-block/components/title/index.js';
@@ -184,7 +180,6 @@ import {
AIPanelGenerating,
AIPanelInput,
} from './root-block/widgets/ai-panel/components/index.js';
import { effects as widgetCodeToolbarEffects } from './root-block/widgets/code-toolbar/effects.js';
import { AFFINE_DOC_REMOTE_SELECTION_WIDGET } from './root-block/widgets/doc-remote-selection/index.js';
import { DragPreview } from './root-block/widgets/drag-handle/components/drag-preview.js';
import { DropIndicator } from './root-block/widgets/drag-handle/components/drop-indicator.js';
@@ -252,6 +247,7 @@ export function effects() {
blockLatexEffects();
blockEdgelessTextEffects();
blockDividerEffects();
blockCodeEffects();
componentCaptionEffects();
componentContextMenuEffects();
@@ -268,7 +264,6 @@ export function effects() {
widgetLinkedDocEffects();
widgetFrameTitleEffects();
widgetEdgelessElementToolbarEffects();
widgetCodeToolbarEffects();
dataViewEffects();
@@ -281,7 +276,6 @@ export function effects() {
'data-view-header-area-text-editing',
HeaderAreaTextCellEditing
);
customElements.define('affine-code-unit', AffineCodeUnit);
customElements.define('affine-database-rich-text-cell', RichTextCell);
customElements.define(
'affine-database-rich-text-cell-editing',
@@ -292,7 +286,6 @@ export function effects() {
customElements.define('database-datasource-block-renderer', BlockRenderer);
customElements.define('affine-page-root', PageRootBlockComponent);
customElements.define('affine-preview-root', PreviewRootBlockComponent);
customElements.define('affine-code', CodeBlockComponent);
customElements.define('mini-mindmap-preview', MiniMindmapPreview);
customElements.define('mini-mindmap-surface-block', MindmapSurfaceBlock);
customElements.define('affine-data-view', DataViewBlockComponent);
@@ -519,7 +512,6 @@ declare global {
updatedBlocks?: BlockModel[];
}
interface BlockConfigs {
'affine:code': CodeBlockConfig;
'affine:page': RootBlockConfig;
}
interface BlockServices {
+1 -1
View File
@@ -16,7 +16,6 @@ export * from './_common/test-utils/test-utils.js';
export * from './_common/transformers/index.js';
export { type AbstractEditor } from './_common/types.js';
export * from './_specs/index.js';
export * from './code-block/index.js';
export * from './data-view-block/index.js';
export * from './database-block/index.js';
export { EdgelessTemplatePanel } from './root-block/edgeless/components/toolbar/template/template-panel.js';
@@ -44,6 +43,7 @@ export {
export * from './surface-ref-block/index.js';
export * from '@blocksuite/affine-block-attachment';
export * from '@blocksuite/affine-block-bookmark';
export * from '@blocksuite/affine-block-code';
export * from '@blocksuite/affine-block-divider';
export * from '@blocksuite/affine-block-edgeless-text';
export * from '@blocksuite/affine-block-embed';
@@ -1,20 +0,0 @@
import { AffineCodeToolbar } from './components/code-toolbar.js';
import { LanguageListButton } from './components/lang-button.js';
import {
AFFINE_CODE_TOOLBAR_WIDGET,
AffineCodeToolbarWidget,
} from './index.js';
export function effects() {
customElements.define('language-list-button', LanguageListButton);
customElements.define('affine-code-toolbar', AffineCodeToolbar);
customElements.define(AFFINE_CODE_TOOLBAR_WIDGET, AffineCodeToolbarWidget);
}
declare global {
interface HTMLElementTagNameMap {
'language-list-button': LanguageListButton;
'affine-code-toolbar': AffineCodeToolbar;
[AFFINE_CODE_TOOLBAR_WIDGET]: AffineCodeToolbarWidget;
}
}
@@ -6,7 +6,6 @@ export {
type AffineAIPanelState,
type AffineAIPanelWidgetConfig,
} from './ai-panel/type.js';
export { AffineCodeToolbarWidget } from './code-toolbar/index.js';
export { AffineDocRemoteSelectionWidget } from './doc-remote-selection/doc-remote-selection.js';
export { AffineDragHandleWidget } from './drag-handle/drag-handle.js';
export {
+3
View File
@@ -37,6 +37,9 @@
{
"path": "../affine/block-list"
},
{
"path": "../affine/block-code"
},
{
"path": "../affine/block-embed"
},
+15
View File
@@ -42,6 +42,19 @@ export const PackageList = [
'blocksuite/framework/store',
],
},
{
location: 'blocksuite/affine/block-code',
name: '@blocksuite/affine-block-code',
workspaceDependencies: [
'blocksuite/affine/components',
'blocksuite/affine/model',
'blocksuite/affine/shared',
'blocksuite/framework/block-std',
'blocksuite/framework/global',
'blocksuite/framework/inline',
'blocksuite/framework/store',
],
},
{
location: 'blocksuite/affine/block-divider',
name: '@blocksuite/affine-block-divider',
@@ -237,6 +250,7 @@ export const PackageList = [
workspaceDependencies: [
'blocksuite/affine/block-attachment',
'blocksuite/affine/block-bookmark',
'blocksuite/affine/block-code',
'blocksuite/affine/block-divider',
'blocksuite/affine/block-edgeless-text',
'blocksuite/affine/block-embed',
@@ -584,6 +598,7 @@ export type PackageName =
| '@blocksuite/affine'
| '@blocksuite/affine-block-attachment'
| '@blocksuite/affine-block-bookmark'
| '@blocksuite/affine-block-code'
| '@blocksuite/affine-block-divider'
| '@blocksuite/affine-block-edgeless-text'
| '@blocksuite/affine-block-embed'
+1
View File
@@ -9,6 +9,7 @@
{ "path": "./blocksuite/affine/all" },
{ "path": "./blocksuite/affine/block-attachment" },
{ "path": "./blocksuite/affine/block-bookmark" },
{ "path": "./blocksuite/affine/block-code" },
{ "path": "./blocksuite/affine/block-divider" },
{ "path": "./blocksuite/affine/block-edgeless-text" },
{ "path": "./blocksuite/affine/block-embed" },
+24
View File
@@ -3289,6 +3289,29 @@ __metadata:
languageName: unknown
linkType: soft
"@blocksuite/affine-block-code@workspace:*, @blocksuite/affine-block-code@workspace:blocksuite/affine/block-code":
version: 0.0.0-use.local
resolution: "@blocksuite/affine-block-code@workspace:blocksuite/affine/block-code"
dependencies:
"@blocksuite/affine-components": "workspace:*"
"@blocksuite/affine-model": "workspace:*"
"@blocksuite/affine-shared": "workspace:*"
"@blocksuite/block-std": "workspace:*"
"@blocksuite/global": "workspace:*"
"@blocksuite/inline": "workspace:*"
"@blocksuite/store": "workspace:*"
"@floating-ui/dom": "npm:^1.6.10"
"@lit/context": "npm:^1.1.2"
"@preact/signals-core": "npm:^1.8.0"
"@toeverything/theme": "npm:^1.1.1"
"@types/mdast": "npm:^4.0.4"
lit: "npm:^3.2.0"
minimatch: "npm:^10.0.1"
shiki: "npm:^1.14.1"
zod: "npm:^3.23.8"
languageName: unknown
linkType: soft
"@blocksuite/affine-block-divider@workspace:*, @blocksuite/affine-block-divider@workspace:blocksuite/affine/block-divider":
version: 0.0.0-use.local
resolution: "@blocksuite/affine-block-divider@workspace:blocksuite/affine/block-divider"
@@ -3645,6 +3668,7 @@ __metadata:
dependencies:
"@blocksuite/affine-block-attachment": "workspace:*"
"@blocksuite/affine-block-bookmark": "workspace:*"
"@blocksuite/affine-block-code": "workspace:*"
"@blocksuite/affine-block-divider": "workspace:*"
"@blocksuite/affine-block-edgeless-text": "workspace:*"
"@blocksuite/affine-block-embed": "workspace:*"