irongit

A better version of regex 101

moonregex/src/App.jsx
127 lines3.5 KBJavaScript
1import { useState, useEffect } from "react";
2import parseBuilder from "./builder";
3import { AiFillSave } from "react-icons/ai";
4
5const placeholder = `Enter your variables here like below.
6group1Delim:\\n
7\tvar1:\\w
8\tvar2:\\d
9\tgroup2Delim:\\s
10\t\tvar3:\\w
11\t\tvar4:\\d`;
12
13function App() {
14 const [valid, setValid] = useState(false);
15 const [build, setBuild] = useState("");
16 const [edited, setEdited] = useState(0);
17 const [target, setTarget] = useState(null);
18 const [save, setSave] = useState(true);
19 const regexInput = document.querySelector(
20 "#regex-app > div > div.QtZzw > div > div.AUc0W > div.rjodX > div.cO83v > div.h9z_E.T886D > div > div > div:nth-child(1) > textarea"
21 );
22 const regexValue = document.querySelector(
23 "#regex-app > div > div.QtZzw > div > div.AUc0W > div.rjodX > div.cO83v > div.h9z_E.T886D > div > div > div.CodeMirror-scroll > div.CodeMirror-sizer > div > div > div > div.CodeMirror-code"
24 );
25 const builder = (
26 <textarea
27 rows="20"
28 className={
29 "w-full p-2 rounded-sm font-re101-input text-input decoration-slate-500 underline" +
30 (valid ? "" : " text-red-500")
31 }
32 placeholder={placeholder}
33 spellCheck="off"
34 onKeyDown={(e) => {
35 switch (e.key) {
36 case "Enter":
37 break;
38 case "Tab":
39 e.preventDefault();
40 const index = e.target.selectionStart;
41 e.target.value =
42 e.target.value.substring(0, index) +
43 "\t" +
44 e.target.value.substring(index);
45 e.target.selectionStart = e.target.selectionEnd = index + 1;
46 break;
47 }
48 if (e.ctrlKey && e.key == "s") {
49 saveBuild();
50 }
51 }}
52 onChangeCapture={(e) => {
53 const parseBuild = parseBuilder(e.target.value);
54 if (!parseBuild) setValid(false);
55 else setValid(true);
56 setBuild(parseBuild);
57 setTarget(e.target);
58 setTimeout(
59 () =>
60 setEdited((old) => {
61 return old - 1;
62 }),
63 1000
64 );
65 setEdited(edited + 1);
66 }}
67 ></textarea>
68 );
69
70 const updateRegex = () => {
71 if (edited !== 0 || !save) return;
72 saveBuild();
73 };
74
75 useEffect(updateRegex, [edited]);
76
77 useEffect(() => {
78 if (save) saveBuild();
79 }, [save]);
80
81 return (
82 <div>
83 <div className="w-full">
84 <div className="w-full text-lg text-center relative">
85 <div>Build Variables</div>
86 <div className="absolute right-2 top-8">
87 {saveButton(setSave, save)}
88 </div>
89 </div>
90 {builder}
91 </div>
92 </div>
93 );
94
95 function saveBuild() {
96 const length = regexValue.textContent.length;
97 for (let i = 0; i < length; i++)
98 regexInput.dispatchEvent(
99 new KeyboardEvent("keydown", {
100 key: "Backspace",
101 code: "Backspace",
102 keyCode: 8,
103 })
104 );
105 regexInput.value = build;
106 setTimeout(() => target?.focus(), 100);
107 }
108}
109
110export default App;
111function saveButton(setSave, save) {
112 const active = "bg-blue-500 h-10 p-1 rounded-sm hover:bg-blue-100";
113 const inactive = "bg-blue-100 h-10 p-1 rounded-sm hover:bg-blue-500";
114 const activeSave = <AiFillSave size="100%" color="white" />;
115 const inactiveSave = <AiFillSave size="100%" color="white" />;
116 return (
117 <button
118 className={save ? active : inactive}
119 onClick={(e) => {
120 e.preventDefault();
121 setSave(!save);
122 }}
123 >
124 {save ? activeSave : inactiveSave}
125 </button>
126 );
127}