From 7918f265d4ec953131028cd21629d0c38c15e0e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BAlio=20C=C3=A9sar=20Batista?= Date: Fri, 14 Apr 2023 19:03:28 -0300 Subject: [PATCH] navbar on pptx --- d2cli/main.go | 30 ++++++++++++------ lib/pptx/pptx.go | 57 ++++++++++++++++++++++++----------- lib/pptx/template.pptx | Bin 26731 -> 26832 bytes lib/pptx/templates/slide.xml | 16 ++++++++-- 4 files changed, 73 insertions(+), 30 deletions(-) diff --git a/d2cli/main.go b/d2cli/main.go index 24a6387d2..7b91422ad 100644 --- a/d2cli/main.go +++ b/d2cli/main.go @@ -372,7 +372,7 @@ func compile(ctx context.Context, ms *xmain.State, plugin d2plugin.Plugin, rende p := pptx.NewPresentation(rootName, description, rootName, username, version.OnlyNumbers()) boardIdToIndex := buildBoardIDToIndex(diagram, nil, nil) - svg, err := renderPPTX(ctx, ms, p, plugin, renderOpts, ruler, outputPath, page, diagram, nil, boardIdToIndex) + svg, err := renderPPTX(ctx, ms, p, plugin, renderOpts, ruler, outputPath, page, diagram, nil, "", boardIdToIndex) if err != nil { return nil, false, err } @@ -785,14 +785,24 @@ func renderPDF(ctx context.Context, ms *xmain.State, plugin d2plugin.Plugin, opt return svg, nil } -func renderPPTX(ctx context.Context, ms *xmain.State, presentation *pptx.Presentation, plugin d2plugin.Plugin, opts d2svg.RenderOpts, ruler *textmeasure.Ruler, outputPath string, page playwright.Page, diagram *d2target.Diagram, boardPath []string, boardIdToIndex map[string]int) ([]byte, error) { - var currBoardPath []string - // Root board doesn't have a name, so we use the output filename +func renderPPTX(ctx context.Context, ms *xmain.State, presentation *pptx.Presentation, plugin d2plugin.Plugin, opts d2svg.RenderOpts, ruler *textmeasure.Ruler, outputPath string, page playwright.Page, diagram *d2target.Diagram, boardPath []pptx.BoardTitle, boardType string, boardIDToIndex map[string]int) ([]byte, error) { + var curr pptx.BoardTitle if diagram.Name == "" { - currBoardPath = append(boardPath, "root") + curr = pptx.BoardTitle{ + Name: "root", + BoardID: "root", + } } else { - currBoardPath = append(boardPath, diagram.Name) + prev := boardPath[len(boardPath)-1] + curr = pptx.BoardTitle{ + Name: diagram.Name, + BoardID: strings.Join([]string{prev.BoardID, boardType, diagram.Name}, "."), + } } + if pageNum, ok := boardIDToIndex[curr.BoardID]; ok { + curr.LinkToSlide = pageNum + 1 + } + currBoardPath := append(boardPath, curr) var svg []byte if !diagram.IsFolderOnly { @@ -867,7 +877,7 @@ func renderPPTX(ctx context.Context, ms *xmain.State, presentation *pptx.Present if err != nil || key.Path[0].Unbox().ScalarString() != "root" { // External link link.ExternalUrl = shape.Link - } else if pageNum, ok := boardIdToIndex[shape.Link]; ok { + } else if pageNum, ok := boardIDToIndex[shape.Link]; ok { // Internal link link.SlideIndex = pageNum + 1 } @@ -875,19 +885,19 @@ func renderPPTX(ctx context.Context, ms *xmain.State, presentation *pptx.Present } for _, dl := range diagram.Layers { - _, err := renderPPTX(ctx, ms, presentation, plugin, opts, ruler, "", page, dl, currBoardPath, boardIdToIndex) + _, err := renderPPTX(ctx, ms, presentation, plugin, opts, ruler, "", page, dl, currBoardPath, LAYERS, boardIDToIndex) if err != nil { return nil, err } } for _, dl := range diagram.Scenarios { - _, err := renderPPTX(ctx, ms, presentation, plugin, opts, ruler, "", page, dl, currBoardPath, boardIdToIndex) + _, err := renderPPTX(ctx, ms, presentation, plugin, opts, ruler, "", page, dl, currBoardPath, SCENARIOS, boardIDToIndex) if err != nil { return nil, err } } for _, dl := range diagram.Steps { - _, err := renderPPTX(ctx, ms, presentation, plugin, opts, ruler, "", page, dl, currBoardPath, boardIdToIndex) + _, err := renderPPTX(ctx, ms, presentation, plugin, opts, ruler, "", page, dl, currBoardPath, STEPS, boardIDToIndex) if err != nil { return nil, err } diff --git a/lib/pptx/pptx.go b/lib/pptx/pptx.go index 9bc885fd8..66d02e317 100644 --- a/lib/pptx/pptx.go +++ b/lib/pptx/pptx.go @@ -16,11 +16,17 @@ import ( "fmt" "image/png" "os" - "strings" "text/template" "time" ) +type BoardTitle struct { + LinkID string + Name string + BoardID string + LinkToSlide int +} + type Presentation struct { Title string Description string @@ -32,8 +38,9 @@ type Presentation struct { Slides []*Slide } + type Slide struct { - BoardPath []string + BoardTitle []BoardTitle Links []*Link Image []byte ImageId string @@ -76,7 +83,7 @@ func NewPresentation(title, description, subject, creator, d2Version string) *Pr } } -func (p *Presentation) AddSlide(pngContent []byte, boardPath []string) (*Slide, error) { +func (p *Presentation) AddSlide(pngContent []byte, titlePath []BoardTitle) (*Slide, error) { src, err := png.Decode(bytes.NewReader(pngContent)) if err != nil { return nil, fmt.Errorf("error decoding PNG image: %v", err) @@ -127,7 +134,7 @@ func (p *Presentation) AddSlide(pngContent []byte, boardPath []string) (*Slide, left := (SLIDE_WIDTH - width) / 2 slide := &Slide{ - BoardPath: make([]string, len(boardPath)), + BoardTitle: make([]BoardTitle, len(titlePath)), ImageId: fmt.Sprintf("slide%dImage", len(p.Slides)+1), Image: pngContent, ImageWidth: width, @@ -137,7 +144,10 @@ func (p *Presentation) AddSlide(pngContent []byte, boardPath []string) (*Slide, ImageScaleFactor: float64(width) / srcWidth, } // it must copy the board path to avoid slice reference issues - copy(slide.BoardPath, boardPath) + for i := 0; i < len(titlePath); i++ { + titlePath[i].LinkID = fmt.Sprintf("navLink%d", i) + slide.BoardTitle[i] = titlePath[i] + } p.Slides = append(p.Slides, slide) return slide, nil @@ -215,11 +225,11 @@ func (p *Presentation) SaveTo(filePath string) error { titles := make([]string, 0, len(p.Slides)) for _, slide := range p.Slides { - titles = append(titles, strings.Join(slide.BoardPath, "/")) + titles = append(titles, slide.BoardTitle[len(slide.BoardTitle)-1].BoardID) } err = addFileFromTemplate(zipWriter, "docProps/app.xml", APP_XML, AppXmlContent{ SlideCount: len(p.Slides), - TitlesOfPartsCount: len(p.Slides) + 3, + TitlesOfPartsCount: len(p.Slides) + 3, // + 3 for fonts and theme D2Version: p.D2Version, Titles: titles, }) @@ -291,6 +301,13 @@ func getSlideXmlRelsContent(imageID string, slide *Slide) RelsSlideXmlContent { }) } + for _, t := range slide.BoardTitle { + content.Links = append(content.Links, RelsSlideXmlLinkContent{ + RelationshipID: t.LinkID, + SlideIndex: t.LinkToSlide, + }) + } + return content } @@ -308,9 +325,14 @@ type SlideLinkXmlContent struct { Height int } +type SlideXmlTitlePathContent struct { + Name string + RelationshipID string +} + type SlideXmlContent struct { Title string - TitlePrefix string + TitlePrefix []SlideXmlTitlePathContent Description string HeaderHeight int ImageID string @@ -323,17 +345,18 @@ type SlideXmlContent struct { } func getSlideXmlContent(imageID string, slide *Slide) SlideXmlContent { - boardPath := slide.BoardPath - boardName := boardPath[len(boardPath)-1] - prefixPath := boardPath[:len(boardPath)-1] - var prefix string - if len(prefixPath) > 0 { - prefix = strings.Join(prefixPath, " / ") + " / " + title := make([]SlideXmlTitlePathContent, len(slide.BoardTitle)-1) + for i := 0; i < len(slide.BoardTitle)-1; i++ { + t := slide.BoardTitle[i] + title[i] = SlideXmlTitlePathContent{ + Name: t.Name, + RelationshipID: t.LinkID, + } } content := SlideXmlContent{ - Title: boardName, - TitlePrefix: prefix, - Description: strings.Join(boardPath, " / "), + Title: slide.BoardTitle[len(slide.BoardTitle)-1].Name, + TitlePrefix: title, + Description: slide.BoardTitle[len(slide.BoardTitle)-1].BoardID, HeaderHeight: HEADER_HEIGHT, ImageID: imageID, ImageLeft: slide.ImageLeft, diff --git a/lib/pptx/template.pptx b/lib/pptx/template.pptx index f87fcd9e2e5c66f49ea051c9e21444cd77454715..783f7014c88be4b7cc38e6378e56526953c8bc78 100644 GIT binary patch delta 2003 zcmZuydpr{g8{Ta0>_pwhnEHb!7D%j0IUoE0EDH%*l}y+%ahVyoFtO9km!b~kwY}y0;txF`>xdR z0oD<8jgbd@Zi2Xlr|26~-|HPKskOHbTaNEcz^_qq@nNLR3pAw}DJ#0lm(~@MR^y(k z6ADomF23Ey*=<;!chY)BT2&Bck(6gfDE!>TN|238#l)(EcJJv&xp!tdgewoZNKBf>ffhQrI0SE$nm3N^pmu%#S`8VhpzPB zMhv1R3fDE-=8+63-F9=`xbOKU{Jgqnw!!9J5(x}>yK~~}g5(U?)1b?wtBi@G&yAZr z_J+#Z$N%Tje8^*){X(3eos#@YcowMa^2j3Obz3YSR(|qP{tfrUaYyJMX*bQV^-l9W z-Z?or9cMj>+#YeQZ@pofnzF%5hv2Y8p_3!h4*Gbi!<9I(vhwDFCQDF%+yl{^j0eY1 zZtX2k%ChmHcjYwEuVtJiv4>t=>AO{^eOl5K*BO_or0hO7Py6&-GE;-A$(>EcHF&2A)^^gP+ zW6N2*Or>{Coj*x7*ft4z_Zk*ds%NVh>`@%+A5bfbQ9DZzekv*U&6u>F<7MlNxv8vj}{F?51;#2OH(Sza0n0h*~L^5X-ZiegF z)|Tt|q=WnVd!Q}_Ie(aOADZQsAbt^D`u9-M{QVKiL1JN{-aTnG&U7Zvj>pYuK2a14 zT`XvMN@A9x#`p^vJk;c9curkMMu-r1r#cE{IeTgb{WOq}*X%7w=qWB#3}u(Pzd$GD zV^dVInQ=|bk@{%A0j~GR^C3r*;r$JZhQzTgciGH?$gR4)nESTl@c6sbFG52){3Ku#sqd-?kDb@|mi+NA_Z$D8@kL`R&utXGo==Bijb8s5BUOWyPmAcm~T}IVU z!fX}58=4~O`k#MxGPqU3lGE)rXsIXyZ*_yge`pX0khCM(kQadeaF=A^ zN?~Bg+?fcDB|_BoGR4ugN?;IICR{ppWiX-C7ESQA8~MZgV*xZ$%YAOT`KbNPN6hQ^ z;Z!;2MVEuW8E%$~Xr#@EThrBvM3Yq6rgri=NW;Hx8KhC6G<@?!26k> zGYcr68Vw>@iVTT`fh%NNdp=n0zz8+Cd>p_vao@i+b3h^v&%_oGX` z(4-1@b%pB9&2R7;;=;+#YT(ytiECScT1D?befdoyAdmnzZO?SH6fs!(~~Tv4sO z7foJ?Yu-(BnMocMjm;w=3Ag*7&gXMJpYuKE`~9Bt-{B5`=D46LFc@MtWXO^PS13YG z4jBSm#30~$01Y(4lzzgAKC;q#Bp}Aze#M=%MIYHLwOv0k<<*rSwmX~*;5(gU0nGki z0GD7%0H-0hL-&8*atF5CQKJFI!JQsxKt5pSH7qUyZuI|7mKa9@W$lJa1Ja~xNGS=4 znFBzmD+0*Js8YmU&Jm+#YR&ujltWh|f=4`Nq1SHlt4GV7HMGLh4*pKN$9FBpzHuOH z2;L`w+FtnQfEvWcVftKf!_^iYLRvZGo9gOp8#{K&5kOeIRMSzKn?h%qo;nD+(OR_Y`NP zGqowt;NF-G<*Sm(6xY|EY>f@}6eM2R?2hhgVJ!Q$uUu~mf33S7EFp^XW3rM+s{|ae z+YR!u&F%>|rFqdo*LO0^0Aau*=u$TZM8enRQrI%}M3A6IpIamO_%X4v!+bW5-PbncD!^vMi^7=X!LX@W1)`~ z9X6LXPj`Oy1!`SP7gL_@(R>~>)T#Z~%$mPRevs|QWXvA_^XX3~z{xBV#R~~G=h%oT zXuC!34XjETgrd3e2#omcPcWB>Ypuv$&H5hQrV<9J@Z8o z{yr;q?EX1ipLa;4o$cWgK?k~*S!2%|)?0GgelhB_8EGP=me+L=Z;J2Veth#d0*{6( zxEOlnI%g2cl(KaGzD-Tjpup<16AK{>Z|l2U;T(^a^fp|D=4tr0*lgN&T={5%+fo7%Jl$946Cc%@L-f?%r)h+bW0)d6l(Gz0jktS?fn@A6Aki z=OP}y($lEYsR*xQ&!fiTrk@L-;p)F`QahY)azZ#f(0IzH2bT-&@1*D8?bh#RoaEM* zs^`>vqg3Kflxr_Fcd{N#i#imEg{b+J0x_H{X3SrVueK$L4`%hLY-LZi?K%{%QDGi< zud)*wvhL>@B(<*|qnqk9ZHSC%e^$zhy-k;2x&6q$U^#TD(xpCk;UoCBQO8#uBR3=y z>uA~SD=eDhE#ZMmt^V*R9jP##W1N|@C_<3XL|3JS*5l#&PJ|9zt(dKWfmh%tH_oGm zvc+uD8LP`>(0SZ;2laa`QMX}zpQ|GT3do15v9O+GdEk!kPamb5Xb1={sQ;L2L0UW{ XfD@j|fMX~Ylm^g4t)=3;B!0wyD{zQM diff --git a/lib/pptx/templates/slide.xml b/lib/pptx/templates/slide.xml index d138670ea..eace2f28e 100644 --- a/lib/pptx/templates/slide.xml +++ b/lib/pptx/templates/slide.xml @@ -75,9 +75,19 @@ - {{if .TitlePrefix}} - {{.TitlePrefix}} - {{end}} + + {{range .TitlePrefix}} + + + + + {{.Name}} + + / + {{end}} + {{.Title}}