show compile errors in ui
This commit is contained in:
		
							parent
							
								
									a623308496
								
							
						
					
					
						commit
						664dbf4f6b
					
				| 
						 | 
					@ -1,6 +1,8 @@
 | 
				
			||||||
import { useEffect, useState } from "react";
 | 
					import { useEffect, useState } from "react";
 | 
				
			||||||
import { useMonaco, type Monaco } from "@monaco-editor/react";
 | 
					import { useMonaco, type Monaco } from "@monaco-editor/react";
 | 
				
			||||||
import { useImmer, type Updater } from "use-immer";
 | 
					import { useImmer, type Updater } from "use-immer";
 | 
				
			||||||
 | 
					import ThemeProvider from "@mui/material/styles/ThemeProvider";
 | 
				
			||||||
 | 
					import ErrorDisplay from "./playground/ErrorDisplay";
 | 
				
			||||||
import FileView from "./playground/FileView";
 | 
					import FileView from "./playground/FileView";
 | 
				
			||||||
import Editor from "./playground/Editor";
 | 
					import Editor from "./playground/Editor";
 | 
				
			||||||
import Header from "./playground/Header";
 | 
					import Header from "./playground/Header";
 | 
				
			||||||
| 
						 | 
					@ -16,7 +18,6 @@ import "@styles/playground.scss";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import mainFileContent from "@assets/playground/main.shu?raw";
 | 
					import mainFileContent from "@assets/playground/main.shu?raw";
 | 
				
			||||||
import packTomlContent from "@assets/playground/pack.toml?raw";
 | 
					import packTomlContent from "@assets/playground/pack.toml?raw";
 | 
				
			||||||
import ThemeProvider from "@mui/material/styles/ThemeProvider";
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
const FILE_STORAGE_KEY = "playground-files";
 | 
					const FILE_STORAGE_KEY = "playground-files";
 | 
				
			||||||
