mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-17 22:37:04 +08:00
feat(editor): add inline packages (#11048)
This commit is contained in:
@@ -35,6 +35,9 @@
|
||||
"@blocksuite/affine-fragment-outline": "workspace:*",
|
||||
"@blocksuite/affine-gfx-text": "workspace:*",
|
||||
"@blocksuite/affine-gfx-turbo-renderer": "workspace:*",
|
||||
"@blocksuite/affine-inline-link": "workspace:*",
|
||||
"@blocksuite/affine-inline-preset": "workspace:*",
|
||||
"@blocksuite/affine-inline-reference": "workspace:*",
|
||||
"@blocksuite/affine-model": "workspace:*",
|
||||
"@blocksuite/affine-rich-text": "workspace:*",
|
||||
"@blocksuite/affine-shared": "workspace:*",
|
||||
@@ -91,6 +94,9 @@
|
||||
"./blocks/table": "./src/blocks/table.ts",
|
||||
"./data-view": "./src/data-view/index.ts",
|
||||
"./data-view/effects": "./src/data-view/effects.ts",
|
||||
"./inlines/link": "./src/inlines/link.ts",
|
||||
"./inlines/reference": "./src/inlines/reference.ts",
|
||||
"./inlines/preset": "./src/inlines/preset.ts",
|
||||
"./widgets/drag-handle": "./src/widgets/drag-handle.ts",
|
||||
"./widgets/edgeless-auto-connect": "./src/widgets/edgeless-auto-connect.ts",
|
||||
"./widgets/frame-title": "./src/widgets/frame-title.ts",
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
InlineDeltaToPlainTextAdapterExtensions,
|
||||
MarkdownInlineToDeltaAdapterExtensions,
|
||||
NotionHtmlInlineToDeltaAdapterExtensions,
|
||||
} from '@blocksuite/affine-rich-text';
|
||||
} from '@blocksuite/affine-inline-preset';
|
||||
import {
|
||||
AttachmentAdapterFactoryExtension,
|
||||
HtmlAdapterFactoryExtension,
|
||||
|
||||
@@ -45,6 +45,9 @@ import { effects as componentViewDropdownMenuEffects } from '@blocksuite/affine-
|
||||
import { effects as fragmentDocTitleEffects } from '@blocksuite/affine-fragment-doc-title/effects';
|
||||
import { effects as fragmentFramePanelEffects } from '@blocksuite/affine-fragment-frame-panel/effects';
|
||||
import { effects as fragmentOutlineEffects } from '@blocksuite/affine-fragment-outline/effects';
|
||||
import { effects as inlineLinkEffects } from '@blocksuite/affine-inline-link/effects';
|
||||
import { effects as inlinePresetEffects } from '@blocksuite/affine-inline-preset/effects';
|
||||
import { effects as inlineReferenceEffects } from '@blocksuite/affine-inline-reference/effects';
|
||||
import { effects as richTextEffects } from '@blocksuite/affine-rich-text/effects';
|
||||
import { effects as widgetDragHandleEffects } from '@blocksuite/affine-widget-drag-handle/effects';
|
||||
import { effects as widgetEdgelessAutoConnectEffects } from '@blocksuite/affine-widget-edgeless-auto-connect/effects';
|
||||
@@ -113,6 +116,10 @@ export function effects() {
|
||||
dataViewEffects();
|
||||
richTextEffects();
|
||||
|
||||
inlineReferenceEffects();
|
||||
inlinePresetEffects();
|
||||
inlineLinkEffects();
|
||||
|
||||
blockNoteEffects();
|
||||
blockAttachmentEffects();
|
||||
blockBookmarkEffects();
|
||||
|
||||
@@ -25,10 +25,7 @@ import {
|
||||
PageSurfaceRefBlockSpec,
|
||||
} from '@blocksuite/affine-block-surface-ref';
|
||||
import { TableBlockSpec } from '@blocksuite/affine-block-table';
|
||||
import {
|
||||
RefNodeSlotsExtension,
|
||||
RichTextExtensions,
|
||||
} from '@blocksuite/affine-rich-text';
|
||||
import { inlinePresetExtensions } from '@blocksuite/affine-inline-preset';
|
||||
import {
|
||||
DefaultOpenDocExtension,
|
||||
DocDisplayMetaService,
|
||||
@@ -38,10 +35,9 @@ import {
|
||||
import type { ExtensionType } from '@blocksuite/store';
|
||||
|
||||
export const CommonBlockSpecs: ExtensionType[] = [
|
||||
inlinePresetExtensions,
|
||||
DocDisplayMetaService,
|
||||
RefNodeSlotsExtension,
|
||||
EditPropsStore,
|
||||
RichTextExtensions,
|
||||
LatexBlockSpec,
|
||||
ListBlockSpec,
|
||||
DatabaseBlockSpec,
|
||||
|
||||
1
blocksuite/affine/all/src/inlines/link.ts
Normal file
1
blocksuite/affine/all/src/inlines/link.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from '@blocksuite/affine-inline-link';
|
||||
1
blocksuite/affine/all/src/inlines/preset.ts
Normal file
1
blocksuite/affine/all/src/inlines/preset.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from '@blocksuite/affine-inline-preset';
|
||||
1
blocksuite/affine/all/src/inlines/reference.ts
Normal file
1
blocksuite/affine/all/src/inlines/reference.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from '@blocksuite/affine-inline-reference';
|
||||
@@ -32,6 +32,9 @@
|
||||
{ "path": "../fragments/fragment-outline" },
|
||||
{ "path": "../gfx/text" },
|
||||
{ "path": "../gfx/turbo-renderer" },
|
||||
{ "path": "../inlines/link" },
|
||||
{ "path": "../inlines/preset" },
|
||||
{ "path": "../inlines/reference" },
|
||||
{ "path": "../model" },
|
||||
{ "path": "../rich-text" },
|
||||
{ "path": "../shared" },
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@blocksuite/affine-components": "workspace:*",
|
||||
"@blocksuite/affine-inline-preset": "workspace:*",
|
||||
"@blocksuite/affine-model": "workspace:*",
|
||||
"@blocksuite/affine-rich-text": "workspace:*",
|
||||
"@blocksuite/affine-shared": "workspace:*",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { CaptionedBlockComponent } from '@blocksuite/affine-components/caption';
|
||||
import { createLitPortal } from '@blocksuite/affine-components/portal';
|
||||
import { DefaultInlineManagerExtension } from '@blocksuite/affine-inline-preset';
|
||||
import { type CalloutBlockModel } from '@blocksuite/affine-model';
|
||||
import { DefaultInlineManagerExtension } from '@blocksuite/affine-rich-text';
|
||||
import { NOTE_SELECTOR } from '@blocksuite/affine-shared/consts';
|
||||
import {
|
||||
DocModeProvider,
|
||||
@@ -12,7 +12,6 @@ import type { BlockComponent } from '@blocksuite/block-std';
|
||||
import { flip, offset } from '@floating-ui/dom';
|
||||
import { css, html } from 'lit';
|
||||
import { query } from 'lit/decorators.js';
|
||||
|
||||
export class CalloutBlockComponent extends CaptionedBlockComponent<CalloutBlockModel> {
|
||||
static override styles = css`
|
||||
:host {
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
"include": ["./src"],
|
||||
"references": [
|
||||
{ "path": "../../components" },
|
||||
{ "path": "../../inlines/preset" },
|
||||
{ "path": "../../model" },
|
||||
{ "path": "../../rich-text" },
|
||||
{ "path": "../../shared" },
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@blocksuite/affine-components": "workspace:*",
|
||||
"@blocksuite/affine-inline-link": "workspace:*",
|
||||
"@blocksuite/affine-inline-preset": "workspace:*",
|
||||
"@blocksuite/affine-model": "workspace:*",
|
||||
"@blocksuite/affine-rich-text": "workspace:*",
|
||||
"@blocksuite/affine-shared": "workspace:*",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { deleteTextCommand } from '@blocksuite/affine-rich-text';
|
||||
import { deleteTextCommand } from '@blocksuite/affine-inline-preset';
|
||||
import {
|
||||
HtmlAdapter,
|
||||
pasteMiddleware,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { LinkInlineSpecExtension } from '@blocksuite/affine-inline-link';
|
||||
import {
|
||||
BackgroundInlineSpecExtension,
|
||||
BoldInlineSpecExtension,
|
||||
@@ -5,10 +6,9 @@ import {
|
||||
ColorInlineSpecExtension,
|
||||
ItalicInlineSpecExtension,
|
||||
LatexInlineSpecExtension,
|
||||
LinkInlineSpecExtension,
|
||||
StrikeInlineSpecExtension,
|
||||
UnderlineInlineSpecExtension,
|
||||
} from '@blocksuite/affine-rich-text';
|
||||
} from '@blocksuite/affine-inline-preset';
|
||||
import type { AffineTextAttributes } from '@blocksuite/affine-shared/types';
|
||||
import {
|
||||
InlineManagerExtension,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { textKeymap } from '@blocksuite/affine-inline-preset';
|
||||
import { CodeBlockSchema } from '@blocksuite/affine-model';
|
||||
import { textKeymap } from '@blocksuite/affine-rich-text';
|
||||
import { KeymapExtension } from '@blocksuite/block-std';
|
||||
|
||||
export const CodeKeymapExtension = KeymapExtension(textKeymap, {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { affineTextStyles } from '@blocksuite/affine-rich-text';
|
||||
import { affineTextStyles } from '@blocksuite/affine-shared/styles';
|
||||
import type { AffineTextAttributes } from '@blocksuite/affine-shared/types';
|
||||
import { ShadowlessElement } from '@blocksuite/block-std';
|
||||
import { ZERO_WIDTH_SPACE } from '@blocksuite/block-std/inline';
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
"include": ["./src"],
|
||||
"references": [
|
||||
{ "path": "../../components" },
|
||||
{ "path": "../../inlines/link" },
|
||||
{ "path": "../../inlines/preset" },
|
||||
{ "path": "../../model" },
|
||||
{ "path": "../../rich-text" },
|
||||
{ "path": "../../shared" },
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@blocksuite/affine-components": "workspace:*",
|
||||
"@blocksuite/affine-inline-preset": "workspace:*",
|
||||
"@blocksuite/affine-inline-reference": "workspace:*",
|
||||
"@blocksuite/affine-model": "workspace:*",
|
||||
"@blocksuite/affine-rich-text": "workspace:*",
|
||||
"@blocksuite/affine-shared": "workspace:*",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { DefaultInlineManagerExtension } from '@blocksuite/affine-rich-text';
|
||||
import { DefaultInlineManagerExtension } from '@blocksuite/affine-inline-preset';
|
||||
import type { EditorHost } from '@blocksuite/block-std';
|
||||
import { ShadowlessElement } from '@blocksuite/block-std';
|
||||
import type { DetailSlotProps } from '@blocksuite/data-view';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { RefNodeSlotsProvider } from '@blocksuite/affine-rich-text';
|
||||
import { RefNodeSlotsProvider } from '@blocksuite/affine-inline-reference';
|
||||
import { ParseDocUrlProvider } from '@blocksuite/affine-shared/services';
|
||||
import {
|
||||
isValidUrl,
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import type {
|
||||
AffineInlineEditor,
|
||||
RichText,
|
||||
} from '@blocksuite/affine-rich-text';
|
||||
import { DefaultInlineManagerExtension } from '@blocksuite/affine-rich-text';
|
||||
import { DefaultInlineManagerExtension } from '@blocksuite/affine-inline-preset';
|
||||
import type { RichText } from '@blocksuite/affine-rich-text';
|
||||
import {
|
||||
ParseDocUrlProvider,
|
||||
TelemetryProvider,
|
||||
} from '@blocksuite/affine-shared/services';
|
||||
import type { AffineTextAttributes } from '@blocksuite/affine-shared/types';
|
||||
import type {
|
||||
AffineInlineEditor,
|
||||
AffineTextAttributes,
|
||||
} from '@blocksuite/affine-shared/types';
|
||||
import {
|
||||
getViewportElement,
|
||||
isValidUrl,
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import {
|
||||
DefaultInlineManagerExtension,
|
||||
type RichText,
|
||||
} from '@blocksuite/affine-rich-text';
|
||||
import { DefaultInlineManagerExtension } from '@blocksuite/affine-inline-preset';
|
||||
import type { RichText } from '@blocksuite/affine-rich-text';
|
||||
import {
|
||||
ParseDocUrlProvider,
|
||||
TelemetryProvider,
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
"include": ["./src"],
|
||||
"references": [
|
||||
{ "path": "../../components" },
|
||||
{ "path": "../../inlines/preset" },
|
||||
{ "path": "../../inlines/reference" },
|
||||
{ "path": "../../model" },
|
||||
{ "path": "../../rich-text" },
|
||||
{ "path": "../../shared" },
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
"dependencies": {
|
||||
"@blocksuite/affine-block-surface": "workspace:*",
|
||||
"@blocksuite/affine-components": "workspace:*",
|
||||
"@blocksuite/affine-inline-preset": "workspace:*",
|
||||
"@blocksuite/affine-model": "workspace:*",
|
||||
"@blocksuite/affine-rich-text": "workspace:*",
|
||||
"@blocksuite/affine-shared": "workspace:*",
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { TextUtils } from '@blocksuite/affine-block-surface';
|
||||
import { formatBlockCommand } from '@blocksuite/affine-inline-preset';
|
||||
import {
|
||||
type EdgelessTextBlockModel,
|
||||
ListBlockModel,
|
||||
ParagraphBlockModel,
|
||||
} from '@blocksuite/affine-model';
|
||||
import { formatBlockCommand } from '@blocksuite/affine-rich-text';
|
||||
import { ThemeProvider } from '@blocksuite/affine-shared/services';
|
||||
import { matchModels } from '@blocksuite/affine-shared/utils';
|
||||
import type { BlockComponent } from '@blocksuite/block-std';
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
"references": [
|
||||
{ "path": "../block-surface" },
|
||||
{ "path": "../../components" },
|
||||
{ "path": "../../inlines/preset" },
|
||||
{ "path": "../../model" },
|
||||
{ "path": "../../rich-text" },
|
||||
{ "path": "../../shared" },
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
"dependencies": {
|
||||
"@blocksuite/affine-block-surface": "workspace:*",
|
||||
"@blocksuite/affine-components": "workspace:*",
|
||||
"@blocksuite/affine-inline-reference": "workspace:*",
|
||||
"@blocksuite/affine-model": "workspace:*",
|
||||
"@blocksuite/affine-rich-text": "workspace:*",
|
||||
"@blocksuite/affine-shared": "workspace:*",
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { SurfaceBlockModel } from '@blocksuite/affine-block-surface';
|
||||
import { isPeekable, Peekable } from '@blocksuite/affine-components/peek';
|
||||
import { RefNodeSlotsProvider } from '@blocksuite/affine-inline-reference';
|
||||
import type {
|
||||
DocMode,
|
||||
EmbedLinkedDocModel,
|
||||
EmbedLinkedDocStyles,
|
||||
} from '@blocksuite/affine-model';
|
||||
import { RefNodeSlotsProvider } from '@blocksuite/affine-rich-text';
|
||||
import {
|
||||
EMBED_CARD_HEIGHT,
|
||||
EMBED_CARD_WIDTH,
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
import { Peekable } from '@blocksuite/affine-components/peek';
|
||||
import {
|
||||
type DocLinkClickedEvent,
|
||||
RefNodeSlotsProvider,
|
||||
} from '@blocksuite/affine-inline-reference';
|
||||
import {
|
||||
type AliasInfo,
|
||||
type DocMode,
|
||||
@@ -6,10 +10,6 @@ import {
|
||||
NoteDisplayMode,
|
||||
type ReferenceInfo,
|
||||
} from '@blocksuite/affine-model';
|
||||
import {
|
||||
type DocLinkClickedEvent,
|
||||
RefNodeSlotsProvider,
|
||||
} from '@blocksuite/affine-rich-text';
|
||||
import { REFERENCE_NODE } from '@blocksuite/affine-shared/consts';
|
||||
import {
|
||||
DocDisplayMetaProvider,
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
"references": [
|
||||
{ "path": "../block-surface" },
|
||||
{ "path": "../../components" },
|
||||
{ "path": "../../inlines/reference" },
|
||||
{ "path": "../../model" },
|
||||
{ "path": "../../rich-text" },
|
||||
{ "path": "../../shared" },
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
"dependencies": {
|
||||
"@blocksuite/affine-block-note": "workspace:*",
|
||||
"@blocksuite/affine-components": "workspace:*",
|
||||
"@blocksuite/affine-inline-preset": "workspace:*",
|
||||
"@blocksuite/affine-model": "workspace:*",
|
||||
"@blocksuite/affine-rich-text": "workspace:*",
|
||||
"@blocksuite/affine-shared": "workspace:*",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { insertInlineLatex } from '@blocksuite/affine-rich-text';
|
||||
import { insertInlineLatex } from '@blocksuite/affine-inline-preset';
|
||||
import {
|
||||
getSelectedModelsCommand,
|
||||
getTextSelectionCommand,
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
"references": [
|
||||
{ "path": "../block-note" },
|
||||
{ "path": "../../components" },
|
||||
{ "path": "../../inlines/preset" },
|
||||
{ "path": "../../model" },
|
||||
{ "path": "../../rich-text" },
|
||||
{ "path": "../../shared" },
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@blocksuite/affine-components": "workspace:*",
|
||||
"@blocksuite/affine-inline-preset": "workspace:*",
|
||||
"@blocksuite/affine-model": "workspace:*",
|
||||
"@blocksuite/affine-rich-text": "workspace:*",
|
||||
"@blocksuite/affine-shared": "workspace:*",
|
||||
|
||||
@@ -3,11 +3,9 @@ import '@blocksuite/affine-shared/commands';
|
||||
import { CaptionedBlockComponent } from '@blocksuite/affine-components/caption';
|
||||
import { playCheckAnimation } from '@blocksuite/affine-components/icons';
|
||||
import { TOGGLE_BUTTON_PARENT_CLASS } from '@blocksuite/affine-components/toggle-button';
|
||||
import { DefaultInlineManagerExtension } from '@blocksuite/affine-inline-preset';
|
||||
import type { ListBlockModel } from '@blocksuite/affine-model';
|
||||
import {
|
||||
DefaultInlineManagerExtension,
|
||||
type RichText,
|
||||
} from '@blocksuite/affine-rich-text';
|
||||
import type { RichText } from '@blocksuite/affine-rich-text';
|
||||
import {
|
||||
BLOCK_CHILDREN_CONTAINER_PADDING_LEFT,
|
||||
NOTE_SELECTOR,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { textKeymap } from '@blocksuite/affine-inline-preset';
|
||||
import { ListBlockSchema } from '@blocksuite/affine-model';
|
||||
import { markdownInput, textKeymap } from '@blocksuite/affine-rich-text';
|
||||
import { markdownInput } from '@blocksuite/affine-rich-text';
|
||||
import { getSelectedModelsCommand } from '@blocksuite/affine-shared/commands';
|
||||
import { KeymapExtension, TextSelection } from '@blocksuite/block-std';
|
||||
import { IS_MAC } from '@blocksuite/global/env';
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
"include": ["./src"],
|
||||
"references": [
|
||||
{ "path": "../../components" },
|
||||
{ "path": "../../inlines/preset" },
|
||||
{ "path": "../../model" },
|
||||
{ "path": "../../rich-text" },
|
||||
{ "path": "../../shared" },
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
"@blocksuite/affine-block-surface": "workspace:*",
|
||||
"@blocksuite/affine-components": "workspace:*",
|
||||
"@blocksuite/affine-fragment-doc-title": "workspace:*",
|
||||
"@blocksuite/affine-inline-preset": "workspace:*",
|
||||
"@blocksuite/affine-model": "workspace:*",
|
||||
"@blocksuite/affine-rich-text": "workspace:*",
|
||||
"@blocksuite/affine-shared": "workspace:*",
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import {
|
||||
formatBlockCommand,
|
||||
type TextConversionConfig,
|
||||
textConversionConfigs,
|
||||
type TextFormatConfig,
|
||||
textFormatConfigs,
|
||||
} from '@blocksuite/affine-inline-preset';
|
||||
import {
|
||||
type TextConversionConfig,
|
||||
textConversionConfigs,
|
||||
} from '@blocksuite/affine-rich-text';
|
||||
import { isInsideBlockByFlavour } from '@blocksuite/affine-shared/utils';
|
||||
import {
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
{ "path": "../block-surface" },
|
||||
{ "path": "../../components" },
|
||||
{ "path": "../../fragments/fragment-doc-title" },
|
||||
{ "path": "../../inlines/preset" },
|
||||
{ "path": "../../model" },
|
||||
{ "path": "../../rich-text" },
|
||||
{ "path": "../../shared" },
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
"dependencies": {
|
||||
"@blocksuite/affine-components": "workspace:*",
|
||||
"@blocksuite/affine-gfx-turbo-renderer": "workspace:*",
|
||||
"@blocksuite/affine-inline-preset": "workspace:*",
|
||||
"@blocksuite/affine-model": "workspace:*",
|
||||
"@blocksuite/affine-rich-text": "workspace:*",
|
||||
"@blocksuite/affine-shared": "workspace:*",
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import { CaptionedBlockComponent } from '@blocksuite/affine-components/caption';
|
||||
import { TOGGLE_BUTTON_PARENT_CLASS } from '@blocksuite/affine-components/toggle-button';
|
||||
import { DefaultInlineManagerExtension } from '@blocksuite/affine-inline-preset';
|
||||
import type { ParagraphBlockModel } from '@blocksuite/affine-model';
|
||||
import {
|
||||
DefaultInlineManagerExtension,
|
||||
type RichText,
|
||||
} from '@blocksuite/affine-rich-text';
|
||||
import type { RichText } from '@blocksuite/affine-rich-text';
|
||||
import {
|
||||
BLOCK_CHILDREN_CONTAINER_PADDING_LEFT,
|
||||
NOTE_SELECTOR,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { textKeymap } from '@blocksuite/affine-inline-preset';
|
||||
import {
|
||||
CalloutBlockModel,
|
||||
ParagraphBlockModel,
|
||||
@@ -7,7 +8,6 @@ import {
|
||||
focusTextModel,
|
||||
getInlineEditorByModel,
|
||||
markdownInput,
|
||||
textKeymap,
|
||||
} from '@blocksuite/affine-rich-text';
|
||||
import {
|
||||
calculateCollapsedSiblings,
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
"references": [
|
||||
{ "path": "../../components" },
|
||||
{ "path": "../../gfx/turbo-renderer" },
|
||||
{ "path": "../../inlines/preset" },
|
||||
{ "path": "../../model" },
|
||||
{ "path": "../../rich-text" },
|
||||
{ "path": "../../shared" },
|
||||
|
||||
@@ -28,6 +28,9 @@
|
||||
"@blocksuite/affine-components": "workspace:*",
|
||||
"@blocksuite/affine-fragment-doc-title": "workspace:*",
|
||||
"@blocksuite/affine-gfx-text": "workspace:*",
|
||||
"@blocksuite/affine-inline-link": "workspace:*",
|
||||
"@blocksuite/affine-inline-preset": "workspace:*",
|
||||
"@blocksuite/affine-inline-reference": "workspace:*",
|
||||
"@blocksuite/affine-model": "workspace:*",
|
||||
"@blocksuite/affine-rich-text": "workspace:*",
|
||||
"@blocksuite/affine-shared": "workspace:*",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { deleteTextCommand } from '@blocksuite/affine-rich-text';
|
||||
import { deleteTextCommand } from '@blocksuite/affine-inline-preset';
|
||||
import {
|
||||
pasteMiddleware,
|
||||
replaceIdMiddleware,
|
||||
|
||||
@@ -16,9 +16,9 @@ import {
|
||||
formatNativeCommand,
|
||||
formatTextCommand,
|
||||
isFormatSupported,
|
||||
textConversionConfigs,
|
||||
textFormatConfigs,
|
||||
} from '@blocksuite/affine-rich-text';
|
||||
} from '@blocksuite/affine-inline-preset';
|
||||
import { textConversionConfigs } from '@blocksuite/affine-rich-text';
|
||||
import {
|
||||
copySelectedModelsCommand,
|
||||
deleteSelectedModelsCommand,
|
||||
|
||||
@@ -20,21 +20,23 @@ import { getSurfaceBlock } from '@blocksuite/affine-block-surface';
|
||||
import { insertSurfaceRefBlockCommand } from '@blocksuite/affine-block-surface-ref';
|
||||
import { toggleEmbedCardCreateModal } from '@blocksuite/affine-components/embed-card-modal';
|
||||
import { toast } from '@blocksuite/affine-components/toast';
|
||||
import type { FrameBlockModel } from '@blocksuite/affine-model';
|
||||
import { toggleLink } from '@blocksuite/affine-inline-link';
|
||||
import {
|
||||
formatBlockCommand,
|
||||
formatNativeCommand,
|
||||
formatTextCommand,
|
||||
getInlineEditorByModel,
|
||||
getTextStyle,
|
||||
insertContent,
|
||||
insertInlineLatex,
|
||||
toggleBold,
|
||||
toggleCode,
|
||||
toggleItalic,
|
||||
toggleLink,
|
||||
toggleStrike,
|
||||
toggleUnderline,
|
||||
} from '@blocksuite/affine-inline-preset';
|
||||
import type { FrameBlockModel } from '@blocksuite/affine-model';
|
||||
import {
|
||||
getInlineEditorByModel,
|
||||
insertContent,
|
||||
} from '@blocksuite/affine-rich-text';
|
||||
import {
|
||||
copySelectedModelsCommand,
|
||||
|
||||
@@ -5,14 +5,12 @@ import {
|
||||
NewDocIcon,
|
||||
} from '@blocksuite/affine-components/icons';
|
||||
import { toast } from '@blocksuite/affine-components/toast';
|
||||
import {
|
||||
type AffineInlineEditor,
|
||||
insertLinkedNode,
|
||||
} from '@blocksuite/affine-rich-text';
|
||||
import { insertLinkedNode } from '@blocksuite/affine-inline-reference';
|
||||
import {
|
||||
DocModeProvider,
|
||||
TelemetryProvider,
|
||||
} from '@blocksuite/affine-shared/services';
|
||||
import type { AffineInlineEditor } from '@blocksuite/affine-shared/types';
|
||||
import {
|
||||
createDefaultDoc,
|
||||
isFuzzyMatch,
|
||||
|
||||
@@ -25,6 +25,9 @@
|
||||
{ "path": "../../components" },
|
||||
{ "path": "../../fragments/fragment-doc-title" },
|
||||
{ "path": "../../gfx/text" },
|
||||
{ "path": "../../inlines/link" },
|
||||
{ "path": "../../inlines/preset" },
|
||||
{ "path": "../../inlines/reference" },
|
||||
{ "path": "../../model" },
|
||||
{ "path": "../../rich-text" },
|
||||
{ "path": "../../shared" },
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
"dependencies": {
|
||||
"@atlaskit/pragmatic-drag-and-drop": "^1.4.0",
|
||||
"@blocksuite/affine-components": "workspace:*",
|
||||
"@blocksuite/affine-inline-preset": "workspace:*",
|
||||
"@blocksuite/affine-model": "workspace:*",
|
||||
"@blocksuite/affine-rich-text": "workspace:*",
|
||||
"@blocksuite/affine-shared": "workspace:*",
|
||||
|
||||
@@ -5,11 +5,9 @@ import {
|
||||
popupTargetFromElement,
|
||||
} from '@blocksuite/affine-components/context-menu';
|
||||
import { TextBackgroundDuotoneIcon } from '@blocksuite/affine-components/icons';
|
||||
import { DefaultInlineManagerExtension } from '@blocksuite/affine-inline-preset';
|
||||
import type { TableColumn, TableRow } from '@blocksuite/affine-model';
|
||||
import {
|
||||
DefaultInlineManagerExtension,
|
||||
RichText,
|
||||
} from '@blocksuite/affine-rich-text';
|
||||
import { RichText } from '@blocksuite/affine-rich-text';
|
||||
import { cssVarV2 } from '@blocksuite/affine-shared/theme';
|
||||
import { getViewportElement } from '@blocksuite/affine-shared/utils';
|
||||
import { ShadowlessElement } from '@blocksuite/block-std';
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
"include": ["./src"],
|
||||
"references": [
|
||||
{ "path": "../../components" },
|
||||
{ "path": "../../inlines/preset" },
|
||||
{ "path": "../../model" },
|
||||
{ "path": "../../rich-text" },
|
||||
{ "path": "../../shared" },
|
||||
|
||||
46
blocksuite/affine/inlines/link/package.json
Normal file
46
blocksuite/affine/inlines/link/package.json
Normal file
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"name": "@blocksuite/affine-inline-link",
|
||||
"description": "Inline link for BlockSuite.",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "tsc"
|
||||
},
|
||||
"sideEffects": false,
|
||||
"keywords": [],
|
||||
"author": "toeverything",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@blocksuite/affine-components": "workspace:*",
|
||||
"@blocksuite/affine-inline-reference": "workspace:*",
|
||||
"@blocksuite/affine-model": "workspace:*",
|
||||
"@blocksuite/affine-shared": "workspace:*",
|
||||
"@blocksuite/block-std": "workspace:*",
|
||||
"@blocksuite/global": "workspace:*",
|
||||
"@blocksuite/icons": "^2.2.6",
|
||||
"@blocksuite/store": "workspace:*",
|
||||
"@floating-ui/dom": "^1.6.13",
|
||||
"@lit/context": "^1.1.2",
|
||||
"@preact/signals-core": "^1.8.0",
|
||||
"@toeverything/theme": "^1.1.12",
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"collapse-white-space": "^2.1.0",
|
||||
"date-fns": "^4.0.0",
|
||||
"lit": "^3.2.0",
|
||||
"lit-html": "^3.2.1",
|
||||
"lodash-es": "^4.17.21",
|
||||
"rxjs": "^7.8.1",
|
||||
"yjs": "^13.6.21",
|
||||
"zod": "^3.23.8"
|
||||
},
|
||||
"exports": {
|
||||
".": "./src/index.ts",
|
||||
"./effects": "./src/effects.ts"
|
||||
},
|
||||
"files": [
|
||||
"src",
|
||||
"dist",
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.20.0"
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
import {
|
||||
type HtmlAST,
|
||||
HtmlASTToDeltaExtension,
|
||||
} from '@blocksuite/affine-shared/adapters';
|
||||
import type { Element } from 'hast';
|
||||
|
||||
const isElement = (ast: HtmlAST): ast is Element => {
|
||||
return ast.type === 'element';
|
||||
};
|
||||
|
||||
export const htmlLinkElementToDeltaMatcher = HtmlASTToDeltaExtension({
|
||||
name: 'link-element',
|
||||
match: ast => isElement(ast) && ast.tagName === 'a',
|
||||
toDelta: (ast, context) => {
|
||||
if (!isElement(ast)) {
|
||||
return [];
|
||||
}
|
||||
const href = ast.properties?.href;
|
||||
if (typeof href !== 'string') {
|
||||
return [];
|
||||
}
|
||||
const { configs } = context;
|
||||
const baseUrl = configs.get('docLinkBaseUrl') ?? '';
|
||||
if (baseUrl && href.startsWith(baseUrl)) {
|
||||
const path = href.substring(baseUrl.length);
|
||||
// ^ - /{pageId}?mode={mode}&blockIds={blockIds}&elementIds={elementIds}
|
||||
const match = path.match(/^\/([^?]+)(\?.*)?$/);
|
||||
if (match) {
|
||||
const pageId = match?.[1];
|
||||
const search = match?.[2];
|
||||
const searchParams = search ? new URLSearchParams(search) : undefined;
|
||||
const mode = searchParams?.get('mode');
|
||||
const blockIds = searchParams?.get('blockIds')?.split(',');
|
||||
const elementIds = searchParams?.get('elementIds')?.split(',');
|
||||
|
||||
return [
|
||||
{
|
||||
insert: ' ',
|
||||
attributes: {
|
||||
reference: {
|
||||
type: 'LinkedPage',
|
||||
pageId,
|
||||
params: {
|
||||
mode:
|
||||
mode && ['edgeless', 'page'].includes(mode)
|
||||
? (mode as 'edgeless' | 'page')
|
||||
: undefined,
|
||||
blockIds,
|
||||
elementIds,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
}
|
||||
return ast.children.flatMap(child =>
|
||||
context.toDelta(child, { trim: false }).map(delta => {
|
||||
if (href.startsWith('http')) {
|
||||
delta.attributes = {
|
||||
...delta.attributes,
|
||||
link: href,
|
||||
};
|
||||
return delta;
|
||||
}
|
||||
return delta;
|
||||
})
|
||||
);
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,25 @@
|
||||
import type { InlineHtmlAST } from '@blocksuite/affine-shared/adapters';
|
||||
import { InlineDeltaToHtmlAdapterExtension } from '@blocksuite/affine-shared/adapters';
|
||||
|
||||
export const linkDeltaToHtmlAdapterMatcher = InlineDeltaToHtmlAdapterExtension({
|
||||
name: 'link',
|
||||
match: delta => !!delta.attributes?.link,
|
||||
toAST: (delta, _) => {
|
||||
const hast: InlineHtmlAST = {
|
||||
type: 'text',
|
||||
value: delta.insert,
|
||||
};
|
||||
const link = delta.attributes?.link;
|
||||
if (!link) {
|
||||
return hast;
|
||||
}
|
||||
return {
|
||||
type: 'element',
|
||||
tagName: 'a',
|
||||
properties: {
|
||||
href: link,
|
||||
},
|
||||
children: [hast],
|
||||
};
|
||||
},
|
||||
});
|
||||
6
blocksuite/affine/inlines/link/src/adapters/index.ts
Normal file
6
blocksuite/affine/inlines/link/src/adapters/index.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
export * from './html/html-inline';
|
||||
export * from './html/inline-delta';
|
||||
export * from './markdown/inline-delta';
|
||||
export * from './markdown/markdown-inline';
|
||||
export * from './notion-html/html-inline';
|
||||
export * from './plain-text/inline-delta';
|
||||
@@ -0,0 +1,36 @@
|
||||
import { InlineDeltaToMarkdownAdapterExtension } from '@blocksuite/affine-shared/adapters';
|
||||
import type { PhrasingContent } from 'mdast';
|
||||
|
||||
export const linkDeltaToMarkdownAdapterMatcher =
|
||||
InlineDeltaToMarkdownAdapterExtension({
|
||||
name: 'link',
|
||||
match: delta => !!delta.attributes?.link,
|
||||
toAST: (delta, context) => {
|
||||
const mdast: PhrasingContent = {
|
||||
type: 'text',
|
||||
value: delta.insert,
|
||||
};
|
||||
const link = delta.attributes?.link;
|
||||
if (!link) {
|
||||
return mdast;
|
||||
}
|
||||
|
||||
const { current: currentMdast } = context;
|
||||
if ('value' in currentMdast) {
|
||||
if (currentMdast.value === '') {
|
||||
return {
|
||||
type: 'text',
|
||||
value: link,
|
||||
};
|
||||
}
|
||||
if (mdast.value !== link) {
|
||||
return {
|
||||
type: 'link',
|
||||
url: link,
|
||||
children: [currentMdast],
|
||||
};
|
||||
}
|
||||
}
|
||||
return mdast;
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,52 @@
|
||||
import { MarkdownASTToDeltaExtension } from '@blocksuite/affine-shared/adapters';
|
||||
|
||||
export const markdownLinkToDeltaMatcher = MarkdownASTToDeltaExtension({
|
||||
name: 'link',
|
||||
match: ast => ast.type === 'link',
|
||||
toDelta: (ast, context) => {
|
||||
if (!('children' in ast) || !('url' in ast)) {
|
||||
return [];
|
||||
}
|
||||
const { configs } = context;
|
||||
const baseUrl = configs.get('docLinkBaseUrl') ?? '';
|
||||
if (baseUrl && ast.url.startsWith(baseUrl)) {
|
||||
const path = ast.url.substring(baseUrl.length);
|
||||
// ^ - /{pageId}?mode={mode}&blockIds={blockIds}&elementIds={elementIds}
|
||||
const match = path.match(/^\/([^?]+)(\?.*)?$/);
|
||||
if (match) {
|
||||
const pageId = match?.[1];
|
||||
const search = match?.[2];
|
||||
const searchParams = search ? new URLSearchParams(search) : undefined;
|
||||
const mode = searchParams?.get('mode');
|
||||
const blockIds = searchParams?.get('blockIds')?.split(',');
|
||||
const elementIds = searchParams?.get('elementIds')?.split(',');
|
||||
|
||||
return [
|
||||
{
|
||||
insert: ' ',
|
||||
attributes: {
|
||||
reference: {
|
||||
type: 'LinkedPage',
|
||||
pageId,
|
||||
params: {
|
||||
mode:
|
||||
mode && ['edgeless', 'page'].includes(mode)
|
||||
? (mode as 'edgeless' | 'page')
|
||||
: undefined,
|
||||
blockIds,
|
||||
elementIds,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
}
|
||||
return ast.children.flatMap(child =>
|
||||
context.toDelta(child).map(delta => {
|
||||
delta.attributes = { ...delta.attributes, link: ast.url };
|
||||
return delta;
|
||||
})
|
||||
);
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,52 @@
|
||||
import {
|
||||
type HtmlAST,
|
||||
NotionHtmlASTToDeltaExtension,
|
||||
} from '@blocksuite/affine-shared/adapters';
|
||||
import type { Element } from 'hast';
|
||||
|
||||
const isElement = (ast: HtmlAST): ast is Element => {
|
||||
return ast.type === 'element';
|
||||
};
|
||||
|
||||
export const notionHtmlLinkElementToDeltaMatcher =
|
||||
NotionHtmlASTToDeltaExtension({
|
||||
name: 'link-element',
|
||||
match: ast => isElement(ast) && ast.tagName === 'a',
|
||||
toDelta: (ast, context) => {
|
||||
if (!isElement(ast)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const href = ast.properties?.href;
|
||||
if (typeof href !== 'string') {
|
||||
return [];
|
||||
}
|
||||
const { toDelta, options } = context;
|
||||
return ast.children.flatMap(child =>
|
||||
toDelta(child, options).map(delta => {
|
||||
if (options.pageMap) {
|
||||
const pageId = options.pageMap.get(decodeURIComponent(href));
|
||||
if (pageId) {
|
||||
delta.attributes = {
|
||||
...delta.attributes,
|
||||
reference: {
|
||||
type: 'LinkedPage',
|
||||
pageId,
|
||||
},
|
||||
};
|
||||
delta.insert = ' ';
|
||||
return delta;
|
||||
}
|
||||
}
|
||||
if (href.startsWith('http')) {
|
||||
delta.attributes = {
|
||||
...delta.attributes,
|
||||
link: href,
|
||||
};
|
||||
return delta;
|
||||
}
|
||||
return delta;
|
||||
})
|
||||
);
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,25 @@
|
||||
import {
|
||||
InlineDeltaToPlainTextAdapterExtension,
|
||||
type TextBuffer,
|
||||
} from '@blocksuite/affine-shared/adapters';
|
||||
|
||||
export const linkDeltaMarkdownAdapterMatch =
|
||||
InlineDeltaToPlainTextAdapterExtension({
|
||||
name: 'link',
|
||||
match: delta => !!delta.attributes?.link,
|
||||
toAST: delta => {
|
||||
const linkText = delta.insert;
|
||||
const node: TextBuffer = {
|
||||
content: linkText,
|
||||
};
|
||||
const link = delta.attributes?.link;
|
||||
if (!link) {
|
||||
return node;
|
||||
}
|
||||
|
||||
const content = `${linkText ? `${linkText}: ` : ''}${link}`;
|
||||
return {
|
||||
content,
|
||||
};
|
||||
},
|
||||
});
|
||||
42
blocksuite/affine/inlines/link/src/command.ts
Normal file
42
blocksuite/affine/inlines/link/src/command.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import type { AffineTextAttributes } from '@blocksuite/affine-shared/types';
|
||||
import type { Command } from '@blocksuite/block-std';
|
||||
import {
|
||||
INLINE_ROOT_ATTR,
|
||||
type InlineRootElement,
|
||||
} from '@blocksuite/block-std/inline';
|
||||
|
||||
import { toggleLinkPopup } from './link-node/link-popup/toggle-link-popup';
|
||||
|
||||
export const toggleLink: Command = (ctx, next) => {
|
||||
const selection = document.getSelection();
|
||||
if (!selection || selection.rangeCount === 0) return false;
|
||||
|
||||
const range = selection.getRangeAt(0);
|
||||
if (range.collapsed) return false;
|
||||
const inlineRoot = range.startContainer.parentElement?.closest<
|
||||
InlineRootElement<AffineTextAttributes>
|
||||
>(`[${INLINE_ROOT_ATTR}]`);
|
||||
if (!inlineRoot) return false;
|
||||
|
||||
const inlineEditor = inlineRoot.inlineEditor;
|
||||
const targetInlineRange = inlineEditor.getInlineRange();
|
||||
|
||||
if (!targetInlineRange || targetInlineRange.length === 0) return false;
|
||||
|
||||
const format = inlineEditor.getFormat(targetInlineRange);
|
||||
if (format.link) {
|
||||
inlineEditor.formatText(targetInlineRange, { link: null });
|
||||
return next();
|
||||
}
|
||||
|
||||
const abortController = new AbortController();
|
||||
const popup = toggleLinkPopup(
|
||||
ctx.std,
|
||||
'create',
|
||||
inlineEditor,
|
||||
targetInlineRange,
|
||||
abortController
|
||||
);
|
||||
abortController.signal.addEventListener('abort', () => popup.remove());
|
||||
return next();
|
||||
};
|
||||
7
blocksuite/affine/inlines/link/src/effects.ts
Normal file
7
blocksuite/affine/inlines/link/src/effects.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { AffineLink } from './link-node/affine-link';
|
||||
import { LinkPopup } from './link-node/link-popup/link-popup';
|
||||
|
||||
export function effects() {
|
||||
customElements.define('link-popup', LinkPopup);
|
||||
customElements.define('affine-link', AffineLink);
|
||||
}
|
||||
9
blocksuite/affine/inlines/link/src/exts.ts
Normal file
9
blocksuite/affine/inlines/link/src/exts.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import type { ExtensionType } from '@blocksuite/store';
|
||||
|
||||
import { LinkInlineSpecExtension } from './inline-spec';
|
||||
import { linkToolbar } from './toolbar';
|
||||
|
||||
export const inlineLinkExtensions: ExtensionType[] = [
|
||||
LinkInlineSpecExtension,
|
||||
linkToolbar,
|
||||
];
|
||||
6
blocksuite/affine/inlines/link/src/index.ts
Normal file
6
blocksuite/affine/inlines/link/src/index.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
export * from './adapters';
|
||||
export * from './command';
|
||||
export * from './exts';
|
||||
export * from './inline-spec';
|
||||
export * from './link-node';
|
||||
export * from './toolbar';
|
||||
20
blocksuite/affine/inlines/link/src/inline-spec.ts
Normal file
20
blocksuite/affine/inlines/link/src/inline-spec.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import type { AffineTextAttributes } from '@blocksuite/affine-shared/types';
|
||||
import { StdIdentifier } from '@blocksuite/block-std';
|
||||
import { InlineSpecExtension } from '@blocksuite/block-std/inline';
|
||||
import { html } from 'lit';
|
||||
import { z } from 'zod';
|
||||
|
||||
export const LinkInlineSpecExtension =
|
||||
InlineSpecExtension<AffineTextAttributes>('link', provider => {
|
||||
const std = provider.get(StdIdentifier);
|
||||
return {
|
||||
name: 'link',
|
||||
schema: z.string().optional().nullable().catch(undefined),
|
||||
match: delta => {
|
||||
return !!delta.attributes?.link;
|
||||
},
|
||||
renderer: ({ delta }) => {
|
||||
return html`<affine-link .std=${std} .delta=${delta}></affine-link>`;
|
||||
},
|
||||
};
|
||||
});
|
||||
@@ -1,9 +1,11 @@
|
||||
import { whenHover } from '@blocksuite/affine-components/hover';
|
||||
import { RefNodeSlotsProvider } from '@blocksuite/affine-inline-reference';
|
||||
import type { ReferenceInfo } from '@blocksuite/affine-model';
|
||||
import {
|
||||
ParseDocUrlProvider,
|
||||
ToolbarRegistryIdentifier,
|
||||
} from '@blocksuite/affine-shared/services';
|
||||
import { affineTextStyles } from '@blocksuite/affine-shared/styles';
|
||||
import type { AffineTextAttributes } from '@blocksuite/affine-shared/types';
|
||||
import type { BlockComponent, BlockStdScope } from '@blocksuite/block-std';
|
||||
import { BLOCK_ID_ATTR, ShadowlessElement } from '@blocksuite/block-std';
|
||||
@@ -18,9 +20,6 @@ import { css, html } from 'lit';
|
||||
import { property } from 'lit/decorators.js';
|
||||
import { type StyleInfo, styleMap } from 'lit/directives/style-map.js';
|
||||
|
||||
import { RefNodeSlotsProvider } from '../../../../extension';
|
||||
import { affineTextStyles } from '../affine-text';
|
||||
|
||||
export class AffineLink extends WithDisposable(ShadowlessElement) {
|
||||
static override styles = css`
|
||||
affine-link a:hover [data-v-text='true'] {
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { EditorIconButton } from '@blocksuite/affine-components/toolbar';
|
||||
import type { AffineInlineEditor } from '@blocksuite/affine-shared/types';
|
||||
import {
|
||||
isValidUrl,
|
||||
normalizeUrl,
|
||||
@@ -13,7 +14,6 @@ import { html, LitElement } from 'lit';
|
||||
import { property, query } from 'lit/decorators.js';
|
||||
import { choose } from 'lit/directives/choose.js';
|
||||
|
||||
import type { AffineInlineEditor } from '../../../affine-inline-specs';
|
||||
import { linkPopupStyle } from './styles';
|
||||
|
||||
export class LinkPopup extends WithDisposable(LitElement) {
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { AffineInlineEditor } from '@blocksuite/affine-shared/types';
|
||||
import type { BlockStdScope } from '@blocksuite/block-std';
|
||||
import type { InlineRange } from '@blocksuite/block-std/inline';
|
||||
|
||||
import type { AffineInlineEditor } from '../../../affine-inline-specs';
|
||||
import { LinkPopup } from './link-popup';
|
||||
|
||||
export function toggleLinkPopup(
|
||||
9
blocksuite/affine/inlines/link/src/toolbar.ts
Normal file
9
blocksuite/affine/inlines/link/src/toolbar.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { ToolbarModuleExtension } from '@blocksuite/affine-shared/services';
|
||||
import { BlockFlavourIdentifier } from '@blocksuite/block-std';
|
||||
|
||||
import { builtinInlineLinkToolbarConfig } from './link-node/configs/toolbar.js';
|
||||
|
||||
export const linkToolbar = ToolbarModuleExtension({
|
||||
id: BlockFlavourIdentifier('affine:link'),
|
||||
config: builtinInlineLinkToolbarConfig,
|
||||
});
|
||||
18
blocksuite/affine/inlines/link/tsconfig.json
Normal file
18
blocksuite/affine/inlines/link/tsconfig.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"extends": "../../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src",
|
||||
"outDir": "./dist",
|
||||
"tsBuildInfoFile": "./dist/tsconfig.tsbuildinfo"
|
||||
},
|
||||
"include": ["./src"],
|
||||
"references": [
|
||||
{ "path": "../../components" },
|
||||
{ "path": "../reference" },
|
||||
{ "path": "../../model" },
|
||||
{ "path": "../../shared" },
|
||||
{ "path": "../../../framework/block-std" },
|
||||
{ "path": "../../../framework/global" },
|
||||
{ "path": "../../../framework/store" }
|
||||
]
|
||||
}
|
||||
54
blocksuite/affine/inlines/preset/package.json
Normal file
54
blocksuite/affine/inlines/preset/package.json
Normal file
@@ -0,0 +1,54 @@
|
||||
{
|
||||
"name": "@blocksuite/affine-inline-preset",
|
||||
"description": "Inline preset for BlockSuite.",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "tsc"
|
||||
},
|
||||
"sideEffects": false,
|
||||
"keywords": [],
|
||||
"author": "toeverything",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@blocksuite/affine-components": "workspace:*",
|
||||
"@blocksuite/affine-inline-link": "workspace:*",
|
||||
"@blocksuite/affine-inline-reference": "workspace:*",
|
||||
"@blocksuite/affine-model": "workspace:*",
|
||||
"@blocksuite/affine-rich-text": "workspace:*",
|
||||
"@blocksuite/affine-shared": "workspace:*",
|
||||
"@blocksuite/block-std": "workspace:*",
|
||||
"@blocksuite/global": "workspace:*",
|
||||
"@blocksuite/icons": "^2.2.6",
|
||||
"@blocksuite/store": "workspace:*",
|
||||
"@floating-ui/dom": "^1.6.13",
|
||||
"@lit/context": "^1.1.2",
|
||||
"@preact/signals-core": "^1.8.0",
|
||||
"@toeverything/theme": "^1.1.12",
|
||||
"@types/hast": "^3.0.4",
|
||||
"@types/katex": "^0.16.7",
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"@types/mdast": "^4.0.4",
|
||||
"collapse-white-space": "^2.1.0",
|
||||
"date-fns": "^4.0.0",
|
||||
"katex": "^0.16.11",
|
||||
"lit": "^3.2.0",
|
||||
"lit-html": "^3.2.1",
|
||||
"lodash-es": "^4.17.21",
|
||||
"remark-math": "^6.0.0",
|
||||
"rxjs": "^7.8.1",
|
||||
"shiki": "^3.0.0",
|
||||
"yjs": "^13.6.21",
|
||||
"zod": "^3.23.8"
|
||||
},
|
||||
"exports": {
|
||||
".": "./src/index.ts",
|
||||
"./effects": "./src/effects.ts"
|
||||
},
|
||||
"files": [
|
||||
"src",
|
||||
"dist",
|
||||
"!src/__tests__",
|
||||
"!dist/__tests__"
|
||||
],
|
||||
"version": "0.20.0"
|
||||
}
|
||||
@@ -15,3 +15,10 @@ export const InlineAdapterExtensions: ExtensionType[] = [
|
||||
InlineDeltaToMarkdownAdapterExtensions,
|
||||
MarkdownInlineToDeltaAdapterExtensions,
|
||||
].flat();
|
||||
|
||||
export * from './html/html-inline';
|
||||
export * from './html/inline-delta';
|
||||
export * from './markdown/inline-delta';
|
||||
export * from './markdown/markdown-inline';
|
||||
export * from './notion-html/html-inline';
|
||||
export * from './plain-text/inline-delta';
|
||||
@@ -1,3 +1,4 @@
|
||||
import { htmlLinkElementToDeltaMatcher } from '@blocksuite/affine-inline-link';
|
||||
import {
|
||||
type HtmlAST,
|
||||
HtmlASTToDeltaExtension,
|
||||
@@ -136,67 +137,6 @@ export const htmlUnderlineElementToDeltaMatcher = HtmlASTToDeltaExtension({
|
||||
},
|
||||
});
|
||||
|
||||
export const htmlLinkElementToDeltaMatcher = HtmlASTToDeltaExtension({
|
||||
name: 'link-element',
|
||||
match: ast => isElement(ast) && ast.tagName === 'a',
|
||||
toDelta: (ast, context) => {
|
||||
if (!isElement(ast)) {
|
||||
return [];
|
||||
}
|
||||
const href = ast.properties?.href;
|
||||
if (typeof href !== 'string') {
|
||||
return [];
|
||||
}
|
||||
const { configs } = context;
|
||||
const baseUrl = configs.get('docLinkBaseUrl') ?? '';
|
||||
if (baseUrl && href.startsWith(baseUrl)) {
|
||||
const path = href.substring(baseUrl.length);
|
||||
// ^ - /{pageId}?mode={mode}&blockIds={blockIds}&elementIds={elementIds}
|
||||
const match = path.match(/^\/([^?]+)(\?.*)?$/);
|
||||
if (match) {
|
||||
const pageId = match?.[1];
|
||||
const search = match?.[2];
|
||||
const searchParams = search ? new URLSearchParams(search) : undefined;
|
||||
const mode = searchParams?.get('mode');
|
||||
const blockIds = searchParams?.get('blockIds')?.split(',');
|
||||
const elementIds = searchParams?.get('elementIds')?.split(',');
|
||||
|
||||
return [
|
||||
{
|
||||
insert: ' ',
|
||||
attributes: {
|
||||
reference: {
|
||||
type: 'LinkedPage',
|
||||
pageId,
|
||||
params: {
|
||||
mode:
|
||||
mode && ['edgeless', 'page'].includes(mode)
|
||||
? (mode as 'edgeless' | 'page')
|
||||
: undefined,
|
||||
blockIds,
|
||||
elementIds,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
}
|
||||
return ast.children.flatMap(child =>
|
||||
context.toDelta(child, { trim: false }).map(delta => {
|
||||
if (href.startsWith('http')) {
|
||||
delta.attributes = {
|
||||
...delta.attributes,
|
||||
link: href,
|
||||
};
|
||||
return delta;
|
||||
}
|
||||
return delta;
|
||||
})
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
export const htmlMarkElementToDeltaMatcher = HtmlASTToDeltaExtension({
|
||||
name: 'mark-element',
|
||||
match: ast => isElement(ast) && ast.tagName === 'mark',
|
||||
@@ -1,8 +1,7 @@
|
||||
import { linkDeltaToHtmlAdapterMatcher } from '@blocksuite/affine-inline-link';
|
||||
import { referenceDeltaToHtmlAdapterMatcher } from '@blocksuite/affine-inline-reference';
|
||||
import type { InlineHtmlAST } from '@blocksuite/affine-shared/adapters';
|
||||
import {
|
||||
AdapterTextUtils,
|
||||
InlineDeltaToHtmlAdapterExtension,
|
||||
} from '@blocksuite/affine-shared/adapters';
|
||||
import { InlineDeltaToHtmlAdapterExtension } from '@blocksuite/affine-shared/adapters';
|
||||
import { ThemeProvider } from '@blocksuite/affine-shared/services';
|
||||
|
||||
export const boldDeltaToHtmlAdapterMatcher = InlineDeltaToHtmlAdapterExtension({
|
||||
@@ -74,66 +73,6 @@ export const underlineDeltaToHtmlAdapterMatcher =
|
||||
},
|
||||
});
|
||||
|
||||
export const referenceDeltaToHtmlAdapterMatcher =
|
||||
InlineDeltaToHtmlAdapterExtension({
|
||||
name: 'reference',
|
||||
match: delta => !!delta.attributes?.reference,
|
||||
toAST: (delta, context) => {
|
||||
let hast: InlineHtmlAST = {
|
||||
type: 'text',
|
||||
value: delta.insert,
|
||||
};
|
||||
const reference = delta.attributes?.reference;
|
||||
if (!reference) {
|
||||
return hast;
|
||||
}
|
||||
|
||||
const { configs } = context;
|
||||
const title = configs.get(`title:${reference.pageId}`);
|
||||
const url = AdapterTextUtils.generateDocUrl(
|
||||
configs.get('docLinkBaseUrl') ?? '',
|
||||
String(reference.pageId),
|
||||
reference.params ?? Object.create(null)
|
||||
);
|
||||
if (title) {
|
||||
hast.value = title;
|
||||
}
|
||||
hast = {
|
||||
type: 'element',
|
||||
tagName: 'a',
|
||||
properties: {
|
||||
href: url,
|
||||
},
|
||||
children: [hast],
|
||||
};
|
||||
|
||||
return hast;
|
||||
},
|
||||
});
|
||||
|
||||
export const linkDeltaToHtmlAdapterMatcher = InlineDeltaToHtmlAdapterExtension({
|
||||
name: 'link',
|
||||
match: delta => !!delta.attributes?.link,
|
||||
toAST: (delta, _) => {
|
||||
const hast: InlineHtmlAST = {
|
||||
type: 'text',
|
||||
value: delta.insert,
|
||||
};
|
||||
const link = delta.attributes?.link;
|
||||
if (!link) {
|
||||
return hast;
|
||||
}
|
||||
return {
|
||||
type: 'element',
|
||||
tagName: 'a',
|
||||
properties: {
|
||||
href: link,
|
||||
},
|
||||
children: [hast],
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export const highlightBackgroundDeltaToHtmlAdapterMatcher =
|
||||
InlineDeltaToHtmlAdapterExtension({
|
||||
name: 'highlight-background',
|
||||
@@ -1,5 +1,6 @@
|
||||
import { linkDeltaToMarkdownAdapterMatcher } from '@blocksuite/affine-inline-link';
|
||||
import { referenceDeltaToMarkdownAdapterMatcher } from '@blocksuite/affine-inline-reference';
|
||||
import {
|
||||
AdapterTextUtils,
|
||||
FOOTNOTE_DEFINITION_PREFIX,
|
||||
InlineDeltaToMarkdownAdapterExtension,
|
||||
} from '@blocksuite/affine-shared/adapters';
|
||||
@@ -57,77 +58,6 @@ export const inlineCodeDeltaToMarkdownAdapterMatcher =
|
||||
}),
|
||||
});
|
||||
|
||||
export const referenceDeltaToMarkdownAdapterMatcher =
|
||||
InlineDeltaToMarkdownAdapterExtension({
|
||||
name: 'reference',
|
||||
match: delta => !!delta.attributes?.reference,
|
||||
toAST: (delta, context) => {
|
||||
let mdast: PhrasingContent = {
|
||||
type: 'text',
|
||||
value: delta.insert,
|
||||
};
|
||||
const reference = delta.attributes?.reference;
|
||||
if (!reference) {
|
||||
return mdast;
|
||||
}
|
||||
|
||||
const { configs } = context;
|
||||
const title = configs.get(`title:${reference.pageId}`);
|
||||
const params = reference.params ?? {};
|
||||
const url = AdapterTextUtils.generateDocUrl(
|
||||
configs.get('docLinkBaseUrl') ?? '',
|
||||
String(reference.pageId),
|
||||
params
|
||||
);
|
||||
mdast = {
|
||||
type: 'link',
|
||||
url,
|
||||
children: [
|
||||
{
|
||||
type: 'text',
|
||||
value: title ?? '',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
return mdast;
|
||||
},
|
||||
});
|
||||
|
||||
export const linkDeltaToMarkdownAdapterMatcher =
|
||||
InlineDeltaToMarkdownAdapterExtension({
|
||||
name: 'link',
|
||||
match: delta => !!delta.attributes?.link,
|
||||
toAST: (delta, context) => {
|
||||
const mdast: PhrasingContent = {
|
||||
type: 'text',
|
||||
value: delta.insert,
|
||||
};
|
||||
const link = delta.attributes?.link;
|
||||
if (!link) {
|
||||
return mdast;
|
||||
}
|
||||
|
||||
const { current: currentMdast } = context;
|
||||
if ('value' in currentMdast) {
|
||||
if (currentMdast.value === '') {
|
||||
return {
|
||||
type: 'text',
|
||||
value: link,
|
||||
};
|
||||
}
|
||||
if (mdast.value !== link) {
|
||||
return {
|
||||
type: 'link',
|
||||
url: link,
|
||||
children: [currentMdast],
|
||||
};
|
||||
}
|
||||
}
|
||||
return mdast;
|
||||
},
|
||||
});
|
||||
|
||||
export const latexDeltaToMarkdownAdapterMatcher =
|
||||
InlineDeltaToMarkdownAdapterExtension({
|
||||
name: 'inlineLatex',
|
||||
@@ -1,3 +1,4 @@
|
||||
import { markdownLinkToDeltaMatcher } from '@blocksuite/affine-inline-link';
|
||||
import { FootNoteReferenceParamsSchema } from '@blocksuite/affine-model';
|
||||
import {
|
||||
FOOTNOTE_DEFINITION_PREFIX,
|
||||
@@ -74,57 +75,6 @@ export const markdownDeleteToDeltaMatcher = MarkdownASTToDeltaExtension({
|
||||
},
|
||||
});
|
||||
|
||||
export const markdownLinkToDeltaMatcher = MarkdownASTToDeltaExtension({
|
||||
name: 'link',
|
||||
match: ast => ast.type === 'link',
|
||||
toDelta: (ast, context) => {
|
||||
if (!('children' in ast) || !('url' in ast)) {
|
||||
return [];
|
||||
}
|
||||
const { configs } = context;
|
||||
const baseUrl = configs.get('docLinkBaseUrl') ?? '';
|
||||
if (baseUrl && ast.url.startsWith(baseUrl)) {
|
||||
const path = ast.url.substring(baseUrl.length);
|
||||
// ^ - /{pageId}?mode={mode}&blockIds={blockIds}&elementIds={elementIds}
|
||||
const match = path.match(/^\/([^?]+)(\?.*)?$/);
|
||||
if (match) {
|
||||
const pageId = match?.[1];
|
||||
const search = match?.[2];
|
||||
const searchParams = search ? new URLSearchParams(search) : undefined;
|
||||
const mode = searchParams?.get('mode');
|
||||
const blockIds = searchParams?.get('blockIds')?.split(',');
|
||||
const elementIds = searchParams?.get('elementIds')?.split(',');
|
||||
|
||||
return [
|
||||
{
|
||||
insert: ' ',
|
||||
attributes: {
|
||||
reference: {
|
||||
type: 'LinkedPage',
|
||||
pageId,
|
||||
params: {
|
||||
mode:
|
||||
mode && ['edgeless', 'page'].includes(mode)
|
||||
? (mode as 'edgeless' | 'page')
|
||||
: undefined,
|
||||
blockIds,
|
||||
elementIds,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
}
|
||||
return ast.children.flatMap(child =>
|
||||
context.toDelta(child).map(delta => {
|
||||
delta.attributes = { ...delta.attributes, link: ast.url };
|
||||
return delta;
|
||||
})
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
export const markdownListToDeltaMatcher = MarkdownASTToDeltaExtension({
|
||||
name: 'list',
|
||||
match: ast => ast.type === 'list',
|
||||
@@ -1,3 +1,4 @@
|
||||
import { notionHtmlLinkElementToDeltaMatcher } from '@blocksuite/affine-inline-link';
|
||||
import {
|
||||
HastUtils,
|
||||
type HtmlAST,
|
||||
@@ -185,49 +186,6 @@ export const notionHtmlUnderlineElementToDeltaMatcher =
|
||||
},
|
||||
});
|
||||
|
||||
export const notionHtmlLinkElementToDeltaMatcher =
|
||||
NotionHtmlASTToDeltaExtension({
|
||||
name: 'link-element',
|
||||
match: ast => isElement(ast) && ast.tagName === 'a',
|
||||
toDelta: (ast, context) => {
|
||||
if (!isElement(ast)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const href = ast.properties?.href;
|
||||
if (typeof href !== 'string') {
|
||||
return [];
|
||||
}
|
||||
const { toDelta, options } = context;
|
||||
return ast.children.flatMap(child =>
|
||||
toDelta(child, options).map(delta => {
|
||||
if (options.pageMap) {
|
||||
const pageId = options.pageMap.get(decodeURIComponent(href));
|
||||
if (pageId) {
|
||||
delta.attributes = {
|
||||
...delta.attributes,
|
||||
reference: {
|
||||
type: 'LinkedPage',
|
||||
pageId,
|
||||
},
|
||||
};
|
||||
delta.insert = ' ';
|
||||
return delta;
|
||||
}
|
||||
}
|
||||
if (href.startsWith('http')) {
|
||||
delta.attributes = {
|
||||
...delta.attributes,
|
||||
link: href,
|
||||
};
|
||||
return delta;
|
||||
}
|
||||
return delta;
|
||||
})
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
export const notionHtmlMarkElementToDeltaMatcher =
|
||||
NotionHtmlASTToDeltaExtension({
|
||||
name: 'mark-element',
|
||||
@@ -0,0 +1,30 @@
|
||||
import { linkDeltaMarkdownAdapterMatch } from '@blocksuite/affine-inline-link';
|
||||
import { referenceDeltaMarkdownAdapterMatch } from '@blocksuite/affine-inline-reference';
|
||||
import {
|
||||
InlineDeltaToPlainTextAdapterExtension,
|
||||
type TextBuffer,
|
||||
} from '@blocksuite/affine-shared/adapters';
|
||||
import type { ExtensionType } from '@blocksuite/store';
|
||||
|
||||
export const latexDeltaMarkdownAdapterMatch =
|
||||
InlineDeltaToPlainTextAdapterExtension({
|
||||
name: 'inlineLatex',
|
||||
match: delta => !!delta.attributes?.latex,
|
||||
toAST: delta => {
|
||||
const node: TextBuffer = {
|
||||
content: delta.insert,
|
||||
};
|
||||
if (!delta.attributes?.latex) {
|
||||
return node;
|
||||
}
|
||||
return {
|
||||
content: delta.attributes?.latex,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export const InlineDeltaToPlainTextAdapterExtensions: ExtensionType[] = [
|
||||
referenceDeltaMarkdownAdapterMatch,
|
||||
linkDeltaMarkdownAdapterMatch,
|
||||
latexDeltaMarkdownAdapterMatch,
|
||||
];
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
StrikethroughIcon,
|
||||
UnderlineIcon,
|
||||
} from '@blocksuite/affine-components/icons';
|
||||
import { toggleLink } from '@blocksuite/affine-inline-link';
|
||||
import { type EditorHost, TextSelection } from '@blocksuite/block-std';
|
||||
import type { TemplateResult } from 'lit';
|
||||
|
||||
@@ -14,7 +15,6 @@ import {
|
||||
toggleBold,
|
||||
toggleCode,
|
||||
toggleItalic,
|
||||
toggleLink,
|
||||
toggleStrike,
|
||||
toggleUnderline,
|
||||
} from './text-style.js';
|
||||
@@ -1,3 +1,4 @@
|
||||
import { clearMarksOnDiscontinuousInput } from '@blocksuite/affine-rich-text';
|
||||
import { getSelectedBlocksCommand } from '@blocksuite/affine-shared/commands';
|
||||
import type { AffineTextAttributes } from '@blocksuite/affine-shared/types';
|
||||
import type { Command, TextSelection } from '@blocksuite/block-std';
|
||||
@@ -7,7 +8,6 @@ import {
|
||||
} from '@blocksuite/block-std/inline';
|
||||
|
||||
import { FORMAT_TEXT_SUPPORT_FLAVOURS } from './consts.js';
|
||||
import { clearMarksOnDiscontinuousInput } from './utils.js';
|
||||
|
||||
// for text selection
|
||||
export const formatTextCommand: Command<{
|
||||
@@ -16,13 +16,8 @@ export {
|
||||
toggleBold,
|
||||
toggleCode,
|
||||
toggleItalic,
|
||||
toggleLink,
|
||||
toggleStrike,
|
||||
toggleTextStyleCommand,
|
||||
toggleUnderline,
|
||||
} from './text-style.js';
|
||||
export {
|
||||
clearMarksOnDiscontinuousInput,
|
||||
insertContent,
|
||||
isFormatSupported,
|
||||
} from './utils.js';
|
||||
export { isFormatSupported } from './utils.js';
|
||||
@@ -4,12 +4,7 @@ import {
|
||||
} from '@blocksuite/affine-shared/commands';
|
||||
import type { AffineTextAttributes } from '@blocksuite/affine-shared/types';
|
||||
import type { Command } from '@blocksuite/block-std';
|
||||
import {
|
||||
INLINE_ROOT_ATTR,
|
||||
type InlineRootElement,
|
||||
} from '@blocksuite/block-std/inline';
|
||||
|
||||
import { toggleLinkPopup } from '../inline/index.js';
|
||||
import { formatBlockCommand } from './format-block.js';
|
||||
import { formatNativeCommand } from './format-native.js';
|
||||
import { formatTextCommand } from './format-text.js';
|
||||
@@ -71,40 +66,6 @@ export const toggleUnderline = toggleTextStyleCommandWrapper('underline');
|
||||
export const toggleStrike = toggleTextStyleCommandWrapper('strike');
|
||||
export const toggleCode = toggleTextStyleCommandWrapper('code');
|
||||
|
||||
export const toggleLink: Command = (ctx, next) => {
|
||||
const selection = document.getSelection();
|
||||
if (!selection || selection.rangeCount === 0) return false;
|
||||
|
||||
const range = selection.getRangeAt(0);
|
||||
if (range.collapsed) return false;
|
||||
const inlineRoot = range.startContainer.parentElement?.closest<
|
||||
InlineRootElement<AffineTextAttributes>
|
||||
>(`[${INLINE_ROOT_ATTR}]`);
|
||||
if (!inlineRoot) return false;
|
||||
|
||||
const inlineEditor = inlineRoot.inlineEditor;
|
||||
const targetInlineRange = inlineEditor.getInlineRange();
|
||||
|
||||
if (!targetInlineRange || targetInlineRange.length === 0) return false;
|
||||
|
||||
const format = inlineEditor.getFormat(targetInlineRange);
|
||||
if (format.link) {
|
||||
inlineEditor.formatText(targetInlineRange, { link: null });
|
||||
return next();
|
||||
}
|
||||
|
||||
const abortController = new AbortController();
|
||||
const popup = toggleLinkPopup(
|
||||
ctx.std,
|
||||
'create',
|
||||
inlineEditor,
|
||||
targetInlineRange,
|
||||
abortController
|
||||
);
|
||||
abortController.signal.addEventListener('abort', () => popup.remove());
|
||||
return next();
|
||||
};
|
||||
|
||||
export const getTextStyle: Command<{}, { textStyle: AffineTextAttributes }> = (
|
||||
ctx,
|
||||
next
|
||||
@@ -3,11 +3,13 @@ import {
|
||||
getSelectedBlocksCommand,
|
||||
getTextSelectionCommand,
|
||||
} from '@blocksuite/affine-shared/commands';
|
||||
import type { AffineTextAttributes } from '@blocksuite/affine-shared/types';
|
||||
import type {
|
||||
AffineInlineEditor,
|
||||
AffineTextAttributes,
|
||||
} from '@blocksuite/affine-shared/types';
|
||||
import {
|
||||
BLOCK_ID_ATTR,
|
||||
type BlockComponent,
|
||||
type BlockStdScope,
|
||||
type Chain,
|
||||
type InitCommandCtx,
|
||||
} from '@blocksuite/block-std';
|
||||
@@ -17,11 +19,7 @@ import {
|
||||
type InlineRange,
|
||||
type InlineRootElement,
|
||||
} from '@blocksuite/block-std/inline';
|
||||
import type { BlockModel } from '@blocksuite/store';
|
||||
import { effect } from '@preact/signals-core';
|
||||
|
||||
import { getInlineEditorByModel } from '../dom.js';
|
||||
import type { AffineInlineEditor } from '../inline/index.js';
|
||||
import {
|
||||
FORMAT_BLOCK_SUPPORT_FLAVOURS,
|
||||
FORMAT_NATIVE_SUPPORT_FLAVOURS,
|
||||
@@ -209,50 +207,3 @@ export function isFormatSupported(chain: Chain<InitCommandCtx>) {
|
||||
(_type, inlineEditors) => inlineEditors.length > 0
|
||||
);
|
||||
}
|
||||
|
||||
// When the user selects a range, check if it matches the previous selection.
|
||||
// If it does, apply the marks from the previous selection.
|
||||
// If it does not, remove the marks from the previous selection.
|
||||
export function clearMarksOnDiscontinuousInput(
|
||||
inlineEditor: InlineEditor
|
||||
): void {
|
||||
let inlineRange = inlineEditor.getInlineRange();
|
||||
const dispose = effect(() => {
|
||||
const r = inlineEditor.inlineRange$.value;
|
||||
if (
|
||||
inlineRange &&
|
||||
r &&
|
||||
(inlineRange.index === r.index || inlineRange.index === r.index + 1)
|
||||
) {
|
||||
inlineRange = r;
|
||||
} else {
|
||||
inlineEditor.resetMarks();
|
||||
dispose();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function insertContent(
|
||||
std: BlockStdScope,
|
||||
model: BlockModel,
|
||||
text: string,
|
||||
attributes?: AffineTextAttributes
|
||||
) {
|
||||
if (!model.text) {
|
||||
console.error("Can't insert text! Text not found");
|
||||
return;
|
||||
}
|
||||
const inlineEditor = getInlineEditorByModel(std, model);
|
||||
if (!inlineEditor) {
|
||||
console.error("Can't insert text! Inline editor not found");
|
||||
return;
|
||||
}
|
||||
const inlineRange = inlineEditor.getInlineRange();
|
||||
const index = inlineRange ? inlineRange.index : model.text.length;
|
||||
model.text.insert(text, index, attributes as Record<string, unknown>);
|
||||
// Update the caret to the end of the inserted text
|
||||
inlineEditor.setInlineRange({
|
||||
index: index + text.length,
|
||||
length: 0,
|
||||
});
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import { LinkInlineSpecExtension } from '@blocksuite/affine-inline-link';
|
||||
import { ReferenceInlineSpecExtension } from '@blocksuite/affine-inline-reference';
|
||||
import type { AffineTextAttributes } from '@blocksuite/affine-shared/types';
|
||||
import { InlineManagerExtension } from '@blocksuite/block-std/inline';
|
||||
import type { ExtensionType } from '@blocksuite/store';
|
||||
|
||||
import {
|
||||
BackgroundInlineSpecExtension,
|
||||
@@ -8,17 +9,11 @@ import {
|
||||
CodeInlineSpecExtension,
|
||||
ColorInlineSpecExtension,
|
||||
FootNoteInlineSpecExtension,
|
||||
InlineAdapterExtensions,
|
||||
InlineSpecExtensions,
|
||||
ItalicInlineSpecExtension,
|
||||
LatexInlineSpecExtension,
|
||||
LinkInlineSpecExtension,
|
||||
MarkdownExtensions,
|
||||
ReferenceInlineSpecExtension,
|
||||
StrikeInlineSpecExtension,
|
||||
UnderlineInlineSpecExtension,
|
||||
} from './inline/index.js';
|
||||
import { LatexEditorInlineManagerExtension } from './inline/presets/nodes/latex-node/latex-editor-menu.js';
|
||||
} from './inline-spec';
|
||||
|
||||
export const DefaultInlineManagerExtension =
|
||||
InlineManagerExtension<AffineTextAttributes>({
|
||||
@@ -37,11 +32,3 @@ export const DefaultInlineManagerExtension =
|
||||
FootNoteInlineSpecExtension.identifier,
|
||||
],
|
||||
});
|
||||
|
||||
export const RichTextExtensions: ExtensionType[] = [
|
||||
InlineSpecExtensions,
|
||||
MarkdownExtensions,
|
||||
LatexEditorInlineManagerExtension,
|
||||
DefaultInlineManagerExtension,
|
||||
InlineAdapterExtensions,
|
||||
].flat();
|
||||
29
blocksuite/affine/inlines/preset/src/effects.ts
Normal file
29
blocksuite/affine/inlines/preset/src/effects.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { AffineText } from './nodes/affine-text';
|
||||
import { AffineFootnoteNode } from './nodes/footnote-node/footnote-node';
|
||||
import { FootNotePopup } from './nodes/footnote-node/footnote-popup';
|
||||
import { FootNotePopupChip } from './nodes/footnote-node/footnote-popup-chip';
|
||||
import { LatexEditorMenu } from './nodes/latex-node/latex-editor-menu';
|
||||
import { LatexEditorUnit } from './nodes/latex-node/latex-editor-unit';
|
||||
import { AffineLatexNode } from './nodes/latex-node/latex-node';
|
||||
|
||||
export function effects() {
|
||||
customElements.define('affine-text', AffineText);
|
||||
customElements.define('latex-editor-menu', LatexEditorMenu);
|
||||
customElements.define('latex-editor-unit', LatexEditorUnit);
|
||||
customElements.define('affine-latex-node', AffineLatexNode);
|
||||
customElements.define('affine-footnote-node', AffineFootnoteNode);
|
||||
customElements.define('footnote-popup', FootNotePopup);
|
||||
customElements.define('footnote-popup-chip', FootNotePopupChip);
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
'affine-latex-node': AffineLatexNode;
|
||||
'affine-footnote-node': AffineFootnoteNode;
|
||||
'footnote-popup': FootNotePopup;
|
||||
'footnote-popup-chip': FootNotePopupChip;
|
||||
'affine-text': AffineText;
|
||||
'latex-editor-unit': LatexEditorUnit;
|
||||
'latex-editor-menu': LatexEditorMenu;
|
||||
}
|
||||
}
|
||||
13
blocksuite/affine/inlines/preset/src/exts.ts
Normal file
13
blocksuite/affine/inlines/preset/src/exts.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { InlineAdapterExtensions } from './adapters/extensions';
|
||||
import { DefaultInlineManagerExtension } from './default-inline-manager';
|
||||
import { InlineSpecExtensions } from './inline-spec';
|
||||
import { MarkdownExtensions } from './markdown';
|
||||
import { LatexEditorInlineManagerExtension } from './nodes/latex-node/latex-editor-menu';
|
||||
|
||||
export const inlinePresetExtensions = [
|
||||
DefaultInlineManagerExtension,
|
||||
...MarkdownExtensions,
|
||||
LatexEditorInlineManagerExtension,
|
||||
...InlineSpecExtensions,
|
||||
...InlineAdapterExtensions,
|
||||
];
|
||||
12
blocksuite/affine/inlines/preset/src/index.ts
Normal file
12
blocksuite/affine/inlines/preset/src/index.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import type * as RichTextEffects from '@blocksuite/affine-rich-text/effects';
|
||||
|
||||
declare type _GLOBAL_ = typeof RichTextEffects;
|
||||
|
||||
export * from './adapters/extensions';
|
||||
export * from './command';
|
||||
export * from './default-inline-manager';
|
||||
export * from './exts';
|
||||
export * from './inline-spec';
|
||||
export * from './keymap';
|
||||
export * from './markdown';
|
||||
export * from './nodes';
|
||||
@@ -1,24 +1,18 @@
|
||||
import { FootNoteSchema, ReferenceInfoSchema } from '@blocksuite/affine-model';
|
||||
import { ToolbarModuleExtension } from '@blocksuite/affine-shared/services';
|
||||
import { inlineLinkExtensions } from '@blocksuite/affine-inline-link';
|
||||
import { inlineReferenceExtensions } from '@blocksuite/affine-inline-reference';
|
||||
import { FootNoteSchema } from '@blocksuite/affine-model';
|
||||
import type { AffineTextAttributes } from '@blocksuite/affine-shared/types';
|
||||
import { BlockFlavourIdentifier, StdIdentifier } from '@blocksuite/block-std';
|
||||
import { StdIdentifier } from '@blocksuite/block-std';
|
||||
import {
|
||||
type InlineEditor,
|
||||
type InlineRootElement,
|
||||
InlineSpecExtension,
|
||||
} from '@blocksuite/block-std/inline';
|
||||
import type { ExtensionType } from '@blocksuite/store';
|
||||
import { html } from 'lit';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { FootNoteNodeConfigIdentifier } from './nodes/footnote-node/footnote-config.js';
|
||||
import { builtinInlineLinkToolbarConfig } from './nodes/link-node/configs/toolbar.js';
|
||||
import { builtinInlineReferenceToolbarConfig } from './nodes/reference-node/configs/toolbar.js';
|
||||
import {
|
||||
ReferenceNodeConfigExtension,
|
||||
ReferenceNodeConfigProvider,
|
||||
} from './nodes/reference-node/reference-config.js';
|
||||
|
||||
export type AffineInlineEditor = InlineEditor<AffineTextAttributes>;
|
||||
export type AffineInlineRootElement = InlineRootElement<AffineTextAttributes>;
|
||||
|
||||
export const BoldInlineSpecExtension =
|
||||
@@ -126,65 +120,6 @@ export const LatexInlineSpecExtension =
|
||||
};
|
||||
});
|
||||
|
||||
export const ReferenceInlineSpecExtension =
|
||||
InlineSpecExtension<AffineTextAttributes>('reference', provider => {
|
||||
const std = provider.get(StdIdentifier);
|
||||
const configProvider = new ReferenceNodeConfigProvider(std);
|
||||
const config =
|
||||
provider.getOptional(ReferenceNodeConfigExtension.identifier) ?? {};
|
||||
if (config.customContent) {
|
||||
configProvider.setCustomContent(config.customContent);
|
||||
}
|
||||
if (config.interactable !== undefined) {
|
||||
configProvider.setInteractable(config.interactable);
|
||||
}
|
||||
if (config.hidePopup !== undefined) {
|
||||
configProvider.setHidePopup(config.hidePopup);
|
||||
}
|
||||
return {
|
||||
name: 'reference',
|
||||
schema: z
|
||||
.object({
|
||||
type: z.enum([
|
||||
// @deprecated Subpage is deprecated, use LinkedPage instead
|
||||
'Subpage',
|
||||
'LinkedPage',
|
||||
]),
|
||||
})
|
||||
.merge(ReferenceInfoSchema)
|
||||
.optional()
|
||||
.nullable()
|
||||
.catch(undefined),
|
||||
match: delta => {
|
||||
return !!delta.attributes?.reference;
|
||||
},
|
||||
renderer: ({ delta, selected }) => {
|
||||
return html`<affine-reference
|
||||
.std=${std}
|
||||
.delta=${delta}
|
||||
.selected=${selected}
|
||||
.config=${configProvider}
|
||||
></affine-reference>`;
|
||||
},
|
||||
embed: true,
|
||||
};
|
||||
});
|
||||
|
||||
export const LinkInlineSpecExtension =
|
||||
InlineSpecExtension<AffineTextAttributes>('link', provider => {
|
||||
const std = provider.get(StdIdentifier);
|
||||
return {
|
||||
name: 'link',
|
||||
schema: z.string().optional().nullable().catch(undefined),
|
||||
match: delta => {
|
||||
return !!delta.attributes?.link;
|
||||
},
|
||||
renderer: ({ delta }) => {
|
||||
return html`<affine-link .std=${std} .delta=${delta}></affine-link>`;
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
export const LatexEditorUnitSpecExtension =
|
||||
InlineSpecExtension<AffineTextAttributes>({
|
||||
name: 'latex-editor-unit',
|
||||
@@ -217,7 +152,7 @@ export const FootNoteInlineSpecExtension =
|
||||
};
|
||||
});
|
||||
|
||||
export const InlineSpecExtensions = [
|
||||
export const InlineSpecExtensions: ExtensionType[] = [
|
||||
BoldInlineSpecExtension,
|
||||
ItalicInlineSpecExtension,
|
||||
UnderlineInlineSpecExtension,
|
||||
@@ -226,18 +161,8 @@ export const InlineSpecExtensions = [
|
||||
BackgroundInlineSpecExtension,
|
||||
ColorInlineSpecExtension,
|
||||
LatexInlineSpecExtension,
|
||||
ReferenceInlineSpecExtension,
|
||||
LinkInlineSpecExtension,
|
||||
...inlineLinkExtensions,
|
||||
...inlineReferenceExtensions,
|
||||
LatexEditorUnitSpecExtension,
|
||||
FootNoteInlineSpecExtension,
|
||||
|
||||
ToolbarModuleExtension({
|
||||
id: BlockFlavourIdentifier('affine:reference'),
|
||||
config: builtinInlineReferenceToolbarConfig,
|
||||
}),
|
||||
|
||||
ToolbarModuleExtension({
|
||||
id: BlockFlavourIdentifier('affine:link'),
|
||||
config: builtinInlineLinkToolbarConfig,
|
||||
}),
|
||||
];
|
||||
@@ -1,3 +1,8 @@
|
||||
import {
|
||||
focusTextModel,
|
||||
getInlineEditorByModel,
|
||||
selectTextModel,
|
||||
} from '@blocksuite/affine-rich-text';
|
||||
import {
|
||||
BlockSelection,
|
||||
type BlockStdScope,
|
||||
@@ -5,12 +10,6 @@ import {
|
||||
type UIEventHandler,
|
||||
} from '@blocksuite/block-std';
|
||||
|
||||
import {
|
||||
focusTextModel,
|
||||
getInlineEditorByModel,
|
||||
selectTextModel,
|
||||
} from '../dom.js';
|
||||
|
||||
export const textCommonKeymap = (
|
||||
std: BlockStdScope
|
||||
): Record<string, UIEventHandler> => {
|
||||
@@ -1,4 +1,6 @@
|
||||
import { insertLinkedNode } from '@blocksuite/affine-inline-reference';
|
||||
import { CodeBlockModel } from '@blocksuite/affine-model';
|
||||
import { getInlineEditorByModel } from '@blocksuite/affine-rich-text';
|
||||
import { BRACKET_PAIRS } from '@blocksuite/affine-shared/consts';
|
||||
import { createDefaultDoc, matchModels } from '@blocksuite/affine-shared/utils';
|
||||
import {
|
||||
@@ -8,9 +10,6 @@ import {
|
||||
} from '@blocksuite/block-std';
|
||||
import type { InlineEditor } from '@blocksuite/block-std/inline';
|
||||
|
||||
import { getInlineEditorByModel } from '../dom.js';
|
||||
import { insertLinkedNode } from '../linked-node.js';
|
||||
|
||||
export const bracketKeymap = (
|
||||
std: BlockStdScope
|
||||
): Record<string, UIEventHandler> => {
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user