diff --git a/go.mod b/go.mod index 2233d108..013fe1f4 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/ufukty/kask -go 1.24.2 +go 1.24.4 require ( github.com/alecthomas/chroma v0.10.0 @@ -11,4 +11,5 @@ require ( require ( github.com/dlclark/regexp2 v1.11.5 // indirect github.com/stretchr/testify v1.8.1 // indirect + github.com/ufukty/diagramer v0.1.0 // indirect ) diff --git a/go.sum b/go.sum index 8363808d..9df718e9 100644 --- a/go.sum +++ b/go.sum @@ -18,6 +18,10 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/ufukty/diagramer v0.0.1 h1:ZUrW+zWZBMOVp4HWoRkN3/klZD5WFFojUOubN50e7NA= +github.com/ufukty/diagramer v0.0.1/go.mod h1:fLoTnqzvqEqIifDyXANoPbM8g87a+x2CpsIRBDo9VaQ= +github.com/ufukty/diagramer v0.1.0 h1:9VXJoj7B0Hd70zjb5oV0yxqlRYdZ2L/VgqsA2UD63ew= +github.com/ufukty/diagramer v0.1.0/go.mod h1:fLoTnqzvqEqIifDyXANoPbM8g87a+x2CpsIRBDo9VaQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/builder/markdown/hook/diagramer/render.go b/internal/builder/markdown/hook/diagramer/render.go new file mode 100644 index 00000000..d98b922a --- /dev/null +++ b/internal/builder/markdown/hook/diagramer/render.go @@ -0,0 +1,12 @@ +package diagramer + +import ( + "io" + + "github.com/gomarkdown/markdown/ast" + "github.com/ufukty/diagramer/pkg/sequence/parser" +) + +func Render(w io.Writer, node *ast.CodeBlock, entering bool) (ast.WalkStatus, bool) { + parser.Reader(node.Literal) +} diff --git a/vendor/github.com/ufukty/diagramer/LICENSE b/vendor/github.com/ufukty/diagramer/LICENSE new file mode 100644 index 00000000..f264da86 --- /dev/null +++ b/vendor/github.com/ufukty/diagramer/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 Ufuktan Yıldırım + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/ufukty/diagramer/pkg/sequence/parser/file.go b/vendor/github.com/ufukty/diagramer/pkg/sequence/parser/file.go new file mode 100644 index 00000000..e0db6987 --- /dev/null +++ b/vendor/github.com/ufukty/diagramer/pkg/sequence/parser/file.go @@ -0,0 +1,60 @@ +package parser + +import ( + "bufio" + "fmt" + "io" + "os" + "strings" + + "github.com/ufukty/diagramer/pkg/sequence/parser/parse" + "github.com/ufukty/diagramer/pkg/sequence/parser/parse/ast" +) + +func Reader(src io.Reader) (*ast.Diagram, error) { + diagram := &ast.Diagram{ + Lifelines: make(map[string]*ast.Lifeline), + Messages: []*ast.Message{}, + AutoNumber: false, + } + + scanner := bufio.NewScanner(src) + for i := 0; scanner.Scan(); i++ { + line := strings.TrimSpace(scanner.Text()) + if line == "" || strings.HasPrefix(line, "%%") { + continue + } + + switch { + case line == "sequenceDiagram": + continue + + case line == "autoNumber": + diagram.AutoNumber = true + + case strings.HasPrefix(line, "participant") || strings.HasPrefix(line, "actor"): + if p := parse.Lifeline(line); p != nil { + diagram.Lifelines[p.Name] = p + } + + case strings.Contains(line, "->>"): + if m := parse.Message(line); m != nil { + diagram.Messages = append(diagram.Messages, m) + } + + default: + fmt.Printf("skipping line #%d: %s\n", i, line) + } + } + + return diagram, nil +} + +func File(path string) (*ast.Diagram, error) { + file, err := os.Open(path) + if err != nil { + return nil, fmt.Errorf("opening: %w", err) + } + defer file.Close() //nolint:errcheck + return Reader(file) +} diff --git a/vendor/github.com/ufukty/diagramer/pkg/sequence/parser/parse/ast/ast.go b/vendor/github.com/ufukty/diagramer/pkg/sequence/parser/parse/ast/ast.go new file mode 100644 index 00000000..45c5411b --- /dev/null +++ b/vendor/github.com/ufukty/diagramer/pkg/sequence/parser/parse/ast/ast.go @@ -0,0 +1,21 @@ +package ast + +// Lifeline represents a diagram participant or actor +type Lifeline struct { + Type string + Alias string + Name string +} + +// Message represents a message between lifelines +type Message struct { + From string + To string + Content string +} + +type Diagram struct { + Lifelines map[string]*Lifeline + Messages []*Message + AutoNumber bool +} diff --git a/vendor/github.com/ufukty/diagramer/pkg/sequence/parser/parse/parse.go b/vendor/github.com/ufukty/diagramer/pkg/sequence/parser/parse/parse.go new file mode 100644 index 00000000..5d0a101a --- /dev/null +++ b/vendor/github.com/ufukty/diagramer/pkg/sequence/parser/parse/parse.go @@ -0,0 +1,44 @@ +package parse + +import ( + "regexp" + + "github.com/ufukty/diagramer/pkg/sequence/parser/parse/ast" +) + +var ( + regexLifeline = regexp.MustCompile(`(participant|actor)\s+(\w+)(?:\s+as\s+(.+))?`) + regexMessage = regexp.MustCompile(`([^\s-]+)\s*(?:->>[-+]?)\s*([^\s:]*)(?::\s*(.+))?`) +) + +func Lifeline(line string) *ast.Lifeline { + match := regexLifeline.FindStringSubmatch(line) + if len(match) < 3 { + return nil + } + p := &ast.Lifeline{ + Type: match[1], + Alias: "", + Name: match[2], + } + if len(match) > 3 { + p.Alias = match[3] + } + return p +} + +func Message(line string) *ast.Message { + match := regexMessage.FindStringSubmatch(line) + if len(match) < 4 { + return nil + } + m := &ast.Message{ + From: match[1], + To: match[2], + Content: "", + } + if len(match) > 3 { + m.Content = match[3] + } + return m +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 64b3a742..fdbbf286 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -43,6 +43,11 @@ github.com/gomarkdown/markdown/html github.com/gomarkdown/markdown/parser # github.com/stretchr/testify v1.8.1 ## explicit; go 1.13 +# github.com/ufukty/diagramer v0.1.0 +## explicit; go 1.24.4 +github.com/ufukty/diagramer/pkg/sequence/parser +github.com/ufukty/diagramer/pkg/sequence/parser/parse +github.com/ufukty/diagramer/pkg/sequence/parser/parse/ast # gopkg.in/yaml.v3 v3.0.1 ## explicit gopkg.in/yaml.v3