LoginSignup
0
0

More than 1 year has passed since last update.

特殊文字をLaTeXコマンドに変換するWebアプリをReact + Material UIで作ってみた

Posted at

はじめに

LaTeXで文章を書いていると、しばしば特殊文字(ラテン文字等)の文字化けが発生します。例えば、コピペしたBibTeXにヨーロッパ圏の著者がいたとか。一番安直な解決方法は特殊文字をLaTeXコマンドに変換することです。そこで、特殊文字をLaTeXコマンドへ変換するWebアプリ(DeepLShaper風)をReactとMaterial UIで作成してみました。

実装

今回は「新しい React アプリを作る」の「Create React App」を参考にして、シングルページアプリケーションを作成していきます。完成版は以下の通りです。
webapp.PNG

開発環境

Create React App」に

あなたのマシンに Node >= 14.0.0 及び npm >= 5.6 の環境が必要です。

と記載してあったので、nodeとnpmのバージョンを確認しておきます。

$ node -v
v16.8.0
$ npm -v
7.21.0

雛形の作成

プロジェクトを作成します。

npx create-react-app special-character-to-latex-cmd-app

今回はMaterial UIのコンポーネントを使用するため、そのインストールを行います。

cd special-character-to-latex-cmd-app
npm install @mui/material @emotion/react @emotion/styled

続いて、src下にcomponentsディレクトリを作成し、その下にApp.jsForm.jsLaTeXCmdTable.jsを作成します。(ディレクトリ構造は「Example Projects」の「Calculator」を参考にしています。)

src/
├── components
│   ├── App.js
│   ├── App.test.js
│   ├── Form.css
│   ├── Form.js
│   └── LatexCmdTable.js
├── index.css
├── index.js
├── latex-cmd.json
├── reportWebVitals.js
└── setupTests.js

Form.jsでは特殊文字をLaTeXコマンドへ変換するためのテキストフォームを提供するコンポーネントを、LaTeXCmdTable.jsでは特殊文字とLaTeXコマンドの対応表を表示するためのコンポーネントを定義しています。App.jsではForm.jsLaTeXCmdTable.jsをまとめる親コンポーネントを定義します。

latex-cmd.jsonには特殊文字とLaTeXコマンドの対応関係が記述されています。

latex-cmd(一部抜粋).json
{
    "à": "{\\` a}",
    "è": "{\\` e}",
    "ì": "{\\` i}",
    "ò": "{\\` o}",
    "ù": "{\\` u}",
    "À": "{\\` A}",
    "È": "{\\` E}",
}

続いて、編集が必要な各ファイルについて説明します。

index.js

