Add Svelte docs site and WASM playground

This commit is contained in:
2026-06-17 00:07:11 +09:00
parent 58d2c9b423
commit 4020b7c2d5
23 changed files with 2359 additions and 1 deletions
+14
View File
@@ -0,0 +1,14 @@
[package]
name = "decodal-wasm"
version = "0.1.0"
edition = "2024"
[lib]
crate-type = ["cdylib", "rlib"]
[dependencies]
decodal-core = { path = "../decodal-core" }
wasm-bindgen = "0.2"
[package.metadata.wasm-pack.profile.release]
wasm-opt = false
+96
View File
@@ -0,0 +1,96 @@
use decodal_core::{Data, EmptyLoader, Engine};
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn evaluate(source: &str) -> String {
match evaluate_inner(source) {
Ok(output) => format!("{{\"ok\":true,\"output\":{}}}", json_string(&output)),
Err(error) => format!("{{\"ok\":false,\"error\":{}}}", json_string(&error)),
}
}
fn evaluate_inner(source: &str) -> Result<String, String> {
let mut engine = Engine::new(EmptyLoader);
let module = engine
.add_root_source("playground", "playground", source)
.map_err(format_diagnostic)?;
let value = engine.eval_module(module).map_err(format_diagnostic)?;
let data = engine.materialize(&value).map_err(format_diagnostic)?;
Ok(format_data(&data, 0))
}
fn format_diagnostic(diagnostic: decodal_core::Diagnostic) -> String {
format!(
"{:?} at {}:{}..{}: {}",
diagnostic.kind,
diagnostic.span.source.0,
diagnostic.span.start,
diagnostic.span.end,
diagnostic.message,
)
}
fn format_data(data: &Data, indent: usize) -> String {
match data {
Data::String(value) => json_string(value),
Data::Int(value) => value.to_string(),
Data::Float(value) => value.to_string(),
Data::Bool(value) => value.to_string(),
Data::Array(items) => {
if items.is_empty() {
return String::from("[]");
}
let mut out = String::from("[\n");
for (index, item) in items.iter().enumerate() {
out.push_str(&" ".repeat(indent + 2));
out.push_str(&format_data(item, indent + 2));
if index + 1 != items.len() {
out.push(',');
}
out.push('\n');
}
out.push_str(&" ".repeat(indent));
out.push(']');
out
}
Data::Object(fields) => {
if fields.is_empty() {
return String::from("{}");
}
let mut out = String::from("{\n");
for (index, field) in fields.iter().enumerate() {
out.push_str(&" ".repeat(indent + 2));
out.push_str(&json_string(&field.name));
out.push_str(": ");
out.push_str(&format_data(&field.value, indent + 2));
if index + 1 != fields.len() {
out.push(',');
}
out.push('\n');
}
out.push_str(&" ".repeat(indent));
out.push('}');
out
}
}
}
fn json_string(value: &str) -> String {
let mut out = String::from("\"");
for ch in value.chars() {
match ch {
'"' => out.push_str("\\\""),
'\\' => out.push_str("\\\\"),
'\n' => out.push_str("\\n"),
'\r' => out.push_str("\\r"),
'\t' => out.push_str("\\t"),
ch if ch.is_control() => {
use core::fmt::Write;
let _ = write!(out, "\\u{:04x}", ch as u32);
}
ch => out.push(ch),
}
}
out.push('"');
out
}