navbar on pptx

This commit is contained in:
Júlio César Batista 2023-04-14 19:03:28 -03:00
parent a15bc2d687
commit 7918f265d4
No known key found for this signature in database
GPG key ID: 10C4B861BF314878
4 changed files with 73 additions and 30 deletions

View file

@ -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()) p := pptx.NewPresentation(rootName, description, rootName, username, version.OnlyNumbers())
boardIdToIndex := buildBoardIDToIndex(diagram, nil, nil) 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 { if err != nil {
return nil, false, err return nil, false, err
} }
@ -785,14 +785,24 @@ func renderPDF(ctx context.Context, ms *xmain.State, plugin d2plugin.Plugin, opt
return svg, nil 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) { 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 currBoardPath []string var curr pptx.BoardTitle
// Root board doesn't have a name, so we use the output filename
if diagram.Name == "" { if diagram.Name == "" {
currBoardPath = append(boardPath, "root") curr = pptx.BoardTitle{
Name: "root",
BoardID: "root",
}
} else { } 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 var svg []byte
if !diagram.IsFolderOnly { 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" { if err != nil || key.Path[0].Unbox().ScalarString() != "root" {
// External link // External link
link.ExternalUrl = shape.Link link.ExternalUrl = shape.Link
} else if pageNum, ok := boardIdToIndex[shape.Link]; ok { } else if pageNum, ok := boardIDToIndex[shape.Link]; ok {
// Internal link // Internal link
link.SlideIndex = pageNum + 1 link.SlideIndex = pageNum + 1
} }
@ -875,19 +885,19 @@ func renderPPTX(ctx context.Context, ms *xmain.State, presentation *pptx.Present
} }
for _, dl := range diagram.Layers { 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 { if err != nil {
return nil, err return nil, err
} }
} }
for _, dl := range diagram.Scenarios { 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 { if err != nil {
return nil, err return nil, err
} }
} }
for _, dl := range diagram.Steps { 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 { if err != nil {
return nil, err return nil, err
} }

View file

@ -16,11 +16,17 @@ import (
"fmt" "fmt"
"image/png" "image/png"
"os" "os"
"strings"
"text/template" "text/template"
"time" "time"
) )
type BoardTitle struct {
LinkID string
Name string
BoardID string
LinkToSlide int
}
type Presentation struct { type Presentation struct {
Title string Title string
Description string Description string
@ -32,8 +38,9 @@ type Presentation struct {
Slides []*Slide Slides []*Slide
} }
type Slide struct { type Slide struct {
BoardPath []string BoardTitle []BoardTitle
Links []*Link Links []*Link
Image []byte Image []byte
ImageId string 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)) src, err := png.Decode(bytes.NewReader(pngContent))
if err != nil { if err != nil {
return nil, fmt.Errorf("error decoding PNG image: %v", err) 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 left := (SLIDE_WIDTH - width) / 2
slide := &Slide{ slide := &Slide{
BoardPath: make([]string, len(boardPath)), BoardTitle: make([]BoardTitle, len(titlePath)),
ImageId: fmt.Sprintf("slide%dImage", len(p.Slides)+1), ImageId: fmt.Sprintf("slide%dImage", len(p.Slides)+1),
Image: pngContent, Image: pngContent,
ImageWidth: width, ImageWidth: width,
@ -137,7 +144,10 @@ func (p *Presentation) AddSlide(pngContent []byte, boardPath []string) (*Slide,
ImageScaleFactor: float64(width) / srcWidth, ImageScaleFactor: float64(width) / srcWidth,
} }
// it must copy the board path to avoid slice reference issues // 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) p.Slides = append(p.Slides, slide)
return slide, nil return slide, nil
@ -215,11 +225,11 @@ func (p *Presentation) SaveTo(filePath string) error {
titles := make([]string, 0, len(p.Slides)) titles := make([]string, 0, len(p.Slides))
for _, slide := range 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{ err = addFileFromTemplate(zipWriter, "docProps/app.xml", APP_XML, AppXmlContent{
SlideCount: len(p.Slides), SlideCount: len(p.Slides),
TitlesOfPartsCount: len(p.Slides) + 3, TitlesOfPartsCount: len(p.Slides) + 3, // + 3 for fonts and theme
D2Version: p.D2Version, D2Version: p.D2Version,
Titles: titles, 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 return content
} }
@ -308,9 +325,14 @@ type SlideLinkXmlContent struct {
Height int Height int
} }
type SlideXmlTitlePathContent struct {
Name string
RelationshipID string
}
type SlideXmlContent struct { type SlideXmlContent struct {
Title string Title string
TitlePrefix string TitlePrefix []SlideXmlTitlePathContent
Description string Description string
HeaderHeight int HeaderHeight int
ImageID string ImageID string
@ -323,17 +345,18 @@ type SlideXmlContent struct {
} }
func getSlideXmlContent(imageID string, slide *Slide) SlideXmlContent { func getSlideXmlContent(imageID string, slide *Slide) SlideXmlContent {
boardPath := slide.BoardPath title := make([]SlideXmlTitlePathContent, len(slide.BoardTitle)-1)
boardName := boardPath[len(boardPath)-1] for i := 0; i < len(slide.BoardTitle)-1; i++ {
prefixPath := boardPath[:len(boardPath)-1] t := slide.BoardTitle[i]
var prefix string title[i] = SlideXmlTitlePathContent{
if len(prefixPath) > 0 { Name: t.Name,
prefix = strings.Join(prefixPath, " / ") + " / " RelationshipID: t.LinkID,
}
} }
content := SlideXmlContent{ content := SlideXmlContent{
Title: boardName, Title: slide.BoardTitle[len(slide.BoardTitle)-1].Name,
TitlePrefix: prefix, TitlePrefix: title,
Description: strings.Join(boardPath, " / "), Description: slide.BoardTitle[len(slide.BoardTitle)-1].BoardID,
HeaderHeight: HEADER_HEIGHT, HeaderHeight: HEADER_HEIGHT,
ImageID: imageID, ImageID: imageID,
ImageLeft: slide.ImageLeft, ImageLeft: slide.ImageLeft,

Binary file not shown.

View file

@ -75,9 +75,19 @@
<a:defRPr sz="2400" /> <a:defRPr sz="2400" />
</a:lvl1pPr> </a:lvl1pPr>
</a:lstStyle> </a:lstStyle>
<a:p> {{if .TitlePrefix}} <a:r> <a:p>
<a:t>{{.TitlePrefix}}</a:t> {{range .TitlePrefix}}
</a:r> {{end}} <a:r> <a:r>
<a:rPr>
<a:hlinkClick r:id="{{.RelationshipID}}" invalidUrl=""
action="ppaction://hlinksldjump" tgtFrame="" tooltip=""
history="1" highlightClick="0" endSnd="0" />
</a:rPr>
<a:t>{{.Name}}</a:t>
</a:r>
<a:r><a:t> / </a:t></a:r>
{{end}}
<a:r>
<a:rPr b="1" /> <a:rPr b="1" />
<a:t>{{.Title}}</a:t> <a:t>{{.Title}}</a:t>
</a:r> </a:r>