Created
July 1, 2023 20:13
-
-
Save matisiekpl/b660f017f549e110a5f03a8b916ac54d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"encoding/base64" | |
"fmt" | |
"github.com/matisiekpl/figma" | |
"image" | |
"image/draw" | |
) | |
func RenderRemote(mainImage draw.Image, frame figma.Node, node figma.Node, dry bool, images map[string][]byte) { | |
if dry { | |
images[node.ID] = nil | |
return | |
} | |
relativeX, relativeY := GetRelativePosition(frame, node) | |
html := fmt.Sprintf("<html><body><div><img src='data:image/png;base64,%s'></div></body></html>", base64.StdEncoding.EncodeToString(images[node.ID])) | |
html += fmt.Sprintf("<style> div { position: relative; width: %fpx; height: %fpx; } </style>", frame.AbsoluteBoundingBox.Width, frame.AbsoluteBoundingBox.Height) | |
html += fmt.Sprintf("<style> img { position: absolute; left: %fpx; top: %fpx; } </style>", relativeX, relativeY) | |
html = AddStyling(html, node, "img") | |
layer := RenderHTML(html, frame.ID, false) | |
draw.Draw(mainImage, layer.Bounds(), layer, image.Point{}, draw.Over) | |
} | |
func RenderRecursively(context RenderContext, mainImage draw.Image, frame figma.Node, node figma.Node, dry bool, images map[string][]byte) { | |
if CheckIfNodeHasDynamicElements(node) { | |
if CheckIfNodeIsDynamic(node) { | |
if !dry { | |
if node.Type == figma.NodeTypeText { | |
label := node.Characters | |
label = "Dark mode" | |
drawing := RenderText(node, frame, label) | |
draw.Draw(mainImage, drawing.Bounds(), drawing, image.Point{}, draw.Over) | |
} | |
} | |
} else { | |
for _, child := range node.Children { | |
RenderRecursively(context, mainImage, frame, child, dry, images) | |
} | |
} | |
} else { | |
RenderRemote(mainImage, frame, node, dry, images) | |
} | |
} | |
func RenderFrame(context RenderContext, frame figma.Node) (image.Image, error) { | |
InitChrome(frame) | |
mainImage := image.NewRGBA(image.Rect(0, 0, int(frame.AbsoluteBoundingBox.Width), int(frame.AbsoluteBoundingBox.Height))) | |
html := fmt.Sprintf("<style> body { background-color: rgba(%f,%f,%f,%f); } </style>", frame.BackgroundColor.Red*255, frame.BackgroundColor.Green*255, frame.BackgroundColor.Blue*255, frame.BackgroundColor.Alpha*255) | |
back := RenderHTML(html, frame.ID, false) | |
draw.Draw(mainImage, back.Bounds(), back, image.Point{}, draw.Over) | |
var images = make(map[string][]byte) | |
RenderRecursively(context, mainImage, frame, frame, true, images) | |
var ids []string | |
for k := range images { | |
ids = append(ids, k) | |
} | |
images, err := SendRenderRequest(context, ids) | |
if err != nil { | |
return nil, err | |
} | |
RenderRecursively(context, mainImage, frame, frame, false, images) | |
return mainImage, nil | |
} | |
func RenderText(node figma.Node, frame figma.Node, label string) image.Image { | |
relativeX, relativeY := GetRelativePosition(frame, node) | |
html := fmt.Sprintf("<html><head><link rel='stylesheet' href='https://fonts.googleapis.com/css?family=%s'></head><body>", node.Style.FontFamily) | |
html += fmt.Sprintf("<style> div { width: %fpx; } </style>", node.AbsoluteBoundingBox.Width) | |
html += fmt.Sprintf("<style> header { height: %fpx; } </style>", node.AbsoluteBoundingBox.Height) | |
html += fmt.Sprintf("<style> div { font-size: %fpx; } </style>", node.Style.FontSize) | |
html += fmt.Sprintf("<style> div { font-weight: %f } </style>", node.Style.FontWeight) | |
html += fmt.Sprintf("<style> div { color: rgba(%f,%f,%f,%f) } </style>", node.Fills[0].Color.Red*255, node.Fills[0].Color.Green*255, node.Fills[0].Color.Blue*255, node.Fills[0].Color.Alpha*255) | |
if node.Style.Italic { | |
html += "<style> div { font-style: italic; } </style>" | |
} | |
if node.Style.TextAlignHorizontal == "LEFT" { | |
html += "<style> div { text-align: left;} </style>" | |
} | |
if node.Style.TextAlignHorizontal == "RIGHT" { | |
html += "<style> div { text-align: right; } </style>" | |
} | |
if node.Style.TextAlignHorizontal == "CENTER" { | |
html += "<style> div { text-align: center; } </style>" | |
} | |
if node.Style.TextAlignVertical == "BOTTOM" { | |
html += "<style> div { position: absolute; bottom: 0; } </style>" | |
html += "<style> header { position: relative; } </style>" | |
} | |
if node.Style.TextAlignVertical == "CENTER" { | |
html += "<style> div { position: absolute; top: 50%; transform: translateY(-50%); } </style>" | |
html += "<style> header { position: relative; } </style>" | |
} | |
html += "<style> frame { position: relative; width: 100%; height: 100% } </style>" | |
html += fmt.Sprintf("<style> component { position: absolute; left: %fpx; top: %fpx; } </style>", relativeX, relativeY) | |
html += fmt.Sprintf("<style> body { font-family: '%s', serif; } </style>", node.Style.FontFamily) | |
html += AddStyling(html, node, "div") | |
html += fmt.Sprintf("<frame><component><header><div>%s</div></header></component></frame>", label) | |
html += "</body></html>" | |
return RenderHTML(html, frame.ID, true) | |
} | |
type RenderContext struct { | |
Token string | |
FileKey string | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment