Home About Contact
lexical , React , Note Taking

簡単なエディタをつくる試み lexical を調べる(その6)

前回 Markdown Preview を追加したときに、bold や italic の マークアップは問題なくレンダリングできたのですが、 たとえば、リストアイテムのマークアップを入れると 意図通り作動しなくなっていました。

この問題を解決します。

initialConfig に nodes を追加

リストアイテムをレンダリングできるようにするには次のようにします。

src/Preview.js

import { ListNode, ListItemNode } from '@lexical/list';

...

function Preview( { textValue='' } ) {

  const initialConfig = {
    ...
    nodes: [
        ListNode,
        ListItemNode],
  };

これでリストアイテムはレンダリングできるようになります。 しかし、 たとえば見出しマークアップを入れると意図通りレンダリングされません。 結局、おもなマークアップ全部に対応したければ次のようにします。

src/Preview.js

import { HeadingNode, QuoteNode } from "@lexical/rich-text";
import { ListNode, ListItemNode } from '@lexical/list';
import { CodeHighlightNode, CodeNode } from "@lexical/code";

...

function Preview( { textValue='' } ) { 

  const initialConfig = {
    ...
    nodes: [
        HeadingNode,
        ListNode,
        ListItemNode,
        QuoteNode,
        CodeNode, CodeHighlightNode],
  };

これで見出し / リスト / クォート / コードブロック に対応できるようになりました。

テーブルのマークアップに対するレンダリング用のそれも用意されているようですが、試していません。

まとめ

完成した src/Preview.js 全体を掲載します。

import React from "react";
import {LexicalComposer} from '@lexical/react/LexicalComposer';
import {PlainTextPlugin} from '@lexical/react/LexicalPlainTextPlugin';
import {ContentEditable} from '@lexical/react/LexicalContentEditable';
import {useLexicalComposerContext} from '@lexical/react/LexicalComposerContext';
import LexicalErrorBoundary from '@lexical/react/LexicalErrorBoundary';

import { HeadingNode, QuoteNode } from "@lexical/rich-text";
import { ListNode, ListItemNode } from '@lexical/list';
import { CodeHighlightNode, CodeNode } from "@lexical/code";

import {
  $convertFromMarkdownString,
  TRANSFORMERS,
} from '@lexical/markdown';


const theme = {
  paragraph: 'preview-paragraph',
  code: "preview-code",
};

function onError(error) {
  console.error(error);
}

function UpdatePlugin({toTextValue}) {
  const [editor] = useLexicalComposerContext();

  editor.update(()=>{
    $convertFromMarkdownString(toTextValue(), TRANSFORMERS);
  });
}

function Preview( { textValue='' } ) {

  const initialConfig = {
    namespace: 'MyPreview',
    editable: false,
    theme,
    onError,
    editorState: () => $convertFromMarkdownString(textValue, TRANSFORMERS),
    nodes: [
        HeadingNode,
        ListNode,
        ListItemNode,
        QuoteNode,
        CodeNode, CodeHighlightNode],
  };

  return (
    <LexicalComposer initialConfig={initialConfig}>
      <PlainTextPlugin
        contentEditable={<ContentEditable style={{ outline: 'none' }} />}
        ErrorBoundary={LexicalErrorBoundary}
      />
      <UpdatePlugin toTextValue={()=>textValue} />
    </LexicalComposer>
  );
}

export default Preview;

補足)スタイルの指定

theme を設定することで、該当部分のクラス名を指定できます。

const theme = {
  paragraph: 'preview-paragraph',
  code: "preview-code",
};

このクラス名を指して CSS を設定すれば意図通りのスタイルを適用できます。