Skip to content

BlockSuite API Documentation / @blocksuite/affine-block-image

@blocksuite/affine-block-image

Classes

Extension

EdgelessClipboardImageConfig

Understanding Extensions

Extensions provide a way to extend the functionality of a system using dependency injection. They allow you to register services, implementations, and factories in the DI container, which can then be retrieved and used by different parts of the application.

Extensions are particularly useful for:

  • Registering different implementations for different types
  • Creating pluggable architecture where components can be added or removed
  • Managing dependencies between different parts of the application

Usage Example: Fruit Processing System

Let's consider a fruit processing system where different types of fruits need different processing methods. We'll show how to implement this using extensions.

Step 1: Define the interfaces

ts
interface FruitProcessor {
  process(fruit: Fruit): void;
}

interface Fruit {
  type: string;
  // other properties
}

Step 2: Create a service identifier

ts
import { createIdentifier } from '@blocksuite/global/di';

const FruitProcessorProvider = createIdentifier<FruitProcessor>('fruit-processor-provider');

Step 3: Create implementations

ts
class AppleProcessor implements FruitProcessor {
  process(fruit: Fruit): void {
    console.log('Slicing apple');
    // Apple-specific processing
  }
}

class BananaProcessor implements FruitProcessor {
  process(fruit: Fruit): void {
    console.log('Peeling banana');
    // Banana-specific processing
  }
}

Step 4: Create an extension factory

ts
const FruitProcessorExtension = (
  fruitType: string,
  implementation: new () => FruitProcessor
): ExtensionType => {
  return {
    setup: di => {
      di.addImpl(FruitProcessorProvider(fruitType), implementation);
    }
  };
};

Step 5: Create concrete extensions

ts
export const AppleProcessorExtension = FruitProcessorExtension('apple', AppleProcessor);
export const BananaProcessorExtension = FruitProcessorExtension('banana', BananaProcessor);

Step 6: Use the extensions

ts
import { Container } from '@blocksuite/global/di';

class FruitProcessingSystem {
  provider: ServiceProvider;

  constructor(extensions: ExtensionType[]) {
    const container = new Container();

    // Set up all extensions
    extensions.forEach(ext => ext.setup(container));

    // Create a provider from the container
    this.provider = container.provider();
  }

  processFruit(fruit: Fruit) {
    // Get the appropriate processor based on fruit type
    const processor = this.provider.get(FruitProcessorProvider(fruit.type));

    // Process the fruit
    processor.process(fruit);
  }
}

// Initialize the system with extensions
const system = new FruitProcessingSystem([
  AppleProcessorExtension,
  BananaProcessorExtension
]);

// Use the system
system.processFruit({ type: 'apple' });  // Output: Slicing apple
system.processFruit({ type: 'banana' }); // Output: Peeling banana

Note: We deliberately used a non-block specific example here. In BlockSuite, the extension pattern can be applied to any entity that can be configured by third parties, not just blocks. This includes different tools in the whiteboard, different column types in database blocks, and many other extensible components. The pattern remains the same regardless of what you're extending.

Extends
Constructors
Properties
key

readonly static key: "affine:image" = 'affine:image'

Overrides

EdgelessClipboardConfig.key

Accessors
Methods
createBlock()

createBlock(image): Promise<string | null>

Parameters
image

BlockSnapshot

Returns

Promise<string | null>

Overrides

EdgelessClipboardConfig.createBlock


ImageLayoutHandlerExtension

Understanding Extensions

Extensions provide a way to extend the functionality of a system using dependency injection. They allow you to register services, implementations, and factories in the DI container, which can then be retrieved and used by different parts of the application.

Extensions are particularly useful for:

  • Registering different implementations for different types
  • Creating pluggable architecture where components can be added or removed
  • Managing dependencies between different parts of the application

Usage Example: Fruit Processing System

Let's consider a fruit processing system where different types of fruits need different processing methods. We'll show how to implement this using extensions.

Step 1: Define the interfaces

ts
interface FruitProcessor {
  process(fruit: Fruit): void;
}

interface Fruit {
  type: string;
  // other properties
}

Step 2: Create a service identifier

ts
import { createIdentifier } from '@blocksuite/global/di';

const FruitProcessorProvider = createIdentifier<FruitProcessor>('fruit-processor-provider');

Step 3: Create implementations

ts
class AppleProcessor implements FruitProcessor {
  process(fruit: Fruit): void {
    console.log('Slicing apple');
    // Apple-specific processing
  }
}

