aboutsummaryrefslogtreecommitdiff
path: root/www/index.js
diff options
context:
space:
mode:
Diffstat (limited to 'www/index.js')
-rw-r--r--www/index.js69
1 files changed, 58 insertions, 11 deletions
diff --git a/www/index.js b/www/index.js
index 2665873..52253c0 100644
--- a/www/index.js
+++ b/www/index.js
@@ -1,5 +1,7 @@
1import {SynNode, put_cst} from "cstea"; 1import {SynNode, put_cst} from "cstea";
2import {EditorState, EditorView, basicSetup} from "@codemirror/basic-setup" 2import {EditorState, EditorView, basicSetup} from "@codemirror/basic-setup"
3import {Decoration, DecorationSet} from "@codemirror/view"
4import {StateField, StateEffect} from "@codemirror/state"
3import {rust} from "@codemirror/lang-rust" 5import {rust} from "@codemirror/lang-rust"
4 6
5let cst = document.getElementById('cst'); 7let cst = document.getElementById('cst');
@@ -18,32 +20,77 @@ let view = new EditorView({
18 parent: document.getElementById('source-code') 20 parent: document.getElementById('source-code')
19}) 21})
20 22
23const doHighlight = StateEffect.define()
24
25const highlightField = StateField.define({
26 create() {
27 return Decoration.none;
28 },
29 update(highlight, tr) {
30 for (let e of tr.effects) if (e.is(doHighlight)) {
31 return (Decoration.none).update({
32 add: [hlMark.range(e.value.from, e.value.to)]
33 });
34 }
35 },
36 provide: f => EditorView.decorations.from(f)
37})
38
39const hlMark = Decoration.mark({class: "cm-highlight"})
40
41const hlTheme = EditorView.baseTheme({
42 ".cm-highlight": { textDecoration: "underline 3px red" }
43})
44
45function highlightArea(view, textRange) {
46 let effects = [doHighlight.of({from: textRange.start(), to: textRange.end()})];
47 if (!view.state.field(highlightField, false)) {
48 effects.push(StateEffect.appendConfig.of([highlightField, hlTheme]));
49 }
50 view.dispatch({effects});
51}
52
21function render_cst(synRoot) { 53function render_cst(synRoot) {
22 cst.innerText += "\n" + synRoot.to_string(); 54 let nodeDiv = document.createElement("div");
55 nodeDiv.className = "syntax-node";
56 let r = synRoot.range();
57 let synText = wrap(synRoot.text() + synRoot.range().to_string(), "pre");
58 synText.onmouseover = () => {
59 console.log(r.to_string());
60 highlightArea(view, r);
61 }
62 nodeDiv.appendChild(synText);
23 if (!synRoot.is_token()) { 63 if (!synRoot.is_token()) {
24 synRoot.children().forEach(node => { 64 synRoot.children().forEach(node => {
25 render_cst(node); 65 nodeDiv.appendChild(render_cst(node));
26 return;
27 }); 66 });
28 } else {
29 return;
30 } 67 }
68 return nodeDiv;
69}
70
71function wrap(s, tag) {
72 let t = document.createElement(tag);
73 t.innerText = s;
74 return t;
31} 75}
32 76
33function render_err(errorList) { 77function render_err(errorList) {
34 cst.innerText = ""; 78 let errDiv = document.createElement("div");
79 errDiv.className = "syntax-err";
35 errorList.forEach(err => { 80 errorList.forEach(err => {
36 cst.innerText += "\n" + err.to_string(); 81 errDiv.appendChild(wrap(err.to_string(), "pre"));
82 highlightArea(view, err.range());
37 }); 83 });
84 return errDiv;
38} 85}
39 86
40function doRender() { 87function doRender() {
41 let sourceFile = view.state.doc.toString();; 88 let sourceFile = view.state.doc.toString();;
42 cst.innerText = ""; 89 cst.innerHTML = "";
43 try { 90 try {
44 var synRoot = SynNode.from_str(sourceFile); 91 let synRoot = SynNode.from_str(sourceFile);
45 render_cst(synRoot); 92 cst.appendChild(render_cst(synRoot));
46 } catch (synError) { 93 } catch (synError) {
47 render_err(synError) 94 cst.appendChild(render_err(synError));
48 } 95 }
49} 96}