From be538d6ebfc4e87765e26d5db80087a6c9b09914 Mon Sep 17 00:00:00 2001 From: ikawaha Date: Thu, 24 Oct 2024 22:06:37 +0900 Subject: [PATCH 1/2] chore: Use embedded graphviz instead of the dot command --- cmd/server/demo.go | 39 +++++++++++---------------------------- go.mod | 13 ++++++++++++- go.sum | 22 ++++++++++++++++++++++ 3 files changed, 45 insertions(+), 29 deletions(-) diff --git a/cmd/server/demo.go b/cmd/server/demo.go index d022d74..45247bd 100644 --- a/cmd/server/demo.go +++ b/cmd/server/demo.go @@ -7,12 +7,10 @@ import ( "errors" "fmt" "html/template" - "io" "net/http" - "os/exec" "strings" - "time" + "github.com/goccy/go-graphviz" "github.com/ikawaha/kagome/v2/tokenizer" ) @@ -27,11 +25,6 @@ var ( demoT = template.Must(template.New("demo").Parse(demoHTML)) ) -const ( - graphvizCmd = "dot" - cmdTimeout = 25 * time.Second -) - // TokenizeDemoHandler represents the tokenizer demo server struct. type TokenizeDemoHandler struct { tokenizer *tokenizer.Tokenizer @@ -80,31 +73,21 @@ func toRecords(tokens []tokenizer.Token) []record { } func (h *TokenizeDemoHandler) analyzeGraph(ctx context.Context, sen string, mode tokenizer.TokenizeMode) (records []record, svg string, err error) { - if _, err := exec.LookPath(graphvizCmd); err != nil { - return nil, "", errors.New("circo/graphviz is not installed in your $PATH") - } - ctx, cancel := context.WithTimeout(ctx, cmdTimeout) - defer cancel() var b bytes.Buffer - cmd := exec.CommandContext(ctx, graphvizCmd, "-Tsvg") - r0, w0 := io.Pipe() - cmd.Stdin = r0 - cmd.Stdout = &b - cmd.Stderr = Stderr - if err := cmd.Start(); err != nil { - return nil, "", fmt.Errorf("process done with error, %w", err) + tokens := h.tokenizer.AnalyzeGraph(&b, sen, mode) + graph, err := graphviz.ParseBytes(b.Bytes()) + if err != nil { + return nil, "", err } - tokens := h.tokenizer.AnalyzeGraph(w0, sen, mode) - if err := w0.Close(); err != nil { - return nil, "", fmt.Errorf("pipe close error, %w", err) + g, err := graphviz.New(ctx) + if err != nil { + return nil, "", err } - if err := cmd.Wait(); err != nil { - return nil, "", fmt.Errorf("process done with error, %w", err) + b.Reset() + if err := g.Render(ctx, graph, graphviz.SVG, &b); err != nil { + return nil, "", fmt.Errorf("render error: %w", err) } svg = b.String() - if pos := strings.Index(svg, " 0 { - svg = svg[pos:] - } records = toRecords(tokens) return records, svg, nil } diff --git a/go.mod b/go.mod index bb688a8..193dcaf 100644 --- a/go.mod +++ b/go.mod @@ -1,9 +1,20 @@ module github.com/ikawaha/kagome/v2 -go 1.19 +go 1.23.2 require ( + github.com/goccy/go-graphviz v0.2.4 github.com/ikawaha/kagome-dict v1.1.0 github.com/ikawaha/kagome-dict/ipa v1.2.0 github.com/ikawaha/kagome-dict/uni v1.2.0 ) + +require ( + github.com/disintegration/imaging v1.6.2 // indirect + github.com/flopp/go-findfont v0.1.0 // indirect + github.com/fogleman/gg v1.3.0 // indirect + github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect + github.com/tetratelabs/wazero v1.8.1 // indirect + golang.org/x/image v0.21.0 // indirect + golang.org/x/text v0.19.0 // indirect +) diff --git a/go.sum b/go.sum index 38cdc3c..3e9d21e 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,28 @@ +github.com/corona10/goimagehash v1.1.0 h1:teNMX/1e+Wn/AYSbLHX8mj+mF9r60R1kBeqE9MkoYwI= +github.com/corona10/goimagehash v1.1.0/go.mod h1:VkvE0mLn84L4aF8vCb6mafVajEb6QYMHl2ZJLn0mOGI= +github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c= +github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4= +github.com/flopp/go-findfont v0.1.0 h1:lPn0BymDUtJo+ZkV01VS3661HL6F4qFlkhcJN55u6mU= +github.com/flopp/go-findfont v0.1.0/go.mod h1:wKKxRDjD024Rh7VMwoU90i6ikQRCr+JTHB5n4Ejkqvw= +github.com/fogleman/gg v1.3.0 h1:/7zJX8F6AaYQc57WQCyN9cAIz+4bCJGO9B+dyW29am8= +github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= +github.com/goccy/go-graphviz v0.2.4 h1:3ujZoLVp7dT2lxuUPeaZvkFQtHU8E54d/LlDc/idrHQ= +github.com/goccy/go-graphviz v0.2.4/go.mod h1:hssjl/qbvUXGmloY81BwXt2nqoApKo7DFgDj5dLJGb8= +github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g= +github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/ikawaha/kagome-dict v1.1.0 h1:ePU16KkyonhYLo4YDf/UExmZJBhY/6C946T1SOg1TI4= github.com/ikawaha/kagome-dict v1.1.0/go.mod h1:tcbTxQQll5voEBnJqGYt2zJuCouUL6buAOrpSxzo9Fg= github.com/ikawaha/kagome-dict/ipa v1.2.0 h1:lgehXOf2USDkBwGPEBD9sbbOBk3WlkhZ2zejPSLjIJA= github.com/ikawaha/kagome-dict/ipa v1.2.0/go.mod h1:LRtB3BXipG3Iu4V+KI/E1E7r9GMa79WgAH6IAW4wy6A= github.com/ikawaha/kagome-dict/uni v1.2.0 h1:BMv15D69ngwD0Yqc3QiniAYpYAQ+IRDvBGTk/Jqj8dw= github.com/ikawaha/kagome-dict/uni v1.2.0/go.mod h1:wHaaFLLTKRJVGzElVED9RiMABZ8GSsaaJ7Tn3wzNon4= +github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ= +github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= +github.com/tetratelabs/wazero v1.8.1 h1:NrcgVbWfkWvVc4UtT4LRLDf91PsOzDzefMdwhLfA550= +github.com/tetratelabs/wazero v1.8.1/go.mod h1:yAI0XTsMBhREkM/YDAK/zNou3GoiAce1P6+rp/wQhjs= +golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.21.0 h1:c5qV36ajHpdj4Qi0GnE0jUc/yuo33OLFaa0d+crTD5s= +golang.org/x/image v0.21.0/go.mod h1:vUbsLavqK/W303ZroQQVKQ+Af3Yl6Uz1Ppu5J/cLz78= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= From e8712760b331d185ce7f736b7a22c76f0b98fa4f Mon Sep 17 00:00:00 2001 From: ikawaha Date: Thu, 24 Oct 2024 22:12:39 +0900 Subject: [PATCH 2/2] chore: Update --- cmd/server/demo_test.go | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/cmd/server/demo_test.go b/cmd/server/demo_test.go index 331d718..9917995 100644 --- a/cmd/server/demo_test.go +++ b/cmd/server/demo_test.go @@ -6,7 +6,6 @@ import ( "io" "net/http" "net/http/httptest" - "os/exec" "reflect" "strings" "testing" @@ -60,9 +59,6 @@ func TestTokenizeDemoHandler_ServeHTTP(t *testing.T) { }) t.Run("w/ lattice", func(t *testing.T) { - if _, err := exec.LookPath(graphvizCmd); err != nil { - t.Skipf("graphviz command not found, %v", err) - } req := httptest.NewRequest(http.MethodPost, `/?s=ねこです&r=Search&lattice=true`, nil) w := httptest.NewRecorder() (&TokenizeDemoHandler{tokenizer: tnz}).ServeHTTP(w, req) @@ -86,9 +82,6 @@ func TestTokenizeDemoHandler_ServeHTTP(t *testing.T) { } func TestTokenizeDemoHandler_analyzeGraph(t *testing.T) { - if _, err := exec.LookPath(graphvizCmd); err != nil { - t.Skipf("graphviz command not found, %v", err) - } tnz, err := tokenizer.New(loadTestDict(t)) if err != nil { t.Fatalf("unexpected error, %v", err) @@ -116,11 +109,8 @@ func TestTokenizeDemoHandler_analyzeGraph(t *testing.T) { }; !reflect.DeepEqual(got, want) { t.Errorf("got %+v, want %v", got, want) } - if !strings.HasPrefix(svg, "