parent
9998b0039b
commit
8e07980b06
8 changed files with 152 additions and 46 deletions
|
|
@ -19,7 +19,6 @@ import (
|
|||
"oss.terrastruct.com/util-go/go2"
|
||||
"oss.terrastruct.com/util-go/xmain"
|
||||
|
||||
"oss.terrastruct.com/d2/d2graph"
|
||||
"oss.terrastruct.com/d2/d2lib"
|
||||
"oss.terrastruct.com/d2/d2plugin"
|
||||
"oss.terrastruct.com/d2/d2renderers/d2animate"
|
||||
|
|
@ -339,7 +338,7 @@ func compile(ctx context.Context, ms *xmain.State, plugin d2plugin.Plugin, rende
|
|||
|
||||
if filepath.Ext(outputPath) == ".pdf" {
|
||||
pageMap := pdf.BuildPDFPageMap(diagram, nil, nil)
|
||||
pdf, err := renderPDF(ctx, ms, plugin, renderOpts, outputPath, page, ruler, diagram, g, nil, nil, pageMap)
|
||||
pdf, err := renderPDF(ctx, ms, plugin, renderOpts, outputPath, page, ruler, diagram, nil, nil, pageMap)
|
||||
if err != nil {
|
||||
return pdf, false, err
|
||||
}
|
||||
|
|
@ -348,13 +347,13 @@ func compile(ctx context.Context, ms *xmain.State, plugin d2plugin.Plugin, rende
|
|||
return pdf, true, nil
|
||||
} else {
|
||||
compileDur := time.Since(start)
|
||||
boards, err := render(ctx, ms, compileDur, plugin, renderOpts, inputPath, outputPath, bundle, forceAppendix, page, ruler, diagram, g)
|
||||
boards, err := render(ctx, ms, compileDur, plugin, renderOpts, inputPath, outputPath, bundle, forceAppendix, page, ruler, diagram)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
out := boards[0]
|
||||
if animateInterval > 0 {
|
||||
out, err = d2animate.Wrap(diagram, g, boards, renderOpts, int(animateInterval))
|
||||
out, err = d2animate.Wrap(diagram, boards, renderOpts, int(animateInterval))
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
|
|
@ -372,7 +371,7 @@ func compile(ctx context.Context, ms *xmain.State, plugin d2plugin.Plugin, rende
|
|||
}
|
||||
}
|
||||
|
||||
func render(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, g *d2graph.Graph) ([][]byte, error) {
|
||||
func render(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) {
|
||||
if diagram.Name != "" {
|
||||
ext := filepath.Ext(outputPath)
|
||||
outputPath = strings.TrimSuffix(outputPath, ext)
|
||||
|
|
@ -418,21 +417,21 @@ func render(ctx context.Context, ms *xmain.State, compileDur time.Duration, plug
|
|||
|
||||
var boards [][]byte
|
||||
for _, dl := range diagram.Layers {
|
||||
childrenBoards, err := render(ctx, ms, compileDur, plugin, opts, inputPath, layersOutputPath, bundle, forceAppendix, page, ruler, dl, g)
|
||||
childrenBoards, err := render(ctx, ms, compileDur, plugin, opts, inputPath, layersOutputPath, bundle, forceAppendix, page, ruler, dl)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
boards = append(boards, childrenBoards...)
|
||||
}
|
||||
for _, dl := range diagram.Scenarios {
|
||||
childrenBoards, err := render(ctx, ms, compileDur, plugin, opts, inputPath, scenariosOutputPath, bundle, forceAppendix, page, ruler, dl, g)
|
||||
childrenBoards, err := render(ctx, ms, compileDur, plugin, opts, inputPath, scenariosOutputPath, bundle, forceAppendix, page, ruler, dl)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
boards = append(boards, childrenBoards...)
|
||||
}
|
||||
for _, dl := range diagram.Steps {
|
||||
childrenBoards, err := render(ctx, ms, compileDur, plugin, opts, inputPath, stepsOutputPath, bundle, forceAppendix, page, ruler, dl, g)
|
||||
childrenBoards, err := render(ctx, ms, compileDur, plugin, opts, inputPath, stepsOutputPath, bundle, forceAppendix, page, ruler, dl)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -441,7 +440,7 @@ func render(ctx context.Context, ms *xmain.State, compileDur time.Duration, plug
|
|||
|
||||
if !diagram.IsFolderOnly {
|
||||
start := time.Now()
|
||||
out, err := _render(ctx, ms, plugin, opts, boardOutputPath, bundle, forceAppendix, page, ruler, diagram, g)
|
||||
out, err := _render(ctx, ms, plugin, opts, boardOutputPath, bundle, forceAppendix, page, ruler, diagram)
|
||||
if err != nil {
|
||||
return boards, err
|
||||
}
|
||||
|
|
@ -456,9 +455,9 @@ func render(ctx context.Context, ms *xmain.State, compileDur time.Duration, plug
|
|||
return nil, 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, g *d2graph.Graph) ([]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 := filepath.Ext(outputPath) == ".png"
|
||||
svg, err := d2svg.Render(diagram, g, &d2svg.RenderOpts{
|
||||
svg, err := d2svg.Render(diagram, &d2svg.RenderOpts{
|
||||
Pad: opts.Pad,
|
||||
Sketch: opts.Sketch,
|
||||
Center: opts.Center,
|
||||
|
|
@ -526,7 +525,7 @@ func _render(ctx context.Context, ms *xmain.State, plugin d2plugin.Plugin, opts
|
|||
return svg, nil
|
||||
}
|
||||
|
||||
func renderPDF(ctx context.Context, ms *xmain.State, plugin d2plugin.Plugin, opts d2svg.RenderOpts, outputPath string, page playwright.Page, ruler *textmeasure.Ruler, diagram *d2target.Diagram, g *d2graph.Graph, pdf *pdflib.GoFPDF, boardPath []string, pageMap map[string]int) (svg []byte, err error) {
|
||||
func renderPDF(ctx context.Context, ms *xmain.State, plugin d2plugin.Plugin, opts d2svg.RenderOpts, outputPath string, page playwright.Page, ruler *textmeasure.Ruler, diagram *d2target.Diagram, pdf *pdflib.GoFPDF, boardPath []string, pageMap map[string]int) (svg []byte, err error) {
|
||||
var isRoot bool
|
||||
if pdf == nil {
|
||||
pdf = pdflib.Init()
|
||||
|
|
@ -551,7 +550,7 @@ func renderPDF(ctx context.Context, ms *xmain.State, plugin d2plugin.Plugin, opt
|
|||
// make the bg fill within the png transparent so that the pdf bg fill is the only bg color present
|
||||
diagram.Root.Fill = "transparent"
|
||||
|
||||
svg, err = d2svg.Render(diagram, g, &d2svg.RenderOpts{
|
||||
svg, err = d2svg.Render(diagram, &d2svg.RenderOpts{
|
||||
Pad: opts.Pad,
|
||||
Sketch: opts.Sketch,
|
||||
Center: opts.Center,
|
||||
|
|
@ -595,19 +594,19 @@ func renderPDF(ctx context.Context, ms *xmain.State, plugin d2plugin.Plugin, opt
|
|||
}
|
||||
|
||||
for _, dl := range diagram.Layers {
|
||||
_, err := renderPDF(ctx, ms, plugin, opts, "", page, ruler, dl, g, pdf, currBoardPath, pageMap)
|
||||
_, err := renderPDF(ctx, ms, plugin, opts, "", page, ruler, dl, pdf, currBoardPath, pageMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
for _, dl := range diagram.Scenarios {
|
||||
_, err := renderPDF(ctx, ms, plugin, opts, "", page, ruler, dl, g, pdf, currBoardPath, pageMap)
|
||||
_, err := renderPDF(ctx, ms, plugin, opts, "", page, ruler, dl, pdf, currBoardPath, pageMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
for _, dl := range diagram.Steps {
|
||||
_, err := renderPDF(ctx, ms, plugin, opts, "", page, ruler, dl, g, pdf, currBoardPath, pageMap)
|
||||
_, err := renderPDF(ctx, ms, plugin, opts, "", page, ruler, dl, pdf, currBoardPath, pageMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1501,21 +1501,6 @@ func (g *Graph) Texts() []*d2target.MText {
|
|||
return texts
|
||||
}
|
||||
|
||||
func (g *Graph) UniqueChars() string {
|
||||
var uniqueChars string
|
||||
uniqueMap := make(map[rune]bool)
|
||||
texts := g.Texts()
|
||||
for _, t := range texts {
|
||||
for _, char := range t.Text {
|
||||
if _, exists := uniqueMap[char]; !exists {
|
||||
uniqueMap[char] = true
|
||||
uniqueChars = uniqueChars + string(char)
|
||||
}
|
||||
}
|
||||
}
|
||||
return uniqueChars
|
||||
}
|
||||
|
||||
func Key(k *d2ast.KeyPath) []string {
|
||||
return d2format.KeyPath(k)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import (
|
|||
"math"
|
||||
"strings"
|
||||
|
||||
"oss.terrastruct.com/d2/d2graph"
|
||||
"oss.terrastruct.com/d2/d2renderers/d2sketch"
|
||||
"oss.terrastruct.com/d2/d2renderers/d2svg"
|
||||
"oss.terrastruct.com/d2/d2target"
|
||||
|
|
@ -44,7 +43,7 @@ func makeKeyframe(delayMS, durationMS, totalMS, identifier int) string {
|
|||
}`, identifier, percentageBefore, percentageStart, percentageEnd, percentageAfter)
|
||||
}
|
||||
|
||||
func Wrap(rootDiagram *d2target.Diagram, g *d2graph.Graph, svgs [][]byte, renderOpts d2svg.RenderOpts, intervalMS int) ([]byte, error) {
|
||||
func Wrap(rootDiagram *d2target.Diagram, svgs [][]byte, renderOpts d2svg.RenderOpts, intervalMS int) ([]byte, error) {
|
||||
buf := &bytes.Buffer{}
|
||||
|
||||
// TODO account for stroke width of root border
|
||||
|
|
@ -75,7 +74,7 @@ func Wrap(rootDiagram *d2target.Diagram, g *d2graph.Graph, svgs [][]byte, render
|
|||
return nil, err
|
||||
}
|
||||
|
||||
d2svg.EmbedFonts(buf, diagramHash, svgsStr, rootDiagram.FontFamily, g.UniqueChars())
|
||||
d2svg.EmbedFonts(buf, diagramHash, svgsStr, rootDiagram.FontFamily, rootDiagram.GetUniqueChars())
|
||||
|
||||
themeStylesheet, err := d2svg.ThemeCSS(diagramHash, renderOpts.ThemeID, renderOpts.DarkThemeID)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -32,10 +32,11 @@ func (f FontFamily) Font(size int, style FontStyle) Font {
|
|||
}
|
||||
}
|
||||
|
||||
func (f Font) GetEncodedSubset(cutSet string) string {
|
||||
func (f Font) GetEncodedSubset(cutset string) string {
|
||||
fontBuf := make([]byte, len(FontFaces[f]))
|
||||
copy(fontBuf, FontFaces[f])
|
||||
fontBuf = gofpdf.UTF8CutFont(fontBuf, cutSet)
|
||||
// gofpdf subset only accepts .ttf fonts
|
||||
fontBuf = gofpdf.UTF8CutFont(fontBuf, cutset)
|
||||
|
||||
fontBuf, err := fontlib.Sfnt2Woff(fontBuf)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -1633,7 +1633,7 @@ const DEFAULT_THEME int64 = 0
|
|||
|
||||
var DEFAULT_DARK_THEME *int64 = nil // no theme selected
|
||||
|
||||
func Render(diagram *d2target.Diagram, g *d2graph.Graph, opts *RenderOpts) ([]byte, error) {
|
||||
func Render(diagram *d2target.Diagram, opts *RenderOpts) ([]byte, error) {
|
||||
var sketchRunner *d2sketch.Runner
|
||||
pad := DEFAULT_PADDING
|
||||
themeID := DEFAULT_THEME
|
||||
|
|
@ -1727,7 +1727,7 @@ func Render(diagram *d2target.Diagram, g *d2graph.Graph, opts *RenderOpts) ([]by
|
|||
// generate style elements that will be appended to the SVG tag
|
||||
upperBuf := &bytes.Buffer{}
|
||||
if opts.MasterID == "" {
|
||||
EmbedFonts(upperBuf, diagramHash, buf.String(), diagram.FontFamily, g.UniqueChars()) // EmbedFonts *must* run before `d2sketch.DefineFillPatterns`, but after all elements are appended to `buf`
|
||||
EmbedFonts(upperBuf, diagramHash, buf.String(), diagram.FontFamily, diagram.GetUniqueChars()) // EmbedFonts *must* run before `d2sketch.DefineFillPatterns`, but after all elements are appended to `buf`
|
||||
themeStylesheet, err := ThemeCSS(diagramHash, themeID, darkThemeID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ type ClassField struct {
|
|||
|
||||
func (cf ClassField) Text(fontSize int) *MText {
|
||||
return &MText{
|
||||
Text: fmt.Sprintf("%s%s%s", cf.VisibilityToken(), cf.Name, cf.Type),
|
||||
Text: fmt.Sprintf("%s%s", cf.Name, cf.Type),
|
||||
FontSize: fontSize,
|
||||
IsBold: false,
|
||||
IsItalic: false,
|
||||
|
|
@ -44,6 +44,35 @@ func (cf ClassField) VisibilityToken() string {
|
|||
}
|
||||
}
|
||||
|
||||
func (cf ClassField) GetUniqueChars(uniqueMap map[rune]bool) string {
|
||||
var uniqueChars string
|
||||
for _, char := range "+-#" {
|
||||
if _, exists := uniqueMap[char]; !exists {
|
||||
uniqueMap[char] = true
|
||||
uniqueChars = uniqueChars + string(char)
|
||||
}
|
||||
}
|
||||
for _, char := range cf.Name {
|
||||
if _, exists := uniqueMap[char]; !exists {
|
||||
uniqueMap[char] = true
|
||||
uniqueChars = uniqueChars + string(char)
|
||||
}
|
||||
}
|
||||
for _, char := range cf.Type {
|
||||
if _, exists := uniqueMap[char]; !exists {
|
||||
uniqueMap[char] = true
|
||||
uniqueChars = uniqueChars + string(char)
|
||||
}
|
||||
}
|
||||
for _, char := range cf.Visibility {
|
||||
if _, exists := uniqueMap[char]; !exists {
|
||||
uniqueMap[char] = true
|
||||
uniqueChars = uniqueChars + string(char)
|
||||
}
|
||||
}
|
||||
return uniqueChars
|
||||
}
|
||||
|
||||
type ClassMethod struct {
|
||||
Name string `json:"name"`
|
||||
Return string `json:"return"`
|
||||
|
|
@ -70,3 +99,32 @@ func (cm ClassMethod) VisibilityToken() string {
|
|||
return "+"
|
||||
}
|
||||
}
|
||||
|
||||
func (cm ClassMethod) GetUniqueChars(uniqueMap map[rune]bool) string {
|
||||
var uniqueChars string
|
||||
for _, char := range "+-#" {
|
||||
if _, exists := uniqueMap[char]; !exists {
|
||||
uniqueMap[char] = true
|
||||
uniqueChars = uniqueChars + string(char)
|
||||
}
|
||||
}
|
||||
for _, char := range cm.Name {
|
||||
if _, exists := uniqueMap[char]; !exists {
|
||||
uniqueMap[char] = true
|
||||
uniqueChars = uniqueChars + string(char)
|
||||
}
|
||||
}
|
||||
for _, char := range cm.Return {
|
||||
if _, exists := uniqueMap[char]; !exists {
|
||||
uniqueMap[char] = true
|
||||
uniqueChars = uniqueChars + string(char)
|
||||
}
|
||||
}
|
||||
for _, char := range cm.Visibility {
|
||||
if _, exists := uniqueMap[char]; !exists {
|
||||
uniqueMap[char] = true
|
||||
uniqueChars = uniqueChars + string(char)
|
||||
}
|
||||
}
|
||||
return uniqueChars
|
||||
}
|
||||
|
|
|
|||
|
|
@ -237,6 +237,54 @@ func (diagram Diagram) BoundingBox() (topLeft, bottomRight Point) {
|
|||
return Point{x1, y1}, Point{x2, y2}
|
||||
}
|
||||
|
||||
func (diagram Diagram) GetUniqueChars() string {
|
||||
var uniqueChars string
|
||||
uniqueMap := make(map[rune]bool)
|
||||
for _, s := range diagram.Shapes {
|
||||
for _, char := range s.Label {
|
||||
if _, exists := uniqueMap[char]; !exists {
|
||||
uniqueMap[char] = true
|
||||
uniqueChars = uniqueChars + string(char)
|
||||
}
|
||||
}
|
||||
for _, char := range s.Tooltip {
|
||||
if _, exists := uniqueMap[char]; !exists {
|
||||
uniqueMap[char] = true
|
||||
uniqueChars = uniqueChars + string(char)
|
||||
}
|
||||
}
|
||||
for _, char := range s.Link {
|
||||
if _, exists := uniqueMap[char]; !exists {
|
||||
uniqueMap[char] = true
|
||||
uniqueChars = uniqueChars + string(char)
|
||||
}
|
||||
}
|
||||
if s.Type == ShapeClass {
|
||||
for _, cf := range s.Fields {
|
||||
uniqueChars = uniqueChars + cf.GetUniqueChars(uniqueMap)
|
||||
}
|
||||
for _, cm := range s.Methods {
|
||||
uniqueChars = uniqueChars + cm.GetUniqueChars(uniqueMap)
|
||||
}
|
||||
}
|
||||
if s.Type == ShapeSQLTable {
|
||||
for _, c := range s.Columns {
|
||||
uniqueChars = uniqueChars + c.GetUniqueChars(uniqueMap)
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, c := range diagram.Connections {
|
||||
for _, char := range c.Label {
|
||||
if _, exists := uniqueMap[char]; !exists {
|
||||
uniqueMap[char] = true
|
||||
uniqueChars = uniqueChars + string(char)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return uniqueChars
|
||||
}
|
||||
|
||||
func NewDiagram() *Diagram {
|
||||
return &Diagram{
|
||||
Root: Shape{
|
||||
|
|
|
|||
|
|
@ -37,13 +37,6 @@ func (c SQLColumn) Texts(fontSize int) []*MText {
|
|||
IsItalic: false,
|
||||
Shape: "sql_table",
|
||||
},
|
||||
{
|
||||
Text: c.ConstraintAbbr(),
|
||||
FontSize: fontSize,
|
||||
IsBold: false,
|
||||
IsItalic: false,
|
||||
Shape: "sql_table",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -59,3 +52,26 @@ func (c SQLColumn) ConstraintAbbr() string {
|
|||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func (c SQLColumn) GetUniqueChars(uniqueMap map[rune]bool) string {
|
||||
var uniqueChars string
|
||||
for _, char := range c.Name.Label {
|
||||
if _, exists := uniqueMap[char]; !exists {
|
||||
uniqueMap[char] = true
|
||||
uniqueChars = uniqueChars + string(char)
|
||||
}
|
||||
}
|
||||
for _, char := range c.Type.Label {
|
||||
if _, exists := uniqueMap[char]; !exists {
|
||||
uniqueMap[char] = true
|
||||
uniqueChars = uniqueChars + string(char)
|
||||
}
|
||||
}
|
||||
for _, char := range c.ConstraintAbbr() {
|
||||
if _, exists := uniqueMap[char]; !exists {
|
||||
uniqueMap[char] = true
|
||||
uniqueChars = uniqueChars + string(char)
|
||||
}
|
||||
}
|
||||
return uniqueChars
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue