Merge branch 'master' into shape-specific-inner-boxes

This commit is contained in:
Gavin Nishizawa 2023-02-01 10:30:46 -08:00
commit 1b1cdaff15
No known key found for this signature in database
GPG key ID: AE3B177777CE55CD
35 changed files with 3479 additions and 82 deletions

View file

@ -228,6 +228,7 @@ let us know and we'll be happy to include it here!
- **Comparison site**: [https://github.com/terrastruct/text-to-diagram-site](https://github.com/terrastruct/text-to-diagram-site)
- **Playground**: [https://github.com/terrastruct/d2-playground](https://github.com/terrastruct/d2-playground)
- **Language docs**: [https://github.com/terrastruct/d2-docs](https://github.com/terrastruct/d2-docs)
- **Hosted icons**: [https://icons.terrastruct.com](https://icons.terrastruct.com)
## FAQ

View file

@ -1,9 +1,12 @@
#### Features 🚀
- `double-circle` keyword implemented. [#565](https://github.com/terrastruct/d2/pull/565)
- `double-border` keyword implemented. [#565](https://github.com/terrastruct/d2/pull/565)
- The [Dockerfile](./docs/INSTALL.md#docker) now supports rendering PNGs [#594](https://github.com/terrastruct/d2/issues/594)
- There was a minor breaking change as part of this where the default working directory of the Dockerfile is now `/home/debian/src` instead of `/root/src` to allow UID remapping with [`fixuid`](https://github.com/boxboat/fixuid).
- `d2 fmt` accepts multiple files to be formatted [#718](https://github.com/terrastruct/d2/issues/718)
#### Improvements 🧹
- Reduces default padding of shapes. [#702](https://github.com/terrastruct/d2/pull/702)
@ -14,5 +17,7 @@
#### Bugfixes ⛑️
- Fixes groups overlapping in sequence diagrams when they end in a self loop. [#728](https://github.com/terrastruct/d2/pull/728)
- Fixed dimensions of unlabeled squares or circles with only a set width or height. [#702](https://github.com/terrastruct/d2/pull/702)
- Fixed scaling of actor shapes in sequence diagrams. [#702](https://github.com/terrastruct/d2/pull/702)
- Code snippets use bold and italic font styles as determined by highlighter [#710](https://github.com/terrastruct/d2/issues/710), [#741](https://github.com/terrastruct/d2/issues/741)

View file

@ -13,7 +13,7 @@
.Nm d2
.Ar layout Op Ar name
.Nm d2
.Ar fmt Ar file.d2
.Ar fmt Ar file.d2 ...
.Sh DESCRIPTION
.Nm
compiles and renders
@ -83,10 +83,8 @@ Print version information and exit.
Lists available layout engine options with short help.
.It Ar layout Op Ar name
Display long help for a particular layout engine, including its configuration options.
.It Ar fmt Ar file.d2
Format
.Ar file.d2
.Ns .
.It Ar fmt Ar file.d2 ...
Format all passed files.
.El
.Sh SEE ALSO
.Xr d2plugin-tala 1

View file

@ -1074,6 +1074,12 @@ func appendTextDedup(texts []*d2target.MText, t *d2target.MText) []*d2target.MTe
}
func (g *Graph) SetDimensions(mtexts []*d2target.MText, ruler *textmeasure.Ruler, fontFamily *d2fonts.FontFamily) error {
if ruler != nil && fontFamily != nil {
if ok := ruler.HasFontFamilyLoaded(fontFamily); !ok {
return fmt.Errorf("ruler does not have entire font family %s loaded, is a style missing?", *fontFamily)
}
}
for _, obj := range g.Objects {
obj.Box = &geo.Box{}

View file

@ -97,3 +97,12 @@ func (e *Edge) ContainedBy(obj *Object) bool {
}
return false
}
func (e *Edge) GetGroup() *Object {
for _, ref := range e.References {
if ref.ScopeObj.IsSequenceDiagramGroup() {
return ref.ScopeObj
}
}
return nil
}

View file

@ -451,6 +451,8 @@ func (sd *sequenceDiagram) placeSpans() {
// routeMessages routes horizontal edges (messages) from Src to Dst lifeline (actor/span center)
// in another step, routes are adjusted to spans borders when necessary
func (sd *sequenceDiagram) routeMessages() error {
var prevIsLoop bool
var prevGroup *d2graph.Object
messageOffset := sd.maxActorHeight + sd.yStep
for _, message := range sd.messages {
message.ZIndex = MESSAGE_Z_INDEX
@ -460,6 +462,14 @@ func (sd *sequenceDiagram) routeMessages() error {
noteOffset += note.Height + sd.yStep
}
}
// we need extra space if the previous message is a loop in a different group
group := message.GetGroup()
if prevIsLoop && prevGroup != group {
messageOffset += MIN_MESSAGE_DISTANCE
}
prevGroup = group
startY := messageOffset + noteOffset
var startX, endX float64
@ -496,11 +506,13 @@ func (sd *sequenceDiagram) routeMessages() error {
geo.NewPoint(midX, endY),
geo.NewPoint(endX, endY),
}
prevIsLoop = true
} else {
message.Route = []*geo.Point{
geo.NewPoint(startX, startY),
geo.NewPoint(endX, startY),
}
prevIsLoop = false
}
messageOffset += sd.yStep

View file

@ -78,6 +78,12 @@ var sourceSansProItalicBase64 string
//go:embed encoded/SourceCodePro-Regular.txt
var sourceCodeProRegularBase64 string
//go:embed encoded/SourceCodePro-Bold.txt
var sourceCodeProBoldBase64 string
//go:embed encoded/SourceCodePro-Italic.txt
var sourceCodeProItalicBase64 string
//go:embed encoded/ArchitectsDaughter-Regular.txt
var architectsDaughterRegularBase64 string
@ -108,6 +114,14 @@ func init() {
Family: SourceCodePro,
Style: FONT_STYLE_REGULAR,
}: sourceCodeProRegularBase64,
{
Family: SourceCodePro,
Style: FONT_STYLE_BOLD,
}: sourceCodeProBoldBase64,
{
Family: SourceCodePro,
Style: FONT_STYLE_ITALIC,
}: sourceCodeProItalicBase64,
{
Family: HandDrawn,
Style: FONT_STYLE_REGULAR,
@ -144,6 +158,22 @@ func init() {
Family: SourceCodePro,
Style: FONT_STYLE_REGULAR,
}] = b
b, err = fontFacesFS.ReadFile("ttf/SourceCodePro-Bold.ttf")
if err != nil {
panic(err)
}
FontFaces[Font{
Family: SourceCodePro,
Style: FONT_STYLE_BOLD,
}] = b
b, err = fontFacesFS.ReadFile("ttf/SourceCodePro-Italic.ttf")
if err != nil {
panic(err)
}
FontFaces[Font{
Family: SourceCodePro,
Style: FONT_STYLE_ITALIC,
}] = b
b, err = fontFacesFS.ReadFile("ttf/SourceSansPro-Bold.ttf")
if err != nil {
panic(err)

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

View file

@ -47,7 +47,8 @@ func styleAttr(styles map[chroma.TokenType]string, tt chroma.TokenType) string {
}
}
}
return styles[tt]
out := strings.Replace(styles[tt], `font-weight="bold"`, `class="text-mono-bold"`, -1)
return strings.Replace(out, `font-style="italic"`, `class="text-mono-italic"`, -1)
}
// <<< END

View file

@ -1185,6 +1185,44 @@ func embedFonts(buf *bytes.Buffer, fontFamily *d2fonts.FontFamily) {
}
}
triggers = []string{
`class="text-mono-bold"`,
}
for _, t := range triggers {
if strings.Contains(content, t) {
fmt.Fprintf(buf, `
.text-mono-bold {
font-family: "font-mono-bold";
}
@font-face {
font-family: font-mono-bold;
src: url("%s");
}`,
d2fonts.FontEncodings[d2fonts.SourceCodePro.Font(0, d2fonts.FONT_STYLE_BOLD)])
break
}
}
triggers = []string{
`class="text-mono-italic"`,
}
for _, t := range triggers {
if strings.Contains(content, t) {
fmt.Fprintf(buf, `
.text-mono-italic {
font-family: "font-mono-italic";
}
@font-face {
font-family: font-mono-italic;
src: url("%s");
}`,
d2fonts.FontEncodings[d2fonts.SourceCodePro.Font(0, d2fonts.FONT_STYLE_ITALIC)])
break
}
}
buf.WriteString(`]]></style>`)
}

View file

@ -394,6 +394,56 @@ x -> a: {
label: You don't have to know how the computer works,\njust how to work the computer.
style.opacity: 0.4
}
`,
},
{
name: "sequence_diagram_self_edge_group_overlap",
script: `
shape: sequence_diagram
a: A
b: B
c: C
group 1: {
a -> a
}
group 2: {
a -> b
}
group 3: {
a -> a.a
}
group 4: {
a.a -> b
}
group 5: {
b -> b
b -> b
}
group 6: {
b -> a
}
group 7: {
a -> a
}
group 8: {
a -> a
}
a -> a
group 9: {
a -> a
}
a -> a
b -> c
group 10: {
c -> c
}
b -> c
group 11: {
c -> c
}
b -> c
`,
},
}

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 185 KiB

After

Width:  |  Height:  |  Size: 350 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 185 KiB

After

Width:  |  Height:  |  Size: 350 KiB

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 336 KiB

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 336 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 512 KiB

After

Width:  |  Height:  |  Size: 601 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 512 KiB

After

Width:  |  Height:  |  Size: 601 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 508 KiB

After

Width:  |  Height:  |  Size: 673 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 508 KiB

After

Width:  |  Height:  |  Size: 673 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 668 KiB

After

Width:  |  Height:  |  Size: 757 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 668 KiB

After

Width:  |  Height:  |  Size: 757 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 513 KiB

After

Width:  |  Height:  |  Size: 602 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 513 KiB

After

Width:  |  Height:  |  Size: 602 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 513 KiB

After

Width:  |  Height:  |  Size: 602 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 513 KiB

After

Width:  |  Height:  |  Size: 602 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 842 KiB

After

Width:  |  Height:  |  Size: 931 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 842 KiB

After

Width:  |  Height:  |  Size: 931 KiB

30
fmt.go
View file

@ -17,26 +17,24 @@ func fmtCmd(ctx context.Context, ms *xmain.State) (err error) {
ms.Opts = xmain.NewOpts(ms.Env, ms.Log, ms.Opts.Flags.Args()[1:])
if len(ms.Opts.Args) == 0 {
return xmain.UsageErrorf("fmt must be passed the file to be formatted")
} else if len(ms.Opts.Args) > 1 {
return xmain.UsageErrorf("fmt accepts only one argument for the file to be formatted")
return xmain.UsageErrorf("fmt must be passed at least one file to be formatted")
}
inputPath := ms.Opts.Args[0]
input, err := ms.ReadPath(inputPath)
if err != nil {
return err
}
for _, inputPath := range ms.Opts.Args {
input, err := ms.ReadPath(inputPath)
if err != nil {
return err
}
m, err := d2parser.Parse(inputPath, bytes.NewReader(input), nil)
if err != nil {
return err
}
m, err := d2parser.Parse(inputPath, bytes.NewReader(input), nil)
if err != nil {
return err
}
output := []byte(d2format.Format(m))
if !bytes.Equal(output, input) {
return ms.WritePath(inputPath, output)
output := []byte(d2format.Format(m))
if !bytes.Equal(output, input) {
return ms.WritePath(inputPath, output)
}
}
return nil
}

View file

@ -18,7 +18,7 @@ func help(ms *xmain.State) {
fmt.Fprintf(ms.Stdout, `Usage:
%[1]s [--watch=false] [--theme=0] file.d2 [file.svg | file.png]
%[1]s layout [name]
%[1]s fmt file.d2
%[1]s fmt file.d2 ...
%[1]s compiles and renders file.d2 to file.svg | file.png
It defaults to file.svg if an output path is not provided.
@ -33,7 +33,7 @@ Flags:
Subcommands:
%[1]s layout - Lists available layout engine options with short help
%[1]s layout [name] - Display long help for a particular layout engine, including its configuration options
%[1]s fmt file.d2 - Format file.d2
%[1]s fmt file.d2 ... - Format passed files
See more docs and the source code at https://oss.terrastruct.com/d2
`, filepath.Base(ms.Name), ms.Opts.Defaults())

View file

@ -15,6 +15,7 @@ import (
)
const TAB_SIZE = 4
const SIZELESS_FONT_SIZE = 0
// ASCII is a set of all ASCII runes. These runes are codepoints from 32 to 127 inclusive.
var ASCII []rune
@ -135,9 +136,25 @@ func NewRuler() (*Ruler, error) {
return r, nil
}
func (r *Ruler) HasFontFamilyLoaded(fontFamily *d2fonts.FontFamily) bool {
for _, fontStyle := range d2fonts.FontStyles {
font := d2fonts.Font{
Family: *fontFamily,
Style: fontStyle,
Size: SIZELESS_FONT_SIZE,
}
_, ok := r.ttfs[font]
if !ok {
return false
}
}
return true
}
func (r *Ruler) addFontSize(font d2fonts.Font) {
sizeless := font
sizeless.Size = 0
sizeless.Size = SIZELESS_FONT_SIZE
face := truetype.NewFace(r.ttfs[sizeless], &truetype.Options{
Size: float64(font.Size),
})