diff --git a/Frank.Mermaid.Tests/FlowchartTests.cs b/Frank.Mermaid.Tests/FlowchartTests.cs new file mode 100644 index 0000000..3186970 --- /dev/null +++ b/Frank.Mermaid.Tests/FlowchartTests.cs @@ -0,0 +1,104 @@ +using Frank.Mermaid.Flowchart; +using Frank.Mermaid.Timeline; +using Xunit.Abstractions; + +namespace Frank.Mermaid.Tests; + +public class FlowchartTests +{ + private readonly ITestOutputHelper _outputHelper; + + public FlowchartTests(ITestOutputHelper outputHelper) + { + _outputHelper = outputHelper; + } + + [Fact] + public void Test1() + { + var flowchart = new Flowchart.Flowchart(); + var node1 = new Node("Node 1"); + var node2 = new Node("Node 2"); + flowchart.AddNode(node1); + flowchart.AddNode(node2); + + var link = new Link(node1, node2); + flowchart.AddLink(link); + + var subgraph = new Subgraph("Subgraph 1", Direction.TopToBottom); + var subgraphNode1 = new Node("Subgraph Node 1"); + var subgraphNode2 = new Node("Subgraph Node 2"); + subgraph.AddNode(subgraphNode1); + subgraph.AddNode(subgraphNode2); + + var subgraphLink = new Link(subgraphNode1, subgraphNode2, "Subgraph Link 1"); + subgraph.AddLink(subgraphLink); + + var link2 = new Link(subgraph, node2, "Subgraph Link to Node 2"); + flowchart.AddLink(link2); + + flowchart.AddSubgraph(subgraph); + + var writer = flowchart.ToMermaidSyntax(); + var result = writer.ToString(); + + _outputHelper.WriteLine(result); + } + + [Fact] + public void Test2() + { + /* + Testcase: + flowchart LR + subgraph subgraph1 + direction TB + top1[top] --> bottom1[bottom] + end + subgraph subgraph2 + direction TB + top2[top] --> bottom2[bottom] + end + %% ^ These subgraphs are identical, except for the links to them: + + %% Link *to* subgraph1: subgraph1 direction is maintained + outside --> subgraph1 + %% Link *within* subgraph2: + %% subgraph2 inherits the direction of the top-level graph (LR) + outside ---> top2 + */ + + var flowchart = new Flowchart.Flowchart(); + + var subgraph1 = new Subgraph("subgraph1", Direction.TopToBottom); + var top1 = new Node("top"); + var bottom1 = new Node("bottom"); + subgraph1.AddNode(top1); + subgraph1.AddNode(bottom1); + var link1 = new Link(top1, bottom1); + subgraph1.AddLink(link1); + flowchart.AddSubgraph(subgraph1); + + var subgraph2 = new Subgraph("subgraph2", Direction.TopToBottom); + var top2 = new Node("top"); + var bottom2 = new Node("bottom"); + subgraph2.AddNode(top2); + subgraph2.AddNode(bottom2); + var link2 = new Link(top2, bottom2); + subgraph2.AddLink(link2); + flowchart.AddSubgraph(subgraph2); + + var outside = new Node("outside"); + flowchart.AddNode(outside); + var link3 = new Link(outside, subgraph1); + flowchart.AddLink(link3); + + var link4 = new Link(outside, top2); + flowchart.AddLink(link4); + + var writer = flowchart.ToMermaidSyntax(); + var result = writer.ToString(); + + _outputHelper.WriteLine(result); + } +} \ No newline at end of file diff --git a/Frank.Mermaid.Tests/TimelineTests.cs b/Frank.Mermaid.Tests/TimelineTests.cs new file mode 100644 index 0000000..ade07dd --- /dev/null +++ b/Frank.Mermaid.Tests/TimelineTests.cs @@ -0,0 +1,39 @@ +using Frank.Mermaid.Timeline; +using Xunit.Abstractions; + +namespace Frank.Mermaid.Tests; + +public class TimelineTests +{ + private readonly ITestOutputHelper _outputHelper; + + public TimelineTests(ITestOutputHelper outputHelper) + { + _outputHelper = outputHelper; + } + + [Fact] + public void Test1() + { + var timeline = new Timeline.Timeline("My Timeline"); + var section1 = new Section("Section 1"); + section1.AddEvent(new Event("Event 1", new DateTime(2022, 1, 1))); + section1.AddEvent(new Event("Event 2", new DateTime(2022, 1, 2))); + timeline.AddSection(section1); + + var section2 = new Section("Section 2"); + section2.AddEvent(new Event("Event 3", new DateTime(2022, 1, 3))); + section2.AddEvent(new Event("Event 4", new DateTime(2022, 1, 4))); + timeline.AddSection(section2); + + var section3 = new Section("Section 3"); + section3.AddEvent(new Event("Event 5", new DateTime(2022, 1, 5))); + section3.AddEvent(new Event("Event 6", new DateTime(2022, 1, 6))); + timeline.AddSection(section3); + + var writer = timeline.ToMermaidSyntax(); + var result = writer.ToString(); + + _outputHelper.WriteLine(result); + } +} \ No newline at end of file diff --git a/Frank.Mermaid.Tests/UnitTest1.cs b/Frank.Mermaid.Tests/UnitTest1.cs deleted file mode 100644 index e25f9f7..0000000 --- a/Frank.Mermaid.Tests/UnitTest1.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Frank.Mermaid.Tests; - -public class UnitTest1 -{ - [Fact] - public void Test1() - { - } -} \ No newline at end of file diff --git a/Frank.Mermaid/Class1.cs b/Frank.Mermaid/Class1.cs deleted file mode 100644 index e3c68ad..0000000 --- a/Frank.Mermaid/Class1.cs +++ /dev/null @@ -1,5 +0,0 @@ -namespace Frank.Mermaid; - -public class Class1 -{ -} \ No newline at end of file diff --git a/Frank.Mermaid/Flowchart/Direction.cs b/Frank.Mermaid/Flowchart/Direction.cs new file mode 100644 index 0000000..8bcf14e --- /dev/null +++ b/Frank.Mermaid/Flowchart/Direction.cs @@ -0,0 +1,10 @@ +namespace Frank.Mermaid.Flowchart; + +public enum Direction +{ + TopToBottom, + TopDown, + BottomToTop, + RightToLeft, + LeftToRight +} \ No newline at end of file diff --git a/Frank.Mermaid/Flowchart/DirectionExtensions.cs b/Frank.Mermaid/Flowchart/DirectionExtensions.cs new file mode 100644 index 0000000..d161d13 --- /dev/null +++ b/Frank.Mermaid/Flowchart/DirectionExtensions.cs @@ -0,0 +1,17 @@ +namespace Frank.Mermaid.Flowchart; + +public static class DirectionExtensions +{ + public static string ToMermaidSyntax(this Direction direction) + { + return direction switch + { + Direction.TopToBottom => "TB", + Direction.TopDown => "TD", + Direction.BottomToTop => "BT", + Direction.RightToLeft => "RL", + Direction.LeftToRight => "LR", + _ => throw new ArgumentOutOfRangeException(nameof(direction), direction, null) + }; + } +} \ No newline at end of file diff --git a/Frank.Mermaid/Flowchart/Flowchart.cs b/Frank.Mermaid/Flowchart/Flowchart.cs new file mode 100644 index 0000000..d8b130d --- /dev/null +++ b/Frank.Mermaid/Flowchart/Flowchart.cs @@ -0,0 +1,55 @@ +using CodegenCS; + +namespace Frank.Mermaid.Flowchart; + +public class Flowchart : IMermaidable +{ + private readonly List _nodes = new(); + private readonly List _links = new(); + private readonly List _subgraphs = new(); + private readonly Direction _direction; + + public Flowchart(Direction direction = Direction.TopToBottom) + { + _direction = direction; + } + + public void AddSubgraph(Subgraph subgraph) => _subgraphs.Add(subgraph); + public void AddSubgraphs(IEnumerable subgraphs) => _subgraphs.AddRange(subgraphs); + + public void AddNode(Node node) => _nodes.Add(node); + public void AddNodes(IEnumerable nodes) => _nodes.AddRange(nodes); + + public void AddLink(Link link) => _links.Add(link); + public void AddLinks(IEnumerable links) => _links.AddRange(links); + + /// + public Guid Id { get; } = Guid.NewGuid(); + + /// + public ICodegenTextWriter ToMermaidSyntax() + { + var writer = new CodegenTextWriter(); + writer.WriteLine("flowchart {0}", _direction.ToMermaidSyntax()); + writer.IncreaseIndent(); + + foreach (var node in _nodes) + { + writer.Write(node.ToMermaidSyntax()); + } + + foreach (var link in _links) + { + writer.Write(link.ToMermaidSyntax()); + } + + foreach (var subgraph in _subgraphs) + { + writer.Write(subgraph.ToMermaidSyntax()); + } + + writer.DecreaseIndent(); + + return writer; + } +} \ No newline at end of file diff --git a/Frank.Mermaid/Flowchart/Line.cs b/Frank.Mermaid/Flowchart/Line.cs new file mode 100644 index 0000000..36904b7 --- /dev/null +++ b/Frank.Mermaid/Flowchart/Line.cs @@ -0,0 +1,50 @@ +using CodegenCS; + +namespace Frank.Mermaid.Flowchart; + +public class Line : IMermaidable +{ + private readonly LineStyle _lineStyle; + private readonly int _lineWidth; + + public Line(LineStyle lineStyle, int lineWidth = 1) + { + _lineStyle = lineStyle; + _lineWidth = lineWidth; + } + + /// + public Guid Id { get; } = Guid.NewGuid(); + + /// + public ICodegenTextWriter ToMermaidSyntax() + { + var writer = new CodegenTextWriter(); + var arrow = _lineStyle.ToString().Contains("Arrow") ? ">" : ""; + + switch (_lineStyle) + { + case LineStyle.Normal: + case LineStyle.NormalWithArrow: + writer.Write(new string('-', _lineWidth)); + break; + case LineStyle.Thick: + case LineStyle.ThickWithArrow: + writer.Write(new string('=', _lineWidth)); + break; + case LineStyle.Dotted: + case LineStyle.DottedWithArrow: + for (var i = 0; i < _lineWidth; i++) + { + writer.Write(i == _lineWidth - 1 ? "." : ".-"); + } + break; + default: + throw new ArgumentOutOfRangeException(); + } + + writer.Write(arrow); + + return writer; + } +} \ No newline at end of file diff --git a/Frank.Mermaid/Flowchart/LineStyle.cs b/Frank.Mermaid/Flowchart/LineStyle.cs new file mode 100644 index 0000000..5c26137 --- /dev/null +++ b/Frank.Mermaid/Flowchart/LineStyle.cs @@ -0,0 +1,11 @@ +namespace Frank.Mermaid.Flowchart; + +public enum LineStyle +{ + Normal, + NormalWithArrow, + Thick, + ThickWithArrow, + Dotted, + DottedWithArrow +} \ No newline at end of file diff --git a/Frank.Mermaid/Flowchart/Link.cs b/Frank.Mermaid/Flowchart/Link.cs new file mode 100644 index 0000000..5ea76c5 --- /dev/null +++ b/Frank.Mermaid/Flowchart/Link.cs @@ -0,0 +1,69 @@ +using CodegenCS; + +namespace Frank.Mermaid.Flowchart; + +public class Link : IMermaidable +{ + public Link(string source, string target, string? label = null) + { + Source = source; + Target = target; + Label = label; + } + + public string? Label { get; } + + public string Target { get; } + + public string Source { get; } + + public Line Line { get; private set; } = new Line(LineStyle.Normal, 3); + + public Link(IMermaidable source, IMermaidable target, string? label = null) + { + Source = GetIdentifier(source); + Target = GetIdentifier(target); + Label = label; + } + + private string? GetIdentifier(IMermaidable source) + { + if (source is Subgraph subgraph) + { + return subgraph.Label; + } + + return source.Id.ToString("N"); + } + + public void SetLineStyle(Line line) + { + Line = line; + } + + /// + public Guid Id { get; } = Guid.NewGuid(); + + /// + public ICodegenTextWriter ToMermaidSyntax() + { + var writer = new CodegenTextWriter(); + + writer.Write("{0} {1}{2} {3}", Source, Line.ToMermaidSyntax(), GetLabel(), Target); + + writer.WriteLine(); + return writer; + } + + private string GetLabel() => !string.IsNullOrWhiteSpace(Label) ? $"|{Label}|" : string.Empty; + + /* + Length 1 2 3 + Normal --- ---- ----- + Normal with arrow --> ---> ----> + Thick === ==== ===== + Thick with arrow ==> ===> ====> + Dotted -.- -..- -...- + Dotted with arrow -.-> -..-> -...-> + */ +} \ No newline at end of file diff --git a/Frank.Mermaid/Flowchart/LinkType.cs b/Frank.Mermaid/Flowchart/LinkType.cs new file mode 100644 index 0000000..fb11519 --- /dev/null +++ b/Frank.Mermaid/Flowchart/LinkType.cs @@ -0,0 +1,9 @@ +namespace Frank.Mermaid.Flowchart; + +public enum LinkType +{ + Default, + Dotted, + Thick, + DottedThick +} \ No newline at end of file diff --git a/Frank.Mermaid/Flowchart/Node.cs b/Frank.Mermaid/Flowchart/Node.cs new file mode 100644 index 0000000..ad618f5 --- /dev/null +++ b/Frank.Mermaid/Flowchart/Node.cs @@ -0,0 +1,46 @@ +using CodegenCS; + +namespace Frank.Mermaid.Flowchart; + +public class Node : IMermaidable +{ + public Node(Guid id, string label, Shape shape) + { + Id = id; + Label = label; + Shape = shape; + } + + public Node(string label) : this(Guid.NewGuid(), label, Shape.Rectangle) + { + } + + public Node(string label, Shape shape) : this(Guid.NewGuid(), label, shape) + { + } + + /// + public Guid Id { get; } + public string Label { get; } + public Shape Shape { get; } + + /// + public ICodegenTextWriter ToMermaidSyntax() + { + var label = Shape switch + { + Shape.Circle => $"(({Label}))", + Shape.Subroutine => $"[[{Label}]]", + Shape.Rounded => $"({Label})", + Shape.Hexagon => $"{{{{{Label}}}}}", + Shape.Database => $"[({Label})]", + Shape.Rectangle => $"[{Label}]", // Default case + _ => $"[{Label}]" // Default case + }; + + var writer = new CodegenTextWriter(); + writer.WriteLine("{0}{1}", this.GetId(), label); + return writer; + } + +} diff --git a/Frank.Mermaid/Flowchart/Shape.cs b/Frank.Mermaid/Flowchart/Shape.cs new file mode 100644 index 0000000..c486187 --- /dev/null +++ b/Frank.Mermaid/Flowchart/Shape.cs @@ -0,0 +1,12 @@ +namespace Frank.Mermaid.Flowchart; + +public enum Shape +{ + Rectangle, + Rounded, + Circle, + Subroutine, + Database, + Diamond, + Hexagon +} \ No newline at end of file diff --git a/Frank.Mermaid/Flowchart/Subgraph.cs b/Frank.Mermaid/Flowchart/Subgraph.cs new file mode 100644 index 0000000..767911e --- /dev/null +++ b/Frank.Mermaid/Flowchart/Subgraph.cs @@ -0,0 +1,67 @@ +using CodegenCS; + +namespace Frank.Mermaid.Flowchart; +// Define the line styles using an enumeration + +public class Subgraph : IMermaidable +{ + public Subgraph(string label, Direction direction) + { + Label = label; + Direction = direction; + } + + public void AddNode(Node node) => Nodes.Add(node); + public void AddNodes(IEnumerable nodes) => Nodes.AddRange(nodes); + + public void AddLink(Link link) => Links.Add(link); + public void AddLinks(IEnumerable links) => Links.AddRange(links); + + public void AddSubgraph(Subgraph subgraph) => _subgraphs.Add(subgraph); + public void AddSubgraphs(IEnumerable subgraphs) => _subgraphs.AddRange(subgraphs); + + /// + public Guid Id { get; } = Guid.NewGuid(); + + public string Label { get; } + + public Direction Direction { get; } + + public List Nodes { get; } = new(); + + private List Links { get; } = new(); + + + + private readonly List _subgraphs = new(); + + /// + public ICodegenTextWriter ToMermaidSyntax() + { + var writer = new CodegenTextWriter(); + writer.WriteLine("subgraph {0}", Label); + writer.IncreaseIndent(); + + writer.WriteLine("direction {0}", Direction.ToMermaidSyntax()); + + foreach (var node in Nodes) + { + writer.Write(node.ToMermaidSyntax()); + } + + foreach (var link in Links) + { + writer.Write(link.ToMermaidSyntax()); + } + + foreach (var subgraph in _subgraphs) + { + writer.Write(subgraph.ToMermaidSyntax()); + } + + + writer.DecreaseIndent(); + writer.WriteLine("end"); + return writer; + } +} \ No newline at end of file diff --git a/Frank.Mermaid/Frank.Mermaid.csproj b/Frank.Mermaid/Frank.Mermaid.csproj index 2b8a13c..3233c00 100644 --- a/Frank.Mermaid/Frank.Mermaid.csproj +++ b/Frank.Mermaid/Frank.Mermaid.csproj @@ -3,4 +3,8 @@ + + + + diff --git a/Frank.Mermaid/IMermaidable.cs b/Frank.Mermaid/IMermaidable.cs new file mode 100644 index 0000000..be3b816 --- /dev/null +++ b/Frank.Mermaid/IMermaidable.cs @@ -0,0 +1,27 @@ +using CodegenCS; + +namespace Frank.Mermaid; + +public interface IMermaidable +{ + /// + /// The unique identifier of the object. + /// + public Guid Id { get; } + + /// + /// Returns a string representation of the object in Mermaid syntax. + /// + /// a string representation of the object in Mermaid syntax + public ICodegenTextWriter ToMermaidSyntax(); +} + +public static class MermaidableExtensions +{ + /// + /// Returns the unique identifier of the object as a string without dashes. + /// + /// + /// + public static string GetId(this IMermaidable source) => source.Id.ToString("N"); +} \ No newline at end of file diff --git a/Frank.Mermaid/Timeline/Event.cs b/Frank.Mermaid/Timeline/Event.cs new file mode 100644 index 0000000..55c76e4 --- /dev/null +++ b/Frank.Mermaid/Timeline/Event.cs @@ -0,0 +1,45 @@ +using CodegenCS; + +namespace Frank.Mermaid.Timeline; + +public class Event : IMermaidable +{ + private readonly string _title; + private readonly DateTime _date; + public readonly TimePeriod TimePeriod; + + public Event(string title, DateTime date, TimePeriod timePeriod = TimePeriod.Day) + { + _title = title; + _date = date; + TimePeriod = timePeriod; + } + + /// + public Guid Id { get; } = Guid.NewGuid(); + + public ICodegenTextWriter ToMermaidSyntax() + { + var writer = new CodegenTextWriter(); + writer.Write("{0} : {1}", GetPeriodString(_date), _title); + return writer; + } + + private string GetPeriodString(DateTime dateTime) + { + return TimePeriod switch + { + TimePeriod.Year => dateTime.ToString("yyyy"), + TimePeriod.Month => dateTime.ToString("yyyy-MM"), + TimePeriod.Day => dateTime.ToString("yyyy-MM-dd"), + TimePeriod.Hour => dateTime.ToString("yyyy-MM-dd HH"), + TimePeriod.Minute => dateTime.ToString("yyyy-MM-dd HH:mm"), + TimePeriod.Second => dateTime.ToString("yyyy-MM-dd HH:mm:ss"), + TimePeriod.Millisecond => dateTime.ToString("yyyy-MM-dd HH:mm:ss.fff"), + TimePeriod.Microsecond => dateTime.ToString("yyyy-MM-dd HH:mm:ss.ffffff"), + TimePeriod.Nanosecond => dateTime.ToString("yyyy-MM-dd HH:mm:ss.fffffff"), + TimePeriod.Tick => dateTime.ToString("yyyy-MM-dd HH:mm:ss.fffffffff"), + _ => throw new ArgumentOutOfRangeException() + }; + } +} \ No newline at end of file diff --git a/Frank.Mermaid/Timeline/Section.cs b/Frank.Mermaid/Timeline/Section.cs new file mode 100644 index 0000000..f0b59fb --- /dev/null +++ b/Frank.Mermaid/Timeline/Section.cs @@ -0,0 +1,35 @@ +using CodegenCS; + +namespace Frank.Mermaid.Timeline; + +public class Section : IMermaidable +{ + private readonly string _title; + private readonly List _events = new(); + + public Section(string title) + { + _title = title; + } + + public void AddEvent(Event @event) => _events.Add(@event); + + public void AddEvents(IEnumerable events) => _events.AddRange(events); + + /// + public Guid Id { get; } = Guid.NewGuid(); + + public ICodegenTextWriter ToMermaidSyntax() + { + var writer = new CodegenTextWriter(); + writer.WriteLine("section {0}", _title); + + writer.IncreaseIndent(); + foreach (var @event in _events) + { + writer.WriteLine(@event.ToMermaidSyntax()); + } + + return writer; + } +} \ No newline at end of file diff --git a/Frank.Mermaid/Timeline/TimePeriod.cs b/Frank.Mermaid/Timeline/TimePeriod.cs new file mode 100644 index 0000000..017c466 --- /dev/null +++ b/Frank.Mermaid/Timeline/TimePeriod.cs @@ -0,0 +1,15 @@ +namespace Frank.Mermaid.Timeline; + +public enum TimePeriod +{ + Year, + Month, + Day, + Hour, + Minute, + Second, + Millisecond, + Microsecond, + Nanosecond, + Tick +} \ No newline at end of file diff --git a/Frank.Mermaid/Timeline/Timeline.cs b/Frank.Mermaid/Timeline/Timeline.cs new file mode 100644 index 0000000..46692bc --- /dev/null +++ b/Frank.Mermaid/Timeline/Timeline.cs @@ -0,0 +1,45 @@ +using CodegenCS; + +namespace Frank.Mermaid.Timeline; + +public class Timeline(string title) : IMermaidable +{ + private readonly List
_sections = new(); + private readonly List _events = new(); + + public void AddSection(Section section) => _sections.Add(section); + public void AddSections(IEnumerable
sections) => _sections.AddRange(sections); + + public void AddEvent(Event @event) => _events.Add(@event); + public void AddEvents(IEnumerable events) => _events.AddRange(events); + + /// + public Guid Id { get; } = Guid.NewGuid(); + + public ICodegenTextWriter ToMermaidSyntax() + { + var writer = new CodegenTextWriter(); + writer.WriteLine("timeline"); + writer.IncreaseIndent(); + writer.WriteLine("title {0}", title); + + if (_sections.Any()) + { + foreach (var section in _sections) + { + writer.Write(section.ToMermaidSyntax()); + } + + writer.DecreaseIndent(); + } + else + { + foreach (var @event in _events) + { + writer.Write(@event.ToMermaidSyntax()); + } + } + + return writer; + } +} \ No newline at end of file diff --git a/Frank.Mermaid/XyChart/Axis.cs b/Frank.Mermaid/XyChart/Axis.cs new file mode 100644 index 0000000..7bf0fcd --- /dev/null +++ b/Frank.Mermaid/XyChart/Axis.cs @@ -0,0 +1,23 @@ +using CodegenCS; + +namespace Frank.Mermaid.XyChart; + +public class Axis : IMermaidable +{ + public string Title { get; } + public bool Logarithmic { get; } + + /// + public Guid Id { get; } + + /// + public ICodegenTextWriter ToMermaidSyntax() + { + var writer = new CodegenTextWriter(); + writer.WriteLine("axis {0}", Title); + writer.IncreaseIndent(); + writer.WriteLine("log {0}", Logarithmic.ToString().ToLower()); + writer.DecreaseIndent(); + return writer; + } +} \ No newline at end of file diff --git a/Frank.Mermaid/XyChart/Point.cs b/Frank.Mermaid/XyChart/Point.cs new file mode 100644 index 0000000..9ea3d86 --- /dev/null +++ b/Frank.Mermaid/XyChart/Point.cs @@ -0,0 +1,20 @@ +using CodegenCS; + +namespace Frank.Mermaid.XyChart; + +public class Point : IMermaidable +{ + public double X { get; } + public double Y { get; } + + /// + public Guid Id { get; } = Guid.NewGuid(); + + /// + public ICodegenTextWriter ToMermaidSyntax() + { + var writer = new CodegenTextWriter(); + writer.WriteLine("{0} {1}", X, Y); + return writer; + } +} \ No newline at end of file diff --git a/Frank.Mermaid/XyChart/Series.cs b/Frank.Mermaid/XyChart/Series.cs new file mode 100644 index 0000000..bbca8ea --- /dev/null +++ b/Frank.Mermaid/XyChart/Series.cs @@ -0,0 +1,28 @@ +using CodegenCS; + +namespace Frank.Mermaid.XyChart; + +public class Series : IMermaidable +{ + public string Name { get; } + public List Points { get; } + + /// + public Guid Id { get; } + + /// + public ICodegenTextWriter ToMermaidSyntax() + { + var writer = new CodegenTextWriter(); + writer.WriteLine("series {0}", Name); + writer.IncreaseIndent(); + foreach (var point in Points) + { + writer.WriteLine(point.ToMermaidSyntax()); + } + + writer.DecreaseIndent(); + + return writer; + } +} \ No newline at end of file diff --git a/Frank.Mermaid/XyChart/XyChart.cs b/Frank.Mermaid/XyChart/XyChart.cs new file mode 100644 index 0000000..45eb44d --- /dev/null +++ b/Frank.Mermaid/XyChart/XyChart.cs @@ -0,0 +1,38 @@ +using CodegenCS; + +namespace Frank.Mermaid.XyChart; + +/// +/// Represents an XY chart. +/// +/// Beta +public class XyChart : IMermaidable +{ + public string Title { get; } + public Axis XAxis { get; } + public Axis YAxis { get; } + public List Series { get; } + + /// + public Guid Id { get; } + + /// + public ICodegenTextWriter ToMermaidSyntax() + { + var writer = new CodegenTextWriter(); + writer.WriteLine("xyChart {0}", Title); + writer.IncreaseIndent(); + writer.WriteLine("xAxis"); + writer.WriteLine(XAxis.ToMermaidSyntax()); + writer.WriteLine("yAxis"); + writer.WriteLine(YAxis.ToMermaidSyntax()); + foreach (var series in Series) + { + writer.WriteLine(series.ToMermaidSyntax()); + } + + writer.DecreaseIndent(); + + return writer; + } +} \ No newline at end of file