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