react-markdownとgraphviz-reactでフロー図作成
21:24
ReactでMarkdownアプリを作っています。今回はMarkdownでフロー図を描きたいと思いgraphviz-reactを導入しました。
前回の内容は以下を参照してください。
今回の手順は以下のとおりです。
graphviz-reactとreact-error-boundaryのインストール
graphviz-reactとreact-error-boundaryをインストールします。
前提として過去に紹介しているDocker環境を使います。
インストール前にdocker-composeを停止します。
docker-compose.ymlファイルがある場所で以下のコマンドを入力してください。
docker-compose down
インストールを行います。
docker-compose run --rm front sh -c "cd markdown-app && npm install graphviz-react react-error-boundary"
package.jsonに記載されていれば成功です。
project/
┗ front/
┣ Dockerfile
┗ src/
┗ markdown-app/
┗ package.json
以下のように記載されます。
・・・略・・・
"dependencies": {
"@emotion/react": "^11.9.0",
"@emotion/styled": "^11.8.1",
"@mui/icons-material": "^5.8.0",
"@mui/material": "^5.8.0",
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^13.2.0",
"@testing-library/user-event": "^13.5.0",
"@types/jest": "^27.5.1",
"@types/node": "^16.11.36",
"@types/react": "^18.0.9",
"@types/react-dom": "^18.0.4",
"axios": "^0.27.2",
"graphviz-react": "^1.2.0",
"react": "^18.1.0",
"react-dom": "^18.1.0",
"react-error-boundary": "^3.1.4",
"react-markdown": "^8.0.3",
"react-router-dom": "^6.3.0",
"react-scripts": "5.0.1",
"remark-gfm": "^3.0.1",
"typescript": "^4.6.4",
"web-vitals": "^2.1.4"
},
・・・略・・・
以上でインストールは終了です。
マークダウン表示テンプレートの変更
マークダウン表示テンプレート(ViewTemplate.tsx)の内容です。
import React, { FC, useState } from "react";
import remarkGfm from "remark-gfm";
import ReactMarkdown from "react-markdown";
import Graphviz from "graphviz-react";
import { Box, Container, ThemeProvider, Toolbar, CssBaseline } from "@mui/material";
import { MarkdownType } from "../../types/MarkdownType.type";
import { Theme } from "../uilibs/theme/Theme";
import { SubHeaderNavigation } from "../uilibs/organisms/SubHeaderNavigation";
import { HeaderNavigation } from "../uilibs/organisms/HeaderNavigation";
import { LeftNaviagtion } from "../uilibs/organisms/LeftNaviagtion";
import { ErrorBoundary } from "react-error-boundary";
interface Props {
markdown: MarkdownType;
setMarkdown: React.Dispatch<React.SetStateAction<MarkdownType>>;
editMode: boolean;
insertMode: boolean;
setInsertMode: React.Dispatch<React.SetStateAction<boolean>>;
onClickSwitchMode: (event: React.MouseEvent<HTMLButtonElement>) => void;
setUrlLocation: React.Dispatch<React.SetStateAction<string>>;
};
const ErrorFallback = () => {
return (
<div role="alert">
<pre>表示できません</pre>
</div>
)
}
export const ViewTemplate: FC<Props> = (props) => {
const { markdown, setMarkdown, editMode, insertMode, setInsertMode, onClickSwitchMode, setUrlLocation } = props;
return (
<ThemeProvider theme={Theme}>
<Box sx={{ display: "flex" }}>
<CssBaseline />
<HeaderNavigation />
<LeftNaviagtion setUrlLocation={setUrlLocation} />
<Box component="main" sx={{ flexGrow: 1 }}>
<Toolbar />
<SubHeaderNavigation markdown={markdown} setMarkdown={setMarkdown} editMode={editMode} insertMode={insertMode} setInsertMode={setInsertMode} onClickSwitchMode={onClickSwitchMode} />
<Container className="markdown-view" maxWidth="xl">
<ReactMarkdown
children={markdown.body}
remarkPlugins={[remarkGfm]}
components={{
code({ node, inline, className, children, ...props }) {
const match = /language-flow/.exec(className || '');
return match ? (
<ErrorBoundary FallbackComponent={ErrorFallback} >
<Graphviz dot={String(children)} />
</ErrorBoundary>
) : (
<code className={className} {...props}>
{children}
</code>
)
}
}}
/>
</Container>
</Box>
</Box>
</ThemeProvider>
);
};
マークダウン編集テンプレートの変更
マークダウン編集テンプレート(EditTemplate.tsx)の内容です。
import { ThemeProvider } from "@emotion/react";
import { Container, Toolbar } from "@mui/material";
import { Box } from "@mui/system";
import Graphviz from "graphviz-react";
import { FC, useEffect } from "react";
import { ErrorBoundary } from "react-error-boundary";
import ReactMarkdown from "react-markdown";
import remarkGfm from "remark-gfm";
import { MarkdownType } from "../../types/MarkdownType.type";
import { MarkdownEditTextFiled } from "../uilibs/atoms/MarkdownEditTextFiled";
import { HeaderNavigation } from "../uilibs/organisms/HeaderNavigation";
import { SubHeaderNavigation } from "../uilibs/organisms/SubHeaderNavigation";
import { Theme } from "../uilibs/theme/Theme";
interface Props {
markdown: MarkdownType;
setMarkdown: React.Dispatch<React.SetStateAction<MarkdownType>>;
editMode: boolean;
insertMode: boolean;
setInsertMode: React.Dispatch<React.SetStateAction<boolean>>;
onClickSwitchMode: (event: React.MouseEvent<HTMLButtonElement>) => void;
};
const ErrorFallback = () => {
return (
<div role="alert">
<p>Something went wrong:</p>
<pre>表示できません</pre>
</div>
)
}
export const EditTemplate: FC<Props> = (props) => {
const { markdown, setMarkdown, editMode, insertMode, setInsertMode, onClickSwitchMode } = props;
const StyleTemplateBox = { display: "flex", flexDirection: "column", height: "100vh" };
const StyleMainBox = { display: "flex", flexDirection: "row", height: "100vh", width: '100%' };
const StyleLeftBox = { height: "100vh", width: '50%', backgroundColor: Theme.palette.primary.main };
const StyleRightBox = { height: "100vh", width: '50%' };
const onChangeValue = (event: React.ChangeEvent<HTMLTextAreaElement>) => { setMarkdown({ url: markdown.url, title: markdown.title, body: event.target.value }); };
useEffect(() => {
}, [markdown.body]);
return (
<ThemeProvider theme={Theme}>
<Box sx={StyleTemplateBox}>
<HeaderNavigation />
<Toolbar />
<SubHeaderNavigation markdown={markdown} setMarkdown={setMarkdown} editMode={editMode} insertMode={insertMode} setInsertMode={setInsertMode} onClickSwitchMode={onClickSwitchMode} />
<Box sx={StyleMainBox}>
<Box sx={StyleLeftBox}>
<Container>
<MarkdownEditTextFiled markdown={markdown} onChangeValue={onChangeValue} />
</Container >
</Box>
<Box sx={StyleRightBox}>
<Container className="markdown-view" >
<ReactMarkdown
children={markdown.body}
remarkPlugins={[remarkGfm]}
components={{
code({ node, inline, className, children, ...props }) {
const match = /language-flow/.exec(className || '');
return match ? (
<ErrorBoundary FallbackComponent={ErrorFallback} >
<Graphviz dot={String(children)} />
</ErrorBoundary>
) : (
<code className={className} {...props}>
{children}
</code>
)
}
}}
/>
</Container >
</Box>
</Box>
</Box>
</ThemeProvider>
);
};
画面確認
docker-compose upを使って各コンテナを起動します。
docker-compose.ymlファイルがある場所で以下のコマンドを実行します。
docker-compose up
起動したら以下のURLをブラウザに入力します。
http://localhost:3000
以下ブラウザの表示です。
markdownページの表示モードです。
まとめ
今回はMarkdownでフロー図を書くために、graphviz-reactを導入しました。
0 件のコメント:
コメントを投稿
コメントをお待ちしています。