Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
HtmlRenderer.cs
1using SkiaSharp;
2using System;
3using System.Collections.Generic;
4using System.Text;
5using System.Threading.Tasks;
6using System.Xml;
12using Waher.Events;
13using Waher.Script;
17
19{
23 public class HtmlRenderer : Renderer
24 {
28 public readonly HtmlSettings htmlSettings;
29
35 : base()
36 {
37 this.htmlSettings = HtmlSettings;
38 }
39
46 : base(Output)
47 {
48 this.htmlSettings = HtmlSettings;
49 }
50
57 : base(Document)
58 {
59 this.htmlSettings = HtmlSettings;
60 }
61
69 : base(Output, Document)
70 {
71 this.htmlSettings = HtmlSettings;
72 }
73
77 public override Task RenderDocumentHeader()
78 {
79 StringBuilder sb = null;
80 string Title;
81 string Description;
82 string s2;
83 bool First;
84
85 this.Output.AppendLine("<!DOCTYPE html>");
86 this.Output.AppendLine("<html itemscope itemtype=\"http://schema.org/WebPage\">");
87 this.Output.AppendLine("<head>");
88
89 if (this.Document.TryGetMetaData("TITLE", out KeyValuePair<string, bool>[] Values))
90 {
91 foreach (KeyValuePair<string, bool> P in Values)
92 {
93 if (sb is null)
94 sb = new StringBuilder();
95 else
96 sb.Append(' ');
97
98 sb.Append(P.Key);
99 }
100
101 if (this.Document.TryGetMetaData("SUBTITLE", out Values))
102 {
103 sb.Append(" -");
104 foreach (KeyValuePair<string, bool> P in Values)
105 {
106 sb.Append(' ');
107 sb.Append(P.Key);
108 }
109 }
110
111 Title = XML.HtmlAttributeEncode(sb.ToString());
112 sb = null;
113
114 this.Output.Append("<title>");
115 if (string.IsNullOrEmpty(Title))
116 this.Output.Append(' ');
117 else
118 this.Output.Append(Title);
119 this.Output.AppendLine("</title>");
120
121 this.Output.Append("<meta itemprop=\"name\" content=\"");
122 this.Output.Append(Title);
123 this.Output.AppendLine("\"/>");
124
125 this.Output.Append("<meta name=\"twitter:title\" content=\"");
126 this.Output.Append(Title);
127 this.Output.AppendLine("\"/>");
128
129 this.Output.Append("<meta name=\"og:title\" content=\"");
130 this.Output.Append(Title);
131 this.Output.AppendLine("\"/>");
132 }
133 else
134 this.Output.AppendLine("<title> </title>");
135
136 if (this.Document.TryGetMetaData("DESCRIPTION", out Values))
137 {
138 foreach (KeyValuePair<string, bool> P in Values)
139 {
140 if (sb is null)
141 sb = new StringBuilder();
142 else
143 sb.Append(' ');
144
145 sb.Append(P.Key);
146 }
147
148 if (!(sb is null))
149 {
150 Description = XML.HtmlAttributeEncode(sb.ToString());
151
152 this.Output.Append("<meta itemprop=\"description\" content=\"");
153 this.Output.Append(Description);
154 this.Output.AppendLine("\"/>");
155
156 this.Output.Append("<meta name=\"twitter:description\" content=\"");
157 this.Output.Append(Description);
158 this.Output.AppendLine("\"/>");
159
160 this.Output.Append("<meta name=\"og:description\" content=\"");
161 this.Output.Append(Description);
162 this.Output.AppendLine("\"/>");
163 }
164 }
165
166 if (this.Document.TryGetMetaData("AUTHOR", out Values))
167 {
168 if (sb is null || string.IsNullOrEmpty(s2 = sb.ToString()))
169 sb = new StringBuilder("Author:");
170 else
171 {
172 char ch = s2[s2.Length - 1];
173
174 if (!char.IsPunctuation(ch))
175 sb.Append(',');
176
177 sb.Append(" Author:");
178 }
179
180 foreach (KeyValuePair<string, bool> P in Values)
181 {
182 sb.Append(' ');
183 sb.Append(P.Key);
184 }
185 }
186
187 if (this.Document.TryGetMetaData("DATE", out Values))
188 {
189 if (sb is null || string.IsNullOrEmpty(s2 = sb.ToString()))
190 sb = new StringBuilder("Date:");
191 else
192 {
193 char ch = s2[s2.Length - 1];
194
195 if (!char.IsPunctuation(ch))
196 sb.Append(',');
197
198 sb.Append(" Date:");
199 }
200
201 foreach (KeyValuePair<string, bool> P in Values)
202 {
203 sb.Append(' ');
204 sb.Append(P.Key);
205 }
206 }
207
208 // add default viewport
209 if (!this.Document.TryGetMetaData("VIEWPORT", out Values) || Values.Length == 0)
210 {
211 this.Output.AppendLine("<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"/>");
212
213 }
214
215 if (!(sb is null))
216 {
217 this.Output.Append("<meta name=\"description\" content=\"");
218 this.Output.Append(XML.HtmlAttributeEncode(sb.ToString()));
219 this.Output.AppendLine("\"/>");
220 }
221
222 foreach (KeyValuePair<string, KeyValuePair<string, bool>[]> MetaData in this.Document.MetaData)
223 {
224 switch (MetaData.Key)
225 {
226 case "ACCESS-CONTROL-ALLOW-ORIGIN":
227 case "ALLOWSCRIPTTAG":
228 case "ALTERNATE":
229 case "AUDIOAUTOPLAY":
230 case "AUDIOCONTROLS":
231 case "BODYONLY":
232 case "CONTENT-SECURITY-POLICY":
233 case "COPYRIGHT":
234 case "CACHE-CONTROL":
235 case "CSS":
236 case "DATE":
237 case "DESCRIPTION":
238 case "HELP":
239 case "ICON":
240 case "INIT":
241 case "JAVASCRIPT":
242 case "LOGIN":
243 case "MASTER":
244 case "NEXT":
245 case "PARAMETER":
246 case "PUBLIC-KEY-PINS":
247 case "PREV":
248 case "PREVIOUS":
249 case "PRIVILEGE":
250 case "SCRIPT":
251 case "STRICT-TRANSPORT-SECURITY":
252 case "SUBTITLE":
253 case "SUNSET":
254 case "TITLE":
255 case "USERVARIABLE":
256 case "VARY":
257 case "VIDEOAUTOPLAY":
258 case "VIDEOCONTROLS":
259 break;
260
261 case "KEYWORDS":
262 First = true;
263 this.Output.Append("<meta name=\"keywords\" content=\"");
264
265 foreach (KeyValuePair<string, bool> P in MetaData.Value)
266 {
267 if (First)
268 First = false;
269 else
270 this.Output.Append(", ");
271
272 this.Output.Append(XML.HtmlAttributeEncode(P.Key));
273 }
274
275 this.Output.AppendLine("\"/>");
276 break;
277
278 case "AUTHOR":
279 foreach (KeyValuePair<string, bool> P in MetaData.Value)
280 {
281 this.Output.Append("<meta name=\"author\" content=\"");
282 this.Output.Append(XML.HtmlAttributeEncode(P.Key));
283 this.Output.AppendLine("\"/>");
284 }
285 break;
286
287 case "IMAGE":
288 foreach (KeyValuePair<string, bool> P in MetaData.Value)
289 {
290 s2 = XML.HtmlAttributeEncode(P.Key);
291
292 this.Output.Append("<meta itemprop=\"image\" content=\"");
293 this.Output.Append(s2);
294 this.Output.AppendLine("\"/>");
295
296 this.Output.Append("<meta name=\"twitter:image\" content=\"");
297 this.Output.Append(s2);
298 this.Output.AppendLine("\"/>");
299
300 this.Output.Append("<meta name=\"og:image\" content=\"");
301 this.Output.Append(s2);
302 this.Output.AppendLine("\"/>");
303 }
304 break;
305
306 case "WEB":
307 foreach (KeyValuePair<string, bool> P in MetaData.Value)
308 {
309 this.Output.Append("<meta name=\"og:url\" content=\"");
310 this.Output.Append(XML.HtmlAttributeEncode(P.Key));
311 this.Output.AppendLine("\"/>");
312 }
313 break;
314
315 case "REFRESH":
316 foreach (KeyValuePair<string, bool> P in MetaData.Value)
317 {
318 this.Output.Append("<meta http-equiv=\"refresh\" content=\"");
319 this.Output.Append(XML.HtmlAttributeEncode(P.Key));
320 this.Output.AppendLine("\"/>");
321 }
322 break;
323
324 case "VIEWPORT":
325 foreach (KeyValuePair<string, bool> P in MetaData.Value)
326 {
327 this.Output.Append("<meta name=\"viewport\" content=\"");
328 this.Output.Append(XML.HtmlAttributeEncode(P.Key));
329 this.Output.AppendLine("\"/>");
330 }
331 break;
332
333 default:
334 foreach (KeyValuePair<string, bool> P in MetaData.Value)
335 {
336 this.Output.Append("<meta name=\"");
337 this.Output.Append(XML.HtmlAttributeEncode(MetaData.Key));
338 this.Output.Append("\" content=\"");
339 this.Output.Append(XML.HtmlAttributeEncode(P.Key));
340 this.Output.AppendLine("\"/>");
341 }
342 break;
343 }
344 }
345
346 bool HighlightStyle = false;
347
348 foreach (KeyValuePair<string, KeyValuePair<string, bool>[]> MetaData in this.Document.MetaData)
349 {
350 switch (MetaData.Key)
351 {
352 case "COPYRIGHT":
353 foreach (KeyValuePair<string, bool> P in MetaData.Value)
354 {
355 this.Output.Append("<link rel=\"copyright\" href=\"");
356 this.Output.Append(XML.HtmlAttributeEncode(this.Document.CheckURL(P.Key, null)));
357 this.Output.AppendLine("\"/>");
358 }
359 break;
360
361 case "PREVIOUS":
362 case "PREV":
363 foreach (KeyValuePair<string, bool> P in MetaData.Value)
364 {
365
366 this.Output.Append("<link rel=\"prev\" href=\"");
367 this.Output.Append(XML.HtmlAttributeEncode(this.Document.CheckURL(P.Key, null)));
368 this.Output.AppendLine("\"/>");
369 }
370 break;
371
372 case "NEXT":
373 foreach (KeyValuePair<string, bool> P in MetaData.Value)
374 {
375 this.Output.Append("<link rel=\"next\" href=\"");
376 this.Output.Append(XML.HtmlAttributeEncode(this.Document.CheckURL(P.Key, null)));
377 this.Output.AppendLine("\"/>");
378 }
379 break;
380
381 case "ALTERNATE":
382 foreach (KeyValuePair<string, bool> P in MetaData.Value)
383 {
384 this.Output.Append("<link rel=\"alternate\" href=\"");
385 this.Output.Append(XML.HtmlAttributeEncode(this.Document.CheckURL(P.Key, null)));
386 this.Output.AppendLine("\"/>");
387 }
388 break;
389
390 case "HELP":
391 foreach (KeyValuePair<string, bool> P in MetaData.Value)
392 {
393 this.Output.Append("<link rel=\"help\" href=\"");
394 this.Output.Append(XML.HtmlAttributeEncode(this.Document.CheckURL(P.Key, null)));
395 this.Output.AppendLine("\"/>");
396 }
397 break;
398
399 case "ICON":
400 foreach (KeyValuePair<string, bool> P in MetaData.Value)
401 {
402 this.Output.Append("<link rel=\"shortcut icon\" href=\"");
403 this.Output.Append(XML.HtmlAttributeEncode(this.Document.CheckURL(P.Key, null)));
404 this.Output.AppendLine("\"/>");
405 }
406 break;
407
408 case "CSS":
409 foreach (KeyValuePair<string, bool> P in MetaData.Value)
410 {
411 s2 = this.Document.CheckURL(P.Key, null);
412 if (s2.StartsWith("/Highlight/styles/", StringComparison.OrdinalIgnoreCase))
413 HighlightStyle = true;
414
415 this.Output.Append("<link rel=\"stylesheet\" href=\"");
416 this.Output.Append(XML.HtmlAttributeEncode(s2));
417 this.Output.AppendLine("\"/>");
418 }
419 break;
420
421 case "JAVASCRIPT":
422 foreach (KeyValuePair<string, bool> P in MetaData.Value)
423 {
424 this.Output.Append("<script type=\"application/javascript\" src=\"");
425 this.Output.Append(XML.HtmlAttributeEncode(this.Document.CheckURL(P.Key, null)));
426 this.Output.AppendLine("\"></script>");
427 }
428 break;
429 }
430 }
431
433 {
434 if (!HighlightStyle)
435 this.Output.AppendLine("<link rel=\"stylesheet\" href=\"/highlight/styles/default.css\">");
436
437 this.Output.AppendLine("<script src=\"/highlight/highlight.pack.js\"></script>");
438 this.Output.AppendLine("<script>hljs.initHighlightingOnLoad();</script>");
439 }
440
441 this.Output.AppendLine("</head>");
442 this.Output.AppendLine("<body>");
443
444 return Task.CompletedTask;
445 }
446
450 public override async Task RenderFootnotes()
451 {
452 this.Output.AppendLine("<div class=\"footnotes\">");
453 this.Output.AppendLine("<hr />");
454 this.Output.AppendLine("<ol>");
455
456 foreach (string Key in this.Document.FootnoteOrder)
457 {
458 if ((this.Document?.TryGetFootnoteNumber(Key, out int Nr) ?? false) &&
459 (this.Document?.TryGetFootnote(Key, out Footnote Footnote) ?? false) &&
461 {
462 this.Output.Append("<li id=\"fn-");
463 this.Output.Append(Nr.ToString());
464 this.Output.Append("\">");
465
466 if (!Footnote.BacklinkAdded)
467 {
468 InlineHTML Backlink = new InlineHTML(this.Document, "<a href=\"#fnref-" + Nr.ToString() + "\" class=\"footnote-backref\">&#8617;</a>");
469
471 P.AddChildren(Backlink);
472 else
473 Footnote.AddChildren(Backlink);
474
475 Footnote.BacklinkAdded = true;
476 }
477
478 await Footnote.Render(this);
479
480 this.Output.AppendLine("</li>");
481 }
482 }
483
484 this.Output.AppendLine("</ol>");
485 this.Output.AppendLine("</div>");
486 }
487
491 public override Task RenderDocumentFooter()
492 {
493 this.Output.AppendLine("</body>");
494 this.Output.Append("</html>");
495
496 return Task.CompletedTask;
497 }
498
499 #region Span Elements
500
505 public override async Task Render(Abbreviation Element)
506 {
507 this.Output.Append("<abbr data-title=\"");
508 this.Output.Append(XML.HtmlAttributeEncode(Element.Description).Replace(" ", "&nbsp;"));
509 this.Output.Append("\">");
510
511 await this.RenderChildren(Element);
512
513 this.Output.Append("</abbr>");
514 }
515
520 public override Task Render(AutomaticLinkMail Element)
521 {
522 string s = Element.EMail;
523 byte[] Data = Encoding.ASCII.GetBytes(s);
524 StringBuilder sb = new StringBuilder();
525
526 foreach (byte b in Data)
527 {
528 sb.Append("&#x");
529 sb.Append(b.ToString("X2"));
530 sb.Append(';');
531 }
532
533 s = sb.ToString();
534
535 sb.Clear();
536 Data = Encoding.ASCII.GetBytes("mailto:");
537 foreach (byte b in Data)
538 {
539 sb.Append("&#x");
540 sb.Append(b.ToString("X2"));
541 sb.Append(';');
542 }
543
544 this.Output.Append("<a href=\"");
545 this.Output.Append(sb.ToString());
546 this.Output.Append(s);
547 this.Output.Append("\">");
548 this.Output.Append(s);
549 this.Output.Append("</a>");
550
551 return Task.CompletedTask;
552 }
553
558 public override Task Render(AutomaticLinkUrl Element)
559 {
560 bool IsRelative = Element.URL.IndexOf(':') < 0;
561
562 this.Output.Append("<a href=\"");
563 this.Output.Append(XML.HtmlAttributeEncode(this.Document.CheckURL(Element.URL, null)));
564
565 if (!IsRelative)
566 this.Output.Append("\" target=\"_blank");
567
568 this.Output.Append("\">");
569 this.Output.Append(XML.HtmlValueEncode(Element.URL));
570 this.Output.Append("</a>");
571
572 return Task.CompletedTask;
573 }
574
579 public override async Task Render(Delete Element)
580 {
581 this.Output.Append("<del>");
582 await this.RenderChildren(Element);
583 this.Output.Append("</del>");
584 }
585
590 public override Task Render(DetailsReference Element)
591 {
592 if (!(this.Document.Detail is null))
593 return this.RenderDocument(this.Document.Detail, true);
594 else
595 return this.Render((MetaReference)Element);
596 }
597
602 public override Task Render(EmojiReference Element)
603 {
604 IEmojiSource EmojiSource = this.Document.EmojiSource;
605
606 if (EmojiSource is null)
607 {
608 this.Output.Append(Element.Delimiter);
609 this.Output.Append(Element.Emoji.ShortName);
610 this.Output.Append(Element.Delimiter);
611 }
612 else if (!EmojiSource.EmojiSupported(Element.Emoji))
613 this.Output.Append(Element.Emoji.Unicode);
614 else
615 EmojiSource.GenerateHTML(this.Output, Element.Emoji, Element.Level, this.Document.Settings.EmbedEmojis);
616
617 return Task.CompletedTask;
618 }
619
624 public override async Task Render(Emphasize Element)
625 {
626 this.Output.Append("<em>");
627 await this.RenderChildren(Element);
628 this.Output.Append("</em>");
629 }
630
635 public override async Task Render(FootnoteReference Element)
636 {
637 string s;
638
639 if (!(this.Document?.TryGetFootnote(Element.Key, out Footnote Footnote) ?? false))
640 Footnote = null;
641
642 if (Element.AutoExpand && !(Footnote is null))
643 await this.Render(Footnote);
644 else if (this.Document?.TryGetFootnoteNumber(Element.Key, out int Nr) ?? false)
645 {
646 s = Nr.ToString();
647
648 this.Output.Append("<sup id=\"fnref-");
649 this.Output.Append(s);
650 this.Output.Append("\"><a href=\"#fn-");
651 this.Output.Append(s);
652 this.Output.Append("\" class=\"footnote-ref\">");
653 this.Output.Append(s);
654 this.Output.Append("</a></sup>");
655
656 if (!(Footnote is null))
657 Footnote.Referenced = true;
658 }
659 }
660
665 public override Task Render(HashTag Element)
666 {
667 this.Output.Append("<mark");
668
669 string s = this.htmlSettings?.HashtagClass;
670
671 if (!string.IsNullOrEmpty(s))
672 {
673 this.Output.Append(" class=\"");
674 this.Output.Append(XML.HtmlAttributeEncode(s));
675 this.Output.Append('"');
676 }
677
678 s = this.htmlSettings?.HashtagClickScript;
679
680 if (!string.IsNullOrEmpty(s))
681 {
682 this.Output.Append(" onclick=\"");
683 this.Output.Append(XML.HtmlAttributeEncode(s));
684 this.Output.Append('"');
685 }
686
687 this.Output.Append('>');
688 this.Output.Append(Element.Tag);
689 this.Output.Append("</mark>");
690
691 return Task.CompletedTask;
692 }
693
698 public override Task Render(HtmlEntity Element)
699 {
700 if (this.htmlSettings?.XmlEntitiesOnly ?? true)
701 {
702 switch (Element.Entity)
703 {
704 case "quot":
705 case "amp":
706 case "apos":
707 case "lt":
708 case "gt":
709 case "nbsp": // Has syntactic significance when parsing HTML or Markdown
710 this.Output.Append('&');
711 this.Output.Append(Element.Entity);
712 this.Output.Append(';');
713 break;
714
715 case "QUOT":
716 case "AMP":
717 case "LT":
718 case "GT":
719 this.Output.Append('&');
720 this.Output.Append(Element.Entity.ToLower());
721 this.Output.Append(';');
722 break;
723
724 default:
725 string s = Html.HtmlEntity.EntityToCharacter(Element.Entity);
726 if (!string.IsNullOrEmpty(s))
727 this.Output.Append(s);
728 break;
729 }
730 }
731 else
732 {
733 this.Output.Append('&');
734 this.Output.Append(Element.Entity);
735 this.Output.Append(';');
736 }
737
738 return Task.CompletedTask;
739 }
740
745 public override Task Render(HtmlEntityUnicode Element)
746 {
747 this.Output.Append("&#");
748 this.Output.Append(Element.Code.ToString());
749 this.Output.Append(';');
750
751 return Task.CompletedTask;
752 }
753
758 public override Task Render(InlineCode Element)
759 {
760 this.Output.Append("<code>");
761 this.Output.Append(XML.HtmlValueEncode(Element.Code));
762 this.Output.Append("</code>");
763
764 return Task.CompletedTask;
765 }
766
771 public override Task Render(InlineHTML Element)
772 {
773 this.Output.Append(Element.HTML);
774
775 return Task.CompletedTask;
776 }
777
782 public override async Task Render(InlineScript Element)
783 {
784 object Result = await Element.EvaluateExpression();
785
786 await this.RenderObject(Result, Element.AloneInParagraph, Element.Variables);
787 }
788
795 public async Task RenderObject(object Result, bool AloneInParagraph, Variables Variables)
796 {
797 if (Result is null)
798 return;
799
800 if (Result is XmlDocument Xml)
801 Result = await MarkdownDocument.TransformXml(Xml, Variables);
802 else if (Result is IToMatrix ToMatrix)
803 Result = ToMatrix.ToMatrix();
804
805 if (Result is Graph G)
806 {
807 PixelInformation Pixels = G.CreatePixels(out GraphSettings GraphSettings);
808 byte[] Bin = Pixels.EncodeAsPng();
809
810 if (AloneInParagraph)
811 this.Output.Append("<figure>");
812
813 this.Output.Append("<img border=\"2\" width=\"");
814 this.Output.Append(GraphSettings.Width.ToString());
815 this.Output.Append("\" height=\"");
816 this.Output.Append(GraphSettings.Height.ToString());
817 this.Output.Append("\" src=\"data:image/png;base64,");
818 this.Output.Append(Convert.ToBase64String(Bin, 0, Bin.Length));
819 this.Output.Append("\" alt=\"");
820
821 if (G is Graph2D Graph2D && !string.IsNullOrEmpty(Graph2D.Title))
822 this.Output.Append(XML.Encode(Graph2D.Title));
823 else
824 this.Output.Append("Graph");
825
826 this.Output.Append("\" />");
827
828 if (AloneInParagraph)
829 this.Output.Append("</figure>");
830 }
831 else if (Result is PixelInformation Pixels)
832 {
833 byte[] Bin = Pixels.EncodeAsPng();
834
835 if (AloneInParagraph)
836 this.Output.Append("<figure>");
837
838 this.Output.Append("<img border=\"2\" width=\"");
839 this.Output.Append(Pixels.Width.ToString());
840 this.Output.Append("\" height=\"");
841 this.Output.Append(Pixels.Height.ToString());
842 this.Output.Append("\" src=\"data:image/png;base64,");
843 this.Output.Append(Convert.ToBase64String(Bin, 0, Bin.Length));
844 this.Output.Append("\" alt=\"Image\" />");
845
846 if (AloneInParagraph)
847 this.Output.Append("</figure>");
848 }
849 else if (Result is SKImage Img)
850 {
851 using (SKData Data = Img.Encode(SKEncodedImageFormat.Png, 100))
852 {
853 byte[] Bin = Data.ToArray();
854
855 if (AloneInParagraph)
856 this.Output.Append("<figure>");
857
858 this.Output.Append("<img border=\"2\" width=\"");
859 this.Output.Append(Img.Width.ToString());
860 this.Output.Append("\" height=\"");
861 this.Output.Append(Img.Height.ToString());
862 this.Output.Append("\" src=\"data:image/png;base64,");
863 this.Output.Append(Convert.ToBase64String(Bin, 0, Bin.Length));
864 this.Output.Append("\" alt=\"Image\" />");
865
866 if (AloneInParagraph)
867 this.Output.Append("</figure>");
868 }
869 }
870 else if (Result is MarkdownDocument Doc)
871 {
872 await this.RenderDocument(Doc, true); // Does not call ProcessAsyncTasks()
873 Doc.ProcessAsyncTasks();
874 }
875 else if (Result is MarkdownContent Markdown)
876 {
877 Doc = await MarkdownDocument.CreateAsync(Markdown.Markdown, Markdown.Settings ?? new MarkdownSettings());
878 await this.RenderDocument(Doc, true); // Does not call ProcessAsyncTasks()
879 Doc.ProcessAsyncTasks();
880 }
881 else if (Result is Exception ex)
882 {
883 ex = Log.UnnestException(ex);
884
885 this.Output.AppendLine("<font class=\"error\">");
886
887 if (ex is AggregateException ex2)
888 {
889 foreach (Exception ex3 in ex2.InnerExceptions)
890 {
891 this.Output.Append("<p>");
892 this.Output.Append(XML.HtmlValueEncode(ex3.Message));
893 this.Output.AppendLine("</p>");
894 }
895 }
896 else
897 {
898 if (AloneInParagraph)
899 this.Output.Append("<p>");
900
901 this.Output.Append(XML.HtmlValueEncode(ex.Message));
902
903 if (AloneInParagraph)
904 this.Output.Append("</p>");
905 }
906
907 this.Output.AppendLine("</font>");
908 }
909 else if (Result is ObjectMatrix M && !(M.ColumnNames is null))
910 {
911 this.Output.Append("<table><thead><tr>");
912
913 foreach (string s2 in M.ColumnNames)
914 {
915 this.Output.Append("<th>");
916 this.Output.Append(FormatText(XML.HtmlValueEncode(s2)));
917 this.Output.Append("</th>");
918 }
919
920 this.Output.Append("</tr></thead><tbody>");
921
922 int x, y;
923
924 for (y = 0; y < M.Rows; y++)
925 {
926 this.Output.Append("<tr>");
927
928 for (x = 0; x < M.Columns; x++)
929 {
930 this.Output.Append("<td>");
931
932 object Item = M.GetElement(x, y).AssociatedObjectValue;
933 if (!(Item is null))
934 {
935 if (Item is string s2)
936 this.Output.Append(FormatText(XML.HtmlValueEncode(s2)));
937 else if (Item is MarkdownElement Element)
938 await Element.Render(this);
939 else
940 this.Output.Append(FormatText(XML.HtmlValueEncode(Expression.ToString(Item))));
941 }
942
943 this.Output.Append("</td>");
944 }
945
946 this.Output.Append("</tr>");
947 }
948
949 this.Output.Append("</tbody></table>");
950 }
951 else if (Result is Array A)
952 {
953 foreach (object Item in A)
954 await this.RenderObject(Item, false, Variables);
955 }
956 else
957 {
958 if (AloneInParagraph)
959 this.Output.Append("<p>");
960
961 this.Output.Append(XML.HtmlValueEncode(Result?.ToString() ?? string.Empty));
962
963 if (AloneInParagraph)
964 this.Output.Append("</p>");
965 }
966
967 if (AloneInParagraph)
968 this.Output.AppendLine();
969 }
970
971 private static string FormatText(string s)
972 {
973 return s.Replace("\r\n", "\n").Replace("\n", "<br/>").Replace("\r", "<br/>").
974 Replace("\t", "&nbsp;&nbsp;&nbsp;").Replace(" ", "&nbsp;");
975 }
976
981 public override Task Render(InlineText Element)
982 {
983 this.Output.Append(XML.HtmlValueEncode(Element.Value));
984
985 return Task.CompletedTask;
986 }
987
992 public override async Task Render(Insert Element)
993 {
994 this.Output.Append("<ins>");
995 await this.RenderChildren(Element);
996 this.Output.Append("</ins>");
997 }
998
1003 public override Task Render(LineBreak Element)
1004 {
1005 this.Output.AppendLine("<br/>");
1006
1007 return Task.CompletedTask;
1008 }
1009
1014 public override Task Render(Link Element)
1015 {
1016 return this.Render(Element.Url, Element.Title, Element.Children, Element.Document);
1017 }
1018
1026 public async Task Render(string Url, string Title, IEnumerable<MarkdownElement> ChildNodes, MarkdownDocument Document)
1027 {
1028 bool IsRelative = Url.IndexOf(':') < 0;
1029
1030 if (!IsRelative && Url.StartsWith("javascript:", StringComparison.OrdinalIgnoreCase))
1031 {
1032 this.Output.Append("<a href=\"#\" onclick=\"");
1033 this.Output.Append(XML.HtmlAttributeEncode(System.Net.WebUtility.UrlDecode(Url.Substring(11))));
1034 IsRelative = true;
1035 }
1036 else
1037 {
1038 this.Output.Append("<a href=\"");
1039 this.Output.Append(XML.HtmlAttributeEncode(Document.CheckURL(Url, null)));
1040 }
1041
1042 if (!string.IsNullOrEmpty(Title))
1043 {
1044 this.Output.Append("\" title=\"");
1045 this.Output.Append(XML.HtmlAttributeEncode(Title));
1046 }
1047
1048 if (!IsRelative)
1049 this.Output.Append("\" target=\"_blank");
1050
1051 this.Output.Append("\">");
1052
1053 foreach (MarkdownElement E in ChildNodes)
1054 await E.Render(this);
1055
1056 this.Output.Append("</a>");
1057 }
1058
1063 public override Task Render(LinkReference Element)
1064 {
1066
1067 if (!(Multimedia is null))
1068 return this.Render(Multimedia.Items[0].Url, Multimedia.Items[0].Title, Element.Children, Element.Document);
1069 else
1070 return this.RenderChildren(Element);
1071 }
1072
1077 public override Task Render(MetaReference Element)
1078 {
1079 bool FirstOnRow = true;
1080
1081 if (Element.TryGetMetaData(out KeyValuePair<string, bool>[] Values))
1082 {
1083 foreach (KeyValuePair<string, bool> P in Values)
1084 {
1085 if (FirstOnRow)
1086 FirstOnRow = false;
1087 else
1088 this.Output.Append(' ');
1089
1090 this.Output.Append(XML.HtmlValueEncode(P.Key));
1091 if (P.Value)
1092 {
1093 this.Output.AppendLine("<br/>");
1094 FirstOnRow = true;
1095 }
1096 }
1097 }
1098
1099 return Task.CompletedTask;
1100 }
1101
1106 public override Task Render(Model.SpanElements.Multimedia Element)
1107 {
1108 IMultimediaHtmlRenderer Renderer = Element.MultimediaHandler<IMultimediaHtmlRenderer>();
1109 if (Renderer is null)
1110 return this.RenderChildren(Element);
1111 else
1112 return Renderer.RenderHtml(this, Element.Items, Element.Children, Element.AloneInParagraph, Element.Document);
1113 }
1114
1119 public override Task Render(MultimediaReference Element)
1120 {
1122
1123 if (!(Multimedia is null))
1124 {
1126 if (!(Renderer is null))
1127 return Renderer.RenderHtml(this, Multimedia.Items, Element.Children, Element.AloneInParagraph, Element.Document);
1128 }
1129
1130 return this.RenderChildren(Element);
1131 }
1132
1137 public override async Task Render(StrikeThrough Element)
1138 {
1139 this.Output.Append("<s>");
1140 await this.RenderChildren(Element);
1141 this.Output.Append("</s>");
1142 }
1143
1148 public override async Task Render(Strong Element)
1149 {
1150 this.Output.Append("<strong>");
1151 await this.RenderChildren(Element);
1152 this.Output.Append("</strong>");
1153 }
1154
1159 public override async Task Render(SubScript Element)
1160 {
1161 this.Output.Append("<sub>");
1162 await this.RenderChildren(Element);
1163 this.Output.Append("</sub>");
1164 }
1165
1170 public override async Task Render(SuperScript Element)
1171 {
1172 this.Output.Append("<sup>");
1173 await this.RenderChildren(Element);
1174 this.Output.Append("</sup>");
1175 }
1176
1181 public override async Task Render(Underline Element)
1182 {
1183 this.Output.Append("<u>");
1184 await this.RenderChildren(Element);
1185 this.Output.Append("</u>");
1186 }
1187
1188 #endregion
1189
1190 #region Block elements
1191
1196 public override async Task Render(BlockQuote Element)
1197 {
1198 this.Output.AppendLine("<blockquote>");
1199 await this.RenderChildren(Element);
1200 this.Output.AppendLine("</blockquote>");
1201 }
1202
1207 public override async Task Render(BulletList Element)
1208 {
1209 this.Output.AppendLine("<ul>");
1210 await this.RenderChildren(Element);
1211 this.Output.AppendLine("</ul>");
1212 }
1213
1218 public override async Task Render(CenterAligned Element)
1219 {
1220 this.Output.AppendLine("<div class='horizontalAlignCenter'>");
1221 await this.RenderChildren(Element);
1222 this.Output.AppendLine("</div>");
1223 }
1224
1229 public override async Task Render(CodeBlock Element)
1230 {
1231 ICodeContentHtmlRenderer Renderer = Element.CodeContentHandler<ICodeContentHtmlRenderer>();
1232
1233 if (!(Renderer is null))
1234 {
1235 try
1236 {
1237 if (await Renderer.RenderHtml(this, Element.Rows, Element.Language, Element.Indent, Element.Document))
1238 return;
1239 }
1240 catch (Exception ex)
1241 {
1242 ex = Log.UnnestException(ex);
1243
1244 this.Output.AppendLine("<font class=\"error\">");
1245
1246 if (ex is AggregateException ex2)
1247 {
1248 foreach (Exception ex3 in ex2.InnerExceptions)
1249 {
1250 this.Output.Append("<p>");
1251 this.Output.Append(XML.HtmlValueEncode(ex3.Message));
1252 this.Output.AppendLine("</p>");
1253 }
1254 }
1255 else
1256 {
1257 this.Output.Append("<p>");
1258 this.Output.Append(XML.HtmlValueEncode(ex.Message));
1259 this.Output.Append("</p>");
1260 }
1261
1262 this.Output.Append("</font>");
1263 }
1264 }
1265
1266 int i;
1267
1268 this.Output.Append("<pre><code class=\"");
1269
1270 if (string.IsNullOrEmpty(Element.Language))
1271 this.Output.Append("nohighlight");
1272 else
1273 this.Output.Append(XML.Encode(Element.Language));
1274
1275 this.Output.Append("\">");
1276
1277 for (i = Element.Start; i <= Element.End; i++)
1278 {
1279 this.Output.Append(Element.IndentString);
1280 this.Output.AppendLine(XML.HtmlValueEncode(Element.Rows[i]));
1281 }
1282
1283 this.Output.AppendLine("</code></pre>");
1284 }
1285
1290 public override Task Render(CommentBlock Element)
1291 {
1292 return Task.CompletedTask;
1293 }
1294
1299 public override async Task Render(DefinitionDescriptions Element)
1300 {
1301 foreach (MarkdownElement E in Element.Children)
1302 {
1303 this.Output.Append("<dd>");
1304 await E.Render(this);
1305 this.Output.AppendLine("</dd>");
1306 }
1307 }
1308
1313 public override async Task Render(DefinitionList Element)
1314 {
1315 this.Output.AppendLine("<dl>");
1316 await this.RenderChildren(Element);
1317 this.Output.AppendLine("</dl>");
1318 }
1319
1324 public override async Task Render(DefinitionTerms Element)
1325 {
1326 foreach (MarkdownElement E in Element.Children)
1327 {
1328 this.Output.Append("<dt>");
1329 await E.Render(this);
1330 this.Output.AppendLine("</dt>");
1331 }
1332 }
1333
1338 public override async Task Render(DeleteBlocks Element)
1339 {
1340 this.Output.AppendLine("<blockquote class=\"deleted\">");
1341
1342 foreach (MarkdownElement E in Element.Children)
1343 await E.Render(this);
1344
1345 this.Output.AppendLine("</blockquote>");
1346 }
1347
1352 public override Task Render(Footnote Element)
1353 {
1354 return this.RenderChildren(Element);
1355 }
1356
1361 public override async Task Render(Header Element)
1362 {
1363 this.Output.Append("<h");
1364 this.Output.Append(Element.Level.ToString());
1365
1366 string Id = await Element.Id;
1367
1368 if (!string.IsNullOrEmpty(Id))
1369 {
1370 this.Output.Append(" id=\"");
1371 this.Output.Append(XML.HtmlAttributeEncode(Id));
1372 this.Output.Append("\"");
1373 }
1374
1376 this.Output.Append(" class=\"tocReference\"");
1377
1378 this.Output.Append('>');
1379
1380 await this.RenderChildren(Element);
1381
1382 this.Output.Append("</h");
1383 this.Output.Append(Element.Level.ToString());
1384 this.Output.AppendLine(">");
1385 }
1386
1391 public override Task Render(HorizontalRule Element)
1392 {
1393 this.Output.AppendLine("<hr/>");
1394
1395 return Task.CompletedTask;
1396 }
1397
1402 public override async Task Render(HtmlBlock Element)
1403 {
1404 await this.RenderChildren(Element);
1405 this.Output.AppendLine();
1406 }
1407
1412 public override async Task Render(InsertBlocks Element)
1413 {
1414 this.Output.AppendLine("<blockquote class=\"inserted\">");
1415 await this.RenderChildren(Element);
1416 this.Output.AppendLine("</blockquote>");
1417 }
1418
1423 public override Task Render(InvisibleBreak Element)
1424 {
1425 return Task.CompletedTask; // TODO
1426 }
1427
1432 public override async Task Render(LeftAligned Element)
1433 {
1434 this.Output.AppendLine("<div class='horizontalAlignLeft'>");
1435 await this.RenderChildren(Element);
1436 this.Output.AppendLine("</div>");
1437 }
1438
1443 public override async Task Render(MarginAligned Element)
1444 {
1445 this.Output.AppendLine("<div class='horizontalAlignMargins'>");
1446 await this.RenderChildren(Element);
1447 this.Output.AppendLine("</div>");
1448 }
1449
1454 public override Task Render(NestedBlock Element)
1455 {
1456 return this.RenderChildren(Element);
1457 }
1458
1463 public override async Task Render(NumberedItem Element)
1464 {
1465 if (Element.NumberExplicit)
1466 {
1467 this.Output.Append("<li value=\"");
1468 this.Output.Append(Element.Number.ToString());
1469 this.Output.Append("\">");
1470 }
1471 else
1472 this.Output.Append("<li>");
1473
1474 await this.RenderChild(Element);
1475
1476 this.Output.AppendLine("</li>");
1477 }
1478
1483 public override async Task Render(NumberedList Element)
1484 {
1485 NumberedItem Item;
1486 int Expected = 0;
1487
1488 this.Output.AppendLine("<ol>");
1489
1490 foreach (MarkdownElement E in Element.Children)
1491 {
1492 Expected++;
1493 Item = E as NumberedItem;
1494
1495 if (Item is null)
1496 await E.Render(this);
1497 else if (Item.Number == Expected)
1498 {
1499 this.Output.Append("<li>");
1500 await Item.Child.Render(this);
1501 this.Output.AppendLine("</li>");
1502 }
1503 else
1504 {
1505 await Item.Render(this);
1506 Expected = Item.Number;
1507 }
1508 }
1509
1510 this.Output.AppendLine("</ol>");
1511 }
1512
1517 public override async Task Render(Paragraph Element)
1518 {
1519 if (!Element.Implicit)
1520 this.Output.Append("<p>");
1521
1522 await this.RenderChildren(Element);
1523
1524 if (!Element.Implicit)
1525 this.Output.AppendLine("</p>");
1526 }
1527
1532 public override async Task Render(RightAligned Element)
1533 {
1534 this.Output.AppendLine("<div class='horizontalAlignRight'>");
1535 await this.RenderChildren(Element);
1536 this.Output.AppendLine("</div>");
1537 }
1538
1543 public override async Task Render(Sections Element)
1544 {
1545 this.GenerateSectionHTML(Element.InitialNrColumns);
1546 await this.RenderChildren(Element);
1547 this.Output.AppendLine("</section>");
1548 }
1549
1550 private void GenerateSectionHTML(int NrColumns)
1551 {
1552 this.Output.Append("<section");
1553
1554 if (NrColumns > 1)
1555 {
1556 string s = NrColumns.ToString();
1557
1558 this.Output.Append(" style=\"-webkit-column-count:");
1559 this.Output.Append(s);
1560 this.Output.Append(";-moz-column-count:");
1561 this.Output.Append(s);
1562 this.Output.Append(";column-count:");
1563 this.Output.Append(s);
1564 this.Output.Append('"');
1565 }
1566
1567 this.Output.AppendLine(">");
1568 }
1569
1574 public override Task Render(SectionSeparator Element)
1575 {
1576 this.Output.AppendLine("</section>");
1577 this.GenerateSectionHTML(Element.NrColumns);
1578
1579 return Task.CompletedTask;
1580 }
1581
1586 public override async Task Render(Table Element)
1587 {
1589 MarkdownElement[] Row;
1590 TextAlignment?[] CellAlignments;
1591 int NrRows, RowIndex;
1592 int NrColumns = Element.Columns;
1593 int i, j, k;
1594
1595 this.Output.AppendLine("<table>");
1596
1597 if (!string.IsNullOrEmpty(Element.Id))
1598 {
1599 this.Output.Append("<caption id=\"");
1600 this.Output.Append(XML.HtmlAttributeEncode(Element.Id));
1601 this.Output.Append("\">");
1602
1603 if (string.IsNullOrEmpty(Element.Caption))
1604 this.Output.Append(XML.HtmlValueEncode(Element.Id));
1605 else
1606 this.Output.Append(XML.HtmlValueEncode(Element.Caption));
1607
1608 this.Output.AppendLine("</caption>");
1609 }
1610
1611 this.Output.AppendLine("<colgroup>");
1612 foreach (TextAlignment Alignment in Element.ColumnAlignments)
1613 {
1614 this.Output.Append("<col style=\"text-align:");
1615 this.Output.Append(Alignment.ToString().ToLower());
1616 this.Output.AppendLine("\"/>");
1617 }
1618 this.Output.AppendLine("</colgroup>");
1619
1620 this.Output.AppendLine("<thead>");
1621
1622 NrRows = Element.Headers.Length;
1623 for (RowIndex = 0; RowIndex < NrRows; RowIndex++)
1624 {
1625 Row = Element.Headers[RowIndex];
1626 CellAlignments = Element.HeaderCellAlignments[RowIndex];
1627
1628 this.Output.AppendLine("<tr>");
1629
1630 for (i = 0; i < NrColumns; i++)
1631 {
1632 E = Row[i];
1633 if (E is null)
1634 continue;
1635
1636 k = 1;
1637 j = i + 1;
1638 while (j < NrColumns && Row[j++] is null)
1639 k++;
1640
1641 this.Output.Append("<th style=\"text-align:");
1642 this.Output.Append((CellAlignments[i] ?? Element.ColumnAlignments[i]).ToString().ToLower());
1643
1644 if (k > 1)
1645 {
1646 this.Output.Append("\" colspan=\"");
1647 this.Output.Append(k.ToString());
1648 }
1649
1650 this.Output.Append("\">");
1651 await E.Render(this);
1652 this.Output.AppendLine("</th>");
1653 }
1654
1655 this.Output.AppendLine("</tr>");
1656 }
1657 this.Output.AppendLine("</thead>");
1658
1659 this.Output.AppendLine("<tbody>");
1660
1661 NrRows = Element.Rows.Length;
1662 for (RowIndex = 0; RowIndex < NrRows; RowIndex++)
1663 {
1664 Row = Element.Rows[RowIndex];
1665 CellAlignments = Element.RowCellAlignments[RowIndex];
1666
1667 this.Output.AppendLine("<tr>");
1668
1669 for (i = 0; i < NrColumns; i++)
1670 {
1671 E = Row[i];
1672 if (E is null)
1673 continue;
1674
1675 k = 1;
1676 j = i + 1;
1677 while (j < NrColumns && Row[j++] is null)
1678 k++;
1679
1680 this.Output.Append("<td style=\"text-align:");
1681 this.Output.Append((CellAlignments[i] ?? Element.ColumnAlignments[i]).ToString().ToLower());
1682
1683 if (k > 1)
1684 {
1685 this.Output.Append("\" colspan=\"");
1686 this.Output.Append(k.ToString());
1687 }
1688
1689 this.Output.Append("\">");
1690 await E.Render(this);
1691 this.Output.AppendLine("</td>");
1692 }
1693
1694 this.Output.AppendLine("</tr>");
1695 }
1696 this.Output.AppendLine("</tbody>");
1697
1698 this.Output.AppendLine("</table>");
1699 }
1700
1705 public override async Task Render(TaskItem Element)
1706 {
1707 this.Output.Append("<li class=\"taskListItem\"><input disabled=\"disabled");
1708
1709 if (Element.CheckPosition > 0)
1710 {
1711 this.Output.Append("\" id=\"item");
1712 this.Output.Append(Element.CheckPosition.ToString());
1713 this.Output.Append("\" data-position=\"");
1714 this.Output.Append(Element.CheckPosition.ToString());
1715 }
1716
1717 this.Output.Append("\" type=\"checkbox\"");
1718
1719 if (Element.IsChecked)
1720 this.Output.Append(" checked=\"checked\"");
1721
1722 this.Output.Append("/><span></span><label class=\"taskListItemLabel\"");
1723
1724 if (Element.CheckPosition > 0)
1725 {
1726 this.Output.Append(" for=\"item");
1727 this.Output.Append(Element.CheckPosition.ToString());
1728 this.Output.Append("\"");
1729 }
1730
1731 this.Output.Append('>');
1732
1733 if (Element.Child is NestedBlock NestedBlock)
1734 {
1735 bool EndLabel = true;
1736 bool First = true;
1737
1738 foreach (MarkdownElement E in NestedBlock.Children)
1739 {
1740 if (First)
1741 {
1742 First = false;
1743
1744 if (E.InlineSpanElement)
1745 await E.Render(this);
1746 else
1747 {
1748 await NestedBlock.Render(this);
1749 break;
1750 }
1751 }
1752 else
1753 {
1754 if (!E.InlineSpanElement)
1755 {
1756 this.Output.Append("</label>");
1757 EndLabel = false;
1758 }
1759
1760 await E.Render(this);
1761 }
1762 }
1763
1764 if (EndLabel)
1765 this.Output.Append("</label>");
1766
1767 this.Output.AppendLine("</li>");
1768 }
1769 else
1770 {
1771 await Element.Child.Render(this);
1772 this.Output.AppendLine("</label></li>");
1773 }
1774 }
1775
1780 public override async Task Render(TaskList Element)
1781 {
1782 this.Output.AppendLine("<ul class=\"taskList\">");
1783 await this.RenderChildren(Element);
1784 this.Output.AppendLine("</ul>");
1785 }
1786
1791 public override async Task Render(UnnumberedItem Element)
1792 {
1793 this.Output.Append("<li");
1794
1795 MarkdownDocument Detail = Element.Document.Detail;
1796
1797 if (!(Detail is null))
1798 {
1799 if (Element.Child is Link Link)
1800 {
1801 if (string.Compare(Detail.ResourceName, Link.Url, true) == 0)
1802 this.Output.Append(" class=\"active\"");
1803 }
1804 else if (Element.Child is LinkReference LinkReference)
1805 {
1806 string Label = LinkReference.Label;
1808
1809 if (!(Multimedia is null) && Multimedia.Items.Length == 1 &&
1810 string.Compare(Multimedia.Items[0].Url, Detail.ResourceName, true) == 0)
1811 {
1812 this.Output.Append(" class=\"active\"");
1813 }
1814 }
1815 }
1816
1817 this.Output.Append('>');
1818 await Element.Child.Render(this);
1819 this.Output.AppendLine("</li>");
1820 }
1821
1822 #endregion
1823
1824 }
1825}
string ShortName
Emoji short name.
string Unicode
Unicode representation of emoji.
Class that can be used to encapsulate Markdown to be returned from a Web Service, bypassing any encod...
Contains a markdown document. This markdown document class supports original markdown,...
static async Task< object > TransformXml(XmlDocument Xml, Variables Variables)
Transforms XML to an object that is easier to visualize.
bool IncludesTableOfContents
If the document contains a Table of Contents.
string CheckURL(string Url, string URL)
Checks the URL if it needs redirection to a proxy.
bool SyntaxHighlighting
If syntax highlighting is used in the document.
IEnumerable< KeyValuePair< string, KeyValuePair< string, bool >[]> > MetaData
Meta-data
bool TryGetMetaData(string Key, out KeyValuePair< string, bool >[] Value)
Tries to get a meta-data value given its key.
IEnumerable< string > FootnoteOrder
Order of footnotes.
IEmojiSource EmojiSource
Source for emojis in the document.
string ResourceName
Local resource name of Markdown document, if referenced through a web server. Master documents use th...
MarkdownDocument Detail
Detail document of a master document.
Multimedia GetReference(string Label)
Gets the multimedia information referenced by a label.
static Task< MarkdownDocument > CreateAsync(string MarkdownText, params Type[] TransparentExceptionTypes)
Contains a markdown document. This markdown document class supports original markdown,...
Contains settings that the Markdown parser uses to customize its behavior.
Represents a block quote in a markdown document.
Definition: BlockQuote.cs:11
Represents a bullet list in a markdown document.
Definition: BulletList.cs:11
Represents a center-aligned set of blocks in a markdown document.
Represents a code block in a markdown document.
Definition: CodeBlock.cs:16
string IndentString
String used for indentation.
Definition: CodeBlock.cs:273
Represents a comment block in a markdown document.
Definition: CommentBlock.cs:10
Represents a definition list in a markdown document.
Represents inserted blocks in a markdown document.
Definition: DeleteBlocks.cs:11
override Task Render(IRenderer Output)
Renders the element.
bool Referenced
If the Footnote has been referenced during rendering, and therefore needs to be shown at the end of t...
Definition: Footnote.cs:51
Represents a header in a markdown document.
Definition: Header.cs:15
Represents a block of HTML in a markdown document.
Definition: HtmlBlock.cs:11
Represents inserted blocks in a markdown document.
Definition: InsertBlocks.cs:11
Represents a left-aligned set of blocks in a markdown document.
Definition: LeftAligned.cs:11
Represents a margin-aligned set of blocks in a markdown document.
Represents a nested block with no special formatting rules in a markdown document.
Definition: NestedBlock.cs:11
override Task Render(IRenderer Output)
Renders the element.
Represents a numbered item in an ordered list.
Definition: NumberedItem.cs:10
bool NumberExplicit
If number is explicitly provided (true) or inferred (false).
Definition: NumberedItem.cs:40
Represents a numbered list in a markdown document.
Definition: NumberedList.cs:11
Represents a paragraph in a markdown document.
Definition: Paragraph.cs:11
bool Implicit
If paragraph is implicit or not.
Definition: Paragraph.cs:41
Represents a right-aligned set of blocks in a markdown document.
Definition: RightAligned.cs:11
int NrColumns
Number of columns in following section.
Represents a sequence of sections.
Definition: Sections.cs:11
int InitialNrColumns
Number of columns for initial section.
Definition: Sections.cs:32
Represents a table in a markdown document.
Definition: Table.cs:11
Represents a task item in a task list.
Definition: TaskItem.cs:10
int CheckPosition
Position of the checkmark in the original markdown text document.
Definition: TaskItem.cs:36
bool IsChecked
If the item is checked or not.
Definition: TaskItem.cs:31
Represents a task list in a markdown document.
Definition: TaskList.cs:11
Represents an unnumbered item in an ordered list.
override IEnumerable< MarkdownElement > Children
Any children of the element.
MarkdownElement LastChild
Last child, or null if none.
void AddChildren(params MarkdownElement[] NewChildren)
Adds children to the element.
Abstract base class for all markdown elements.
abstract Task Render(IRenderer Output)
Renders the element.
virtual IEnumerable< MarkdownElement > Children
Any children of the element.
abstract bool InlineSpanElement
If the element is an inline span element.
MarkdownDocument Document
Markdown document.
string Delimiter
Delimiter string used to identify emoji.
int Level
Level (number of colons used to define the emoji)
bool AutoExpand
If the footnote should automatically be expanded when rendered, if format supports auto-expansion.
Represents an HTML entity in Unicode format.
bool AloneInParagraph
If the element is alone in a paragraph.
Definition: InlineScript.cs:55
async Task< object > EvaluateExpression()
Evaluates the script expression.
Definition: InlineScript.cs:71
bool TryGetMetaData(out KeyValuePair< string, bool >[] Values)
Tries to get meta-data from the document.
MultimediaItem[] Items
Multimedia items.
Definition: Multimedia.cs:40
bool AloneInParagraph
If the element is alone in a paragraph.
Renders HTML from a Markdown document.
Definition: HtmlRenderer.cs:24
override async Task Render(BlockQuote Element)
Renders Element .
override async Task Render(Sections Element)
Renders Element .
override async Task Render(DeleteBlocks Element)
Renders Element .
override Task RenderDocumentFooter()
Renders the document header.
override Task Render(SectionSeparator Element)
Renders Element .
override async Task Render(Insert Element)
Renders Element .
override async Task Render(FootnoteReference Element)
Renders Element .
override async Task Render(UnnumberedItem Element)
Renders Element .
override Task Render(DetailsReference Element)
Renders Element .
override async Task Render(NumberedList Element)
Renders Element .
override async Task Render(InsertBlocks Element)
Renders Element .
override Task Render(CommentBlock Element)
Renders Element .
override Task Render(NestedBlock Element)
Renders Element .
HtmlRenderer(StringBuilder Output, HtmlSettings HtmlSettings)
Renders HTML from a Markdown document.
Definition: HtmlRenderer.cs:45
override Task Render(Link Element)
Renders Element .
override async Task Render(RightAligned Element)
Renders Element .
override async Task Render(DefinitionTerms Element)
Renders Element .
async Task RenderObject(object Result, bool AloneInParagraph, Variables Variables)
Generates HTML from Script output.
override Task Render(InlineText Element)
Renders Element .
override async Task Render(HtmlBlock Element)
Renders Element .
override async Task Render(LeftAligned Element)
Renders Element .
override async Task Render(SuperScript Element)
Renders Element .
override Task Render(LinkReference Element)
Renders Element .
override async Task Render(CodeBlock Element)
Renders Element .
override async Task Render(DefinitionDescriptions Element)
Renders Element .
override Task Render(HtmlEntity Element)
Renders Element .
override async Task Render(Table Element)
Renders Element .
override async Task Render(Strong Element)
Renders Element .
override Task Render(HtmlEntityUnicode Element)
Renders Element .
override Task Render(AutomaticLinkMail Element)
Renders Element .
override async Task RenderFootnotes()
Renders footnotes.
override async Task Render(Emphasize Element)
Renders Element .
override Task Render(EmojiReference Element)
Renders Element .
override async Task Render(Header Element)
Renders Element .
override Task Render(InlineCode Element)
Renders Element .
readonly HtmlSettings htmlSettings
HTML settings.
Definition: HtmlRenderer.cs:28
HtmlRenderer(HtmlSettings HtmlSettings, MarkdownDocument Document)
Renders HTML from a Markdown document.
Definition: HtmlRenderer.cs:56
override async Task Render(InlineScript Element)
Renders Element .
override Task Render(MetaReference Element)
Renders Element .
override Task Render(MultimediaReference Element)
Renders Element .
override Task Render(HashTag Element)
Renders Element .
override async Task Render(DefinitionList Element)
Renders Element .
override async Task Render(BulletList Element)
Renders Element .
override Task Render(InlineHTML Element)
Renders Element .
HtmlRenderer(StringBuilder Output, HtmlSettings HtmlSettings, MarkdownDocument Document)
Renders HTML from a Markdown document.
Definition: HtmlRenderer.cs:68
override async Task Render(MarginAligned Element)
Renders Element .
override async Task Render(Delete Element)
Renders Element .
override async Task Render(Paragraph Element)
Renders Element .
override Task Render(Model.SpanElements.Multimedia Element)
Renders Element .
override Task Render(AutomaticLinkUrl Element)
Renders Element .
override async Task Render(CenterAligned Element)
Renders Element .
async Task Render(string Url, string Title, IEnumerable< MarkdownElement > ChildNodes, MarkdownDocument Document)
Generates HTML for a link.
override Task Render(Footnote Element)
Renders Element .
override async Task Render(Underline Element)
Renders Element .
override async Task Render(SubScript Element)
Renders Element .
override async Task Render(TaskItem Element)
Renders Element .
override Task RenderDocumentHeader()
Renders the document header.
Definition: HtmlRenderer.cs:77
override async Task Render(TaskList Element)
Renders Element .
override async Task Render(NumberedItem Element)
Renders Element .
override async Task Render(Abbreviation Element)
Renders Element .
HtmlRenderer(HtmlSettings HtmlSettings)
Renders HTML from a Markdown document.
Definition: HtmlRenderer.cs:34
override async Task Render(StrikeThrough Element)
Renders Element .
override Task Render(HorizontalRule Element)
Renders Element .
override Task Render(InvisibleBreak Element)
Renders Element .
override Task Render(LineBreak Element)
Renders Element .
Contains settings that the HTML export uses to customize HTML output.
Definition: HtmlSettings.cs:7
Abstract base class for Markdown renderers.
Definition: Renderer.cs:14
readonly StringBuilder Output
Renderer output.
Definition: Renderer.cs:18
Task RenderChild(MarkdownElementSingleChild Element)
Renders the child of Element .
Definition: Renderer.cs:175
async Task RenderChildren(MarkdownElementChildren Element)
Renders the children of Element .
Definition: Renderer.cs:147
virtual async Task RenderDocument(MarkdownDocument Document, bool Inclusion)
Renders a document.
Definition: Renderer.cs:75
MarkdownDocument Document
Reference to Markdown document being processed.
Definition: Renderer.cs:23
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 Encode(string s)
Encodes a string for use in XML.
Definition: XML.cs:27
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 Exception UnnestException(Exception Exception)
Unnests an exception, to extract the relevant inner exception.
Definition: Log.cs:818
Class managing a script expression.
Definition: Expression.cs:39
static string ToString(double Value)
Converts a value to a string, that can be parsed as part of an expression.
Definition: Expression.cs:4496
Handles two-dimensional graphs.
Definition: Graph2D.cs:26
string Title
Title for graph.
Definition: Graph2D.cs:251
Base class for graphs.
Definition: Graph.cs:79
Contains pixel information
virtual byte[] EncodeAsPng()
Encodes the pixels into a binary PNG image.
ToMatrix(ScriptNode Operand, bool NullCheck, int Start, int Length, Expression Expression)
To-Matrix operator.
Definition: ToMatrix.cs:22
Collection of variables.
Definition: Variables.cs:25
Interface for Emoji sources. Emoji sources provide emojis to content providers.
Definition: IEmojiSource.cs:12
Task GenerateHTML(StringBuilder Output, EmojiInfo Emoji, bool EmbedImage)
Generates HTML for a given Emoji.
bool EmojiSupported(EmojiInfo Emoji)
If the emoji is supported by the emoji source.
Interface for multimedia content HTML renderers.
Interface for objects that can be converted into matrices.
Definition: IToMatrix.cs:9
TextAlignment
Text alignment of contents.