class BananaProcessor implements FruitProcessor {
  process(fruit: Fruit): void {
    console.log('Peeling banana');
    // Banana-specific processing
  }
}

Step 4: Create an extension factory

ts
const FruitProcessorExtension = (
  fruitType: string,
  implementation: new () => FruitProcessor
): ExtensionType => {
  return {
    setup: di => {
      di.addImpl(FruitProcessorProvider(fruitType), implementation);
    }
  };
};

Step 5: Create concrete extensions

ts
export const AppleProcessorExtension = FruitProcessorExtension('apple', AppleProcessor);
export const BananaProcessorExtension = FruitProcessorExtension('banana', BananaProcessor);

Step 6: Use the extensions

ts
import { Container } from '@blocksuite/global/di';

class FruitProcessingSystem {
  provider: ServiceProvider;

  constructor(extensions: ExtensionType[]) {
    const container = new Container();

    // Set up all extensions
    extensions.forEach(ext => ext.setup(container));

    // Create a provider from the container
    this.provider = container.provider();
  }

  processFruit(fruit: Fruit) {
    // Get the appropriate processor based on fruit type
    const processor = this.provider.get(FruitProcessorProvider(fruit.type));

    // Process the fruit
    processor.process(fruit);
  }
}

// Initialize the system with extensions
const system = new FruitProcessingSystem([
  AppleProcessorExtension,
  BananaProcessorExtension
]);

// Use the system
system.processFruit({ type: 'apple' });  // Output: Slicing apple
system.processFruit({ type: 'banana' }); // Output: Peeling banana

Note: We deliberately used a non-block specific example here. In BlockSuite, the extension pattern can be applied to any entity that can be configured by third parties, not just blocks. This includes different tools in the whiteboard, different column types in database blocks, and many other extensible components. The pattern remains the same regardless of what you're extending.

Extends
Constructors
Properties
blockType

readonly blockType: "affine:image" = 'affine:image'

Overrides

BlockLayoutHandlerExtension.blockType

Methods
calculateBound()

calculateBound(layout): object

Parameters
layout

ImageLayout

Returns

object

rect

rect: Rect

subRects

subRects: Rect[]

Overrides

BlockLayoutHandlerExtension.calculateBound

queryLayout()

queryLayout(model, host, viewportRecord): ImageLayout | null

Parameters
model

BlockModel

host

EditorHost

viewportRecord

ViewportRecord

Returns

ImageLayout | null

Overrides

BlockLayoutHandlerExtension.queryLayout

setup()

static setup(di): void

Parameters
di

Container

Returns

void

Overrides

BlockLayoutHandlerExtension.setup

Other

ImageBlockComponent

Extends
Constructors
Other
resizeable$

resizeable$: ReadonlySignal<boolean>

resourceController

resourceController: ResourceController

blobUrl
Get Signature

get blobUrl(): string | null

Returns

string | null

blockContainerStyles
Overrides

CaptionedBlockComponent.blockContainerStyles

hoverableContainer
isCommentHighlighted
Get Signature

get isCommentHighlighted(): boolean

Returns

boolean

resizableImg
Get Signature

get resizableImg(): HTMLElement | undefined

Returns

HTMLElement | undefined

useCaptionEditor
Overrides

CaptionedBlockComponent.useCaptionEditor

useZeroWidth
Overrides

CaptionedBlockComponent.useZeroWidth

connectedCallback()

connectedCallback(): void

Returns

void

Overrides

CaptionedBlockComponent.connectedCallback

convertToCardView()

convertToCardView(): void

Returns

void

copy()

copy(): void

Returns

void

download()

download(): void

Returns

void

refreshData()

refreshData(): void

Returns

void

renderBlock()

renderBlock(): TemplateResult<1>

Returns

TemplateResult<1>

Overrides

CaptionedBlockComponent.renderBlock

attributes
controllers
dev-mode
lifecycle
properties
rendering
styles
updates
firstUpdated()

firstUpdated(): void

Invoked when the element is first updated. Implement to perform one time work on the element after update.

ts
firstUpdated() {
  this.renderRoot.getElementById('my-text-area').focus();
}

Setting properties inside this method will trigger the element to update again after this update cycle completes.

Returns

void

Overrides

CaptionedBlockComponent.firstUpdated


ImageEdgelessBlockComponent

Extends
Constructors
Other
resourceController

resourceController: ResourceController

blobUrl
Get Signature

get blobUrl(): string | null

Returns

string | null

captionEditor
resizableImg
connectedCallback()

connectedCallback(): void

Returns

void

Overrides

GfxBlockComponent.connectedCallback

