Skip to content

Commit

Permalink
define new theme
Browse files Browse the repository at this point in the history
  • Loading branch information
alixander committed Mar 16, 2023
1 parent ad4d483 commit 4c8c2b1
Show file tree
Hide file tree
Showing 19 changed files with 2,680 additions and 12 deletions.
5 changes: 3 additions & 2 deletions d2cli/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -273,8 +273,9 @@ func compile(ctx context.Context, ms *xmain.State, plugin d2plugin.Plugin, sketc

layout := plugin.Layout
opts := &d2lib.CompileOptions{
Layout: layout,
Ruler: ruler,
Layout: layout,
Ruler: ruler,
ThemeID: themeID,
}
if sketch {
opts.FontFamily = go2.Pointer(d2fonts.HandDrawn)
Expand Down
40 changes: 33 additions & 7 deletions d2exporter/export.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"oss.terrastruct.com/d2/d2graph"
"oss.terrastruct.com/d2/d2renderers/d2fonts"
"oss.terrastruct.com/d2/d2target"
"oss.terrastruct.com/d2/d2themes"
"oss.terrastruct.com/d2/lib/color"
)

Expand All @@ -20,22 +21,25 @@ func Export(ctx context.Context, g *d2graph.Graph, fontFamily *d2fonts.FontFamil
if fontFamily == nil {
fontFamily = go2.Pointer(d2fonts.SourceSansPro)
}
if g.Theme != nil && g.Theme.SpecialRules.Mono {
fontFamily = go2.Pointer(d2fonts.SourceCodePro)
}
diagram.FontFamily = fontFamily

diagram.Shapes = make([]d2target.Shape, len(g.Objects))
for i := range g.Objects {
diagram.Shapes[i] = toShape(g.Objects[i])
diagram.Shapes[i] = toShape(g.Objects[i], g.Theme)
}

diagram.Connections = make([]d2target.Connection, len(g.Edges))
for i := range g.Edges {
diagram.Connections[i] = toConnection(g.Edges[i])
diagram.Connections[i] = toConnection(g.Edges[i], g.Theme)
}

return diagram, nil
}

func applyTheme(shape *d2target.Shape, obj *d2graph.Object) {
func applyTheme(shape *d2target.Shape, obj *d2graph.Object, theme *d2themes.Theme) {
shape.Stroke = obj.GetStroke(shape.StrokeDash)
shape.Fill = obj.GetFill()
if obj.Attributes.Shape.Value == d2target.ShapeText {
Expand All @@ -46,6 +50,23 @@ func applyTheme(shape *d2target.Shape, obj *d2graph.Object) {
shape.SecondaryAccentColor = color.AA2
shape.NeutralAccentColor = color.N2
}

// Theme options that change more than color
if theme != nil {
if theme.SpecialRules.OuterContainerDoubleBorder {
if obj.Level() == 1 && len(obj.ChildrenArray) > 0 {
shape.DoubleBorder = true
}
}
if theme.SpecialRules.ContainerDots {
if len(obj.ChildrenArray) > 0 {
shape.FillPattern = "dots"
}
}
if theme.SpecialRules.Mono {
shape.FontFamily = "mono"
}
}
}

func applyStyles(shape *d2target.Shape, obj *d2graph.Object) {
Expand Down Expand Up @@ -102,7 +123,7 @@ func applyStyles(shape *d2target.Shape, obj *d2graph.Object) {
}
}

func toShape(obj *d2graph.Object) d2target.Shape {
func toShape(obj *d2graph.Object, theme *d2themes.Theme) d2target.Shape {
shape := d2target.BaseShape()
shape.SetType(obj.Attributes.Shape.Value)
shape.ID = obj.AbsID()
Expand All @@ -127,7 +148,7 @@ func toShape(obj *d2graph.Object) d2target.Shape {
}

applyStyles(shape, obj)
applyTheme(shape, obj)
applyTheme(shape, obj, theme)
shape.Color = text.GetColor(shape.Italic)
applyStyles(shape, obj)

Expand Down Expand Up @@ -168,7 +189,7 @@ func toShape(obj *d2graph.Object) d2target.Shape {
return *shape
}

func toConnection(edge *d2graph.Edge) d2target.Connection {
func toConnection(edge *d2graph.Edge, theme *d2themes.Theme) d2target.Connection {
connection := d2target.BaseConnection()
connection.ID = edge.AbsID()
connection.ZIndex = edge.ZIndex
Expand Down Expand Up @@ -208,7 +229,9 @@ func toConnection(edge *d2graph.Edge) d2target.Connection {
connection.DstLabel = edge.DstArrowhead.Label.Value
}
}

if theme != nil && theme.SpecialRules.NoCornerRadius {
connection.BorderRadius = 0
}
if edge.Attributes.Style.BorderRadius != nil {
connection.BorderRadius, _ = strconv.ParseFloat(edge.Attributes.Style.BorderRadius.Value, 64)
}
Expand Down Expand Up @@ -258,6 +281,9 @@ func toConnection(edge *d2graph.Edge) d2target.Connection {
if edge.Attributes.Style.Bold != nil {
connection.Bold, _ = strconv.ParseBool(edge.Attributes.Style.Bold.Value)
}
if theme != nil && theme.SpecialRules.Mono {
connection.FontFamily = "mono"
}
if edge.Attributes.Style.Font != nil {
connection.FontFamily = edge.Attributes.Style.Font.Value
}
Expand Down
29 changes: 29 additions & 0 deletions d2graph/d2graph.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import (
"oss.terrastruct.com/d2/d2renderers/d2fonts"
"oss.terrastruct.com/d2/d2renderers/d2latex"
"oss.terrastruct.com/d2/d2target"
"oss.terrastruct.com/d2/d2themes"
"oss.terrastruct.com/d2/d2themes/d2themescatalog"
"oss.terrastruct.com/d2/lib/color"
"oss.terrastruct.com/d2/lib/geo"
"oss.terrastruct.com/d2/lib/shape"
Expand All @@ -43,6 +45,8 @@ type Graph struct {
Layers []*Graph `json:"layers,omitempty"`
Scenarios []*Graph `json:"scenarios,omitempty"`
Steps []*Graph `json:"steps,omitempty"`

Theme *d2themes.Theme `json:"theme,omitempty"`
}

func NewGraph() *Graph {
Expand Down Expand Up @@ -1251,6 +1255,11 @@ func (g *Graph) SetDimensions(mtexts []*d2target.MText, ruler *textmeasure.Ruler
}
}

if g.Theme != nil && g.Theme.SpecialRules.Mono {
tmp := d2fonts.SourceCodePro
fontFamily = &tmp
}

for _, obj := range g.Objects {
obj.Box = &geo.Box{}

Expand Down Expand Up @@ -1291,6 +1300,10 @@ func (g *Graph) SetDimensions(mtexts []*d2target.MText, ruler *textmeasure.Ruler
continue
}

if g.Theme != nil && g.Theme.SpecialRules.CapsLock {
obj.Attributes.Label.Value = strings.ToUpper(obj.Attributes.Label.Value)
}

labelDims, err := obj.GetLabelSize(mtexts, ruler, fontFamily)
if err != nil {
return err
Expand Down Expand Up @@ -1408,6 +1421,10 @@ func (g *Graph) SetDimensions(mtexts []*d2target.MText, ruler *textmeasure.Ruler
continue
}

if g.Theme != nil && g.Theme.SpecialRules.CapsLock {
edge.Attributes.Label.Value = strings.ToUpper(edge.Attributes.Label.Value)
}

dims := GetTextDimensions(mtexts, ruler, edge.Text(), fontFamily)
if dims == nil {
return fmt.Errorf("dimensions for edge label %#v not found", edge.Text())
Expand Down Expand Up @@ -1650,3 +1667,15 @@ func (obj *Object) IsDescendantOf(ancestor *Object) bool {
}
return obj.Parent.IsDescendantOf(ancestor)
}

// ApplyTheme applies themes on the graph level
// This is different than on the render level, which only changes colors
// A theme applied on the graph level applies special rules that change the graph
func (g *Graph) ApplyTheme(themeID int64) error {
theme := d2themescatalog.Find(themeID)
if theme == (d2themes.Theme{}) {
return fmt.Errorf("theme %d not found", themeID)
}
g.Theme = &theme
return nil
}
6 changes: 6 additions & 0 deletions d2lib/d2.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ type CompileOptions struct {
MeasuredTexts []*d2target.MText
Ruler *textmeasure.Ruler
Layout func(context.Context, *d2graph.Graph) error
ThemeID int64

// FontFamily controls the font family used for all texts that are not the following:
// - code
Expand Down Expand Up @@ -51,6 +52,11 @@ func Compile(ctx context.Context, input string, opts *CompileOptions) (*d2target
}

func compile(ctx context.Context, g *d2graph.Graph, opts *CompileOptions) (*d2target.Diagram, error) {
err := g.ApplyTheme(opts.ThemeID)
if err != nil {
return nil, err
}

if len(g.Objects) > 0 {
err := g.SetDimensions(opts.MeasuredTexts, opts.Ruler, opts.FontFamily)
if err != nil {
Expand Down
50 changes: 50 additions & 0 deletions d2renderers/d2sketch/sketch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"oss.terrastruct.com/d2/d2lib"
"oss.terrastruct.com/d2/d2renderers/d2fonts"
"oss.terrastruct.com/d2/d2renderers/d2svg"
"oss.terrastruct.com/d2/d2themes/d2themescatalog"
"oss.terrastruct.com/d2/lib/log"
"oss.terrastruct.com/d2/lib/textmeasure"
)
Expand Down Expand Up @@ -505,6 +506,54 @@ darker: {
style.font-color: "#fff"
style.fill: "#000"
}
`,
},
{
name: "terminal",
themeID: d2themescatalog.Terminal.ID,
script: `network: {
cell tower: {
satellites: {
shape: stored_data
style.multiple: true
}
transmitter
satellites -> transmitter: send
satellites -> transmitter: send
satellites -> transmitter: send
}
online portal: {
ui: { shape: hexagon }
}
data processor: {
storage: {
shape: cylinder
style.multiple: true
}
}
cell tower.transmitter -> data processor.storage: phone logs
}
user: {
shape: person
width: 130
}
user -> network.cell tower: make call
user -> network.online portal.ui: access {
style.stroke-dash: 3
}
api server -> network.online portal.ui: display
api server -> logs: persist
logs: { shape: page; style.multiple: true }
network.data processor -> api server
`,
},
{
Expand Down Expand Up @@ -1218,6 +1267,7 @@ func run(t *testing.T, tc testCase) {
Ruler: ruler,
Layout: layout,
FontFamily: go2.Pointer(d2fonts.HandDrawn),
ThemeID: tc.themeID,
})
if !tassert.Nil(t, err) {
return
Expand Down
150 changes: 150 additions & 0 deletions d2renderers/d2sketch/testdata/terminal/sketch.exp.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 3 additions & 2 deletions d2renderers/d2svg/appendix/appendix_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,9 @@ func run(t *testing.T, tc testCase) {
}

diagram, _, err := d2lib.Compile(ctx, tc.script, &d2lib.CompileOptions{
Ruler: ruler,
Layout: d2dagrelayout.DefaultLayout,
Ruler: ruler,
Layout: d2dagrelayout.DefaultLayout,
ThemeID: tc.themeID,
})
if !tassert.Nil(t, err) {
return
Expand Down
1 change: 1 addition & 0 deletions d2renderers/d2svg/dark_theme/dark_theme_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,7 @@ func run(t *testing.T, tc testCase) {
Ruler: ruler,
Layout: d2dagrelayout.DefaultLayout,
FontFamily: go2.Pointer(d2fonts.HandDrawn),
ThemeID: 200,
})
if !tassert.Nil(t, err) {
return
Expand Down
10 changes: 10 additions & 0 deletions d2themes/d2themes.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@ type Theme struct {
ID int64 `json:"id"`
Name string `json:"name"`
Colors ColorPalette `json:"colors"`

SpecialRules SpecialRules `json:"specialRules,omitempty"`
}

type SpecialRules struct {
Mono bool `json:"mono"`
NoCornerRadius bool `json:"noCornerRadius"`
OuterContainerDoubleBorder bool `json:"outerContainerDoubleBorder"`
ContainerDots bool `json:"containerDots"`
CapsLock bool `json:"capsLock"`
}

func (t *Theme) IsDark() bool {
Expand Down
1 change: 1 addition & 0 deletions d2themes/d2themescatalog/catalog.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ var LightCatalog = []d2themes.Theme{
EarthTones,
EvergladeGreen,
ButteredToast,
Terminal,
}

var DarkCatalog = []d2themes.Theme{
Expand Down
42 changes: 42 additions & 0 deletions d2themes/d2themescatalog/terminal.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package d2themescatalog

import "oss.terrastruct.com/d2/d2themes"

var Terminal = d2themes.Theme{
ID: 300,
Name: "Terminal",
Colors: d2themes.ColorPalette{
Neutrals: TerminalNeutral,

B1: "#000410",
B2: "#0000E4",
B3: "#5AA4DC",
B4: "#E7E9EE",
B5: "#F5F6F9",
B6: "#FFFFFF",

AA2: "#008566",
AA4: "#45BBA5",
AA5: "#7ACCBD",

AB4: "#F1C759",
AB5: "#F9E088",
},
SpecialRules: d2themes.SpecialRules{
Mono: true,
NoCornerRadius: true,
OuterContainerDoubleBorder: true,
ContainerDots: true,
CapsLock: true,
},
}

var TerminalNeutral = d2themes.Neutral{
N1: "#000410",
N2: "#0000B8",
N3: "#9499AB",
N4: "#CFD2DD",
N5: "#C3DEF3",
N6: "#EEF1F8",
N7: "#FFFFFF",
}
1 change: 1 addition & 0 deletions docs/examples/lib/3-lowlevel/lowlevel.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
// Remember to add if err != nil checks in production.
func main() {
graph, _ := d2compiler.Compile("", strings.NewReader("x -> y"), nil)
graph.ApplyTheme(d2themescatalog.NeutralDefault.ID)
ruler, _ := textmeasure.NewRuler()
_ = graph.SetDimensions(nil, ruler, nil)
_ = d2dagrelayout.Layout(context.Background(), graph, nil)
Expand Down
Binary file modified e2etests-cli/testdata/TestCLI_E2E/internal_linked_pdf.exp.pdf
Binary file not shown.
Loading

0 comments on commit 4c8c2b1

Please sign in to comment.