Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
PlantUml.cs
1using SkiaSharp;
2using System;
3using System.Collections.Generic;
4using System.Diagnostics;
5using System.IO;
6using System.Text;
7using System.Threading.Tasks;
8using System.Xml;
19using Waher.Events;
22using Waher.Script;
24using Waher.Security;
25using static System.Environment;
26
28{
29 internal enum ResultType
30 {
31 Svg,
32 Png
33 }
34
35 internal class GraphInfo
36 {
37 public string BaseFileName;
38 public string TxtFileName;
39 public string ImageFileName;
40 public string PlantUmlFolder;
41 public string Title;
42 public string AsyncId;
43 public bool Sent;
44 }
45
51 {
52 private static readonly Random rnd = new Random();
53 private static Scheduler scheduler = null;
54 private static string jarPath = null;
55 private static string javaPath = null;
56 private static string plantUmlFolder = null;
57 private static string contentRootFolder = null;
58 private static IMarkdownAsynchronousOutput asyncHtmlOutput = null;
59
63 public PlantUml()
64 {
65 }
66
72 public static void Init(string ContentRootFolder)
73 {
74 try
75 {
76 contentRootFolder = ContentRootFolder;
77
78 if (scheduler is null)
79 {
80 if (Types.TryGetModuleParameter("Scheduler", out object Obj) && Obj is Scheduler Scheduler)
81 scheduler = Scheduler;
82 else
83 {
84 scheduler = new Scheduler();
85
86 Log.Terminating += (Sender, e) =>
87 {
88 scheduler?.Dispose();
89 scheduler = null;
90 };
91 }
92 }
93
94 SearchForInstallationFolder(out string JarPath, out string JavaPath);
95
96 if (string.IsNullOrEmpty(JarPath))
97 Log.Warning("PlantUML not found. PlantUML support will not be available in Markdown.");
98 else if (string.IsNullOrEmpty(JavaPath))
99 Log.Warning("Java not found. PlantUML support will not be available in Markdown.");
100 else
101 {
102 SetPath(JarPath, JavaPath);
103
104 Log.Informational("PlantUML found. Integration with Markdown added.",
105 new KeyValuePair<string, object>("Path", jarPath),
106 new KeyValuePair<string, object>("Java", javaPath));
107
108
110 }
111 }
112 catch (Exception ex)
113 {
114 Log.Exception(ex);
115 }
116 }
117
125 public static void SetPath(string JarPath, string JavaPath)
126 {
127 if (!string.IsNullOrEmpty(jarPath) && JarPath != jarPath)
128 throw new Exception("PlantUML an Java paths have already been set.");
129
130 jarPath = JarPath;
131 javaPath = JavaPath;
132 plantUmlFolder = Path.Combine(contentRootFolder, "PlantUML");
133
134 if (!Directory.Exists(plantUmlFolder))
135 Directory.CreateDirectory(plantUmlFolder);
136
137 DeleteOldFiles(TimeSpan.FromDays(7));
138 }
139
140 private static void DeleteOldFiles(object P)
141 {
142 if (P is TimeSpan MaxAge)
143 DeleteOldFiles(MaxAge, true);
144 }
145
151 public static void DeleteOldFiles(TimeSpan MaxAge, bool Reschedule)
152 {
153 if (string.IsNullOrEmpty(plantUmlFolder))
154 return;
155
156 DateTime Limit = DateTime.Now - MaxAge;
157 int Count = 0;
158
159 DirectoryInfo PlantUmlFolder = new DirectoryInfo(plantUmlFolder);
160 FileInfo[] Files = PlantUmlFolder.GetFiles("*.*");
161
162 foreach (FileInfo FileInfo in Files)
163 {
164 if (FileInfo.LastAccessTime < Limit)
165 {
166 try
167 {
168 File.Delete(FileInfo.FullName);
169 Count++;
170 }
171 catch (Exception ex)
172 {
173 Log.Error("Unable to delete old file: " + ex.Message, FileInfo.FullName);
174 }
175 }
176 }
177
178 if (Count > 0)
179 Log.Informational(Count.ToString() + " old file(s) deleted.", plantUmlFolder);
180
181 if (Reschedule)
182 {
183 lock (rnd)
184 {
185 scheduler.Add(DateTime.Now.AddDays(rnd.NextDouble() * 2), DeleteOldFiles, MaxAge);
186 }
187 }
188 }
189
195 public static void SearchForInstallationFolder(out string JarPath, out string JavaPath)
196 {
197 List<string> Folders = new List<string>();
198
199 Folders.AddRange(FileSystem.GetFolders(new Environment.SpecialFolder[]
200 {
201 SpecialFolder.ProgramFiles,
202 SpecialFolder.ProgramFilesX86
203 }));
204
205 if (Types.TryGetModuleParameter("Runtime", out object Obj) && Obj is string RuntimeFolder)
206 {
207 Folders.Add(Path.Combine(RuntimeFolder, SpecialFolder.ProgramFiles.ToString()));
208 Folders.Add(Path.Combine(RuntimeFolder, SpecialFolder.ProgramFilesX86.ToString()));
209 }
210
211 string PathVar = Environment.GetEnvironmentVariable("PATH");
212 if (!string.IsNullOrEmpty(PathVar))
213 {
214 string[] Paths = PathVar.Split(Path.PathSeparator);
215 Folders.AddRange(Paths);
216 }
217
218 string[] Folders2 = Folders.ToArray();
219
220 JarPath = FileSystem.FindLatestFile(Folders2, "plantuml.jar", 1);
221 JavaPath = FileSystem.FindLatestFile(Folders2, "java" + FileSystem.ExecutableExtension, 3);
222 }
223
229 public Grade Supports(string Language)
230 {
231 if (!string.IsNullOrEmpty(jarPath) && !string.IsNullOrEmpty(javaPath))
232 {
233 int i = Language.IndexOf(':');
234 if (i > 0)
235 Language = Language.Substring(0, i).TrimEnd();
236
237 switch (Language.ToLower())
238 {
239 case "uml": return Grade.Excellent;
240 case "plantuml": return Grade.Perfect;
241 }
242 }
243
244 return Grade.NotAtAll;
245 }
246
250 public bool EvaluatesScript => false;
251
256 public void Register(MarkdownDocument Document)
257 {
258 // Do nothing.
259 }
260
270 public async Task<bool> RenderHtml(HtmlRenderer Renderer, string[] Rows, string Language, int Indent, MarkdownDocument Document)
271 {
272 StringBuilder Output = Renderer.Output;
273 bool GenerateIfNotExists = asyncHtmlOutput is null;
274 GraphInfo Info = await GetGraphInfo(Language, Rows, ResultType.Svg, GenerateIfNotExists);
275 if (GenerateIfNotExists || File.Exists(Info.ImageFileName))
276 {
277 this.GenerateHTML(Output, Info);
278 return true;
279 }
280
281 Info.AsyncId = await asyncHtmlOutput.GenerateStub(MarkdownOutputType.Html, Output, Info.Title, Document);
282
283 foreach (KeyValuePair<AsyncMarkdownProcessing, object> P in Document.AsyncTasks)
284 {
285 if (P.Value is AsyncState AsyncState && AsyncState.Type == ResultType.Svg && AsyncState.GraphInfos.Count < 10)
286 {
287 AsyncState.GraphInfos.Add(Info);
288 return true;
289 }
290 }
291
292 Document.QueueAsyncTask(this.ExecutePlantUml, new AsyncState(ResultType.Svg, Info));
293
294 return true;
295 }
296
297 private class AsyncState
298 {
299 public readonly List<GraphInfo> GraphInfos;
300 public readonly ResultType Type;
301
302 public AsyncState(ResultType Type, GraphInfo Info)
303 {
304 this.Type = Type;
305 this.GraphInfos = new List<GraphInfo>()
306 {
307 Info
308 };
309 }
310 }
311
312 private async Task ExecutePlantUml(object State)
313 {
315 {
316 XmlEntitiesOnly = true
317 }))
318 {
319 AsyncState AsyncState = (AsyncState)State;
320
321 try
322 {
323 await ExecutePlantUml(AsyncState.Type, AsyncState.GraphInfos.ToArray());
324
325 foreach (GraphInfo Info in AsyncState.GraphInfos)
326 {
327 Renderer.Clear();
328
329 this.GenerateHTML(Renderer.Output, Info);
330 await asyncHtmlOutput.ReportResult(MarkdownOutputType.Html, Info.AsyncId, Renderer.ToString());
331 Info.Sent = true;
332 }
333 }
334 catch (Exception ex)
335 {
336 Renderer.Clear();
337 await Renderer.RenderObject(ex, true, new Variables());
338
339 string s = Renderer.ToString();
340
341 foreach (GraphInfo Info in AsyncState.GraphInfos)
342 {
343 if (!Info.Sent)
344 await asyncHtmlOutput.ReportResult(MarkdownOutputType.Html, Info.AsyncId, s);
345 }
346 }
347 }
348 }
349
350 private static async Task ExecutePlantUml(ResultType Type, params GraphInfo[] Files)
351 {
352 StringBuilder Arguments = new StringBuilder();
353 Arguments.Append("-jar \"");
354 Arguments.Append(jarPath);
355 Arguments.Append("\" -quiet -charset UTF-8 -t");
356 Arguments.Append(Type.ToString().ToLower());
357
358 foreach (GraphInfo Info in Files)
359 {
360 Arguments.Append(" \"");
361 Arguments.Append(Info.TxtFileName);
362 Arguments.Append('"');
363 }
364
365 ProcessStartInfo ProcessInformation = new ProcessStartInfo()
366 {
367 FileName = javaPath,
368 Arguments = Arguments.ToString(),
369 UseShellExecute = false,
370 RedirectStandardError = true,
371 RedirectStandardOutput = true,
372 RedirectStandardInput = false,
373 WorkingDirectory = Files[0].PlantUmlFolder,
374 CreateNoWindow = true,
375 WindowStyle = ProcessWindowStyle.Hidden
376 };
377
378 Process P = new Process();
379 TaskCompletionSource<int> ExitSource = new TaskCompletionSource<int>();
380 StringBuilder StandardOutput = new StringBuilder();
381 StringBuilder ErrorOutput = new StringBuilder();
382
383 P.ErrorDataReceived += (Sender, e) =>
384 {
385 ErrorOutput.AppendLine(e.Data);
386 };
387
388 P.OutputDataReceived += (Sender, e) =>
389 {
390 StandardOutput.AppendLine(e.Data);
391 };
392
393 P.Exited += (Sender, e) =>
394 {
395 ExitSource.TrySetResult(P.ExitCode);
396 };
397
398 Task _ = Task.Delay(10000).ContinueWith(Prev =>
399 {
400 ExitSource.TrySetException(new TimeoutException("PlantUML process did not terminate properly."));
401 });
402
403 P.StartInfo = ProcessInformation;
404 P.EnableRaisingEvents = true;
405 P.Start();
406
407 int ExitCode = await ExitSource.Task;
408
409 if (ExitCode != 0)
410 {
411 string Error = P.StandardError.ReadToEnd();
412 throw new Exception(Error);
413 }
414 }
415
416 private void GenerateHTML(StringBuilder Output, GraphInfo Info)
417 {
418 Info.ImageFileName = Info.ImageFileName.Substring(contentRootFolder.Length).Replace(Path.DirectorySeparatorChar, '/');
419 if (!Info.ImageFileName.StartsWith("/"))
420 Info.ImageFileName = "/" + Info.ImageFileName;
421
422 Output.Append("<figure>");
423 Output.Append("<img src=\"");
424 Output.Append(XML.HtmlAttributeEncode(Info.ImageFileName));
425
426 if (!string.IsNullOrEmpty(Info.Title))
427 {
428 Output.Append("\" alt=\"");
429 Output.Append(XML.HtmlAttributeEncode(Info.Title));
430
431 Output.Append("\" title=\"");
432 Output.Append(XML.HtmlAttributeEncode(Info.Title));
433 }
434 else
435 Output.Append("\" alt=\"PlantUML graph");
436
437 Output.Append("\" class=\"aloneUnsized\"/>");
438
439 if (!string.IsNullOrEmpty(Info.Title))
440 {
441 Output.Append("<figcaption>");
442 Output.Append(XML.HtmlValueEncode(Info.Title));
443 Output.Append("</figcaption>");
444 }
445
446 Output.AppendLine("</figure>");
447 }
448
449 internal static Task<GraphInfo> GetGraphInfo(string Language, string[] Rows, ResultType Type)
450 {
451 return GetGraphInfo(Language, MarkdownDocument.AppendRows(Rows), Type);
452 }
453
454 internal static async Task<GraphInfo> GetGraphInfo(string Language, string Graph, ResultType Type)
455 {
456 string FileName = Hashes.ComputeSHA256HashString(Encoding.UTF8.GetBytes(Graph + Language));
457 string PlantUmlFolder = Path.Combine(contentRootFolder, "PlantUML");
458
459 GraphInfo Result = new GraphInfo()
460 {
461 BaseFileName = Path.Combine(PlantUmlFolder, FileName),
462 PlantUmlFolder = PlantUmlFolder
463 };
464 int i = Language.IndexOf(':');
465
466 if (i > 0)
467 Result.Title = Language.Substring(i + 1).Trim();
468 else
469 Result.Title = string.Empty;
470
471 Result.TxtFileName = Result.BaseFileName + ".txt";
472 if (!File.Exists(Result.TxtFileName))
473 await Resources.WriteAllTextAsync(Result.TxtFileName, Graph, Encoding.UTF8);
474
475 switch (Type)
476 {
477 case ResultType.Svg:
478 default:
479 Result.ImageFileName = Result.BaseFileName + "." + ImageCodec.FileExtensionSvg;
480 break;
481
482 case ResultType.Png:
483 Result.ImageFileName = Result.BaseFileName + "." + ImageCodec.FileExtensionPng;
484 break;
485 }
486
487 return Result;
488 }
489
490 internal static Task<GraphInfo> GetGraphInfo(string Language, string[] Rows, ResultType Type, bool GenerateIfNotExists)
491 {
492 return GetGraphInfo(Language, MarkdownDocument.AppendRows(Rows), Type, GenerateIfNotExists);
493 }
494
495 internal static async Task<GraphInfo> GetGraphInfo(string Language, string GraphDefinition, ResultType Type, bool GenerateIfNotExists)
496 {
497 GraphInfo Result = await GetGraphInfo(Language, GraphDefinition, Type);
498
499 if (GenerateIfNotExists && !File.Exists(Result.ImageFileName))
500 await ExecutePlantUml(Type, Result);
501
502 return Result;
503 }
504
514 public async Task<bool> RenderMarkdown(MarkdownRenderer Renderer, string[] Rows, string Language, int Indent, MarkdownDocument Document)
515 {
516 GraphInfo Info = await GetGraphInfo(Language, Rows, ResultType.Png, true);
517 if (Info is null)
518 return false;
519
520 return await ImageContent.GenerateMarkdownFromFile(Renderer.Output, Info.ImageFileName, Info.Title);
521 }
522
523
533 public async Task<bool> RenderText(TextRenderer Renderer, string[] Rows, string Language, int Indent, MarkdownDocument Document)
534 {
535 GraphInfo Info = await GetGraphInfo(Language, Rows, ResultType.Svg, true);
536 if (Info is null)
537 return false;
538
539 Renderer.Output.AppendLine(Info.Title);
540
541 return true;
542 }
543
553 public async Task<bool> RenderWpfXaml(WpfXamlRenderer Renderer, string[] Rows, string Language, int Indent, MarkdownDocument Document)
554 {
555 GraphInfo Info = await GetGraphInfo(Language, Rows, ResultType.Png, true);
556 if (Info is null)
557 return false;
558
559 XmlWriter Output = Renderer.XmlOutput;
560
561 Output.WriteStartElement("Image");
562 Output.WriteAttributeString("Source", Info.ImageFileName);
563 Output.WriteAttributeString("Stretch", "None");
564
565 if (!string.IsNullOrEmpty(Info.Title))
566 Output.WriteAttributeString("ToolTip", Info.Title);
567
568 Output.WriteEndElement();
569
570 return true;
571 }
581 public async Task<bool> RenderXamarinFormsXaml(XamarinFormsXamlRenderer Renderer, string[] Rows, string Language, int Indent, MarkdownDocument Document)
582 {
583 GraphInfo Info = await GetGraphInfo(Language, Rows, ResultType.Png, true);
584 if (Info is null)
585 return false;
586
587 XmlWriter Output = Renderer.XmlOutput;
588
589 Output.WriteStartElement("Image");
590 Output.WriteAttributeString("Source", Info.ImageFileName);
591 Output.WriteEndElement();
592
593 return true;
594 }
595
605 public async Task<bool> RenderLatex(LatexRenderer Renderer, string[] Rows, string Language, int Indent, MarkdownDocument Document)
606 {
607 GraphInfo Info = await GetGraphInfo(Language, Rows, ResultType.Png, true);
608 StringBuilder Output = Renderer.Output;
609
610 Output.AppendLine("\\begin{figure}[h]");
611 Output.AppendLine("\\centering");
612
613 Output.Append("\\fbox{\\includegraphics{");
614 Output.Append(Info.ImageFileName.Replace('\\', '/'));
615 Output.AppendLine("}}");
616
617 if (!string.IsNullOrEmpty(Info.Title))
618 {
619 Output.Append("\\caption{");
620 Output.Append(LatexRenderer.EscapeLaTeX(Info.Title));
621 Output.AppendLine("}");
622 }
623
624 Output.AppendLine("\\end{figure}");
625 Output.AppendLine();
626
627 return true;
628 }
629
637 public async Task<PixelInformation> GenerateImage(string[] Rows, string Language, MarkdownDocument Document)
638 {
639 GraphInfo Info = await GetGraphInfo(Language, Rows, ResultType.Png, true);
640 if (Info is null)
641 return null;
642
643 byte[] Data = await Resources.ReadAllBytesAsync(Info.ImageFileName);
644
645 using (SKBitmap Bitmap = SKBitmap.Decode(Data))
646 {
647 return new PixelInformationPng(Data, Bitmap.Width, Bitmap.Height);
648 }
649 }
650
660 public async Task<bool> RenderContractXml(ContractsRenderer Renderer, string[] Rows, string Language, int Indent, MarkdownDocument Document)
661 {
662 try
663 {
664 GraphInfo Info = await GetGraphInfo(Language, Rows, ResultType.Png, true);
665 if (Info is null)
666 return false;
667
668 byte[] Data = await Resources.ReadAllBytesAsync(Info.ImageFileName);
669 string ContentType = ImageCodec.ContentTypePng;
670
671 if (!(await InternetContent.DecodeAsync(ContentType, Data, null) is SKImage Image))
672 return false;
673
674 XmlWriter Output = Renderer.XmlOutput;
675 int Width = Image.Width;
676 int Height = Image.Height;
677
678 Output.WriteStartElement("imageStandalone");
679
680 Output.WriteAttributeString("contentType", ContentType);
681 Output.WriteAttributeString("width", Width.ToString());
682 Output.WriteAttributeString("height", Height.ToString());
683
684 Output.WriteStartElement("binary");
685 Output.WriteValue(Convert.ToBase64String(Data));
686 Output.WriteEndElement();
687
688 Output.WriteStartElement("caption");
689 if (string.IsNullOrEmpty(Info.Title))
690 Output.WriteElementString("text", "Graph");
691 else
692 Output.WriteElementString("text", Info.Title);
693
694 Output.WriteEndElement();
695 Output.WriteEndElement();
696
697 return true;
698 }
699 catch (Exception ex)
700 {
701 Log.Exception(ex);
702 return false;
703 }
704 }
705 }
706}
Image encoder/decoder.
Definition: ImageCodec.cs:14
const string FileExtensionPng
png
Definition: ImageCodec.cs:75
const string ContentTypePng
image/png
Definition: ImageCodec.cs:30
const string FileExtensionSvg
svg
Definition: ImageCodec.cs:120
Static class managing encoding and decoding of internet content.
static Task< object > DecodeAsync(string ContentType, byte[] Data, Encoding Encoding, KeyValuePair< string, string >[] Fields, Uri BaseUri)
Decodes an object.
Renders Contracts XML from a Markdown document.
Renders LaTeX from a Markdown document.
static string EscapeLaTeX(string s)
Escapes text for output in a LaTeX document.
Contains a markdown document. This markdown document class supports original markdown,...
static string AppendRows(string[] Rows)
Appends a set of rows into a single string with newlines between rows.
static async Task< bool > GenerateMarkdownFromFile(StringBuilder Output, string FileName, string Title)
Generates Markdown embedding an image available in a file.
Definition: ImageContent.cs:56
Class managing PlantUML integration into Markdown documents.
Definition: PlantUml.cs:51
async Task< PixelInformation > GenerateImage(string[] Rows, string Language, MarkdownDocument Document)
Generates an image of the contents.
Definition: PlantUml.cs:637
Grade Supports(string Language)
Checks how well the handler supports multimedia content of a given type.
Definition: PlantUml.cs:229
async Task< bool > RenderMarkdown(MarkdownRenderer Renderer, string[] Rows, string Language, int Indent, MarkdownDocument Document)
Generates Markdown for the code content.
Definition: PlantUml.cs:514
static void DeleteOldFiles(TimeSpan MaxAge, bool Reschedule)
Deletes generated files older than MaxAge .
Definition: PlantUml.cs:151
static void Init(string ContentRootFolder)
Initializes the PlantUML-Markdown integration.
Definition: PlantUml.cs:72
static void SetPath(string JarPath, string JavaPath)
Sets the full path of PlantUML.
Definition: PlantUml.cs:125
async Task< bool > RenderWpfXaml(WpfXamlRenderer Renderer, string[] Rows, string Language, int Indent, MarkdownDocument Document)
Generates WPF XAML for the code content.
Definition: PlantUml.cs:553
async Task< bool > RenderXamarinFormsXaml(XamarinFormsXamlRenderer Renderer, string[] Rows, string Language, int Indent, MarkdownDocument Document)
Generates Xamarin.Forms XAML for the code content.
Definition: PlantUml.cs:581
async Task< bool > RenderHtml(HtmlRenderer Renderer, string[] Rows, string Language, int Indent, MarkdownDocument Document)
Generates HTML for the code content.
Definition: PlantUml.cs:270
async Task< bool > RenderText(TextRenderer Renderer, string[] Rows, string Language, int Indent, MarkdownDocument Document)
Generates plain text for the code content.
Definition: PlantUml.cs:533
bool EvaluatesScript
If script is evaluated for this type of code block.
Definition: PlantUml.cs:250
async Task< bool > RenderLatex(LatexRenderer Renderer, string[] Rows, string Language, int Indent, MarkdownDocument Document)
Generates LaTeX for the code content.
Definition: PlantUml.cs:605
static void SearchForInstallationFolder(out string JarPath, out string JavaPath)
Searches for the installation folder on the local machine.
Definition: PlantUml.cs:195
void Register(MarkdownDocument Document)
Is called on the object when an instance of the element has been created in a document.
Definition: PlantUml.cs:256
PlantUml()
Class managing PlantUML integration into Markdown documents.
Definition: PlantUml.cs:63
async Task< bool > RenderContractXml(ContractsRenderer Renderer, string[] Rows, string Language, int Indent, MarkdownDocument Document)
Generates smart contract XML for the code content.
Definition: PlantUml.cs:660
Renders HTML from a Markdown document.
Definition: HtmlRenderer.cs:24
Contains settings that the HTML export uses to customize HTML output.
Definition: HtmlSettings.cs:7
Renders portable Markdown from a Markdown document.
Abstract base class for Markdown renderers.
Definition: Renderer.cs:14
readonly StringBuilder Output
Renderer output.
Definition: Renderer.cs:18
void Clear()
Clears the underlying StringBuilder.
Definition: Renderer.cs:138
override string ToString()
Returns the renderer output.
Definition: Renderer.cs:130
Renders plain text from a Markdown document.
Definition: TextRenderer.cs:16
Renders XAML (WPF flavour) from a Markdown document.
Renders XAML (Xamarin.Forms flavour) from a Markdown document.
Static class managing loading of resources stored as embedded resources or in content files.
Definition: Resources.cs:15
static async Task< byte[]> ReadAllBytesAsync(string FileName)
Reads a binary file asynchronously.
Definition: Resources.cs:183
static Task WriteAllTextAsync(string FileName, string Text)
Creates a text file asynchronously.
Definition: Resources.cs:267
Static class helping modules to find files installed on the system.
Definition: FileSystem.cs:12
static string[] GetFolders(Environment.SpecialFolder[] Folders, params string[] AppendWith)
Gets the physical locations of special folders.
Definition: FileSystem.cs:126
static string ExecutableExtension
Extension used by executable files on the platform.
Definition: FileSystem.cs:229
static string FindLatestFile(Environment.SpecialFolder[] Folders, string Pattern, bool IncludeSubfolders)
Finds the latest file matching a search pattern, by searching in a set of folders,...
Definition: FileSystem.cs:177
Helps with common XML-related tasks.
Definition: XML.cs:19
static string HtmlValueEncode(string s)
Differs from Encode(String), in that it does not encode the aposotrophe or the quote.
Definition: XML.cs:209
static string HtmlAttributeEncode(string s)
Differs from Encode(String), in that it does not encode the aposotrophe.
Definition: XML.cs:119
Static class managing the application event log. Applications and services log events on this static ...
Definition: Log.cs:13
static void Exception(Exception Exception, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, params KeyValuePair< string, object >[] Tags)
Logs an exception. Event type will be determined by the severity of the exception.
Definition: Log.cs:1647
static void Warning(string Message, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, string StackTrace, params KeyValuePair< string, object >[] Tags)
Logs a warning event.
Definition: Log.cs:566
static void Error(string Message, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, string StackTrace, params KeyValuePair< string, object >[] Tags)
Logs an error event.
Definition: Log.cs:682
static void Informational(string Message, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, string StackTrace, params KeyValuePair< string, object >[] Tags)
Logs an informational event.
Definition: Log.cs:334
Static class that dynamically manages types and interfaces available in the runtime environment.
Definition: Types.cs:14
static bool TryGetModuleParameter(string Name, out object Value)
Tries to get a module parameter value.
Definition: Types.cs:583
Class that can be used to schedule events in time. It uses a timer to execute tasks at the appointed ...
Definition: Scheduler.cs:26
void Dispose()
IDisposable.Dispose
Definition: Scheduler.cs:46
DateTime Add(DateTime When, ScheduledEventCallback Callback, object State)
Adds an event.
Definition: Scheduler.cs:66
Base class for graphs.
Definition: Graph.cs:79
Contains pixel information in PNG format
Collection of variables.
Definition: Variables.cs:25
Contains methods for simple hash calculations.
Definition: Hashes.cs:59
static string ComputeSHA256HashString(byte[] Data)
Computes the SHA-256 hash of a block of binary data.
Definition: Hashes.cs:328
Interface for classes that help output asynchronous markdown output.
Task< string > GenerateStub(MarkdownOutputType Type, StringBuilder Output, string Title, MarkdownDocument Document)
Generates a stub in the output, that will be filled with the asynchronously generated content,...
Task ReportResult(MarkdownOutputType Type, string Id, string Result)
Method called when asynchronous result has been generated in a Markdown document.
Interface for all markdown handlers of code content that generates an image output.
Interface for code content plain text renderers.
Interface for code content WPF XAML renderers.
MarkdownOutputType
Markdown output type.
Grade
Grade enumeration
Definition: Grade.cs:7