convertToCardView()

convertToCardView(): void

Returns

void

copy()

copy(): void

Returns

void

disconnectedCallback()

disconnectedCallback(): void

Returns

void

Overrides

GfxBlockComponent.disconnectedCallback

download()

download(): void

Returns

void

refreshData()

refreshData(): void

Returns

void

renderGfxBlock()

renderGfxBlock(): TemplateResult<1>

Returns

TemplateResult<1>

Overrides

GfxBlockComponent.renderGfxBlock

attributes
controllers
dev-mode
properties
rendering
styles
styles

static styles: CSSResult

Array of styles to apply to the element. The styles should be defined using the css tag function, via constructible stylesheets, or imported from native CSS module scripts.

Note on Content Security Policy:

Element styles are implemented with <style> tags when the browser doesn't support adopted StyleSheets. To use such <style> tags with the style-src CSP directive, the style-src value must either include 'unsafe-inline' or nonce-<base64-value> with <base64-value> replaced be a server-generated nonce.

To provide a nonce to use on generated <style> elements, set window.litNonce to a server-generated nonce in your page's HTML, before loading application code:

html
<script>
  // Generated and unique per request:
  window.litNonce = 'a1b2c3d4';
</script>
Nocollapse
Overrides

GfxBlockComponent.styles

updates

ImageSelection

Extends
Constructors
Properties
group

static group: string

Overrides

BaseSelection.group

type

static type: string

Overrides

BaseSelection.type

Accessors
Methods
equals()

equals(other): boolean

Parameters
other

BaseSelection

Returns

boolean

Overrides

BaseSelection.equals

toJSON()

toJSON(): Record<string, unknown>

Returns

Record<string, unknown>

Overrides

BaseSelection.toJSON

fromJSON()

static fromJSON(json): ImageSelection

Parameters
json

Record<string, unknown>

Returns

ImageSelection

Overrides

BaseSelection.fromJSON

Interfaces

ImageLayout

Extends

Indexable

[key: string]: unknown

Properties

rect

rect: object

h

h: number

w

w: number

x

x: number

y

y: number

Overrides

BlockLayout.rect

type

type: "affine:image"

Overrides

BlockLayout.type

Variables

ImageBlockHtmlAdapterExtension

const ImageBlockHtmlAdapterExtension: ExtensionType & object

Type Declaration

identifier

identifier: ServiceIdentifier<BlockHtmlAdapterMatcher>


imageBlockHtmlAdapterMatcher

const imageBlockHtmlAdapterMatcher: BlockHtmlAdapterMatcher


ImageBlockMarkdownAdapterExtension

const ImageBlockMarkdownAdapterExtension: ExtensionType & object

Type Declaration

identifier

identifier: ServiceIdentifier<BlockMarkdownAdapterMatcher>


imageBlockMarkdownAdapterMatcher

const imageBlockMarkdownAdapterMatcher: BlockMarkdownAdapterMatcher


ImageBlockNotionHtmlAdapterExtension

const ImageBlockNotionHtmlAdapterExtension: ExtensionType & object

Type Declaration

identifier

identifier: ServiceIdentifier<BlockNotionHtmlAdapterMatcher>


imageBlockNotionHtmlAdapterMatcher

const imageBlockNotionHtmlAdapterMatcher: BlockNotionHtmlAdapterMatcher


ImageBlockSpec

const ImageBlockSpec: ExtensionType[]


ImageDropOption

const ImageDropOption: ExtensionType


ImageEdgelessBlockInteraction

const ImageEdgelessBlockInteraction: ExtensionType


ImageLayoutPainterExtension

const ImageLayoutPainterExtension: ExtensionType


insertImagesCommand

const insertImagesCommand: Command<{ placement?: "after" | "before"; removeEmptyLine?: boolean; selectedModels?: BlockModel[]; }, { insertedImageIds: Promise<string[]>; }>

Functions

addImages()

addImages(std, files, options): Promise<string[]>

Parameters

std

BlockStdScope

files

File[]

options
maxWidth?

number

point?

IVec

shouldTransformPoint?

boolean

Returns

Promise<string[]>


addSiblingImageBlocks()

addSiblingImageBlocks(std, files, targetModel, placement): Promise<string[]>

Parameters

std

BlockStdScope

files

File[]

targetModel

BlockModel

placement

"after" | "before"

Returns

Promise<string[]>


downloadImageBlob()

downloadImageBlob(block): Promise<void>

Parameters

block

ImageEdgelessBlockComponent | ImageBlockComponent

Returns

Promise<void>