diff --git a/ci/peek-wasm-size.sh b/ci/peek-wasm-size.sh
new file mode 100755
index 000000000..5c3f85896
--- /dev/null
+++ b/ci/peek-wasm-size.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+OUTPUT_FILE="main.wasm"
+SOURCE_PACKAGE="./d2js"
+
+echo "Building WASM file..."
+GOOS=js GOARCH=wasm go build -ldflags='-s -w' -trimpath -o "$OUTPUT_FILE" "$SOURCE_PACKAGE"
+
+if [ $? -eq 0 ]; then
+ echo "Build successful."
+
+ if [ -f "$OUTPUT_FILE" ]; then
+ FILE_SIZE_BYTES=$(stat -f%z "$OUTPUT_FILE")
+ FILE_SIZE_MB=$(echo "scale=2; $FILE_SIZE_BYTES / 1024 / 1024" | bc)
+
+ echo "File size of $OUTPUT_FILE: $FILE_SIZE_MB MB"
+ else
+ echo "File $OUTPUT_FILE not found!"
+ exit 1
+ fi
+
+ echo "Deleting $OUTPUT_FILE..."
+ rm "$OUTPUT_FILE"
+ echo "File deleted."
+else
+ echo "Build failed."
+ exit 1
+fi
diff --git a/d2js/d2wasm/functions.go b/d2js/d2wasm/functions.go
index 3a2a70330..c73b2eee4 100644
--- a/d2js/d2wasm/functions.go
+++ b/d2js/d2wasm/functions.go
@@ -107,6 +107,52 @@ func GetRefRanges(args []js.Value) (interface{}, error) {
}, nil
}
+func GetELKGraph(args []js.Value) (interface{}, error) {
+ if len(args) < 1 {
+ return nil, &WASMError{Message: "missing JSON argument", Code: 400}
+ }
+ var input CompileRequest
+ if err := json.Unmarshal([]byte(args[0].String()), &input); err != nil {
+ return nil, &WASMError{Message: "invalid JSON input", Code: 400}
+ }
+
+ if input.FS == nil {
+ return nil, &WASMError{Message: "missing 'fs' field in input JSON", Code: 400}
+ }
+
+ if _, ok := input.FS["index"]; !ok {
+ return nil, &WASMError{Message: "missing 'index' file in input fs", Code: 400}
+ }
+
+ fs, err := memfs.New(input.FS)
+ if err != nil {
+ return nil, &WASMError{Message: fmt.Sprintf("invalid fs input: %s", err.Error()), Code: 400}
+ }
+
+ g, _, err := d2compiler.Compile("", strings.NewReader(input.FS["index"]), &d2compiler.CompileOptions{
+ UTF16Pos: true,
+ FS: fs,
+ })
+ if err != nil {
+ return nil, &WASMError{Message: err.Error(), Code: 400}
+ }
+
+ ruler, err := textmeasure.NewRuler()
+ if err != nil {
+ return nil, &WASMError{Message: fmt.Sprintf("text ruler cannot be initialized: %s", err.Error()), Code: 500}
+ }
+ err = g.SetDimensions(nil, ruler, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ elk, err := d2elklayout.ConvertGraph(context.Background(), g, nil)
+ if err != nil {
+ return nil, &WASMError{Message: err.Error(), Code: 400}
+ }
+ return elk, nil
+}
+
func Compile(args []js.Value) (interface{}, error) {
if len(args) < 1 {
return nil, &WASMError{Message: "missing JSON argument", Code: 400}
diff --git a/d2js/js.go b/d2js/js.go
index 514fd5179..3d449ddfb 100644
--- a/d2js/js.go
+++ b/d2js/js.go
@@ -15,6 +15,7 @@ func main() {
api.Register("getParentID", d2wasm.GetParentID)
api.Register("getObjOrder", d2wasm.GetObjOrder)
api.Register("getRefRanges", d2wasm.GetRefRanges)
+ api.Register("getELKGraph", d2wasm.GetELKGraph)
api.Register("compile", d2wasm.Compile)
api.Register("render", d2wasm.Render)
api.Register("getBoardAtPosition", d2wasm.GetBoardAtPosition)
diff --git a/d2js/js/build.js b/d2js/js/build.js
index d8ae1969a..c445f49d4 100644
--- a/d2js/js/build.js
+++ b/d2js/js/build.js
@@ -93,6 +93,7 @@ async function buildAndCopy(buildType) {
resolve(ROOT_DIR, "wasm/wasm_exec.js"),
join(config.outdir, "wasm_exec.js")
);
+ await copyFile(resolve(ROOT_DIR, "src/elk.js"), join(config.outdir, "elk.js"));
}
}
diff --git a/d2js/js/examples/customizable.html b/d2js/js/examples/customizable.html
index aa6fac6cf..13b7a2138 100644
--- a/d2js/js/examples/customizable.html
+++ b/d2js/js/examples/customizable.html
@@ -24,7 +24,16 @@
border-radius: 4px;
font-family: monospace;
}
- .layout-toggle {
+ .options-group {
+ display: flex;
+ flex-direction: column;
+ gap: 12px;
+ padding: 12px;
+ border: 1px solid #eee;
+ border-radius: 4px;
+ }
+ .layout-toggle,
+ .sketch-toggle {
display: flex;
gap: 16px;
align-items: center;
@@ -33,7 +42,8 @@
display: flex;
gap: 12px;
}
- .radio-label {
+ .radio-label,
+ .checkbox-label {
display: flex;
gap: 4px;
align-items: center;
@@ -66,16 +76,24 @@
-
-
Layout:
-
-
-