Fixed ace/keyboard loading

This commit is contained in:
Spxg
2025-05-18 02:07:13 +08:00
parent e6d17b1b54
commit e84d5af619
6 changed files with 40 additions and 41 deletions

1
Cargo.lock generated
View File

@@ -22,7 +22,6 @@ dependencies = [
"serde",
"serde-wasm-bindgen",
"thiserror 2.0.12",
"tokio",
"wasm-bindgen",
"web-sys",
]

View File

@@ -8,6 +8,5 @@ js-sys = "0.3.77"
serde = { version = "1.0.219", features = ["derive"] }
serde-wasm-bindgen = "0.6.5"
thiserror = "2.0.12"
tokio = { version = "1.45.0", features = ["sync"] }
wasm-bindgen = "0.2.100"
web-sys = { version = "0.3.77", features = ["HtmlElement"] }

View File

@@ -1,5 +1,3 @@
use std::sync::Arc;
use js_sys::{Object, Reflect};
use serde::{Deserialize, Serialize};
use wasm_bindgen::{JsCast, JsValue, prelude::Closure};
@@ -7,19 +5,12 @@ use wasm_bindgen::{JsCast, JsValue, prelude::Closure};
// <https://ajaxorg.github.io/ace-api-docs/index.html>
mod bindgen {
use js_sys::Object;
use wasm_bindgen::{
JsValue,
prelude::{Closure, wasm_bindgen},
};
use wasm_bindgen::{JsValue, prelude::wasm_bindgen};
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(js_namespace = ace, js_name = edit, catch)]
pub fn edit(element: &str, options: Option<Object>) -> Result<Editor, JsValue>;
#[wasm_bindgen(js_namespace = ["ace", "config"], js_name = loadModule)]
pub fn load_module(module: &str, callback: &Closure<dyn FnMut(JsValue)>);
#[wasm_bindgen(js_namespace = ace, js_name = require, catch)]
pub fn require(module: &str) -> Result<JsValue, JsValue>;
}
@@ -32,7 +23,7 @@ mod bindgen {
pub fn set_theme(this: &Editor, theme: &str) -> Result<(), JsValue>;
#[wasm_bindgen(method, js_name = setKeyboardHandler, catch)]
pub fn set_keyboard_handler(this: &Editor, handler: &str) -> Result<(), JsValue>;
pub fn set_keyboard_handler(this: &Editor, handler: JsValue) -> Result<(), JsValue>;
#[wasm_bindgen(method, js_name = getValue)]
pub fn get_value(this: &Editor) -> String;
@@ -67,8 +58,13 @@ impl EditorOptionsBuilder {
self
}
pub fn keyboard(mut self, value: &str) -> Self {
self.0.keyboard_handler = value.into();
pub fn keyboard(mut self, value: Option<&str>) -> Self {
let value = if let Some(value) = value {
JsValue::from(value)
} else {
JsValue::null()
};
self.0.keyboard_handler = value;
self
}
@@ -87,7 +83,8 @@ impl EditorOptionsBuilder {
pub struct EditorOptions {
pub mode: String,
pub theme: String,
pub keyboard_handler: String,
#[serde(with = "serde_wasm_bindgen::preserve")]
pub keyboard_handler: JsValue,
pub value: String,
}
@@ -158,23 +155,19 @@ impl Editor {
self.js.set_theme(theme).map_err(EditorError::SetTheme)
}
pub fn set_keyboard_handler(&self, handler: &str) -> Result<()> {
pub fn set_keyboard_handler(&self, handler: Option<&str>) -> Result<()> {
let handler = if let Some(handler) = handler {
JsValue::from(handler)
} else {
JsValue::null()
};
self.js
.set_keyboard_handler(handler)
.map_err(EditorError::SetKeyboardHandler)
}
pub async fn define_vim_w(callback: Box<dyn Fn() + 'static>) -> Result<()> {
let notify = Arc::new(tokio::sync::Notify::new());
let waiter = Arc::clone(&notify);
let load_module = Closure::once(move |_: JsValue| {
notify.notify_waiters();
});
bindgen::load_module("ace/keyboard/vim", &load_module);
waiter.notified().await;
pub fn define_vim_w(callback: Box<dyn Fn() + 'static>) -> Result<()> {
let value = bindgen::require("ace/keyboard/vim").map_err(EditorError::DefineEx)?;
let define_ex = Reflect::get(&value, &JsValue::from("CodeMirror"))

View File

@@ -17,6 +17,11 @@
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.40.1/theme-github.min.js" integrity="sha512-6PQOyKN8ulKmC/NQlWnhk2Upjza1Lj9pbYD/6+gNuNG+U28jW/x9iJQJuiQkfQAFggY1sToW9va3vY4xfpsJaA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.41.0/theme-github_dark.min.js" integrity="sha512-9KPSgJ+mukvk+UY25jG7bM1hOR43Sw9jmJxc5q5aa7RAMoQeyY12PNfwwUAPhe9AtOpUA1jKsDRgxeDCXe/uMg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.41.0/keybinding-emacs.min.js" integrity="sha512-1we+ZK71T6DaWp6q4BJy19k434OD9bA5Og0UfzbTYJSH/uudpJGyutzmySWFpaa9t4D6mQV+EqZSzZjuSMcWRA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.41.0/keybinding-sublime.min.js" integrity="sha512-w/39STWW/Z1LblB2XwmGduzCcCPEL1HUi220daoSjYw4d/XsSzSQm+2no518nufpy5mKKTChZ50oQ9YQE/zDNg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.41.0/keybinding-vim.min.js" integrity="sha512-0GK45OEsRSdhy9Gs16CE1aufzMtn7NI3uRZvvyA3Lg+0LwB92pluTEpBrvxE1bYojIdrIz9BEXi07JpPmCxIWg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.41.0/keybinding-vscode.min.js" integrity="sha512-sALdRE8skRaHi5dri3ejsaAQb1NCbkiBMSUI/IWJQYMzA7k/VvlJ5JLOX3n88OG2S+zEcqeJlaX7GZOeLXyYlQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,300..800;1,300..800&amp;family=Source+Code+Pro:ital,wght@0,200..900;1,200..900&amp;display=swap" rel="stylesheet">

View File

@@ -36,7 +36,9 @@ pub fn ConfigMenu() -> impl IntoView {
let select = HtmlSelectElement::from(JsValue::from(target));
state.editor_config().write().keyboard = select.value();
if let Some(Err(err)) = state.editor().read().as_ref().map(|editor| {
editor.set_keyboard_handler(&format!("ace/keyboard/{}", select.value()))
let keyboard = select.value();
let handler = (keyboard != "ace").then_some(format!("ace/keyboard/{keyboard}"));
editor.set_keyboard_handler(handler.as_deref())
}) {
state
.last_error()

View File

@@ -3,7 +3,6 @@ use istyles::istyles;
use leptos::prelude::*;
use reactive_stores::Store;
use wasm_bindgen::{JsCast, prelude::Closure};
use wasm_bindgen_futures::spawn_local;
use web_sys::UrlSearchParams;
use crate::{
@@ -25,16 +24,20 @@ pub fn Editor() -> impl IntoView {
let params = UrlSearchParams::new_with_str(&search).ok()?;
params.get("code")
};
let opt = EditorOptionsBuilder::default()
.mode("ace/mode/sql")
.theme(&format!(
"ace/theme/{}",
state.editor_config().read_untracked().theme
))
.keyboard(&format!(
"ace/keyboard/{}",
state.editor_config().read_untracked().keyboard
))
.keyboard(
{
let keyboard = &state.editor_config().read_untracked().keyboard;
(keyboard != "ace").then_some(format!("ace/keyboard/{keyboard}"))
}
.as_deref(),
)
.value(&shared_code().unwrap_or_else(|| state.sql().get_untracked()))
.build();
@@ -59,13 +62,11 @@ pub fn Editor() -> impl IntoView {
.set(Some(SQLightError::new_ace_editor(err))),
}
spawn_local(async move {
if let Err(err) = aceditor::Editor::define_vim_w(execute(state)).await {
state
.last_error()
.set(Some(SQLightError::new_ace_editor(err)));
}
});
if let Err(err) = aceditor::Editor::define_vim_w(execute(state)) {
state
.last_error()
.set(Some(SQLightError::new_ace_editor(err)));
}
});
view! {
<div class=styles::container>