From eb2b637b42bc96d2bde7f627b828eaa3c4cc31d6 Mon Sep 17 00:00:00 2001 From: Gavin Nishizawa Date: Mon, 6 Nov 2023 16:32:39 -0800 Subject: [PATCH] fix appendix icon order --- d2renderers/d2svg/appendix/appendix.go | 38 +++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/d2renderers/d2svg/appendix/appendix.go b/d2renderers/d2svg/appendix/appendix.go index 803651f35..736e39d62 100644 --- a/d2renderers/d2svg/appendix/appendix.go +++ b/d2renderers/d2svg/appendix/appendix.go @@ -7,6 +7,7 @@ package appendix import ( "fmt" "regexp" + "sort" "strconv" "strings" @@ -146,19 +147,48 @@ func Append(diagram *d2target.Diagram, ruler *textmeasure.Ruler, in []byte) []by closingIndex := strings.LastIndex(svg, "") svg = svg[:closingIndex] + appendix + svg[closingIndex:] + // icons are numbered according to diagram.Shapes which is based on their order of definition, + // but they appear in the svg according to renderOrder so we have to replace in that order + type appendixIcon struct { + number int + isTooltip bool + shape d2target.Shape + } + var renderOrder []appendixIcon + i := 1 for _, s := range diagram.Shapes { if s.Tooltip != "" { - // The clip-path has a unique ID, so this won't replace any user icons - // In the existing SVG, the transform places it top-left, so we adjust - svg = strings.Replace(svg, d2svg.TooltipIcon, generateNumberedIcon(i, 0, ICON_RADIUS), 1) + renderOrder = append(renderOrder, appendixIcon{i, true, s}) i++ } if s.Link != "" { - svg = strings.Replace(svg, d2svg.LinkIcon, generateNumberedIcon(i, 0, ICON_RADIUS), 1) + renderOrder = append(renderOrder, appendixIcon{i, false, s}) i++ } } + // sort to match render order + sort.SliceStable(renderOrder, func(i, j int) bool { + iZIndex := renderOrder[i].shape.GetZIndex() + jZIndex := renderOrder[j].shape.GetZIndex() + if iZIndex != jZIndex { + return iZIndex < jZIndex + } + return renderOrder[i].shape.Level < renderOrder[j].shape.Level + }) + + // replace each rendered svg icon + for _, icon := range renderOrder { + // The clip-path has a unique ID, so this won't replace any user icons + // In the existing SVG, the transform places it top-left, so we adjust + var iconStr string + if icon.isTooltip { + iconStr = d2svg.TooltipIcon + } else { + iconStr = d2svg.LinkIcon + } + svg = strings.Replace(svg, iconStr, generateNumberedIcon(icon.number, 0, ICON_RADIUS), 1) + } return []byte(svg) }