cli: add --target flag

This commit is contained in:
Michał Wieluński 2023-11-14 21:42:02 +01:00
parent 97cbc6271d
commit b0cbd66219
No known key found for this signature in database
9 changed files with 418 additions and 28 deletions

View file

@ -3,6 +3,7 @@
- ELK now routes `sql_table` edges to the exact columns (ty @landmaj) [#1681](https://github.com/terrastruct/d2/pull/1681) - ELK now routes `sql_table` edges to the exact columns (ty @landmaj) [#1681](https://github.com/terrastruct/d2/pull/1681)
- Adds new unfilled triangle arrowhead. [#1711](https://github.com/terrastruct/d2/pull/1711) - Adds new unfilled triangle arrowhead. [#1711](https://github.com/terrastruct/d2/pull/1711)
- Grid containers can now have custom label positions. [#1715](https://github.com/terrastruct/d2/pull/1715) - Grid containers can now have custom label positions. [#1715](https://github.com/terrastruct/d2/pull/1715)
- A single board from a multi-board diagram can now be rendered with `--target` flag. [#1725](https://github.com/terrastruct/d2/pull/1725)
#### Improvements 🧹 #### Improvements 🧹

View file

@ -111,6 +111,11 @@ Bundle all assets and layers into the output svg
.It Fl -force-appendix Ar false .It Fl -force-appendix Ar false
An appendix for tooltips and links is added to PNG exports since they are not interactive. Setting this to true adds an appendix to SVG exports as well An appendix for tooltips and links is added to PNG exports since they are not interactive. Setting this to true adds an appendix to SVG exports as well
.Ns . .Ns .
.It Fl -target
Target board to render. Pass an empty string to target root board. If target ends with '*', it will be rendered
with all of its scenarios, steps, and layers. Otherwise, only the target board will be rendered. E.g. --target=''
to render root board only or --target='layers.x.*' to render layer 'x' with all of its children
.Ns .
.It Fl d , -debug .It Fl d , -debug
Print debug logs Print debug logs
.Ns . .Ns .

View file

@ -115,6 +115,7 @@ func Run(ctx context.Context, ms *xmain.State) (err error) {
if err != nil { if err != nil {
return err return err
} }
targetFlag := ms.Opts.String("", "target", "", "*", "target board to render. Pass an empty string to target root board. If target ends with '*', it will be rendered with all of its scenarios, steps, and layers. Otherwise, only the target board will be rendered. E.g. --target='' to render root board only or --target='layers.x.*' to render layer 'x' with all of its children.")
fontRegularFlag := ms.Opts.String("D2_FONT_REGULAR", "font-regular", "", "", "path to .ttf file to use for the regular font. If none provided, Source Sans Pro Regular is used.") fontRegularFlag := ms.Opts.String("D2_FONT_REGULAR", "font-regular", "", "", "path to .ttf file to use for the regular font. If none provided, Source Sans Pro Regular is used.")
fontItalicFlag := ms.Opts.String("D2_FONT_ITALIC", "font-italic", "", "", "path to .ttf file to use for the italic font. If none provided, Source Sans Pro Regular-Italic is used.") fontItalicFlag := ms.Opts.String("D2_FONT_ITALIC", "font-italic", "", "", "path to .ttf file to use for the italic font. If none provided, Source Sans Pro Regular-Italic is used.")
@ -310,6 +311,9 @@ func Run(ctx context.Context, ms *xmain.State) (err error) {
if inputPath == "-" { if inputPath == "-" {
return xmain.UsageErrorf("-w[atch] cannot be combined with reading input from stdin") return xmain.UsageErrorf("-w[atch] cannot be combined with reading input from stdin")
} }
if *targetFlag != "*" {
return xmain.UsageErrorf("-w[atch] cannot be combined with --target")
}
w, err := newWatcher(ctx, ms, watcherOpts{ w, err := newWatcher(ctx, ms, watcherOpts{
plugins: plugins, plugins: plugins,
layout: layoutFlag, layout: layoutFlag,
@ -330,10 +334,30 @@ func Run(ctx context.Context, ms *xmain.State) (err error) {
return w.run() return w.run()
} }
var boardPath []string
var noChildren bool
switch *targetFlag {
case "*":
case "":
noChildren = true
default:
target := *targetFlag
if strings.HasSuffix(target, ".*") {
target = target[:len(target)-2]
} else {
noChildren = true
}
key, err := d2parser.ParseKey(target)
if err != nil {
return xmain.UsageErrorf("invalid target: %s", *targetFlag)
}
boardPath = key.IDA()
}
ctx, cancel := timelib.WithTimeout(ctx, time.Minute*2) ctx, cancel := timelib.WithTimeout(ctx, time.Minute*2)
defer cancel() defer cancel()
_, written, err := compile(ctx, ms, plugins, nil, layoutFlag, renderOpts, fontFamily, *animateIntervalFlag, inputPath, outputPath, "", *bundleFlag, *forceAppendixFlag, pw.Page) _, written, err := compile(ctx, ms, plugins, nil, layoutFlag, renderOpts, fontFamily, *animateIntervalFlag, inputPath, outputPath, boardPath, noChildren, *bundleFlag, *forceAppendixFlag, pw.Page)
if err != nil { if err != nil {
if written { if written {
return fmt.Errorf("failed to fully compile (partial render written) %s: %w", ms.HumanPath(inputPath), err) return fmt.Errorf("failed to fully compile (partial render written) %s: %w", ms.HumanPath(inputPath), err)
@ -368,7 +392,7 @@ func LayoutResolver(ctx context.Context, ms *xmain.State, plugins []d2plugin.Plu
} }
} }
func compile(ctx context.Context, ms *xmain.State, plugins []d2plugin.Plugin, fs fs.FS, layout *string, renderOpts d2svg.RenderOpts, fontFamily *d2fonts.FontFamily, animateInterval int64, inputPath, outputPath, boardPath string, bundle, forceAppendix bool, page playwright.Page) (_ []byte, written bool, _ error) { func compile(ctx context.Context, ms *xmain.State, plugins []d2plugin.Plugin, fs fs.FS, layout *string, renderOpts d2svg.RenderOpts, fontFamily *d2fonts.FontFamily, animateInterval int64, inputPath, outputPath string, boardPath []string, noChildren, bundle, forceAppendix bool, page playwright.Page) (_ []byte, written bool, _ error) {
start := time.Now() start := time.Now()
input, err := ms.ReadPath(inputPath) input, err := ms.ReadPath(inputPath)
if err != nil { if err != nil {
@ -400,6 +424,16 @@ func compile(ctx context.Context, ms *xmain.State, plugins []d2plugin.Plugin, fs
} }
cancel() cancel()
diagram = diagram.GetBoard(boardPath)
if diagram == nil {
return nil, false, fmt.Errorf(`render target "%s" not found`, strings.Join(boardPath, "."))
}
if noChildren {
diagram.Layers = nil
diagram.Scenarios = nil
diagram.Steps = nil
}
plugin, _ := d2plugin.FindPlugin(ctx, plugins, *opts.Layout) plugin, _ := d2plugin.FindPlugin(ctx, plugins, *opts.Layout)
if animateInterval > 0 { if animateInterval > 0 {
@ -503,12 +537,13 @@ func compile(ctx context.Context, ms *xmain.State, plugins []d2plugin.Plugin, fs
} }
} }
board := diagram.GetBoard(boardPath) var boards [][]byte
if board == nil { var err error
return nil, false, fmt.Errorf(`Diagram with path "%s" not found. Did you mean to specify a board like "layers.%s"?`, boardPath, boardPath) if noChildren {
boards, err = renderSingle(ctx, ms, compileDur, plugin, renderOpts, inputPath, outputPath, bundle, forceAppendix, page, ruler, diagram)
} else {
boards, err = render(ctx, ms, compileDur, plugin, renderOpts, inputPath, outputPath, bundle, forceAppendix, page, ruler, diagram)
} }
boards, err := render(ctx, ms, compileDur, plugin, renderOpts, inputPath, outputPath, bundle, forceAppendix, page, ruler, board)
if err != nil { if err != nil {
return nil, false, err return nil, false, err
} }
@ -725,6 +760,19 @@ func render(ctx context.Context, ms *xmain.State, compileDur time.Duration, plug
return boards, nil return boards, nil
} }
func renderSingle(ctx context.Context, ms *xmain.State, compileDur time.Duration, plugin d2plugin.Plugin, opts d2svg.RenderOpts, inputPath, outputPath string, bundle, forceAppendix bool, page playwright.Page, ruler *textmeasure.Ruler, diagram *d2target.Diagram) ([][]byte, error) {
start := time.Now()
out, err := _render(ctx, ms, plugin, opts, outputPath, bundle, forceAppendix, page, ruler, diagram)
if err != nil {
return [][]byte{}, err
}
dur := compileDur + time.Since(start)
if opts.MasterID == "" {
ms.Log.Success.Printf("successfully compiled %s to %s in %s", ms.HumanPath(inputPath), ms.HumanPath(outputPath), dur)
}
return [][]byte{out}, nil
}
func _render(ctx context.Context, ms *xmain.State, plugin d2plugin.Plugin, opts d2svg.RenderOpts, outputPath string, bundle, forceAppendix bool, page playwright.Page, ruler *textmeasure.Ruler, diagram *d2target.Diagram) ([]byte, error) { func _render(ctx context.Context, ms *xmain.State, plugin d2plugin.Plugin, opts d2svg.RenderOpts, outputPath string, bundle, forceAppendix bool, page playwright.Page, ruler *textmeasure.Ruler, diagram *d2target.Diagram) ([]byte, error) {
toPNG := getExportExtension(outputPath) == PNG toPNG := getExportExtension(outputPath) == PNG
var scale *float64 var scale *float64

View file

@ -426,7 +426,11 @@ func (w *watcher) compileLoop(ctx context.Context) error {
fs := trackedFS{} fs := trackedFS{}
w.boardpathMu.Lock() w.boardpathMu.Lock()
svg, _, err := compile(ctx, w.ms, w.plugins, &fs, w.layout, w.renderOpts, w.fontFamily, w.animateInterval, w.inputPath, w.outputPath, w.boardPath, w.bundle, w.forceAppendix, w.pw.Page) var boardPath []string
if w.boardPath != "" {
boardPath = strings.Split(w.boardPath, string(os.PathSeparator))
}
svg, _, err := compile(ctx, w.ms, w.plugins, &fs, w.layout, w.renderOpts, w.fontFamily, w.animateInterval, w.inputPath, w.outputPath, boardPath, false, w.bundle, w.forceAppendix, w.pw.Page)
w.boardpathMu.Unlock() w.boardpathMu.Unlock()
errs := "" errs := ""
if err != nil { if err != nil {

View file

@ -6,7 +6,6 @@ import (
"hash/fnv" "hash/fnv"
"math" "math"
"net/url" "net/url"
"os"
"strings" "strings"
"oss.terrastruct.com/util-go/go2" "oss.terrastruct.com/util-go/go2"
@ -73,19 +72,7 @@ type Diagram struct {
Steps []*Diagram `json:"steps,omitempty"` Steps []*Diagram `json:"steps,omitempty"`
} }
// boardPath comes in the form of "x/layers/z/scenarios/a" func (d *Diagram) GetBoard(boardPath []string) *Diagram {
// or "layers/z/scenarios/a"
// or "x/z/a"
func (d *Diagram) GetBoard(boardPath string) *Diagram {
path := strings.Split(boardPath, string(os.PathSeparator))
if len(path) == 0 || len(boardPath) == 0 {
return d
}
return d.getBoard(path)
}
func (d *Diagram) getBoard(boardPath []string) *Diagram {
if len(boardPath) == 0 { if len(boardPath) == 0 {
return d return d
} }
@ -103,7 +90,7 @@ func (d *Diagram) getBoard(boardPath []string) *Diagram {
} }
for _, b := range d.Layers { for _, b := range d.Layers {
if b.Name == boardPath[1] { if b.Name == boardPath[1] {
return b.getBoard(boardPath[2:]) return b.GetBoard(boardPath[2:])
} }
} }
case "scenarios": case "scenarios":
@ -112,7 +99,7 @@ func (d *Diagram) getBoard(boardPath []string) *Diagram {
} }
for _, b := range d.Scenarios { for _, b := range d.Scenarios {
if b.Name == boardPath[1] { if b.Name == boardPath[1] {
return b.getBoard(boardPath[2:]) return b.GetBoard(boardPath[2:])
} }
} }
case "steps": case "steps":
@ -121,24 +108,24 @@ func (d *Diagram) getBoard(boardPath []string) *Diagram {
} }
for _, b := range d.Steps { for _, b := range d.Steps {
if b.Name == boardPath[1] { if b.Name == boardPath[1] {
return b.getBoard(boardPath[2:]) return b.GetBoard(boardPath[2:])
} }
} }
} }
for _, b := range d.Layers { for _, b := range d.Layers {
if b.Name == head { if b.Name == head {
return b.getBoard(boardPath[1:]) return b.GetBoard(boardPath[1:])
} }
} }
for _, b := range d.Scenarios { for _, b := range d.Scenarios {
if b.Name == head { if b.Name == head {
return b.getBoard(boardPath[1:]) return b.GetBoard(boardPath[1:])
} }
} }
for _, b := range d.Steps { for _, b := range d.Steps {
if b.Name == head { if b.Name == head {
return b.getBoard(boardPath[1:]) return b.GetBoard(boardPath[1:])
} }
} }
return nil return nil

View file

@ -239,6 +239,66 @@ You provided: .png`)
testdataIgnoreDiff(t, ".png", png) testdataIgnoreDiff(t, ".png", png)
}, },
}, },
{
name: "target-root",
run: func(t *testing.T, ctx context.Context, dir string, env *xos.Env) {
writeFile(t, dir, "target-root.d2", `title: {
label: Main Plan
}
scenarios: {
b: {
title.label: Backup Plan
}
}`)
err := runTestMain(t, ctx, dir, env, "--target", "", "target-root.d2", "target-root.svg")
assert.Success(t, err)
svg := readFile(t, dir, "target-root.svg")
assert.Testdata(t, ".svg", svg)
},
},
{
name: "target-b",
run: func(t *testing.T, ctx context.Context, dir string, env *xos.Env) {
writeFile(t, dir, "target-b.d2", `title: {
label: Main Plan
}
scenarios: {
b: {
title.label: Backup Plan
}
}`)
err := runTestMain(t, ctx, dir, env, "--target", "b", "target-b.d2", "target-b.svg")
assert.Success(t, err)
svg := readFile(t, dir, "target-b.svg")
assert.Testdata(t, ".svg", svg)
},
},
{
name: "target-nested-with-special-chars",
run: func(t *testing.T, ctx context.Context, dir string, env *xos.Env) {
writeFile(t, dir, "target-nested-with-special-chars.d2", `layers: {
a: {
layers: {
"x / y . z": {
mad
}
}
}
}`)
err := runTestMain(t, ctx, dir, env, "--target", `layers.a.layers."x / y . z"`, "target-nested-with-special-chars.d2", "target-nested-with-special-chars.svg")
assert.Success(t, err)
svg := readFile(t, dir, "target-nested-with-special-chars.svg")
assert.Testdata(t, ".svg", svg)
},
},
{
name: "target-invalid",
run: func(t *testing.T, ctx context.Context, dir string, env *xos.Env) {
writeFile(t, dir, "target-invalid.d2", `x -> y`)
err := runTestMain(t, ctx, dir, env, "--target", "b", "target-invalid.d2", "target-invalid.svg")
assert.ErrorString(t, err, `failed to wait xmain test: e2etests-cli/d2: failed to compile target-invalid.d2: render target "b" not found`)
},
},
{ {
name: "multiboard/life", name: "multiboard/life",
run: func(t *testing.T, ctx context.Context, dir string, env *xos.Env) { run: func(t *testing.T, ctx context.Context, dir string, env *xos.Env) {

View file

@ -0,0 +1,95 @@
<?xml version="1.0" encoding="utf-8"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" d2Version="v0.6.1-HEAD" preserveAspectRatio="xMinYMin meet" viewBox="0 0 334 268"><svg id="d2-svg" class="d2-2079990668" width="334" height="268" viewBox="-101 -101 334 268"><rect x="-101.000000" y="-101.000000" width="334.000000" height="268.000000" rx="0.000000" class=" fill-N7" stroke-width="0" /><style type="text/css"><![CDATA[
.d2-2079990668 .text-bold {
font-family: "d2-2079990668-font-bold";
}
@font-face {
font-family: d2-2079990668-font-bold;
src: url("data:application/font-woff;base64,d09GRgABAAAAAAiIAAoAAAAADbgAAguFAAAAAAAAAAAAAAAAAAAAAAAAAABPUy8yAAAA9AAAAGAAAABgXxHXrmNtYXAAAAFUAAAAaQAAAIIB0gKEZ2x5ZgAAAcAAAAK+AAADHBKeLixoZWFkAAAEgAAAADYAAAA2G38e1GhoZWEAAAS4AAAAJAAAACQKfwXKaG10eAAABNwAAAAsAAAALBYAAnhsb2NhAAAFCAAAABgAAAAYBBoFDm1heHAAAAUgAAAAIAAAACAAIwD3bmFtZQAABUAAAAMoAAAIKgjwVkFwb3N0AAAIaAAAAB0AAAAg/9EAMgADAioCvAAFAAACigJYAAAASwKKAlgAAAFeADIBKQAAAgsHAwMEAwICBGAAAvcAAAADAAAAAAAAAABBREJPACAAIP//Au7/BgAAA9gBESAAAZ8AAAAAAfAClAAAACAAA3icZMy9DcFRAEfR8/yfzygUBjCLCawgSiIaNlGgYwQLWMUkP8lLJBK3vMVB0SmYqk6Ym+lUC0sraxs7ewfHhJ+7/d6888ozj9xzyzWXnJv3X9Frct/A0MjYhA8AAAD//wEAAP//s/kaRwAAAHicVJLLbxpXFIfPvcBM7dLSAYYBzGPMhRke9WsGZiQbC5B5uQa/aG2rrkvLorJk1638qKjXVatKVFWEF9nksUikrCJllzgiUhaRIsXLKNkkchb5A7xAURZ4iAY7TrI6m3u/75zfOWCCeQBcwwdggD6wgBVYAJkZZEKyKBJalVWVcAZVRAw9j63azRtixBiJGKP8Zf9+tYrKP+KD083Vcq32pjoxoV29d6j9h3YOAQxQBsBJ3AAG3BDQmbLkcLB2imZ7hSIGWVIScYEQRpZ6tXyc3UwPhaWp7HahmlPGpHi+8mdysoIb3nwqVrEYv5jJTH0bQf9EicBrKyuxEADueUZxA8xg/8hCEcJecF8V9/L53dxCsZ5OZnFD/GGuVBt5iRbX5SiAzoh22+gp6oALCAAXEBJxRRUEEqBoUVFkycEyRCQUpUqKmqAo1u54kJ3/q4lJxJ8OJkY2xqu/1PuN/sJnrpBtNuk3L6dmVyyDopP92Rvc2tZeyx6yzdmW+2NeJwcACILdNmqhDrgBTAFB1+kWjtaVrN0hS4rKURRy5X7LFP/IDhc8OcInUqlR57BtPLRkntxbrOxO+riqt5RJl1nLT/wA9LgZAOzDLTD3kmBkVaZtRKTZzP/GK9dv37/2ewq3tK1HR9qLh4V9/X23jay4BZazqRmZuZA/Lk00mT4TTVnNIfPqDCanzzkrQr+a6HMPoM554pz8PiQm3guNydT7jXxZWphuenlP2IlOUr6hjTXtCA0qYRen3dG/Z7pF7EAdsIEPgPtA0XcXEESOtennQQL6veg877T4/XqyqvBJt2lOUJZiUXv4Lr415ib/7nxXTw245i6hYL7099AT65d6FsluG71FJ3qPn8zGyGfLfLYw3fTxHsHRrH9u8H9j3lhDce04EXF7UVH7Khf6+h0AAAD//wEAAP//+eOojQAAAAEAAAACC4Usm1jpXw889QABA+gAAAAA2F2ghAAAAADdZi82/jf+xAhtA/EAAQADAAIAAAAAAAAAAQAAA9j+7wAACJj+N/43CG0AAQAAAAAAAAAAAAAAAAAAAAsCsgBQAMgAAAJdAE0CVABNAg8AKgHTACQCJABBAR4AQQI8AEECPQBBAjgAPAAAACwALABgAIIAugDmAP4BGgE8AWwBjgABAAAACwCQAAwAYwAHAAEAAAAAAAAAAAAAAAAABAADeJyclM9uG1UUxn9ObNMKwQJFVbqJ7oJFkejYVEnVNiuH1IpFFAePC0JCSBPP+I8ynhl5Jg7hCVjzFrxFVzwEz4FYo/l87NgF0SaKknx37vnznXO+c4Ed/mabSvUh8Ec9MVxhr35ueIsH9RPD27TrW4arPKn9abhGWJsbrvN5rWf4I95WfzP8gP3qT4YfslttG/6YZ9Udw59sO/4y/Cn7vF3gCrzgV8MVdskMb7HDj4a3eYTFrFR5RNNwjc/YM1xnD+gzoSBmQsIIx5AJI66YEZHjEzFjwpCIEEeHFjGFviYEQo7Rf34N8CmYESjimAJHjE9MQM7YIv4ir5RzZRzqNLO7FgVjAi7kcUlAgiNlREpCxKXiFBRkvKJBg5yB+GYU5HjkTIjxSJkxokGXNqf0GTMhx9FWpJKZT8qQgmsC5XdmUXZmQERCbqyuSAjF04lfJO8Opzi6ZLJdj3y6EeFLHN/Ju+SWyvYrPP26NWabeZdsAubqZ6yuxLq51gTHui3ztvhWuOAV7l792WTy/h6F+l8o8gVXmn+oSSVikuDcLi18Kch3j3Ec6dzBV0e+p0OfE7q8oa9zix49WpzRp8Nr+Xbp4fiaLmccy6MjvLhrSzFn/IDjGzqyKWNH1p/FxCJ+JjN15+I4Ux1TMvW8ZO6p1kgV3n3C5Q6lG+rI5TPQHpWWTvNLtGcBI1NFJoZT9XKpjdz6F5oipqqlnO3tfbkNc9u95RbfkGqHS7UuOJWTWzB631S9dzRzrR+PgJCUC1kMSJnSoOBGvM8JuCLGcazunWhLClornzLPjVQSMRWDDonizMj0NzDd+MZ9sKF7Z29JKP+S6eWqqvtkcerV7YzeqHvLO9+6HK1NoGFTTdfUNBDXxLQfaafW+fvyzfW6pTzliJSY8F8vwDM8muxzwCFjZRjoZm6vQ1MvRJOXHKr6SyJZDaXnyCIc4PGcAw54yfN3+rhk4oyLW3FZz93imCO6HH5QFQv7Lke8Xn37/6y/i2lTtTierk4v7j3FJ3dQ6xfas9v3sqeJlZOYW7TbrTgjYFpycbvrNbnHeP8AAAD//wEAAP//9LdPUXicYmBmAIP/5xiMGLAAAAAAAP//AQAA//8vAQIDAAAA");
}]]></style><style type="text/css"><![CDATA[.shape {
shape-rendering: geometricPrecision;
stroke-linejoin: round;
}
.connection {
stroke-linecap: round;
stroke-linejoin: round;
}
.blend {
mix-blend-mode: multiply;
opacity: 0.5;
}
.d2-2079990668 .fill-N1{fill:#0A0F25;}
.d2-2079990668 .fill-N2{fill:#676C7E;}
.d2-2079990668 .fill-N3{fill:#9499AB;}
.d2-2079990668 .fill-N4{fill:#CFD2DD;}
.d2-2079990668 .fill-N5{fill:#DEE1EB;}
.d2-2079990668 .fill-N6{fill:#EEF1F8;}
.d2-2079990668 .fill-N7{fill:#FFFFFF;}
.d2-2079990668 .fill-B1{fill:#0D32B2;}
.d2-2079990668 .fill-B2{fill:#0D32B2;}
.d2-2079990668 .fill-B3{fill:#E3E9FD;}
.d2-2079990668 .fill-B4{fill:#E3E9FD;}
.d2-2079990668 .fill-B5{fill:#EDF0FD;}
.d2-2079990668 .fill-B6{fill:#F7F8FE;}
.d2-2079990668 .fill-AA2{fill:#4A6FF3;}
.d2-2079990668 .fill-AA4{fill:#EDF0FD;}
.d2-2079990668 .fill-AA5{fill:#F7F8FE;}
.d2-2079990668 .fill-AB4{fill:#EDF0FD;}
.d2-2079990668 .fill-AB5{fill:#F7F8FE;}
.d2-2079990668 .stroke-N1{stroke:#0A0F25;}
.d2-2079990668 .stroke-N2{stroke:#676C7E;}
.d2-2079990668 .stroke-N3{stroke:#9499AB;}
.d2-2079990668 .stroke-N4{stroke:#CFD2DD;}
.d2-2079990668 .stroke-N5{stroke:#DEE1EB;}
.d2-2079990668 .stroke-N6{stroke:#EEF1F8;}
.d2-2079990668 .stroke-N7{stroke:#FFFFFF;}
.d2-2079990668 .stroke-B1{stroke:#0D32B2;}
.d2-2079990668 .stroke-B2{stroke:#0D32B2;}
.d2-2079990668 .stroke-B3{stroke:#E3E9FD;}
.d2-2079990668 .stroke-B4{stroke:#E3E9FD;}
.d2-2079990668 .stroke-B5{stroke:#EDF0FD;}
.d2-2079990668 .stroke-B6{stroke:#F7F8FE;}
.d2-2079990668 .stroke-AA2{stroke:#4A6FF3;}
.d2-2079990668 .stroke-AA4{stroke:#EDF0FD;}
.d2-2079990668 .stroke-AA5{stroke:#F7F8FE;}
.d2-2079990668 .stroke-AB4{stroke:#EDF0FD;}
.d2-2079990668 .stroke-AB5{stroke:#F7F8FE;}
.d2-2079990668 .background-color-N1{background-color:#0A0F25;}
.d2-2079990668 .background-color-N2{background-color:#676C7E;}
.d2-2079990668 .background-color-N3{background-color:#9499AB;}
.d2-2079990668 .background-color-N4{background-color:#CFD2DD;}
.d2-2079990668 .background-color-N5{background-color:#DEE1EB;}
.d2-2079990668 .background-color-N6{background-color:#EEF1F8;}
.d2-2079990668 .background-color-N7{background-color:#FFFFFF;}
.d2-2079990668 .background-color-B1{background-color:#0D32B2;}
.d2-2079990668 .background-color-B2{background-color:#0D32B2;}
.d2-2079990668 .background-color-B3{background-color:#E3E9FD;}
.d2-2079990668 .background-color-B4{background-color:#E3E9FD;}
.d2-2079990668 .background-color-B5{background-color:#EDF0FD;}
.d2-2079990668 .background-color-B6{background-color:#F7F8FE;}
.d2-2079990668 .background-color-AA2{background-color:#4A6FF3;}
.d2-2079990668 .background-color-AA4{background-color:#EDF0FD;}
.d2-2079990668 .background-color-AA5{background-color:#F7F8FE;}
.d2-2079990668 .background-color-AB4{background-color:#EDF0FD;}
.d2-2079990668 .background-color-AB5{background-color:#F7F8FE;}
.d2-2079990668 .color-N1{color:#0A0F25;}
.d2-2079990668 .color-N2{color:#676C7E;}
.d2-2079990668 .color-N3{color:#9499AB;}
.d2-2079990668 .color-N4{color:#CFD2DD;}
.d2-2079990668 .color-N5{color:#DEE1EB;}
.d2-2079990668 .color-N6{color:#EEF1F8;}
.d2-2079990668 .color-N7{color:#FFFFFF;}
.d2-2079990668 .color-B1{color:#0D32B2;}
.d2-2079990668 .color-B2{color:#0D32B2;}
.d2-2079990668 .color-B3{color:#E3E9FD;}
.d2-2079990668 .color-B4{color:#E3E9FD;}
.d2-2079990668 .color-B5{color:#EDF0FD;}
.d2-2079990668 .color-B6{color:#F7F8FE;}
.d2-2079990668 .color-AA2{color:#4A6FF3;}
.d2-2079990668 .color-AA4{color:#EDF0FD;}
.d2-2079990668 .color-AA5{color:#F7F8FE;}
.d2-2079990668 .color-AB4{color:#EDF0FD;}
.d2-2079990668 .color-AB5{color:#F7F8FE;}.appendix text.text{fill:#0A0F25}.md{--color-fg-default:#0A0F25;--color-fg-muted:#676C7E;--color-fg-subtle:#9499AB;--color-canvas-default:#FFFFFF;--color-canvas-subtle:#EEF1F8;--color-border-default:#0D32B2;--color-border-muted:#0D32B2;--color-neutral-muted:#EEF1F8;--color-accent-fg:#0D32B2;--color-accent-emphasis:#0D32B2;--color-attention-subtle:#676C7E;--color-danger-fg:red;}.sketch-overlay-B1{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-B2{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-B3{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B6{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AA2{fill:url(#streaks-dark);mix-blend-mode:overlay}.sketch-overlay-AA4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AA5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AB4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AB5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N1{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-N2{fill:url(#streaks-dark);mix-blend-mode:overlay}.sketch-overlay-N3{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-N4{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-N5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N6{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N7{fill:url(#streaks-bright);mix-blend-mode:darken}.light-code{display: block}.dark-code{display: none}]]></style><g id="title"><g class="shape" ><rect x="0.000000" y="0.000000" width="132.000000" height="66.000000" class=" stroke-B1 fill-B6" style="stroke-width:2;" /></g><text x="66.000000" y="38.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">Backup Plan</text></g><mask id="d2-2079990668" maskUnits="userSpaceOnUse" x="-101" y="-101" width="334" height="268">
<rect x="-101" y="-101" width="334" height="268" fill="white"></rect>
<rect x="22.500000" y="22.500000" width="87" height="21" fill="rgba(0,0,0,0.75)"></rect>
</mask></svg></svg>

After

Width:  |  Height:  |  Size: 9.3 KiB

View file

@ -0,0 +1,95 @@
<?xml version="1.0" encoding="utf-8"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" d2Version="v0.6.1-HEAD" preserveAspectRatio="xMinYMin meet" viewBox="0 0 278 268"><svg id="d2-svg" class="d2-774159559" width="278" height="268" viewBox="-101 -101 278 268"><rect x="-101.000000" y="-101.000000" width="278.000000" height="268.000000" rx="0.000000" class=" fill-N7" stroke-width="0" /><style type="text/css"><![CDATA[
.d2-774159559 .text-bold {
font-family: "d2-774159559-font-bold";
}
@font-face {
font-family: d2-774159559-font-bold;
src: url("data:application/font-woff;base64,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");
}]]></style><style type="text/css"><![CDATA[.shape {
shape-rendering: geometricPrecision;
stroke-linejoin: round;
}
.connection {
stroke-linecap: round;
stroke-linejoin: round;
}
.blend {
mix-blend-mode: multiply;
opacity: 0.5;
}
.d2-774159559 .fill-N1{fill:#0A0F25;}
.d2-774159559 .fill-N2{fill:#676C7E;}
.d2-774159559 .fill-N3{fill:#9499AB;}
.d2-774159559 .fill-N4{fill:#CFD2DD;}
.d2-774159559 .fill-N5{fill:#DEE1EB;}
.d2-774159559 .fill-N6{fill:#EEF1F8;}
.d2-774159559 .fill-N7{fill:#FFFFFF;}
.d2-774159559 .fill-B1{fill:#0D32B2;}
.d2-774159559 .fill-B2{fill:#0D32B2;}
.d2-774159559 .fill-B3{fill:#E3E9FD;}
.d2-774159559 .fill-B4{fill:#E3E9FD;}
.d2-774159559 .fill-B5{fill:#EDF0FD;}
.d2-774159559 .fill-B6{fill:#F7F8FE;}
.d2-774159559 .fill-AA2{fill:#4A6FF3;}
.d2-774159559 .fill-AA4{fill:#EDF0FD;}
.d2-774159559 .fill-AA5{fill:#F7F8FE;}
.d2-774159559 .fill-AB4{fill:#EDF0FD;}
.d2-774159559 .fill-AB5{fill:#F7F8FE;}
.d2-774159559 .stroke-N1{stroke:#0A0F25;}
.d2-774159559 .stroke-N2{stroke:#676C7E;}
.d2-774159559 .stroke-N3{stroke:#9499AB;}
.d2-774159559 .stroke-N4{stroke:#CFD2DD;}
.d2-774159559 .stroke-N5{stroke:#DEE1EB;}
.d2-774159559 .stroke-N6{stroke:#EEF1F8;}
.d2-774159559 .stroke-N7{stroke:#FFFFFF;}
.d2-774159559 .stroke-B1{stroke:#0D32B2;}
.d2-774159559 .stroke-B2{stroke:#0D32B2;}
.d2-774159559 .stroke-B3{stroke:#E3E9FD;}
.d2-774159559 .stroke-B4{stroke:#E3E9FD;}
.d2-774159559 .stroke-B5{stroke:#EDF0FD;}
.d2-774159559 .stroke-B6{stroke:#F7F8FE;}
.d2-774159559 .stroke-AA2{stroke:#4A6FF3;}
.d2-774159559 .stroke-AA4{stroke:#EDF0FD;}
.d2-774159559 .stroke-AA5{stroke:#F7F8FE;}
.d2-774159559 .stroke-AB4{stroke:#EDF0FD;}
.d2-774159559 .stroke-AB5{stroke:#F7F8FE;}
.d2-774159559 .background-color-N1{background-color:#0A0F25;}
.d2-774159559 .background-color-N2{background-color:#676C7E;}
.d2-774159559 .background-color-N3{background-color:#9499AB;}
.d2-774159559 .background-color-N4{background-color:#CFD2DD;}
.d2-774159559 .background-color-N5{background-color:#DEE1EB;}
.d2-774159559 .background-color-N6{background-color:#EEF1F8;}
.d2-774159559 .background-color-N7{background-color:#FFFFFF;}
.d2-774159559 .background-color-B1{background-color:#0D32B2;}
.d2-774159559 .background-color-B2{background-color:#0D32B2;}
.d2-774159559 .background-color-B3{background-color:#E3E9FD;}
.d2-774159559 .background-color-B4{background-color:#E3E9FD;}
.d2-774159559 .background-color-B5{background-color:#EDF0FD;}
.d2-774159559 .background-color-B6{background-color:#F7F8FE;}
.d2-774159559 .background-color-AA2{background-color:#4A6FF3;}
.d2-774159559 .background-color-AA4{background-color:#EDF0FD;}
.d2-774159559 .background-color-AA5{background-color:#F7F8FE;}
.d2-774159559 .background-color-AB4{background-color:#EDF0FD;}
.d2-774159559 .background-color-AB5{background-color:#F7F8FE;}
.d2-774159559 .color-N1{color:#0A0F25;}
.d2-774159559 .color-N2{color:#676C7E;}
.d2-774159559 .color-N3{color:#9499AB;}
.d2-774159559 .color-N4{color:#CFD2DD;}
.d2-774159559 .color-N5{color:#DEE1EB;}
.d2-774159559 .color-N6{color:#EEF1F8;}
.d2-774159559 .color-N7{color:#FFFFFF;}
.d2-774159559 .color-B1{color:#0D32B2;}
.d2-774159559 .color-B2{color:#0D32B2;}
.d2-774159559 .color-B3{color:#E3E9FD;}
.d2-774159559 .color-B4{color:#E3E9FD;}
.d2-774159559 .color-B5{color:#EDF0FD;}
.d2-774159559 .color-B6{color:#F7F8FE;}
.d2-774159559 .color-AA2{color:#4A6FF3;}
.d2-774159559 .color-AA4{color:#EDF0FD;}
.d2-774159559 .color-AA5{color:#F7F8FE;}
.d2-774159559 .color-AB4{color:#EDF0FD;}
.d2-774159559 .color-AB5{color:#F7F8FE;}.appendix text.text{fill:#0A0F25}.md{--color-fg-default:#0A0F25;--color-fg-muted:#676C7E;--color-fg-subtle:#9499AB;--color-canvas-default:#FFFFFF;--color-canvas-subtle:#EEF1F8;--color-border-default:#0D32B2;--color-border-muted:#0D32B2;--color-neutral-muted:#EEF1F8;--color-accent-fg:#0D32B2;--color-accent-emphasis:#0D32B2;--color-attention-subtle:#676C7E;--color-danger-fg:red;}.sketch-overlay-B1{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-B2{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-B3{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B6{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AA2{fill:url(#streaks-dark);mix-blend-mode:overlay}.sketch-overlay-AA4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AA5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AB4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AB5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N1{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-N2{fill:url(#streaks-dark);mix-blend-mode:overlay}.sketch-overlay-N3{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-N4{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-N5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N6{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N7{fill:url(#streaks-bright);mix-blend-mode:darken}.light-code{display: block}.dark-code{display: none}]]></style><g id="mad"><g class="shape" ><rect x="0.000000" y="0.000000" width="76.000000" height="66.000000" class=" stroke-B1 fill-B6" style="stroke-width:2;" /></g><text x="38.000000" y="38.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">mad</text></g><mask id="d2-774159559" maskUnits="userSpaceOnUse" x="-101" y="-101" width="278" height="268">
<rect x="-101" y="-101" width="278" height="268" fill="white"></rect>
<rect x="22.500000" y="22.500000" width="31" height="21" fill="rgba(0,0,0,0.75)"></rect>
</mask></svg></svg>

After

Width:  |  Height:  |  Size: 8.7 KiB

View file

@ -0,0 +1,95 @@
<?xml version="1.0" encoding="utf-8"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" d2Version="v0.6.1-HEAD" preserveAspectRatio="xMinYMin meet" viewBox="0 0 315 268"><svg id="d2-svg" class="d2-1300846817" width="315" height="268" viewBox="-101 -101 315 268"><rect x="-101.000000" y="-101.000000" width="315.000000" height="268.000000" rx="0.000000" class=" fill-N7" stroke-width="0" /><style type="text/css"><![CDATA[
.d2-1300846817 .text-bold {
font-family: "d2-1300846817-font-bold";
}
@font-face {
font-family: d2-1300846817-font-bold;
src: url("data:application/font-woff;base64,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");
}]]></style><style type="text/css"><![CDATA[.shape {
shape-rendering: geometricPrecision;
stroke-linejoin: round;
}
.connection {
stroke-linecap: round;
stroke-linejoin: round;
}
.blend {
mix-blend-mode: multiply;
opacity: 0.5;
}
.d2-1300846817 .fill-N1{fill:#0A0F25;}
.d2-1300846817 .fill-N2{fill:#676C7E;}
.d2-1300846817 .fill-N3{fill:#9499AB;}
.d2-1300846817 .fill-N4{fill:#CFD2DD;}
.d2-1300846817 .fill-N5{fill:#DEE1EB;}
.d2-1300846817 .fill-N6{fill:#EEF1F8;}
.d2-1300846817 .fill-N7{fill:#FFFFFF;}
.d2-1300846817 .fill-B1{fill:#0D32B2;}
.d2-1300846817 .fill-B2{fill:#0D32B2;}
.d2-1300846817 .fill-B3{fill:#E3E9FD;}
.d2-1300846817 .fill-B4{fill:#E3E9FD;}
.d2-1300846817 .fill-B5{fill:#EDF0FD;}
.d2-1300846817 .fill-B6{fill:#F7F8FE;}
.d2-1300846817 .fill-AA2{fill:#4A6FF3;}
.d2-1300846817 .fill-AA4{fill:#EDF0FD;}
.d2-1300846817 .fill-AA5{fill:#F7F8FE;}
.d2-1300846817 .fill-AB4{fill:#EDF0FD;}
.d2-1300846817 .fill-AB5{fill:#F7F8FE;}
.d2-1300846817 .stroke-N1{stroke:#0A0F25;}
.d2-1300846817 .stroke-N2{stroke:#676C7E;}
.d2-1300846817 .stroke-N3{stroke:#9499AB;}
.d2-1300846817 .stroke-N4{stroke:#CFD2DD;}
.d2-1300846817 .stroke-N5{stroke:#DEE1EB;}
.d2-1300846817 .stroke-N6{stroke:#EEF1F8;}
.d2-1300846817 .stroke-N7{stroke:#FFFFFF;}
.d2-1300846817 .stroke-B1{stroke:#0D32B2;}
.d2-1300846817 .stroke-B2{stroke:#0D32B2;}
.d2-1300846817 .stroke-B3{stroke:#E3E9FD;}
.d2-1300846817 .stroke-B4{stroke:#E3E9FD;}
.d2-1300846817 .stroke-B5{stroke:#EDF0FD;}
.d2-1300846817 .stroke-B6{stroke:#F7F8FE;}
.d2-1300846817 .stroke-AA2{stroke:#4A6FF3;}
.d2-1300846817 .stroke-AA4{stroke:#EDF0FD;}
.d2-1300846817 .stroke-AA5{stroke:#F7F8FE;}
.d2-1300846817 .stroke-AB4{stroke:#EDF0FD;}
.d2-1300846817 .stroke-AB5{stroke:#F7F8FE;}
.d2-1300846817 .background-color-N1{background-color:#0A0F25;}
.d2-1300846817 .background-color-N2{background-color:#676C7E;}
.d2-1300846817 .background-color-N3{background-color:#9499AB;}
.d2-1300846817 .background-color-N4{background-color:#CFD2DD;}
.d2-1300846817 .background-color-N5{background-color:#DEE1EB;}
.d2-1300846817 .background-color-N6{background-color:#EEF1F8;}
.d2-1300846817 .background-color-N7{background-color:#FFFFFF;}
.d2-1300846817 .background-color-B1{background-color:#0D32B2;}
.d2-1300846817 .background-color-B2{background-color:#0D32B2;}
.d2-1300846817 .background-color-B3{background-color:#E3E9FD;}
.d2-1300846817 .background-color-B4{background-color:#E3E9FD;}
.d2-1300846817 .background-color-B5{background-color:#EDF0FD;}
.d2-1300846817 .background-color-B6{background-color:#F7F8FE;}
.d2-1300846817 .background-color-AA2{background-color:#4A6FF3;}
.d2-1300846817 .background-color-AA4{background-color:#EDF0FD;}
.d2-1300846817 .background-color-AA5{background-color:#F7F8FE;}
.d2-1300846817 .background-color-AB4{background-color:#EDF0FD;}
.d2-1300846817 .background-color-AB5{background-color:#F7F8FE;}
.d2-1300846817 .color-N1{color:#0A0F25;}
.d2-1300846817 .color-N2{color:#676C7E;}
.d2-1300846817 .color-N3{color:#9499AB;}
.d2-1300846817 .color-N4{color:#CFD2DD;}
.d2-1300846817 .color-N5{color:#DEE1EB;}
.d2-1300846817 .color-N6{color:#EEF1F8;}
.d2-1300846817 .color-N7{color:#FFFFFF;}
.d2-1300846817 .color-B1{color:#0D32B2;}
.d2-1300846817 .color-B2{color:#0D32B2;}
.d2-1300846817 .color-B3{color:#E3E9FD;}
.d2-1300846817 .color-B4{color:#E3E9FD;}
.d2-1300846817 .color-B5{color:#EDF0FD;}
.d2-1300846817 .color-B6{color:#F7F8FE;}
.d2-1300846817 .color-AA2{color:#4A6FF3;}
.d2-1300846817 .color-AA4{color:#EDF0FD;}
.d2-1300846817 .color-AA5{color:#F7F8FE;}
.d2-1300846817 .color-AB4{color:#EDF0FD;}
.d2-1300846817 .color-AB5{color:#F7F8FE;}.appendix text.text{fill:#0A0F25}.md{--color-fg-default:#0A0F25;--color-fg-muted:#676C7E;--color-fg-subtle:#9499AB;--color-canvas-default:#FFFFFF;--color-canvas-subtle:#EEF1F8;--color-border-default:#0D32B2;--color-border-muted:#0D32B2;--color-neutral-muted:#EEF1F8;--color-accent-fg:#0D32B2;--color-accent-emphasis:#0D32B2;--color-attention-subtle:#676C7E;--color-danger-fg:red;}.sketch-overlay-B1{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-B2{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-B3{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B6{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AA2{fill:url(#streaks-dark);mix-blend-mode:overlay}.sketch-overlay-AA4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AA5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AB4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AB5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N1{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-N2{fill:url(#streaks-dark);mix-blend-mode:overlay}.sketch-overlay-N3{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-N4{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-N5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N6{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N7{fill:url(#streaks-bright);mix-blend-mode:darken}.light-code{display: block}.dark-code{display: none}]]></style><g id="title"><g class="shape" ><rect x="0.000000" y="0.000000" width="113.000000" height="66.000000" class=" stroke-B1 fill-B6" style="stroke-width:2;" /></g><text x="56.500000" y="38.500000" class="text-bold fill-N1" style="text-anchor:middle;font-size:16px">Main Plan</text></g><mask id="d2-1300846817" maskUnits="userSpaceOnUse" x="-101" y="-101" width="315" height="268">
<rect x="-101" y="-101" width="315" height="268" fill="white"></rect>
<rect x="22.500000" y="22.500000" width="68" height="21" fill="rgba(0,0,0,0.75)"></rect>
</mask></svg></svg>

After

Width:  |  Height:  |  Size: 9.1 KiB