-
-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Architecture Diagrams #34
Conversation
WalkthroughThe pull request introduces a comprehensive beta feature for generating architecture diagrams using Mermaid syntax. A new Changes
Sequence DiagramsequenceDiagram
participant A as Architecture Builder
participant S as Service
participant G as Group
participant J as Junction
participant E as Edge
A->>S: Add Service
A->>G: Create Group
A->>J: Add Junction
A->>E: Define Edges
A-->>A: Build Diagram
Poem
Tip CodeRabbit's docstrings feature is now available as part of our Early Access Program! Simply use the command Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
Code Metrics Report
Code coverage of files in pull request scope (87.0%)
Reported by octocov |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 6
🧹 Nitpick comments (19)
mermaid/arch/icon.go (4)
3-6
: Consider enhancing the documentation with usage examples.The current documentation could be more comprehensive by including:
- Example usage in architecture diagrams
- Whether custom icons are supported
- Format requirements for custom icons (if supported)
5-5
: Provide more context for the AWS icons TODO.The TODO comment would be more actionable with additional details about:
- Which AWS icons are planned
- Any specific requirements or constraints
- Implementation timeline
Would you like me to help create a GitHub issue to track the AWS icons implementation with detailed requirements?
6-6
: Consider using a more type-safe approach.The current string-based implementation allows for any string value. Consider using an enumeration pattern or validation to ensure only valid icons are used.
Example approach:
type Icon string func (i Icon) Validate() error { valid := map[Icon]bool{ IconCloud: true, IconDatabase: true, IconDisk: true, IconInternet: true, IconServer: true, } if !valid[i] { return fmt.Errorf("invalid icon: %s", i) } return nil }
8-19
: Consider grouping related icons.The current implementation lists icons sequentially. Consider grouping related icons (e.g., storage-related, network-related) using comments or separate constant blocks for better organization as the icon set grows.
Example organization:
const ( // Network-related icons IconCloud Icon = "cloud" IconInternet Icon = "internet" // Storage-related icons IconDatabase Icon = "database" IconDisk Icon = "disk" // Compute-related icons IconServer Icon = "server" )mermaid/arch/config.go (2)
3-4
: Document intended configuration optionsThe empty
config
struct suggests this is a work in progress. Consider documenting the planned configuration options in the struct's documentation to help other developers understand the intended usage and future direction.
11-12
: Add example usage for Option typeThe
Option
type implements the functional options pattern, but lacks usage examples. Consider adding example configurations to help other developers understand how to use this pattern correctly.Example addition:
// Option sets the options for the Architecture struct. // Example usage: // // arch.NewArchitecture( // arch.WithTheme("default"), // arch.WithDirection("TB"), // ) type Option func(*config)mermaid/arch/junction.go (3)
5-7
: Enhance documentation with visual examplesWhile the syntax documentation is helpful, consider adding a visual example of how junctions appear in the generated diagram. This would help developers understand the visual impact of their code.
Example addition:
// Junction are a special type of node which acts as a potential 4-way split between edges. // Syntax: junction {junction id} (in {parent id})? // // Example: // a.Junction("j1") // // Results in: // [Service A] --> j1 // j1 --> [Service B] // j1 --> [Service C]
12-17
: Fix method naming inconsistencyThe method name
JunctionsInParent
(plural) is inconsistent with the singularJunction
. Since it creates a single junction, consider renaming toJunctionInParent
for consistency.-func (a *Architecture) JunctionsInParent(junctionID, parentGroupID string) *Architecture { +func (a *Architecture) JunctionInParent(junctionID, parentGroupID string) *Architecture {
1-1
: Consider architectural improvements for robustnessSeveral architectural improvements could enhance the implementation:
- Create a dedicated validation package for common identifier and input checks
- Implement a MermaidBuilder type for efficient string construction
- Add a consistent error handling strategy across all methods
- Consider using an interface for the Architecture type to allow different implementations
This would improve maintainability and make the codebase more robust.
mermaid/arch/group.go (1)
12-17
: Consider adding validation for empty parameters.While the implementation is good, consider adding validation for empty parameters to prevent potential issues with malformed diagram syntax.
func (a *Architecture) GroupInParentGroup(groupID string, icon Icon, title, parentGroupID string) *Architecture { + if groupID == "" || parentGroupID == "" { + return a + } a.body = append(a.body, fmt.Sprintf(" group %s(%s)[%s] in %s", groupID, icon, title, parentGroupID)) return a }mermaid/arch/junction_test.go (1)
11-33
: Consider adding more test cases for edge scenarios.The test implementation is solid with good practices:
- Parallel test execution
- Proper error handling
- Line ending normalization
- Detailed diff comparison
Consider adding test cases for:
- Empty junction ID or parent group
- Special characters in IDs
- Multiple junctions in the same parent
mermaid/arch/group_test.go (1)
11-33
: Enhance test coverage with additional scenarios.While the basic test case is good, consider adding tests for:
- Empty group ID, title, or parent group
- Special characters in group ID or title
- Nested groups (multiple levels)
- Groups with various icon types
mermaid/arch/architecture.go (2)
46-55
: Simplify error handling in Build() methodThe error handling in Build() can be simplified by removing the nested if condition.
func (a *Architecture) Build() error { if _, err := a.dest.Write([]byte(a.String())); err != nil { - if a.err != nil { - return fmt.Errorf("failed to write: %w: %s", err, a.err.Error()) //nolint:wrapcheck - } - return fmt.Errorf("failed to write: %w", err) + var errMsg string + if a.err != nil { + errMsg = fmt.Sprintf(": %s", a.err.Error()) + } + return fmt.Errorf("failed to write%s: %w", errMsg, err) } return nil }
41-44
: Consider using strings.Builder for better performanceThe String() method could be more efficient by using strings.Builder instead of strings.Join.
func (a *Architecture) String() string { - return strings.Join(a.body, internal.LineFeed()) + var builder strings.Builder + for i, line := range a.body { + if i > 0 { + builder.WriteString(internal.LineFeed()) + } + builder.WriteString(line) + } + return builder.String() }mermaid/arch/edge.go (1)
32-42
: Enhance Edge struct documentationThe Edge struct documentation could be more detailed about field requirements and valid values.
-// Edge represents an edge between two services. -// The edge can be customized with the Position and Arrow. +// Edge represents a connection between two services or junctions in an architecture diagram. +// The edge is defined by: +// - ServiceID: Required. The identifier of the service or junction +// - Position: Required. The connection point (Top, Bottom, Left, Right) +// - Arrow: Optional. The arrow direction at this end of the connection type Edge struct {doc/architecture/main.go (1)
23-97
: Improve readability of diagram construction
- The long chain of method calls could be split for better readability
- The use of io.Discard needs explanation
+// createServices adds all services to the architecture +func createServices(a *arch.Architecture) *arch.Architecture { + return a. + Service("left_disk", arch.IconDisk, "Disk"). + Service("top_disk", arch.IconDisk, "Disk"). + Service("bottom_disk", arch.IconDisk, "Disk"). + Service("top_gateway", arch.IconInternet, "Gateway"). + Service("bottom_gateway", arch.IconInternet, "Gateway") +} + +// createJunctions adds all junctions to the architecture +func createJunctions(a *arch.Architecture) *arch.Architecture { + return a. + Junction("junctionCenter"). + Junction("junctionRight") +} + +// createEdges adds all connections between services and junctions +func createEdges(a *arch.Architecture) *arch.Architecture { + // Add edges here... +} + func main() { // ... - diagram := arch.NewArchitecture(io.Discard). - Service("left_disk", arch.IconDisk, "Disk"). - // ... long chain of methods + // Using io.Discard as we only need the string representation + a := arch.NewArchitecture(io.Discard) + diagram := createServices(a) + diagram = createJunctions(diagram) + diagram = createEdges(diagram) + diagramStr := diagram.String()mermaid/arch/architecture_test.go (2)
96-102
: Consider enhancing error messages.The error messages could be more descriptive to help identify issues faster.
- t.Errorf("unexpected error: %v", err) + t.Errorf("failed to build architecture diagram: %v", err)
17-126
: Consider adding negative test cases.The test covers the happy path well, but consider adding test cases for error scenarios:
- Invalid service IDs
- Duplicate junctions
- Invalid edge connections
Would you like me to help generate these additional test cases?
README.md (1)
789-789
: Add language specification to fenced code block.The fenced code block should specify the language for proper syntax highlighting.
-```` +````markdown🧰 Tools
🪛 Markdownlint (0.37.0)
789-789: null
Fenced code blocks should have a language specified(MD040, fenced-code-language)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
doc/architecture/image.png
is excluded by!**/*.png
📒 Files selected for processing (14)
README.md
(1 hunks)doc/architecture/generated.md
(1 hunks)doc/architecture/main.go
(1 hunks)mermaid/arch/architecture.go
(1 hunks)mermaid/arch/architecture_test.go
(1 hunks)mermaid/arch/config.go
(1 hunks)mermaid/arch/edge.go
(1 hunks)mermaid/arch/group.go
(1 hunks)mermaid/arch/group_test.go
(1 hunks)mermaid/arch/icon.go
(1 hunks)mermaid/arch/junction.go
(1 hunks)mermaid/arch/junction_test.go
(1 hunks)mermaid/arch/service.go
(1 hunks)mermaid/er/config.go
(1 hunks)
✅ Files skipped from review due to trivial changes (2)
- mermaid/er/config.go
- doc/architecture/generated.md
🧰 Additional context used
🪛 Markdownlint (0.37.0)
README.md
686-686: Column: 1
Hard tabs
(MD010, no-hard-tabs)
687-687: Column: 1
Hard tabs
(MD010, no-hard-tabs)
689-689: Column: 1
Hard tabs
(MD010, no-hard-tabs)
690-690: Column: 1
Hard tabs
(MD010, no-hard-tabs)
696-696: Column: 1
Hard tabs
(MD010, no-hard-tabs)
697-697: Column: 1
Hard tabs
(MD010, no-hard-tabs)
698-698: Column: 1
Hard tabs
(MD010, no-hard-tabs)
699-699: Column: 1
Hard tabs
(MD010, no-hard-tabs)
700-700: Column: 1
Hard tabs
(MD010, no-hard-tabs)
702-702: Column: 1
Hard tabs
(MD010, no-hard-tabs)
703-703: Column: 1
Hard tabs
(MD010, no-hard-tabs)
704-704: Column: 1
Hard tabs
(MD010, no-hard-tabs)
705-705: Column: 1
Hard tabs
(MD010, no-hard-tabs)
706-706: Column: 1
Hard tabs
(MD010, no-hard-tabs)
707-707: Column: 1
Hard tabs
(MD010, no-hard-tabs)
708-708: Column: 1
Hard tabs
(MD010, no-hard-tabs)
709-709: Column: 1
Hard tabs
(MD010, no-hard-tabs)
710-710: Column: 1
Hard tabs
(MD010, no-hard-tabs)
711-711: Column: 1
Hard tabs
(MD010, no-hard-tabs)
712-712: Column: 1
Hard tabs
(MD010, no-hard-tabs)
713-713: Column: 1
Hard tabs
(MD010, no-hard-tabs)
714-714: Column: 1
Hard tabs
(MD010, no-hard-tabs)
715-715: Column: 1
Hard tabs
(MD010, no-hard-tabs)
716-716: Column: 1
Hard tabs
(MD010, no-hard-tabs)
717-717: Column: 1
Hard tabs
(MD010, no-hard-tabs)
718-718: Column: 1
Hard tabs
(MD010, no-hard-tabs)
719-719: Column: 1
Hard tabs
(MD010, no-hard-tabs)
720-720: Column: 1
Hard tabs
(MD010, no-hard-tabs)
721-721: Column: 1
Hard tabs
(MD010, no-hard-tabs)
722-722: Column: 1
Hard tabs
(MD010, no-hard-tabs)
723-723: Column: 1
Hard tabs
(MD010, no-hard-tabs)
724-724: Column: 1
Hard tabs
(MD010, no-hard-tabs)
725-725: Column: 1
Hard tabs
(MD010, no-hard-tabs)
726-726: Column: 1
Hard tabs
(MD010, no-hard-tabs)
727-727: Column: 1
Hard tabs
(MD010, no-hard-tabs)
728-728: Column: 1
Hard tabs
(MD010, no-hard-tabs)
729-729: Column: 1
Hard tabs
(MD010, no-hard-tabs)
730-730: Column: 1
Hard tabs
(MD010, no-hard-tabs)
731-731: Column: 1
Hard tabs
(MD010, no-hard-tabs)
732-732: Column: 1
Hard tabs
(MD010, no-hard-tabs)
733-733: Column: 1
Hard tabs
(MD010, no-hard-tabs)
734-734: Column: 1
Hard tabs
(MD010, no-hard-tabs)
735-735: Column: 1
Hard tabs
(MD010, no-hard-tabs)
736-736: Column: 1
Hard tabs
(MD010, no-hard-tabs)
737-737: Column: 1
Hard tabs
(MD010, no-hard-tabs)
738-738: Column: 1
Hard tabs
(MD010, no-hard-tabs)
739-739: Column: 1
Hard tabs
(MD010, no-hard-tabs)
740-740: Column: 1
Hard tabs
(MD010, no-hard-tabs)
741-741: Column: 1
Hard tabs
(MD010, no-hard-tabs)
742-742: Column: 1
Hard tabs
(MD010, no-hard-tabs)
743-743: Column: 1
Hard tabs
(MD010, no-hard-tabs)
744-744: Column: 1
Hard tabs
(MD010, no-hard-tabs)
745-745: Column: 1
Hard tabs
(MD010, no-hard-tabs)
746-746: Column: 1
Hard tabs
(MD010, no-hard-tabs)
747-747: Column: 1
Hard tabs
(MD010, no-hard-tabs)
748-748: Column: 1
Hard tabs
(MD010, no-hard-tabs)
749-749: Column: 1
Hard tabs
(MD010, no-hard-tabs)
750-750: Column: 1
Hard tabs
(MD010, no-hard-tabs)
751-751: Column: 1
Hard tabs
(MD010, no-hard-tabs)
752-752: Column: 1
Hard tabs
(MD010, no-hard-tabs)
753-753: Column: 1
Hard tabs
(MD010, no-hard-tabs)
754-754: Column: 1
Hard tabs
(MD010, no-hard-tabs)
755-755: Column: 1
Hard tabs
(MD010, no-hard-tabs)
756-756: Column: 1
Hard tabs
(MD010, no-hard-tabs)
757-757: Column: 1
Hard tabs
(MD010, no-hard-tabs)
758-758: Column: 1
Hard tabs
(MD010, no-hard-tabs)
759-759: Column: 1
Hard tabs
(MD010, no-hard-tabs)
760-760: Column: 1
Hard tabs
(MD010, no-hard-tabs)
761-761: Column: 1
Hard tabs
(MD010, no-hard-tabs)
762-762: Column: 1
Hard tabs
(MD010, no-hard-tabs)
763-763: Column: 1
Hard tabs
(MD010, no-hard-tabs)
764-764: Column: 1
Hard tabs
(MD010, no-hard-tabs)
765-765: Column: 1
Hard tabs
(MD010, no-hard-tabs)
766-766: Column: 1
Hard tabs
(MD010, no-hard-tabs)
767-767: Column: 1
Hard tabs
(MD010, no-hard-tabs)
768-768: Column: 1
Hard tabs
(MD010, no-hard-tabs)
769-769: Column: 1
Hard tabs
(MD010, no-hard-tabs)
770-770: Column: 1
Hard tabs
(MD010, no-hard-tabs)
771-771: Column: 1
Hard tabs
(MD010, no-hard-tabs)
772-772: Column: 1
Hard tabs
(MD010, no-hard-tabs)
773-773: Column: 1
Hard tabs
(MD010, no-hard-tabs)
774-774: Column: 1
Hard tabs
(MD010, no-hard-tabs)
775-775: Column: 1
Hard tabs
(MD010, no-hard-tabs)
776-776: Column: 1
Hard tabs
(MD010, no-hard-tabs)
778-778: Column: 1
Hard tabs
(MD010, no-hard-tabs)
779-779: Column: 1
Hard tabs
(MD010, no-hard-tabs)
780-780: Column: 1
Hard tabs
(MD010, no-hard-tabs)
781-781: Column: 1
Hard tabs
(MD010, no-hard-tabs)
783-783: Column: 1
Hard tabs
(MD010, no-hard-tabs)
784-784: Column: 1
Hard tabs
(MD010, no-hard-tabs)
785-785: Column: 1
Hard tabs
(MD010, no-hard-tabs)
789-789: null
Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🔇 Additional comments (7)
mermaid/arch/icon.go (1)
10-18
: Verify icon string values against Mermaid documentation.
Let's ensure the icon string values match Mermaid's supported icon syntax.
✅ Verification successful
Icon values are correctly used in Mermaid architecture diagrams
Based on the test file evidence, the icon values are being used correctly in Mermaid's architecture-beta syntax. The test cases demonstrate successful diagram generation with these icons:
IconDisk
("disk") is used for disk servicesIconInternet
("internet") is used for gateway servicesIconCloud
("cloud") is used for group elements
The test assertions pass and validate the correct Mermaid syntax output, confirming these icon values are compatible with Mermaid's architecture diagram specification.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Search for Mermaid documentation or tests that validate these icon values
# Look for Mermaid documentation files
fd -e md -e txt . | xargs rg -l "mermaid.*icon"
# Look for test files that might validate these icons
fd -e go | xargs rg -l "Icon.*Test"
Length of output: 87
Script:
#!/bin/bash
# Let's try a broader search for icon-related code and tests
# Search for icon-related tests
rg -l "func.*Test.*Icon"
# Search for icon validation or usage
rg -l "Icon.*=.*\""
# Search for any documentation mentioning mermaid icons
rg -l "mermaid.*icons?"
# Look specifically in the arch package tests
fd "arch.*test.go$"
Length of output: 150
Script:
#!/bin/bash
# Let's examine the architecture test file and look for icon usage/validation
# Check architecture_test.go for icon usage
cat mermaid/arch/architecture_test.go
# Let's also check if there are any icon-related error messages or validations
rg "Icon.*invalid|invalid.*Icon" -A 2 -B 2
Length of output: 4343
mermaid/arch/group.go (1)
5-10
: LGTM! Well-documented and properly implemented.
The implementation is clean and follows good practices:
- Clear documentation with syntax example
- Proper method chaining
- Consistent indentation
doc/architecture/main.go (1)
1-1
: Reconsider build constraint necessity
The build constraint //go:build linux || darwin
seems unnecessary as this code should work on any OS that can run Go.
mermaid/arch/architecture_test.go (2)
1-4
: LGTM! Clear package documentation.
The package documentation clearly indicates this is a beta feature and warns about potential specification changes.
14-16
: LGTM! Good test setup.
Using t.Parallel() at the test function level is a good practice for concurrent test execution.
README.md (2)
678-681
: LGTM! Clear feature introduction.
The new section clearly introduces the architecture diagram feature and properly references the Mermaid documentation.
682-786
: Replace hard tabs with spaces in code example.
The code example uses hard tabs which should be replaced with spaces for consistent formatting across different editors.
✅ Verification successful
Let me verify the exact location and context of tabs in the README.md file.
Hard tabs found in code examples throughout README.md
The code examples in README.md consistently use hard tabs for indentation. Since these are example code blocks meant for documentation, they should use spaces for better rendering consistency across different platforms and editors.
- Lines 685-786: Architecture diagram example uses tabs
- Lines 49-94: Basic markdown example uses tabs
- Lines 156-175: Go generate example uses tabs
- Multiple other code examples throughout the file also use tabs
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Check for hard tabs in the code example
rg -l '\t' README.md
Length of output: 32
Script:
#!/bin/bash
# Check for tabs specifically in the code block section
rg -U --line-number '\t' README.md -A 1 -B 1
Length of output: 12061
🧰 Tools
🪛 Markdownlint (0.37.0)
686-686: Column: 1
Hard tabs
(MD010, no-hard-tabs)
687-687: Column: 1
Hard tabs
(MD010, no-hard-tabs)
689-689: Column: 1
Hard tabs
(MD010, no-hard-tabs)
690-690: Column: 1
Hard tabs
(MD010, no-hard-tabs)
696-696: Column: 1
Hard tabs
(MD010, no-hard-tabs)
697-697: Column: 1
Hard tabs
(MD010, no-hard-tabs)
698-698: Column: 1
Hard tabs
(MD010, no-hard-tabs)
699-699: Column: 1
Hard tabs
(MD010, no-hard-tabs)
700-700: Column: 1
Hard tabs
(MD010, no-hard-tabs)
702-702: Column: 1
Hard tabs
(MD010, no-hard-tabs)
703-703: Column: 1
Hard tabs
(MD010, no-hard-tabs)
704-704: Column: 1
Hard tabs
(MD010, no-hard-tabs)
705-705: Column: 1
Hard tabs
(MD010, no-hard-tabs)
706-706: Column: 1
Hard tabs
(MD010, no-hard-tabs)
707-707: Column: 1
Hard tabs
(MD010, no-hard-tabs)
708-708: Column: 1
Hard tabs
(MD010, no-hard-tabs)
709-709: Column: 1
Hard tabs
(MD010, no-hard-tabs)
710-710: Column: 1
Hard tabs
(MD010, no-hard-tabs)
711-711: Column: 1
Hard tabs
(MD010, no-hard-tabs)
712-712: Column: 1
Hard tabs
(MD010, no-hard-tabs)
713-713: Column: 1
Hard tabs
(MD010, no-hard-tabs)
714-714: Column: 1
Hard tabs
(MD010, no-hard-tabs)
715-715: Column: 1
Hard tabs
(MD010, no-hard-tabs)
716-716: Column: 1
Hard tabs
(MD010, no-hard-tabs)
717-717: Column: 1
Hard tabs
(MD010, no-hard-tabs)
718-718: Column: 1
Hard tabs
(MD010, no-hard-tabs)
719-719: Column: 1
Hard tabs
(MD010, no-hard-tabs)
720-720: Column: 1
Hard tabs
(MD010, no-hard-tabs)
721-721: Column: 1
Hard tabs
(MD010, no-hard-tabs)
722-722: Column: 1
Hard tabs
(MD010, no-hard-tabs)
723-723: Column: 1
Hard tabs
(MD010, no-hard-tabs)
724-724: Column: 1
Hard tabs
(MD010, no-hard-tabs)
725-725: Column: 1
Hard tabs
(MD010, no-hard-tabs)
726-726: Column: 1
Hard tabs
(MD010, no-hard-tabs)
727-727: Column: 1
Hard tabs
(MD010, no-hard-tabs)
728-728: Column: 1
Hard tabs
(MD010, no-hard-tabs)
729-729: Column: 1
Hard tabs
(MD010, no-hard-tabs)
730-730: Column: 1
Hard tabs
(MD010, no-hard-tabs)
731-731: Column: 1
Hard tabs
(MD010, no-hard-tabs)
732-732: Column: 1
Hard tabs
(MD010, no-hard-tabs)
733-733: Column: 1
Hard tabs
(MD010, no-hard-tabs)
734-734: Column: 1
Hard tabs
(MD010, no-hard-tabs)
735-735: Column: 1
Hard tabs
(MD010, no-hard-tabs)
736-736: Column: 1
Hard tabs
(MD010, no-hard-tabs)
737-737: Column: 1
Hard tabs
(MD010, no-hard-tabs)
738-738: Column: 1
Hard tabs
(MD010, no-hard-tabs)
739-739: Column: 1
Hard tabs
(MD010, no-hard-tabs)
740-740: Column: 1
Hard tabs
(MD010, no-hard-tabs)
741-741: Column: 1
Hard tabs
(MD010, no-hard-tabs)
742-742: Column: 1
Hard tabs
(MD010, no-hard-tabs)
743-743: Column: 1
Hard tabs
(MD010, no-hard-tabs)
744-744: Column: 1
Hard tabs
(MD010, no-hard-tabs)
745-745: Column: 1
Hard tabs
(MD010, no-hard-tabs)
746-746: Column: 1
Hard tabs
(MD010, no-hard-tabs)
747-747: Column: 1
Hard tabs
(MD010, no-hard-tabs)
748-748: Column: 1
Hard tabs
(MD010, no-hard-tabs)
749-749: Column: 1
Hard tabs
(MD010, no-hard-tabs)
750-750: Column: 1
Hard tabs
(MD010, no-hard-tabs)
751-751: Column: 1
Hard tabs
(MD010, no-hard-tabs)
752-752: Column: 1
Hard tabs
(MD010, no-hard-tabs)
753-753: Column: 1
Hard tabs
(MD010, no-hard-tabs)
754-754: Column: 1
Hard tabs
(MD010, no-hard-tabs)
755-755: Column: 1
Hard tabs
(MD010, no-hard-tabs)
756-756: Column: 1
Hard tabs
(MD010, no-hard-tabs)
757-757: Column: 1
Hard tabs
(MD010, no-hard-tabs)
758-758: Column: 1
Hard tabs
(MD010, no-hard-tabs)
759-759: Column: 1
Hard tabs
(MD010, no-hard-tabs)
760-760: Column: 1
Hard tabs
(MD010, no-hard-tabs)
761-761: Column: 1
Hard tabs
(MD010, no-hard-tabs)
762-762: Column: 1
Hard tabs
(MD010, no-hard-tabs)
763-763: Column: 1
Hard tabs
(MD010, no-hard-tabs)
764-764: Column: 1
Hard tabs
(MD010, no-hard-tabs)
765-765: Column: 1
Hard tabs
(MD010, no-hard-tabs)
766-766: Column: 1
Hard tabs
(MD010, no-hard-tabs)
767-767: Column: 1
Hard tabs
(MD010, no-hard-tabs)
768-768: Column: 1
Hard tabs
(MD010, no-hard-tabs)
769-769: Column: 1
Hard tabs
(MD010, no-hard-tabs)
770-770: Column: 1
Hard tabs
(MD010, no-hard-tabs)
771-771: Column: 1
Hard tabs
(MD010, no-hard-tabs)
772-772: Column: 1
Hard tabs
(MD010, no-hard-tabs)
773-773: Column: 1
Hard tabs
(MD010, no-hard-tabs)
774-774: Column: 1
Hard tabs
(MD010, no-hard-tabs)
775-775: Column: 1
Hard tabs
(MD010, no-hard-tabs)
776-776: Column: 1
Hard tabs
(MD010, no-hard-tabs)
778-778: Column: 1
Hard tabs
(MD010, no-hard-tabs)
779-779: Column: 1
Hard tabs
(MD010, no-hard-tabs)
780-780: Column: 1
Hard tabs
(MD010, no-hard-tabs)
781-781: Column: 1
Hard tabs
(MD010, no-hard-tabs)
783-783: Column: 1
Hard tabs
(MD010, no-hard-tabs)
784-784: Column: 1
Hard tabs
(MD010, no-hard-tabs)
785-785: Column: 1
Hard tabs
(MD010, no-hard-tabs)
// ServiceInGroup adds a service in a group to the architecture diagram. | ||
func (a *Architecture) ServiceInGroup(serviceID string, icon Icon, title, groupID string) *Architecture { | ||
a.body = append(a.body, fmt.Sprintf(" service %s(%s)[%s] in %s", serviceID, icon, title, groupID)) | ||
return a | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Protect against Mermaid syntax injection
The ServiceInGroup
method directly interpolates user input into the Mermaid syntax string. This could lead to syntax injection if inputs contain special Mermaid characters.
Consider:
- Adding input validation for groupID
- Escaping special characters in all inputs
- Adding error handling for invalid inputs
// EdgesInAnothorGroup adds a string to connect two services in another group. | ||
// Syntax: {serviceId}{{group}}:{T|B|L|R} {<}?--{>}? {T|B|L|R}:{serviceId}{{group}} | ||
func (a *Architecture) EdgesInAnothorGroup(from, to Edge) *Architecture { | ||
a.body = append( | ||
a.body, | ||
fmt.Sprintf(" %s{group}:%s %s--%s %s:%s{group}", | ||
from.ServiceID, from.Position, from.Arrow, | ||
to.Arrow, to.Position, to.ServiceID, | ||
), | ||
) | ||
return a | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix typo in method name and enhance validation
- The method name has a typo: "Anothor" should be "Another"
- Consider adding validation for Edge fields
-func (a *Architecture) EdgesInAnothorGroup(from, to Edge) *Architecture {
+func (a *Architecture) EdgesInAnotherGroup(from, to Edge) *Architecture {
+ if err := validateEdge(from); err != nil {
+ a.err = fmt.Errorf("invalid 'from' edge: %w", err)
+ return a
+ }
+ if err := validateEdge(to); err != nil {
+ a.err = fmt.Errorf("invalid 'to' edge: %w", err)
+ return a
+ }
a.body = append(
a.body,
fmt.Sprintf(" %s{group}:%s %s--%s %s:%s{group}",
Add this validation helper:
func validateEdge(e Edge) error {
if e.ServiceID == "" {
return fmt.Errorf("service ID is required")
}
if e.Position == "" {
return fmt.Errorf("position is required")
}
return nil
}
func main() { | ||
f, err := os.Create("generated.md") | ||
if err != nil { | ||
panic(err) | ||
} | ||
defer f.Close() | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replace panic with proper error handling
Using panic for error handling is not recommended. Consider returning errors instead.
-func main() {
+func run() error {
f, err := os.Create("generated.md")
if err != nil {
- panic(err)
+ return fmt.Errorf("failed to create file: %w", err)
}
defer f.Close()
// ... diagram creation ...
err = markdown.NewMarkdown(f).
H2("Architecture Diagram").
CodeBlocks(markdown.SyntaxHighlightMermaid, diagram).
Build()
if err != nil {
- panic(err)
+ return fmt.Errorf("failed to build markdown: %w", err)
}
+ return nil
+}
+
+func main() {
+ if err := run(); err != nil {
+ fmt.Fprintf(os.Stderr, "Error: %v\n", err)
+ os.Exit(1)
+ }
}
Also applies to: 99-106
Summary by CodeRabbit
New Features
Bug Fixes
Tests
Documentation