const DEFAULT_FILES = {
 | 
					const DEFAULT_FILES = {
 | 
				
			||||||
| 
						 | 
					@ -40,6 +41,18 @@ const DEFAULT_FILES = {
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default function Playground({ lang }: { lang: PlaygroundLang }) {
 | 
					export default function Playground({ lang }: { lang: PlaygroundLang }) {
 | 
				
			||||||
 | 
					    const [errorMsg, setErrorMsg] = useState<string | null>(null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    useEffect(() => {
 | 
				
			||||||
 | 
					        (window as any).playground = {
 | 
				
			||||||
 | 
					            showError: (message: string) => {
 | 
				
			||||||
 | 
					                if (message.length > 0) {
 | 
				
			||||||
 | 
					                    setErrorMsg(message);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					    }, []);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    initWasm().catch((err) => {
 | 
					    initWasm().catch((err) => {
 | 
				
			||||||
        console.error(err);
 | 
					        console.error(err);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
| 
						 | 
					@ -63,8 +76,6 @@ export default function Playground({ lang }: { lang: PlaygroundLang }) {
 | 
				
			||||||
                    },
 | 
					                    },
 | 
				
			||||||
                } as Directory;
 | 
					                } as Directory;
 | 
				
			||||||
                loadFiles(monaco, updateRootDir, withRoot);
 | 
					                loadFiles(monaco, updateRootDir, withRoot);
 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                alert("Compilation failed");
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            console.error("monaco has not loaded");
 | 
					            console.error("monaco has not loaded");
 | 
				
			||||||
| 
						 | 
					@ -79,8 +90,6 @@ export default function Playground({ lang }: { lang: PlaygroundLang }) {
 | 
				
			||||||
                a.href = data;
 | 
					                a.href = data;
 | 
				
			||||||
                a.download = "shulkerscript-pack.zip";
 | 
					                a.download = "shulkerscript-pack.zip";
 | 
				
			||||||
                a.click();
 | 
					                a.click();
 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                alert("Compilation failed");
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            console.error("monaco has not loaded");
 | 
					            console.error("monaco has not loaded");
 | 
				
			||||||
| 
						 | 
					@ -167,6 +176,7 @@ export default function Playground({ lang }: { lang: PlaygroundLang }) {
 | 
				
			||||||
                    marginTop: "0.5cm",
 | 
					                    marginTop: "0.5cm",
 | 
				
			||||||
                }}
 | 
					                }}
 | 
				
			||||||
            >
 | 
					            >
 | 
				
			||||||
 | 
					                <ErrorDisplay error={errorMsg} setError={setErrorMsg} />
 | 
				
			||||||
                <Header
 | 
					                <Header
 | 
				
			||||||
                    lang={lang.header}
 | 
					                    lang={lang.header}
 | 
				
			||||||
                    onSave={onSave}
 | 
					                    onSave={onSave}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,40 @@
 | 
				
			||||||
 | 
					import Button from "@mui/material/Button";
 | 
				
			||||||
 | 
					import Dialog from "@mui/material/Dialog";
 | 
				
			||||||
 | 
					import DialogActions from "@mui/material/DialogActions";
 | 
				
			||||||
 | 
					import DialogContent from "@mui/material/DialogContent";
 | 
				
			||||||
 | 
					import DialogTitle from "@mui/material/DialogTitle";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default function ErrorDisplay({
 | 
				
			||||||
 | 
					    error,
 | 
				
			||||||
 | 
					    setError,
 | 
				
			||||||
 | 
					}: {
 | 
				
			||||||
 | 
					    error: string | null;
 | 
				
			||||||
 | 
					    setError: (error: string | null) => void;
 | 
				
			||||||
 | 
					}) {
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					        <Dialog open={error !== null} onClose={() => setError(null)}>
 | 
				
			||||||
 | 
					            <DialogTitle>Error during compilation!</DialogTitle>
 | 
				
			||||||
 | 
					            <DialogContent>
 | 
				
			||||||
 | 
					                <div
 | 
				
			||||||
 | 
					                    style={{
 | 
				
			||||||
 | 
					                        backgroundColor: "black",
 | 
				
			||||||
 | 
					                        padding: "15px",
 | 
				
			||||||
 | 
					                        borderRadius: "15px",
 | 
				
			||||||
 | 
					                        fontSize: "1.2em",
 | 
				
			||||||
 | 
					                    }}
 | 
				
			||||||
 | 
					                >
 | 
				
			||||||
 | 
					                    <code
 | 
				
			||||||
 | 
					                        style={{
 | 
				
			||||||
 | 
					                            whiteSpace: "break-spaces",
 | 
				
			||||||
 | 
					                            fontFamily: "monospace",
 | 
				
			||||||
 | 
					                        }}
 | 
				
			||||||
 | 
					                        dangerouslySetInnerHTML={{ __html: error ?? "" }}
 | 
				
			||||||
 | 
					                    ></code>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					            </DialogContent>
 | 
				
			||||||
 | 
					            <DialogActions>
 | 
				
			||||||
 | 
					                <Button onClick={() => setError(null)}>Close</Button>
 | 
				
			||||||
 | 
					            </DialogActions>
 | 
				
			||||||
 | 
					        </Dialog>
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -17,3 +17,5 @@ anyhow = "1.0.86"
 | 
				
			||||||
zip = { version = "2.1.3", default-features = false, features = ["deflate"] }
 | 
					zip = { version = "2.1.3", default-features = false, features = ["deflate"] }
 | 
				
			||||||
base64 = "0.22.1"
 | 
					base64 = "0.22.1"
 | 
				
			||||||
console_error_panic_hook = "0.1.7"
 | 
					console_error_panic_hook = "0.1.7"
 | 
				
			||||||
 | 
					ansi-to-html = "0.2.1"
 | 
				
			||||||
 | 
					colored = "2.1.0"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,8 +1,8 @@
 | 
				
			||||||
use std::{
 | 
					use std::{
 | 
				
			||||||
    cell::Cell,
 | 
					 | 
				
			||||||
    fmt::Display,
 | 
					    fmt::Display,
 | 
				
			||||||
    io::{Cursor, Write},
 | 
					    io::{Cursor, Write},
 | 
				
			||||||
    path::PathBuf,
 | 
					    path::PathBuf,
 | 
				
			||||||
 | 
					    sync::Mutex,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use anyhow::Result;
 | 
					use anyhow::Result;
 | 
				
			||||||
| 
						 | 
					@ -24,6 +24,9 @@ extern "C" {
 | 
				
			||||||
    fn log(s: &str);
 | 
					    fn log(s: &str);
 | 
				
			||||||
    #[wasm_bindgen(js_namespace = console, js_name = error)]
 | 
					    #[wasm_bindgen(js_namespace = console, js_name = error)]
 | 
				
			||||||
    fn log_err(s: &str);
 | 
					    fn log_err(s: &str);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[wasm_bindgen(js_namespace = ["window", "playground"], js_name = showError)]
 | 
				
			||||||
 | 
					    fn show_err(s: &str);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Compiles the given directory into datapack files.
 | 
					/// Compiles the given directory into datapack files.
 | 
				
			||||||
| 
						 | 
					@ -57,38 +60,38 @@ pub fn compile_zip(root_dir: JsValue) -> Option<String> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // write each file to the zip archive
 | 
					    // write each file to the zip archive
 | 
				
			||||||
    for (path, file) in virtual_files {
 | 
					    for (path, file) in virtual_files {
 | 
				
			||||||
        writer
 | 
					        writer.start_file(path, SimpleFileOptions::default()).ok()?;
 | 
				
			||||||
            .start_file(path, SimpleFileOptions::default())
 | 
					 | 
				
			||||||
            .unwrap();
 | 
					 | 
				
			||||||
        match file {
 | 
					        match file {
 | 
				
			||||||
            VFile::Text(text) => {
 | 
					            VFile::Text(text) => {
 | 
				
			||||||
                writer.write_all(text.as_bytes()).unwrap();
 | 
					                writer.write_all(text.as_bytes()).ok()?;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            VFile::Binary(data) => {
 | 
					            VFile::Binary(data) => {
 | 
				
			||||||
                writer.write_all(data).unwrap();
 | 
					                writer.write_all(data).ok()?;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    writer.set_comment("Data pack created with Shulkerscript web compiler");
 | 
					    writer.set_comment("Data pack created with Shulkerscript web compiler");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    writer.finish().unwrap();
 | 
					    writer.finish().ok()?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Some(BASE64_STANDARD.encode(buffer.into_inner()))
 | 
					    Some(BASE64_STANDARD.encode(buffer.into_inner()))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn _compile(root_dir: &VFolder) -> Result<VFolder> {
 | 
					fn _compile(root_dir: &VFolder) -> Result<VFolder> {
 | 
				
			||||||
 | 
					    colored::control::set_override(true);
 | 
				
			||||||
    let printer = Printer::new();
 | 
					    let printer = Printer::new();
 | 
				
			||||||
    util::compile(&printer, root_dir, &get_script_paths(root_dir))
 | 
					    let res = util::compile(&printer, root_dir, &get_script_paths(root_dir));
 | 
				
			||||||
 | 
					    printer.display();
 | 
				
			||||||
 | 
					    res
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct Printer {
 | 
					struct Printer {
 | 
				
			||||||
    printed: Cell<bool>,
 | 
					    queue: Mutex<Vec<String>>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
impl<T: Display> Handler<T> for Printer {
 | 
					impl<T: Display> Handler<T> for Printer {
 | 
				
			||||||
    fn receive<E: Into<T>>(&self, error: E) {
 | 
					    fn receive<E: Into<T>>(&self, error: E) {
 | 
				
			||||||
        log_err(&error.into().to_string());
 | 
					        self.queue.lock().unwrap().push(format!("{}", error.into()));
 | 
				
			||||||
        self.printed.set(true);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn has_received(&self) -> bool {
 | 
					    fn has_received(&self) -> bool {
 | 
				
			||||||
| 
						 | 
					@ -99,12 +102,23 @@ impl Printer {
 | 
				
			||||||
    /// Creates a new [`Printer`].
 | 
					    /// Creates a new [`Printer`].
 | 
				
			||||||
    fn new() -> Self {
 | 
					    fn new() -> Self {
 | 
				
			||||||
        Self {
 | 
					        Self {
 | 
				
			||||||
            printed: Cell::new(false),
 | 
					            queue: Mutex::new(Vec::new()),
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn display(self) {
 | 
				
			||||||
 | 
					        let queue = self
 | 
				
			||||||
 | 
					            .queue
 | 
				
			||||||
 | 
					            .into_inner()
 | 
				
			||||||
 | 
					            .unwrap()
 | 
				
			||||||
 | 
					            .into_iter()
 | 
				
			||||||
 | 
					            .map(|el| ansi_to_html::convert(&el).unwrap())
 | 
				
			||||||
 | 
					            .collect::<Vec<_>>();
 | 
				
			||||||
 | 
					        show_err(&queue.join("\n\n"));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn has_printed(&self) -> bool {
 | 
					    fn has_printed(&self) -> bool {
 | 
				
			||||||
        self.printed.get()
 | 
					        !self.queue.lock().unwrap().is_empty()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue