Skip to content

Commit

Permalink
Merge pull request #40 from 8T4/feature/mermaid-github
Browse files Browse the repository at this point in the history
Feature/mermaid GitHub
  • Loading branch information
yanjustino authored Mar 25, 2023
2 parents bef97d1 + 31b9998 commit 8c90746
Show file tree
Hide file tree
Showing 14 changed files with 251 additions and 9 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/dotnet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ on:
branches: [ main ]

env:
VERSION: 6.0.${{ github.run_number }}
CLI_VERSION: 2.0.${{ github.run_number }}
VERSION: 6.1.${{ github.run_number }}
CLI_VERSION: 2.1.${{ github.run_number }}
NUGET_INDEX: https://api.nuget.org/v3/index.json
BUILD_TYPE: Release

Expand Down
91 changes: 90 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,23 @@
<img src="https://raw.githubusercontent.com/8T4/c4sharp/main/docs/images/8t4-c4-brand-2.png" alt="logo" width='600'>
</p>



<p align="center">

C4Sharp (`C4S`) is a .net library for building diagram as code, based on [C4 Model](https://c4model.com/). It's works
like a superset of [C4-PlantUML](https://github.com/plantuml-stdlib/C4-PlantUML) through which developers can create,
share, and consume [C4 Model diagrams](https://c4model.com/) as code (C#) such as Context, Container, Component and
Deployment diagrams.
Deployment diagrams. The library generates the following diagram types:

![](https://img.shields.io/badge/-png-green)
![](https://img.shields.io/badge/-svg-green)
![](https://img.shields.io/badge/-puml-green)
![](https://img.shields.io/badge/-mermaid-green)

</p>


# GETTING STARTED

> The C4 model is an easy to learn, developer friendly approach to software architecture diagramming. Good software architecture diagrams assist with communication inside/outside of software development/product teams, efficient onboarding of new staff, architecture reviews/evaluations, risk identification (e.g. risk-storming), threat modelling (e.g. STRIDE/LINDDUN), etc.
Expand Down Expand Up @@ -105,6 +114,43 @@ The `C4SCLI` can be used in DevOps pipelines, removing the need to manually comp
```shell
$ c4scli build <solution path> [-o <output path>]
```
see the following sample

```bash
$ mkdir assets
$ c4scli build /src/c4sharp.sln -o /c4

...

C4 diagram PNG files
C4 diagram generated: file:////c4/internet-banking-system-api-application-c4component.png
C4 diagram generated: file:////c4/system-context-diagram-for-internet-banking-system-c4context.png
C4 diagram generated: file:////c4/container-diagram-for-internet-banking-system-c4container.png
C4 diagram generated: file:////c4/system-context-diagram-for-internet-banking-system-c4deployment.png
C4 diagram generated: file:////c4/system-enterprise-diagram-for-internet-banking-system-c4context.png

C4 diagram SVG files
C4 diagram generated: file:////c4/internet-banking-system-api-application-c4component.svg
C4 diagram generated: file:////c4/system-enterprise-diagram-for-internet-banking-system-c4context.svg
C4 diagram generated: file:////c4/system-context-diagram-for-internet-banking-system-c4deployment.svg
C4 diagram generated: file:////c4/container-diagram-for-internet-banking-system-c4container.svg
C4 diagram generated: file:////c4/system-context-diagram-for-internet-banking-system-c4context.svg

C4 diagram MD files
C4 diagram generated: file:////c4/internet-banking-system-api-application-c4component.mermaid.md
C4 diagram generated: file:////c4/system-context-diagram-for-internet-banking-system-c4context.mermaid.md
C4 diagram generated: file:////c4/container-diagram-for-internet-banking-system-c4container.mermaid.md
C4 diagram generated: file:////c4/system-enterprise-diagram-for-internet-banking-system-c4context.mermaid.md

C4 diagram PUML files
C4 diagram generated: file:////c4/system-enterprise-diagram-for-internet-banking-system-c4context.puml
C4 diagram generated: file:////c4/internet-banking-system-api-application-c4component.puml
C4 diagram generated: file:////c4/system-context-diagram-for-internet-banking-system-c4context.puml
C4 diagram generated: file:////c4/container-diagram-for-internet-banking-system-c4container.puml
C4 diagram generated: file:////c4/system-context-diagram-for-internet-banking-system-c4deployment.puml
```


⚠️ *only compatible with projects using c4sharp version 5.0+*


Expand All @@ -128,8 +174,51 @@ protected override IElementStyle? SetStyle()

![img](./docs/images/c4bank-deposit-area-c4container-bw.png)

## Compiling Mermaid Markdown
Now, C4Sharp can compile the [Mermaid](https://github.com/mermaid-js/mermaid) markdown file. For this, you should use the function `UseDiagramMermaidBuilder()`. The following code shows how to compile these files.

```c#
context
.UseDiagramImageBuilder()
.UseDiagramSvgImageBuilder()
.UseDiagramMermaidBuilder()
.Export(diagrams);
```
Using the code above you'll have the following result:

```mermaid
C4Context
title System Enterprise diagram for Internet Banking System
Person_Ext(customer, "Personal Banking Customer", "A customer of the bank, with personal bank accounts.")
Enterprise_Boundary(enterprise.boundary, "Domain A") {
System(BankingSystem, "Internet Banking System", "Allows customers to view information about their bank accounts, and make payments.", $tags="services")
Enterprise_Boundary(enterprise.boundary.1, "Domain Internal Users") {
Person(internalcustomer, "Personal Banking Customer", "An internal customer of the bank, with personal bank accounts.")
}
Enterprise_Boundary(enterprise.boundary.2, "Domain Managers") {
Person(manager, "Manager Banking Customer", "A manager of the bank, with personal bank accounts.")
}
}
System_Ext(Mainframe, "Mainframe Banking System", "Stores all of the core banking information about customers, accounts, transactions, etc.")
System_Ext(MailSystem, "E-mail system", "The internal Microsoft Exchange e-mail system.")
Rel(customer, BankingSystem, "uses")
Rel(internalcustomer, BankingSystem, "uses")
Rel(manager, BankingSystem, "uses")
Rel_Back(customer, MailSystem, "Sends e-mails to")
Rel(BankingSystem, MailSystem, "Sends e-mails", "SMTP")
Rel(BankingSystem, Mainframe, "uses")
```

See the complete code [here](./docs/system-enterprise-diagram-for-internet-banking-system-c4context.mermaid.md).


# LEARN
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
```mermaid
C4Context
title System Enterprise diagram for Internet Banking System
Person_Ext(customer, "Personal Banking Customer", "A customer of the bank, with personal bank accounts.")
Enterprise_Boundary(enterprise.boundary, "Domain A") {
System(BankingSystem, "Internet Banking System", "Allows customers to view information about their bank accounts, and make payments.", $tags="services")
Enterprise_Boundary(enterprise.boundary.1, "Domain Internal Users") {
Person(internalcustomer, "Personal Banking Customer", "An internal customer of the bank, with personal bank accounts.")
}
Enterprise_Boundary(enterprise.boundary.2, "Domain Managers") {
Person(manager, "Manager Banking Customer", "A manager of the bank, with personal bank accounts.")
}
}
System_Ext(Mainframe, "Mainframe Banking System", "Stores all of the core banking information about customers, accounts, transactions, etc.")
System_Ext(MailSystem, "E-mail system", "The internal Microsoft Exchange e-mail system.")
Rel(customer, BankingSystem, "uses")
Rel(internalcustomer, BankingSystem, "uses")
Rel(manager, BankingSystem, "uses")
Rel_Back(customer, MailSystem, "Sends e-mails to")
Rel(BankingSystem, MailSystem, "Sends e-mails", "SMTP")
Rel(BankingSystem, Mainframe, "uses")
```
2 changes: 2 additions & 0 deletions samples/Basic/C4Sharp.Sample/Diagrams/ContainerDiagram.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public class ContainerDiagram: DiagramBuildRunner
Spa,
MobileApp,
SqlDatabase,
RabbitMQ,
BackendApi
)
};
Expand All @@ -40,6 +41,7 @@ public class ContainerDiagram: DiagramBuildRunner
Spa > BackendApi | ("Uses", "async, JSON/HTTPS"),
MobileApp > BackendApi | ("Uses", "async, JSON/HTTPS"),
SqlDatabase < BackendApi | ("Uses", "async, JSON/HTTPS") | Position.Neighbor,
RabbitMQ < BackendApi | ("Uses", "async, JSON"),

People.Customer < Systems.MailSystem | "Sends e-mails to",
Systems.MailSystem < BackendApi | ("Sends e-mails using", "sync, SMTP"),
Expand Down
1 change: 1 addition & 0 deletions samples/Basic/C4Sharp.Sample/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ private static void Main()
context
.UseDiagramImageBuilder()
.UseDiagramSvgImageBuilder()
.UseDiagramMermaidBuilder()
//.UseStandardLibraryBaseUrl() //load the resources from github C4plantuml repository
.Export(diagrams);
}
Expand Down
9 changes: 9 additions & 0 deletions samples/Basic/C4Sharp.Sample/Structures/Containers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,15 @@ public static class Containers
Technology: "SQL Database"
);

public static Queue _rabbitMQ;

Check warning on line 46 in samples/Basic/C4Sharp.Sample/Structures/Containers.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

Non-nullable field '_rabbitMQ' must contain a non-null value when exiting constructor. Consider declaring the field as nullable.

Check warning on line 46 in samples/Basic/C4Sharp.Sample/Structures/Containers.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

Non-nullable field '_rabbitMQ' must contain a non-null value when exiting constructor. Consider declaring the field as nullable.

Check warning on line 46 in samples/Basic/C4Sharp.Sample/Structures/Containers.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

Non-nullable field '_rabbitMQ' must contain a non-null value when exiting constructor. Consider declaring the field as nullable.

Check warning on line 46 in samples/Basic/C4Sharp.Sample/Structures/Containers.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

Non-nullable field '_rabbitMQ' must contain a non-null value when exiting constructor. Consider declaring the field as nullable.

Check warning on line 46 in samples/Basic/C4Sharp.Sample/Structures/Containers.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

Non-nullable field '_rabbitMQ' must contain a non-null value when exiting constructor. Consider declaring the field as nullable.

Check warning on line 46 in samples/Basic/C4Sharp.Sample/Structures/Containers.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

Non-nullable field '_rabbitMQ' must contain a non-null value when exiting constructor. Consider declaring the field as nullable.

Check warning on line 46 in samples/Basic/C4Sharp.Sample/Structures/Containers.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

Non-nullable field '_rabbitMQ' must contain a non-null value when exiting constructor. Consider declaring the field as nullable.

Check warning on line 46 in samples/Basic/C4Sharp.Sample/Structures/Containers.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

Non-nullable field '_rabbitMQ' must contain a non-null value when exiting constructor. Consider declaring the field as nullable.

Check warning on line 46 in samples/Basic/C4Sharp.Sample/Structures/Containers.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

Non-nullable field '_rabbitMQ' must contain a non-null value when exiting constructor. Consider declaring the field as nullable.

Check warning on line 46 in samples/Basic/C4Sharp.Sample/Structures/Containers.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

Non-nullable field '_rabbitMQ' must contain a non-null value when exiting constructor. Consider declaring the field as nullable.

Check warning on line 46 in samples/Basic/C4Sharp.Sample/Structures/Containers.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

Non-nullable field '_rabbitMQ' must contain a non-null value when exiting constructor. Consider declaring the field as nullable.

Check warning on line 46 in samples/Basic/C4Sharp.Sample/Structures/Containers.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

Non-nullable field '_rabbitMQ' must contain a non-null value when exiting constructor. Consider declaring the field as nullable.

Check warning on line 46 in samples/Basic/C4Sharp.Sample/Structures/Containers.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

Non-nullable field '_rabbitMQ' must contain a non-null value when exiting constructor. Consider declaring the field as nullable.

Check warning on line 46 in samples/Basic/C4Sharp.Sample/Structures/Containers.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

Non-nullable field '_rabbitMQ' must contain a non-null value when exiting constructor. Consider declaring the field as nullable.

Check warning on line 46 in samples/Basic/C4Sharp.Sample/Structures/Containers.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

Non-nullable field '_rabbitMQ' must contain a non-null value when exiting constructor. Consider declaring the field as nullable.

Check warning on line 46 in samples/Basic/C4Sharp.Sample/Structures/Containers.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

Non-nullable field '_rabbitMQ' must contain a non-null value when exiting constructor. Consider declaring the field as nullable.

Check warning on line 46 in samples/Basic/C4Sharp.Sample/Structures/Containers.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

Non-nullable field '_rabbitMQ' must contain a non-null value when exiting constructor. Consider declaring the field as nullable.

Check warning on line 46 in samples/Basic/C4Sharp.Sample/Structures/Containers.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

Non-nullable field '_rabbitMQ' must contain a non-null value when exiting constructor. Consider declaring the field as nullable.

public static Queue RabbitMQ => _rabbitMQ ?? new Queue(
Alias: "Queue",
Label: "RabbitMQ",
Description: "Stores user registration information, hashed auth credentials, access logs, etc.",
Technology: "RabbitMQ"
);

private static Database? _oracleDatabase;

public static Database OracleDatabase => _oracleDatabase ??= new Database(
Expand Down
2 changes: 1 addition & 1 deletion src/C4Sharp.Tools/C4Sharp.Tools.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<RepositoryUrl>https://github.com/8T4/c4sharp</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<PackageTags>c4, diagrams</PackageTags>
<PackageVersion>2.0.0</PackageVersion>
<PackageVersion>2.1.0</PackageVersion>
<PackageIconUrl>https://github.com/8T4/c4sharp/blob/main/LICENSE</PackageIconUrl>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<IncludeSymbols>true</IncludeSymbols>
Expand Down
2 changes: 2 additions & 0 deletions src/C4Sharp.Tools/Commands/BuildCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -176,12 +176,14 @@ private static void GenerateC4Diagrams(IEnumerable<IDiagramBuildRunner> runners,

var context = new PlantumlContext()
.UseDiagramImageBuilder()
.UseDiagramMermaidBuilder()
.UseDiagramSvgImageBuilder();

context.Export(directory, runners.Select(r => r.Build()));

PrintFileList(directory, "png");
PrintFileList(directory, "svg");
PrintFileList(directory, "md");
PrintFileList(directory, "puml");
}

Expand Down
2 changes: 1 addition & 1 deletion src/C4Sharp/C4Sharp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<RepositoryUrl>https://github.com/8T4/c4sharp</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<PackageTags>c4, diagrams</PackageTags>
<PackageVersion>6.0.0</PackageVersion>
<PackageVersion>6.1.0</PackageVersion>
<PackageIconUrl>https://github.com/8T4/c4sharp/blob/main/LICENSE</PackageIconUrl>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<IncludeSymbols>true</IncludeSymbols>
Expand Down
2 changes: 1 addition & 1 deletion src/C4Sharp/Diagrams/Diagram.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public record Diagram
public string? Title { get; init; }
public string? Description { get; init; }
public DiagramLayout FlowVisualization { get; init; }
private DiagramType Type { get; }
public DiagramType Type { get; }
public IEnumerable<Structure> Structures { get; init; }
public IEnumerable<Relationship> Relationships { get; init; }
public IElementStyle? Style { get; init; }
Expand Down
1 change: 1 addition & 0 deletions src/C4Sharp/Diagrams/DiagramNamingConvention.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ namespace C4Sharp.Diagrams;
public static class DiagramNamingConvention
{
public static string PumlFileName(this Diagram diagram) => $"{diagram.Slug()}.puml";
public static string MermaidFileName(this Diagram diagram) => $"{diagram.Slug()}.mermaid.md";
public static string Slug(this Diagram diagram) => $"{diagram.Title}-{diagram.Name}".GenerateSlug();
}
36 changes: 36 additions & 0 deletions src/C4Sharp/Diagrams/Plantuml/PlantumlContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public partial class PlantumlContext : IDisposable
private bool StandardLibraryBaseUrl { get; set; }
private bool GenerateDiagramImages { get; set; }
private bool GenerateDiagramSvgImages { get; set; }
private bool GenerateMermaidFiles { get; set; }
private string? PlantumlJarPath { get; set; }
private ProcessStartInfo ProcessInfo { get; }

Expand All @@ -24,6 +25,7 @@ public PlantumlContext()
StandardLibraryBaseUrl = false;
GenerateDiagramImages = false;
GenerateDiagramSvgImages = false;
GenerateMermaidFiles = false;

ProcessInfo = new ProcessStartInfo
{
Expand Down Expand Up @@ -68,6 +70,16 @@ public PlantumlContext UseDiagramSvgImageBuilder()
return this;
}

/// <summary>
/// The C4Sharp will generate *.mermaid.md files of your diagram.
/// </summary>
/// <returns></returns>
public PlantumlContext UseDiagramMermaidBuilder()
{
GenerateMermaidFiles = true;
return this;
}

/// <summary>
/// It creates a Puml file into the default directory "./c4"
/// If the attribute of Session GenerateDiagramImages is true
Expand Down Expand Up @@ -100,6 +112,7 @@ public void Export(string path, IEnumerable<Diagram> diagrams)
foreach (var diagram in enumerable)
{
SavePumlFiles(diagram, path);
SaveMermaidFiles(diagram, path);
}

if (GenerateDiagramImages) SaveDiagramFiles(path, "png");
Expand Down Expand Up @@ -131,6 +144,29 @@ private string SavePumlFiles(Diagram diagram, string path)
throw new PlantumlException($"{nameof(PlantumlException)}: Could not save puml file.", e);
}
}

/// <summary>
/// Save puml file. It's creates path if non exists.
/// </summary>
/// <param name="diagram">C4 Diagram</param>
/// <param name="path">Output path</param>
private string SaveMermaidFiles(Diagram diagram, string path)
{
if (!GenerateMermaidFiles || diagram.Type.Value == DiagramConstants.Deployment)
return string.Empty;

try
{
var filePath = Path.Combine(path, diagram.MermaidFileName());
Directory.CreateDirectory(path);
File.WriteAllText(filePath, diagram.ToMermaidString());
return filePath;
}
catch (Exception e)
{
throw new PlantumlException($"{nameof(PlantumlException)}: Could not save mermaid.md file.", e);
}
}

/// <summary>
/// Execute plantuml.jar
Expand Down
Loading

0 comments on commit 8c90746

Please sign in to comment.