index.jsはReactアプリを実行する際、一番最初に呼び出されるファイルです。ReactDOM.renderメソッドを用いて、<App>コンポーネントをindex.htmlid="root"へ出力しています。
ちなみに、<React.StrictMode>は子孫要素に対して付加的な検査をしたり、警告をするための機能だそうです。(参考:strict モード

src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './components/App';
import reportWebVitals from './reportWebVitals';

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
index(一部抜粋).html
<body>
  <noscript>You need to enable JavaScript to run this app.</noscript>
  <div id="root"></div>
</body>

App.js

App.jsでは、<Form><LatexCmdTable>の2つのコンポーネントを配置し、その間に<hr>を用いて線を引きます。

src/components/App.js
import React from 'react';
import Form from './Form';
import LatexCmdTable from './LatexCmdTable';

function App() {
  return (
    <div>
      <Form />
      <hr size="1" wifth="100%" color="gray"></hr>
      <LatexCmdTable />
    </div>
  );
}

export default App;

Form.js

Form.jsでは特殊文字をLaTeXコマンドへ変換するためのテキストフォームを作成します。見た目をかっこよくするために、ここではMaterial UIが提供するTextFieldコンポーネントを使用します。

import TextField from '@mui/material/TextField';

<Form>は関数コンポーネントを用いて定義します。LaTeXコマンドに変換された出力テキスト(outText)はuseStateフックを用いて関数内にstate変数として宣言します。

function Form() {
  const [outText, setOutText] = useState("");
   ...
}
export default Form;

<TextField>コンポーネントは入力フィールド用(name="input text")と出力フィールド用(name="output text")の2つ配置します。入力フィールドで入力値が変化したとき、コールバック関数handleChangeが呼び出されます。

<TextField 
  name="input field"
  onChange={handleChange}
/>

handleChangeでは、入力フィールド内の特殊文字をLaTeXコマンドに変換します。コールバック関数内では、更新された入力値はevent.target.value (string)からアクセスできます。
replaceメソッドを用いてevent.target.valueに含まれる特殊文字をLaTeXコマンドへ変換します。この時マッチした文字をすべて変換したいので、正規表現を用いています。(RegExpは正規表現オブジェクトです。)
最後に、setOutTextメソッドを用いて、変換後の値をoutTextにセットします。

const handleChange = (event) => {
  tmpText = event.target.value;
  Object.keys(latexCmdJson).forEach(function (key) {
    tmpText = tmpText.replace(RegExp(key, 'g'), latexCmdJson[key]);
  });
  setOutText(tmpText);
}

outTextの値は、出力フィールド(name="output text")の入力要素(value)にセットされます。また、InputPropsから<input>の属性を用いて編集不可に設定します。

<TextField 
  name="output field"
  value={outText} 
  InputProps={{
    readOnly: true,
  }}
/>

全体のコード

src/components/Form.js
import React, { useState } from 'react';
import TextField from '@mui/material/TextField';
import './Form.css';
import latexCmdJson from '../latex-cmd.json';


function Form() {
  const [outText, setOutText] = useState("");
  let tmpText = "";

  const handleChange = (event) => {
    tmpText = event.target.value;
    Object.keys(latexCmdJson).forEach(function (key) {
      tmpText = tmpText.replace(RegExp(key, 'g'), latexCmdJson[key]);
    });
    setOutText(tmpText);
  }

  return (
    <div>
      <div>
        <TextField 
          multiline 
          focused 
          className="textfield-large" 
          label="LaTeX (including special characters)"
          name="input field"
          variant="filled"
          rows={6}
          margin="normal"
          onChange={handleChange}/>
      </div>
      <div>
        <TextField 
          multiline 
          focused 
          className="textfield-large" 
          label="LaTeX (using escaped codes)"
          name="output field" 
          value={outText} 
          variant="filled"
          rows={6}
          margin="normal"
          InputProps={{
            readOnly: true,
          }}/>
      </div>
    </div>
  );
}

export default Form;
src/components/Form.css
.textfield-large {
  width: 100%;
}

LaTeXCmdTable.js

LaTeXCmdTable.jsでは特殊文字とLaTeXコマンドの対応表を表示するためのコンポーネントを定義します。表はMaterial UIの「Basic table」を参考に作成しました。

src/components/LaTeXCmdTable.js
import React from 'react';
import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
import TableCell from '@mui/material/TableCell';
import TableContainer from '@mui/material/TableContainer';
import TableHead from '@mui/material/TableHead';
import TableRow from '@mui/material/TableRow';
import Paper from '@mui/material/Paper';
import latexCmdJson from '../latex-cmd.json';


function createData(key, value){
  return { key, value };
};

let rows = [];

Object.keys(latexCmdJson).forEach(function (key) {
  rows.push(createData(key, latexCmdJson[key]));
});


function LatexCmdTable() {
  return (
    <div>
      <TableContainer component={Paper}>
        <Table sx={{ minWidth: 400 }} aria-label="simple table"s>
          <TableHead>
            <TableRow>
              <TableCell>Special characters</TableCell>
              <TableCell>LaTeX commands</TableCell>
            </TableRow>
          </TableHead>
          <TableBody>
            {rows.map((row) => (
              <TableRow key={row.key}>
                <TableCell>{row.key}</TableCell>
                <TableCell>{row.value}</TableCell>
              </TableRow>
            ))}
          </TableBody>
        </Table>
      </TableContainer>
    </div>
  );
}
export default LatexCmdTable;

完成品

実行方法

git clone https://github.com/yakiimo121/special-character-to-latex-cmd-app
cd special-character-to-latex-cmd-app
npm install
npm start

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0