@readable-js/react-codemirror
Version:
React component for ReadableJS
122 lines • 5.37 kB
JavaScript
import React, { useCallback, useEffect, useRef } from 'react';
import { generateCallStack } from '@readable-js/core';
import { basicSetup, EditorState, EditorView } from '@codemirror/basic-setup';
import { javascript } from '@codemirror/lang-javascript';
import { Compartment } from "@codemirror/state";
import { readablePlugin } from './codemirror-plugin/readable-plugin';
import { linter } from "@codemirror/lint";
import { syntaxTree } from '@codemirror/language';
function stateToCode(state) {
// that won't be performant on large files, but that is not the purpose of readable-js
return Array.from(state.doc.iterLines(1, state.doc.lines + 1)).join('\n');
}
function _ReadableEditor(p) {
var _a;
const editorParentRef = useRef(null);
const readableCompartment = useRef(new Compartment());
const generated = useRef();
const editor = useRef(null);
const $range = useRef(null);
const $minValue = useRef(null);
const $maxValue = useRef(null);
const $currentValue = useRef(null);
const error = useRef(null);
useEffect(() => {
editor.current = new EditorView({
state: EditorState.create({
extensions: [
basicSetup,
javascript(),
readableCompartment.current.of([readablePlugin(getUpdatedCallStack, 0)]),
linter(lintError, { delay: 250 })
],
doc: p.initialCode
}),
parent: editorParentRef.current,
dispatch: (...e) => {
editor.current.update(e);
},
});
return () => {
editor.current.destroy();
};
}, []);
function lintError(view) {
var _a;
const diagnostics = [];
syntaxTree(view.state).iterate({
enter: (type) => {
console.log("typeof error.current! === 'string'");
console.log(error.current);
console.log(typeof error.current);
if (error.current
&& typeof error.current.index === 'number'
&& type.from >= error.current.index
&& error.current.index < type.to) {
diagnostics.push({
from: type.from,
to: type.to,
severity: "error",
message: error.current.description,
});
}
},
});
console.log(view.state.doc.length);
// like undeclared function at root error
if (error.current) {
const str = (_a = error.current.message) !== null && _a !== void 0 ? _a : error.current;
diagnostics.push({
from: 0,
to: view.state.doc.length,
severity: "error",
message: str,
});
}
return diagnostics;
}
function getUpdatedCallStack(view, skipEvaluation) {
if (!skipEvaluation) {
generated.current = generateCallStack(stateToCode(view.state));
}
if (!generated.current.error) {
updateSlider(generated.current.calls.length);
error.current = null;
}
else {
console.log(generated.current.error);
error.current = generated.current.error;
}
return generated.current.calls;
}
function updateSlider(length) {
$range.current.setAttribute('min', '0');
$range.current.setAttribute('max', (length - 1) + '');
$range.current.setAttribute('value', Math.min(parseInt($range.current.value), length - 1) + '');
$minValue.current.innerText = '1';
$maxValue.current.innerText = length + '';
$currentValue.current.innerText = (Math.min(parseInt($range.current.value), length - 1) + 1) + '';
}
const onInput = useCallback((e) => {
// The only way to tell the plugin to update, because external data has changed ?
editor.current.dispatch({
effects: readableCompartment.current.reconfigure([
readablePlugin(getUpdatedCallStack, e.target.value, true)
])
});
}, []);
return (React.createElement("div", null,
React.createElement("div", { className: "slide-container" },
React.createElement("div", null,
"Current step: ",
React.createElement("span", { className: "current-value", ref: $currentValue })),
React.createElement("span", { className: "min-value", ref: $minValue }),
React.createElement("input", { type: "range", defaultValue: "0", className: "slider", id: "myRange", onInput: onInput, ref: $range }),
React.createElement("span", { className: "max-value", ref: $maxValue })),
React.createElement("div", { ref: editorParentRef, style: (_a = p.codeMirrorParentStyle) !== null && _a !== void 0 ? _a : { background: 'white', color: 'black' } })));
}
const ReadableEditor = React.memo(_ReadableEditor, (props, nextProps) => {
return true; // stop ReadableEditor from re-rendering
});
export { ReadableEditor };
//# sourceMappingURL=ReadableEditor.js.map