跳至正文
Wener Notes

editor.js

约 2 分钟阅读
  • 不支持拖拽
  • 不支持布局元素
  • undo、redo 有问题
  • 不支持 markdown
  • 不支持嵌套 block
  • 目前没有 mention 组件
  • 不支持快捷键,不支持 slash 命令

Notes

  • 区分 InlineBlock 和 Block
数据模型
{
  "time": 1550476186479,
  "version": "2.8.1",
  "blocks": [
    {
      "type": "header",
      "data": {
        "text": "With the header of course",
        "level": 2
      }
    },
    {
      "type": "paragraph",
      "data": {
        "text": "So what do we have?"
      }
    }
  ]
}
BlockPlugin.ts
export class MyBlock {
  get shortcut() {
    return 'CMD+M';
  }
  // 默认 Block
  static get isInline() {
    return false;
  }
  static get toolbox() {
    return {
      title: 'Image',
      icon: '<svg width="17" height="15" viewBox="0 0 336 276" xmlns="http://www.w3.org/2000/svg"><path d="M291 150V79c0-19-15-34-34-34H79c-19 0-34 15-34 34v42l67-44 81 72 56-29 42 30zm0 52l-43-30-56 30-81-67-66 39v23c0 19 15 34 34 34h178c17 0 31-13 34-29zM79 0h178c44 0 79 35 79 79v118c0 44-35 79-79 79H79c-44 0-79-35-79-79V79C0 35 35 0 79 0z"/></svg>',
    };
  }
  static get pasteConfig() {
    return {
      tags: ['IMG'],
      files: {
        mimeTypes: ['image/*'],
        extensions: ['gif', 'jpg', 'png'],
      },
      patterns: {
        image: /https?:\/\/\S+\.(gif|jpe?g|tiff|png)$/i,
      },
    };
  }
  static get sanitize() {
    return {
      url: false, // disallow HTML
      caption: {}, // only tags from Inline Toolbar
      mark: {
        class: 'cdx-marker',
      },
    };
  }
  constructor({ block, data, api, config }) {
    this.block = block;
    this.data = data;
    this.api = api;
    this.config = config;
  }
  render() {
    return document.createElement('input');
  }
  renderSettings() {
    return document.createElement('div');
  }
  save(blockContent) {
    return {
      url: blockContent.value,
    };
  }
  // 校验保存的数据
  validate(savedData) {
    if (!savedData.url.trim()) {
      return false;
    }

    return true;
  }
  onPaste(event) {
    switch (event.type) {
      case 'tag':
        const imgTag = event.detail.data;
        this._createImage(imgTag.src);
        break;
      case 'file':
        const file = event.detail.file;
        const reader = new FileReader();

        reader.onload = (loadEvent) => {
          this._createImage(loadEvent.target.result);
        };

        reader.readAsDataURL(file);
        break;
      case 'pattern':
        const src = event.detail.data;

        this._createImage(src);
        break;
    }
  }

  // inline

  surround(range) {}

  checkState(selection) {}
  renderActions() {}

  //
}

Plugins

bash
pnpm add @editorjs/{image,simple-image,link}
TypeScript
import Embed from '@editorjs/embed';
import Table from '@editorjs/table';
import Paragraph from '@editorjs/paragraph';
import List from '@editorjs/list';
import Warning from '@editorjs/warning';
import Code from '@editorjs/code';
import LinkTool from '@editorjs/link';
import Image from '@editorjs/image';
import Raw from '@editorjs/raw';
import Header from '@editorjs/header';
import Quote from '@editorjs/quote';
import Marker from '@editorjs/marker';
import CheckList from '@editorjs/checklist';
import Delimiter from '@editorjs/delimiter';
import InlineCode from '@editorjs/inline-code';
import SimpleImage from '@editorjs/simple-image';

export const EDITOR_JS_TOOLS = {
  // Paragraph 默认就有,除非需要替换
  // paragraph: Paragraph,
  embed: Embed,
  table: Table,
  list: List,
  warning: Warning,
  code: Code,
  linkTool: LinkTool,
  image: Image,
  raw: Raw,
  header: Header,
  quote: Quote,
  marker: Marker,
  checklist: CheckList,
  delimiter: Delimiter,
  inlineCode: InlineCode,
  simpleImage: SimpleImage,
};

关联信息

反向链接、本文链接的其他页面和外部资料。

反向链接

  • Editor Awesome
    笔记 · codex-team/editor.js

    推荐👍 Lexical, Tiptap, QuillJS · React 优先建议选择 Lexical,否则考虑 tiptap/prosemirror · prosemirror · 实现 Editor 的基础库 · tiptap · Hufe921/canvas-editor

参考资料

GitHub6 条
依赖包1 条
最近更新commit 017a4a6编辑