|
2 | 2 | // All rights reserved. Use of this source code is governed |
3 | 3 | // by a GNU GPL-3.0 license that can be found in the LICENSE file. |
4 | 4 |
|
5 | | -package main |
| 5 | +package code2img |
6 | 6 |
|
7 | 7 | import ( |
8 | 8 | "context" |
9 | 9 | "fmt" |
10 | | - "io/ioutil" |
11 | 10 | "math" |
12 | | - "net/http" |
13 | 11 | "net/url" |
14 | | - "os" |
15 | | - "os/signal" |
16 | | - "syscall" |
17 | 12 | "time" |
18 | 13 |
|
19 | 14 | "github.com/chromedp/cdproto/cdp" |
20 | 15 | "github.com/chromedp/cdproto/dom" |
21 | 16 | "github.com/chromedp/cdproto/emulation" |
22 | 17 | "github.com/chromedp/cdproto/page" |
23 | 18 | "github.com/chromedp/chromedp" |
24 | | - "github.com/gin-gonic/gin" |
25 | | - "github.com/google/uuid" |
26 | | - "github.com/sirupsen/logrus" |
27 | 19 | ) |
28 | 20 |
|
29 | | -func main() { |
30 | | - router := gin.Default() |
31 | | - router.Static("/api/v1/code2img/data/code", "./data/code") |
32 | | - router.Static("/api/v1/code2img/data/images", "./data/images") |
33 | | - router.POST("/api/v1/code2img", code2img) |
34 | | - s := &http.Server{Addr: ":8080", Handler: router} |
35 | | - |
36 | | - go func() { |
37 | | - if err := s.ListenAndServe(); err != nil && err != http.ErrServerClosed { |
38 | | - logrus.Fatalf("listen: %s\n", err) |
39 | | - } |
40 | | - }() |
41 | | - |
42 | | - quit := make(chan os.Signal) |
43 | | - signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) |
44 | | - <-quit |
45 | | - logrus.Println("shutting down...") |
46 | | - |
47 | | - ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) |
48 | | - defer cancel() |
49 | | - if err := s.Shutdown(ctx); err != nil { |
50 | | - logrus.Fatal("forced to shutdown: ", err) |
51 | | - } |
52 | | - logrus.Println("server exiting, good bye!") |
53 | | -} |
54 | | - |
55 | | -type form struct { |
56 | | - Code string `json:"code"` |
57 | | -} |
58 | | - |
59 | | -func code2img(c *gin.Context) { |
60 | | - b := form{} |
61 | | - if err := c.ShouldBindJSON(&b); err != nil { |
62 | | - c.String(http.StatusBadRequest, fmt.Sprintf("Error: %s", err)) |
63 | | - return |
64 | | - } |
65 | | - id := uuid.New().String() |
66 | | - gofile := "./data/code/" + id + ".go" |
67 | | - |
68 | | - err := ioutil.WriteFile(gofile, []byte(b.Code), os.ModePerm) |
69 | | - if err != nil { |
70 | | - logrus.Errorf("[%s]: write file error %v", gofile, err) |
71 | | - c.String(http.StatusBadRequest, fmt.Sprintf("Error: %s", err)) |
72 | | - return |
73 | | - } |
74 | | - |
75 | | - err = render("./data/images/"+id+".png", b.Code) |
76 | | - if err != nil { |
77 | | - c.String(http.StatusBadRequest, fmt.Sprintf("Error: %s", err)) |
78 | | - return |
79 | | - } |
80 | | - |
81 | | - c.String(http.StatusOK, "https://golang.design/api/v1/code2img/data/images/"+id+".png") |
82 | | -} |
83 | | - |
84 | | -func render(imgfile, code string) error { |
| 21 | +// Render renders the given code string and returns a binary buffer |
| 22 | +// that contains a carbon-now based image. |
| 23 | +func Render(code string) ([]byte, error) { |
85 | 24 | // https://carbon.now.sh/? |
86 | 25 | // bg=rgba(74%2C144%2C226%2C1)& |
87 | 26 | // t=material& |
@@ -147,15 +86,9 @@ func render(imgfile, code string) error { |
147 | 86 | screenshot(sel, &picbuf, chromedp.NodeReady, chromedp.ByID), |
148 | 87 | }) |
149 | 88 | if err != nil { |
150 | | - return fmt.Errorf("render task error: %w", err) |
151 | | - } |
152 | | - |
153 | | - err = ioutil.WriteFile(imgfile, picbuf, os.ModePerm) |
154 | | - if err != nil { |
155 | | - logrus.Errorf("[%s]: write screenshot error %v", imgfile, err) |
156 | | - return err |
| 89 | + return nil, fmt.Errorf("code2img: render task failed: %w", err) |
157 | 90 | } |
158 | | - return nil |
| 91 | + return picbuf, nil |
159 | 92 | } |
160 | 93 |
|
161 | 94 | func screenshot(sel interface{}, picbuf *[]byte, opts ...chromedp.QueryOption) chromedp.QueryAction { |
|
0 commit comments