背景
前回の投稿では、monaco-editorをスクリプトとして導入する話をしましたが、codemirrorを使用して、同じビジネス上の問題を解決することもできます:ユーザーはjsonを設定する必要があり、jsonに対してカスタムチェックサムを実行する必要があります。
codemirrorとjsonlintをダウンロード
npm i codemirror jsonlint-mod --save
レンダリング
ビジネスコード
import React, {
useEffect, useRef,
} from 'react';
import CodeMirror from 'codemirror';
import jsonlint from 'jsonlint-mod';
import PropTypes from 'prop-types';
// jsonlint その他のCSS
import 'codemirror/addon/lint/javascript-lint';
import 'codemirror/addon/edit/closebrackets';
import 'codemirror/addon/lint/lint.css';
import 'codemirror/addon/lint/lint';
import 'codemirror/addon/lint/json-lint';
// 折りたたみ可能なハイライト用のcssなど
import 'codemirror/addon/fold/foldgutter.css';
import 'codemirror/addon/fold/foldcode.js';
import 'codemirror/addon/fold/foldgutter.js';
import 'codemirror/addon/fold/xml-fold.js';
import 'codemirror/addon/fold/indent-fold.js';
import 'codemirror/addon/fold/brace-fold';
import 'codemirror/addon/fold/markdown-fold.js';
import 'codemirror/addon/fold/comment-fold.js';
import 'codemirror/addon/selection/active-line';
// merge 比較CSS
// import 'codemirror/addon/merge/merge';
import 'codemirror/lib/codemirror.css';
import 'codemirror/mode/javascript/javascript.js';
// テーマのCSS
import 'codemirror/theme/cobalt.css';
import 'codemirror/theme/3024-day.css';
import 'codemirror/theme/rubyblue.css';
// カスタム・スタイル
// import './index.scss';
window.jsonlint = jsonlint;
export default function EditPolicy(props) {
const editorRead = useRef();
const { policy, id, getEditorValue } = props;
useEffect(() => {
const codeReadContainer = document.querySelector(`#jsoneditor-read-component-${id}`);
const ctrlQ = 'ctrl + Q';
editorRead.current = CodeMirror.fromTextArea(codeReadContainer, {
extraKeys: {
Ctrl: 'autocomplete',
[ctrlQ]: cm => cm.foldCode(cm.getCursor()),
},
gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter', 'CodeMirror-lint-markers'],
lint: true,
line: true,
indentUnit: 2,
abSize: 2,
autoCloseBrackets: true,
mode: 'application/json',
lineNumbers: true,
readOnly: false,
theme: 'cobalt',
styleActiveLine: true,
lineWrapping: true,
foldGutter: true,
foldOptions: {
widget: (from, to) => {
let count = '';
let startToken = '{';
let endToken = '}';
const prevLine = editorRead.current.getLine(from.line);
if (prevLine.lastIndexOf('[') > prevLine.lastIndexOf('{')) {
startToken = '[';
endToken = ']';
}
// Get json content
const internal = editorRead.current.getRange(from, to);
const toParse = startToken + internal + endToken;
// Get key count
try {
const parsed = JSON.parse(toParse);
count = Object.keys(parsed).length;
} catch (e) {
//
}
return count ? `↤${count}↦` : '↔';
},
},
});
editorRead.current.setSize('auto', '550px');
}, [id]);
useEffect(() => {
editorRead.current.on('change', (codemirror) => {
if (getEditorValue) {
getEditorValue(codemirror.getValue());
}
});
}, [getEditorValue]);
useEffect(() => {
editorRead.current.setValue(policy);
}, [policy]);
return <textarea id={`jsoneditor-read-component-${id}`} />;
}
EditPolicy.propTypes = {
policy: PropTypes.string.isRequired,
id: PropTypes.string.isRequired,
getEditorValue: PropTypes.func,
};
EditPolicy.defaultProps = {
getEditorValue: () => {},
};