-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathGenerator.Run.cs
95 lines (78 loc) · 4.26 KB
/
Generator.Run.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
using System.Text.Json;
using System.Text.Json.Serialization;
using ICSharpCode.Decompiler.Documentation;
namespace NetAmermaid
{
partial class GenerateHtmlDiagrammer
{
public void Run()
{
var assemblyPath = GetPath(Assembly);
XmlDocumentationFormatter? xmlDocs = CreateXmlDocsFormatter(assemblyPath);
ClassDiagrammer model = BuildModel(assemblyPath, xmlDocs);
GenerateOutput(assemblyPath, model);
}
protected virtual XmlDocumentationFormatter? CreateXmlDocsFormatter(string assemblyPath)
{
var xmlDocsPath = XmlDocs == null ? Path.ChangeExtension(assemblyPath, ".xml") : GetPath(XmlDocs);
XmlDocumentationFormatter? xmlDocs = null;
if (File.Exists(xmlDocsPath)) xmlDocs = new XmlDocumentationFormatter(
new XmlDocumentationProvider(xmlDocsPath), StrippedNamespaces?.ToArray());
else Console.WriteLine("No XML documentation file found. Continuing without.");
return xmlDocs;
}
protected virtual ClassDiagrammer BuildModel(string assemblyPath, XmlDocumentationFormatter? xmlDocs)
=> new ClassDiagrammerFactory(xmlDocs).BuildModel(assemblyPath, Include, Exclude);
private static string SerializeModel(ClassDiagrammer diagrammer)
{
var jsonModel = new
{
diagrammer.OutsideReferences,
/* convert collections to dictionaries for easier access in ES using
* for (let [key, value] of Object.entries(dictionary)) */
TypesByNamespace = diagrammer.TypesByNamespace.ToDictionary(ns => ns.Key,
ns => ns.Value.ToDictionary(t => t.Id, t => t))
};
return JsonSerializer.Serialize(jsonModel, new JsonSerializerOptions
{
WriteIndented = true,
// avoid outputting null properties unnecessarily
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
});
}
private void GenerateOutput(string assemblyPath, ClassDiagrammer model)
{
var htmlSourcePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "html");
string modelJson = SerializeModel(model);
var htmlTemplate = File.ReadAllText(Path.Combine(htmlSourcePath, "template.html"));
var script = File.ReadAllText(Path.Combine(htmlSourcePath, "script.js"));
var html = htmlTemplate
.Replace("{{sourceAssemblyName}}", model.SourceAssemblyName)
.Replace("{{sourceAssemblyVersion}}", model.SourceAssemblyVersion)
.Replace("{{builderVersion}}", AssemblyInfo.Version)
.Replace("{{repoUrl}}", RepoUrl)
.Replace("{{model}}", modelJson)
.Replace("{{script}}", script);
var outputFolder = OutputFolder ?? Path.Combine(Path.GetDirectoryName(assemblyPath) ?? string.Empty, "netAmermaid");
if (!Directory.Exists(outputFolder)) Directory.CreateDirectory(outputFolder);
File.WriteAllText(Path.Combine(outputFolder, "class-diagrammer.html"), html);
// copy required resources to output folder
foreach (var resource in new[] { "styles.css", "netAmermaid.ico" })
File.Copy(Path.Combine(htmlSourcePath, resource), Path.Combine(outputFolder, resource), overwrite: true);
Console.WriteLine("Successfully generated HTML diagrammer.");
if (ReportExludedTypes)
{
string excludedTypes = model.Excluded.Join(Environment.NewLine);
File.WriteAllText(Path.Combine(outputFolder, "excluded types.txt"), excludedTypes);
}
}
private protected virtual string GetPath(string pathOrUri)
{
// convert file:// style argument, see https://stackoverflow.com/a/38245329
if (!Uri.TryCreate(pathOrUri, UriKind.RelativeOrAbsolute, out Uri? uri))
throw new ArgumentException("'{0}' is not a valid URI", pathOrUri);
// support absolute paths as well as file:// URIs and interpret relative path as relative to the current directory
return uri.IsAbsoluteUri ? uri.AbsolutePath : pathOrUri;
}
}
}