diff --git a/d2js/d2wasm/functions.go b/d2js/d2wasm/functions.go index c14c681abe..4526515524 100644 --- a/d2js/d2wasm/functions.go +++ b/d2js/d2wasm/functions.go @@ -280,17 +280,19 @@ func Compile(args []js.Value) (interface{}, error) { Diagram: *diagram, Graph: *g, RenderOptions: RenderOptions{ - ThemeID: renderOpts.ThemeID, - DarkThemeID: renderOpts.DarkThemeID, - Sketch: renderOpts.Sketch, - Pad: renderOpts.Pad, - Center: renderOpts.Center, - Scale: renderOpts.Scale, - ForceAppendix: input.Opts.ForceAppendix, - Target: input.Opts.Target, - AnimateInterval: input.Opts.AnimateInterval, - Salt: input.Opts.Salt, - NoXMLTag: input.Opts.NoXMLTag, + ThemeID: renderOpts.ThemeID, + DarkThemeID: renderOpts.DarkThemeID, + ThemeOverrides: renderOpts.ThemeOverrides, + DarkThemeOverrides: renderOpts.DarkThemeOverrides, + Sketch: renderOpts.Sketch, + Pad: renderOpts.Pad, + Center: renderOpts.Center, + Scale: renderOpts.Scale, + ForceAppendix: input.Opts.ForceAppendix, + Target: input.Opts.Target, + AnimateInterval: input.Opts.AnimateInterval, + Salt: input.Opts.Salt, + NoXMLTag: input.Opts.NoXMLTag, }, }, nil } @@ -382,6 +384,12 @@ func Render(args []js.Value) (interface{}, error) { if input.Opts != nil && input.Opts.DarkThemeID != nil { renderOpts.DarkThemeID = input.Opts.DarkThemeID } + if input.Opts != nil && input.Opts.ThemeOverrides != nil { + renderOpts.ThemeOverrides = input.Opts.ThemeOverrides + } + if input.Opts != nil && input.Opts.DarkThemeOverrides != nil { + renderOpts.DarkThemeOverrides = input.Opts.DarkThemeOverrides + } if input.Opts != nil && input.Opts.Scale != nil { renderOpts.Scale = input.Opts.Scale } diff --git a/d2js/d2wasm/types.go b/d2js/d2wasm/types.go index 7950c97a79..b10e97c1fe 100644 --- a/d2js/d2wasm/types.go +++ b/d2js/d2wasm/types.go @@ -39,17 +39,19 @@ type CompileRequest struct { } type RenderOptions struct { - Pad *int64 `json:"pad"` - Sketch *bool `json:"sketch"` - Center *bool `json:"center"` - ThemeID *int64 `json:"themeID"` - DarkThemeID *int64 `json:"darkThemeID"` - Scale *float64 `json:"scale"` - ForceAppendix *bool `json:"forceAppendix"` - Target *string `json:"target"` - AnimateInterval *int64 `json:"animateInterval"` - Salt *string `json:"salt"` - NoXMLTag *bool `json:"noXMLTag"` + Pad *int64 `json:"pad"` + Sketch *bool `json:"sketch"` + Center *bool `json:"center"` + ThemeID *int64 `json:"themeID"` + DarkThemeID *int64 `json:"darkThemeID"` + ThemeOverrides *d2target.ThemeOverrides `json:"themeOverrides"` + DarkThemeOverrides *d2target.ThemeOverrides `json:"darkThemeOverrides"` + Scale *float64 `json:"scale"` + ForceAppendix *bool `json:"forceAppendix"` + Target *string `json:"target"` + AnimateInterval *int64 `json:"animateInterval"` + Salt *string `json:"salt"` + NoXMLTag *bool `json:"noXMLTag"` } type CompileOptions struct { diff --git a/d2js/js/CHANGELOG.md b/d2js/js/CHANGELOG.md index 18767b5cc8..e3820b2861 100644 --- a/d2js/js/CHANGELOG.md +++ b/d2js/js/CHANGELOG.md @@ -6,6 +6,8 @@ include changes to the main d2 project.** ## Next - Fix TypeScript signatures +- Fix theme-overrides not applying +- Fix grids in ELK layouts ## [0.1.22] ### March 20, 2025 diff --git a/d2js/js/package.json b/d2js/js/package.json index 7355b74739..d337b720d7 100644 --- a/d2js/js/package.json +++ b/d2js/js/package.json @@ -2,7 +2,7 @@ "name": "@terrastruct/d2", "author": "Terrastruct, Inc.", "description": "D2.js is a wrapper around the WASM build of D2, the modern text-to-diagram language.", - "version": "0.1.24", + "version": "0.1.25", "repository": { "type": "git", "url": "git+https://github.com/terrastruct/d2.git", diff --git a/d2js/js/test/unit/basic.test.js b/d2js/js/test/unit/basic.test.js index 93c688e9b8..b35a891cc6 100644 --- a/d2js/js/test/unit/basic.test.js +++ b/d2js/js/test/unit/basic.test.js @@ -232,6 +232,34 @@ layers: { await d2.worker.terminate(); }, 20000); + test("theme overrides work correctly", async () => { + const d2 = new D2(); + + // B1 controls arrow/border color + const resultOverridden = await d2.compile(` +vars: { + d2-config: { + theme-overrides: { + B1: "#000000" + } + } +} + +a -> b +`); + + expect(resultOverridden.renderOptions.themeOverrides).toBeDefined(); + expect(resultOverridden.renderOptions.themeOverrides.b1).toBe("#000000"); + + const svgOverridden = await d2.render( + resultOverridden.diagram, + resultOverridden.renderOptions + ); + + expect(svgOverridden).toContain("fill:#000000"); + await d2.worker.terminate(); + }, 20000); + test("grid layout with elk engine matches go rendering", async () => { const d2 = new D2(); const source = `vars: {