diff options
Diffstat (limited to 'www/index.js')
-rw-r--r-- | www/index.js | 69 |
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 @@ | |||
1 | import {SynNode, put_cst} from "cstea"; | 1 | import {SynNode, put_cst} from "cstea"; |
2 | import {EditorState, EditorView, basicSetup} from "@codemirror/basic-setup" | 2 | import {EditorState, EditorView, basicSetup} from "@codemirror/basic-setup" |
3 | import {Decoration, DecorationSet} from "@codemirror/view" | ||
4 | import {StateField, StateEffect} from "@codemirror/state" | ||
3 | import {rust} from "@codemirror/lang-rust" | 5 | import {rust} from "@codemirror/lang-rust" |
4 | 6 | ||
5 | let cst = document.getElementById('cst'); | 7 | let 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 | ||
23 | const doHighlight = StateEffect.define() | ||
24 | |||
25 | const 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 | |||
39 | const hlMark = Decoration.mark({class: "cm-highlight"}) | ||
40 | |||
41 | const hlTheme = EditorView.baseTheme({ | ||
42 | ".cm-highlight": { textDecoration: "underline 3px red" } | ||
43 | }) | ||
44 | |||
45 | function 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 | |||
21 | function render_cst(synRoot) { | 53 | function 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 | |||
71 | function wrap(s, tag) { | ||
72 | let t = document.createElement(tag); | ||
73 | t.innerText = s; | ||
74 | return t; | ||
31 | } | 75 | } |
32 | 76 | ||
33 | function render_err(errorList) { | 77 | function 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 | ||
40 | function doRender() { | 87 | function 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 | } |