Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
MarkdownRenderer.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{
24 {
25 private bool portableSyntax = true;
26
31 : base()
32 {
33 }
34
39 public MarkdownRenderer(StringBuilder Output)
40 : base(Output)
41 {
42 }
43
49 : base(Document)
50 {
51 }
52
59 : base(Output, Document)
60 {
61 }
62
67 public bool PortableSyntax
68 {
69 get => this.portableSyntax;
70 set => this.portableSyntax = value;
71 }
72
76 public override async Task RenderFootnotes()
77 {
78 if (!(this.Document?.FootnoteOrder is null))
79 {
81 {
82 foreach (string Key in this.Document.FootnoteOrder)
83 {
84 if (!Guid.TryParse(Key, out _) &&
85 (this.Document?.TryGetFootnote(Key, out Footnote Note) ?? false) &&
86 Note.Referenced)
87 {
88 this.Output.AppendLine();
89 this.Output.AppendLine();
90 this.Output.Append("[^");
91 this.Output.Append(Key);
92 this.Output.Append("]:");
93
94 await Note.Render(Renderer);
95
96 string s = Renderer.ToString();
98
99 foreach (string Row in s.Replace("\r\n", "\n").Replace('\r', '\n').Split('\n'))
100 {
101 this.Output.Append('\t');
102 this.Output.AppendLine(Row);
103 }
104 }
105 }
106 }
107 }
108 }
109
110 #region Span Elements
111
116 public override async Task Render(Abbreviation Element)
117 {
118 this.Output.Append('[');
119 await this.RenderChildren(Element);
120 this.Output.Append("](abbr:");
121 this.Output.Append(Element.Description);
122 this.Output.Append(')');
123 }
124
129 public override Task Render(AutomaticLinkMail Element)
130 {
131 this.Output.Append('<');
132 this.Output.Append(Element.EMail);
133 this.Output.Append('>');
134
135 return Task.CompletedTask;
136 }
137
142 public override Task Render(AutomaticLinkUrl Element)
143 {
144 this.Output.Append('<');
145 this.Output.Append(Element.URL);
146 this.Output.Append('>');
147
148 return Task.CompletedTask;
149 }
150
155 public override async Task Render(Delete Element)
156 {
157 this.Output.Append("~~");
158 await this.RenderChildren(Element);
159 this.Output.Append("~~");
160 }
161
166 public override Task Render(DetailsReference Element)
167 {
168 this.Output.Append("[%Details]");
169
170 return Task.CompletedTask;
171 }
172
177 public override Task Render(EmojiReference Element)
178 {
179 this.Output.Append(Element.Delimiter);
180 this.Output.Append(Element.Emoji.ShortName);
181 this.Output.Append(Element.Delimiter);
182
183 return Task.CompletedTask;
184 }
185
190 public override async Task Render(Emphasize Element)
191 {
192 this.Output.Append('*');
193 await this.RenderChildren(Element);
194 this.Output.Append('*');
195 }
196
201 public override async Task Render(FootnoteReference Element)
202 {
203 this.Output.Append("[^");
204
205 if (!(this.Document?.TryGetFootnote(Element.Key, out Footnote Footnote) ?? false))
206 Footnote = null;
207
208 if (Guid.TryParse(Element.Key, out _) && !(Footnote is null))
209 {
211 {
212 await Renderer.Render(Footnote);
213
214 this.Output.Append(Renderer.ToString().TrimEnd());
215 }
216 }
217 else
218 {
219 this.Output.Append(Element.Key);
220
221 if (!(Footnote is null))
222 Footnote.Referenced = true;
223 }
224
225 this.Output.Append(']');
226 }
227
232 public override Task Render(HashTag Element)
233 {
234 this.Output.Append('#');
235 this.Output.Append(Element.Tag);
236
237 return Task.CompletedTask;
238 }
239
244 public override Task Render(HtmlEntity Element)
245 {
246 switch (Element.Entity)
247 {
248 case "quot":
249 case "amp":
250 case "apos":
251 case "lt":
252 case "gt":
253 case "nbsp": // Has syntactic significance when parsing HTML or Markdown
254 this.Output.Append('&');
255 this.Output.Append(Element.Entity);
256 this.Output.Append(';');
257 break;
258
259 case "QUOT":
260 case "AMP":
261 case "LT":
262 case "GT":
263 this.Output.Append('&');
264 this.Output.Append(Element.Entity.ToLower());
265 this.Output.Append(';');
266 break;
267
268 default:
269 string s = Html.HtmlEntity.EntityToCharacter(Element.Entity);
270 if (!string.IsNullOrEmpty(s))
271 this.Output.Append(s);
272 break;
273 }
274
275 return Task.CompletedTask;
276 }
277
282 public override Task Render(HtmlEntityUnicode Element)
283 {
284 this.Output.Append("&#");
285 this.Output.Append(Element.Code.ToString());
286 this.Output.Append(';');
287
288 return Task.CompletedTask;
289 }
290
295 public override Task Render(InlineCode Element)
296 {
297 this.Output.Append('`');
298 this.Output.Append(Element.Code);
299 this.Output.Append('`');
300
301 return Task.CompletedTask;
302 }
303
308 public override Task Render(InlineHTML Element)
309 {
310 this.Output.Append(Element.HTML);
311
312 return Task.CompletedTask;
313 }
314
319 public override async Task Render(InlineScript Element)
320 {
321 object Result = await Element.EvaluateExpression();
322
323 await this.RenderObject(Result, Element.AloneInParagraph, Element.Variables);
324 }
325
332 public async Task RenderObject(object Result, bool AloneInParagraph, Variables Variables)
333 {
334 if (Result is null)
335 return;
336
337 if (Result is XmlDocument Xml)
338 Result = await MarkdownDocument.TransformXml(Xml, Variables);
339 else if (Result is IToMatrix ToMatrix)
340 Result = ToMatrix.ToMatrix();
341
342 if (Result is Graph G)
343 {
345 this.Output.AppendLine();
346 }
347 else if (Result is PixelInformation Pixels)
348 {
349 ToMarkdown.PixelsToMarkdown(Pixels, this.Output);
350 this.Output.AppendLine();
351 }
352 else if (Result is SKImage Img)
353 {
355 this.Output.AppendLine();
356 }
357 else if (Result is MarkdownDocument Doc)
358 {
360 {
361 await Renderer.RenderDocument(Doc, true); // Does not call ProcessAsyncTasks()
362 Doc.ProcessAsyncTasks();
363 }
364 }
365 else if (Result is MarkdownContent Markdown)
366 {
367 Doc = await MarkdownDocument.CreateAsync(Markdown.Markdown, Markdown.Settings ?? new MarkdownSettings());
368
370 {
371 await Renderer.RenderDocument(Doc, true); // Does not call ProcessAsyncTasks()
372 Doc.ProcessAsyncTasks();
373 }
374 }
375 else if (Result is Exception ex)
376 {
377 ex = Log.UnnestException(ex);
378
379 this.Output.Append("<font class=\"error\">");
380
381 if (ex is AggregateException ex2)
382 {
383 foreach (Exception ex3 in ex2.InnerExceptions)
384 {
385 this.Output.Append("<p>");
386 this.Output.Append(XML.HtmlValueEncode(ex3.Message));
387 this.Output.AppendLine("</p>");
388 }
389 }
390 else
391 {
392 if (AloneInParagraph)
393 this.Output.Append("<p>");
394
395 this.Output.Append(MarkdownDocument.Encode(ex.Message));
396
397 if (AloneInParagraph)
398 this.Output.Append("</p>");
399 }
400
401 this.Output.Append("</font>");
402 }
403 else if (Result is IMatrix M)
404 {
406 this.Output.AppendLine();
407 }
408 else if (Result is Array A)
409 {
410 foreach (object Item in A)
411 await this.RenderObject(Item, false, Variables);
412 }
413 else
414 {
415 if (AloneInParagraph)
416 this.Output.Append("<p>");
417
418 this.Output.Append(MarkdownDocument.Encode(Result?.ToString() ?? string.Empty));
419
420 if (AloneInParagraph)
421 this.Output.Append("</p>");
422 }
423
424 if (AloneInParagraph)
425 this.Output.AppendLine();
426 }
427
432 public override Task Render(InlineText Element)
433 {
434 this.Output.Append(MarkdownDocument.Encode(Element.Value));
435
436 return Task.CompletedTask;
437 }
438
443 public override async Task Render(Insert Element)
444 {
445 this.Output.Append("__");
446 await this.RenderChildren(Element);
447 this.Output.Append("__");
448 }
449
454 public override Task Render(LineBreak Element)
455 {
456 this.Output.AppendLine(" ");
457
458 return Task.CompletedTask;
459 }
460
465 public override async Task Render(Link Element)
466 {
467 this.Output.Append('[');
468 await this.RenderChildren(Element);
469 this.Output.Append("](");
470 this.Output.Append(Element.Url);
471
472 if (!string.IsNullOrEmpty(Element.Title))
473 {
474 this.Output.Append(" \"");
475 this.Output.Append(Element.Title.Replace("\"", "\\\""));
476 this.Output.Append('"');
477 }
478
479 this.Output.Append(')');
480 }
481
486 public override async Task Render(LinkReference Element)
487 {
488 this.Output.Append('[');
489 await this.RenderChildren(Element);
490 this.Output.Append("][");
491 this.Output.Append(Element.Label);
492 this.Output.Append(']');
493 }
494
499 public override Task Render(MetaReference Element)
500 {
501 bool FirstOnRow = true;
502
503 if (Element.TryGetMetaData(out KeyValuePair<string, bool>[] Values))
504 {
505 foreach (KeyValuePair<string, bool> P in Values)
506 {
507 if (FirstOnRow)
508 FirstOnRow = false;
509 else
510 this.Output.Append(' ');
511
512 this.Output.Append(MarkdownDocument.Encode(P.Key));
513 if (P.Value)
514 {
515 this.Output.AppendLine(" ");
516 FirstOnRow = true;
517 }
518 }
519 }
520
521 return Task.CompletedTask;
522 }
523
528 public override Task Render(Model.SpanElements.Multimedia Element)
529 {
531 if (Renderer is null)
532 return this.DefaultRenderingMultimedia(Element.Items, Element.Children, Element.AloneInParagraph);
533 else
534 return Renderer.RenderMarkdown(this, Element.Items, Element.Children, Element.AloneInParagraph, Element.Document);
535 }
536
543 private async Task DefaultRenderingMultimedia(MultimediaItem[] Items, IEnumerable<MarkdownElement> ChildNodes,
544 bool AloneInParagraph)
545 {
546 bool First = true;
547
548 this.Output.Append("![");
549
550 foreach (MarkdownElement Child in ChildNodes)
551 await Child.Render(this);
552
553 this.Output.Append(']');
554
555 foreach (MultimediaItem Item in Items)
556 {
557 if (First)
558 First = false;
559 else if (AloneInParagraph)
560 {
561 this.Output.AppendLine();
562 this.Output.Append('\t');
563 }
564
565 this.Output.Append('(');
566 this.Output.Append(Item.Url);
567
568 if (!string.IsNullOrEmpty(Item.Title))
569 {
570 this.Output.Append(" \"");
571 this.Output.Append(Item.Title.Replace("\"", "\\\""));
572 this.Output.Append('"');
573 }
574
575 if (Item.Width.HasValue)
576 {
577 this.Output.Append(' ');
578 this.Output.Append(Item.Width.Value.ToString());
579
580 if (Item.Height.HasValue)
581 {
582 this.Output.Append(' ');
583 this.Output.Append(Item.Height.Value.ToString());
584 }
585 }
586
587 this.Output.Append(')');
588 }
589
590 if (AloneInParagraph)
591 {
592 this.Output.AppendLine();
593 this.Output.AppendLine();
594 }
595 }
596
601 public override Task Render(MultimediaReference Element)
602 {
603 Model.SpanElements.Multimedia Multimedia = Element.Document.GetReference(Element.Label);
604
605 if (!(Multimedia is null))
606 {
608 if (Renderer is null)
609 return this.DefaultRenderingMultimedia(Multimedia.Items, Element.Children, Element.AloneInParagraph);
610 else
611 return Renderer.RenderMarkdown(this, Multimedia.Items, Element.Children, Element.AloneInParagraph, Element.Document);
612 }
613
614 return this.RenderChildren(Element);
615 }
616
621 public override async Task Render(StrikeThrough Element)
622 {
623 this.Output.Append('~');
624 await this.RenderChildren(Element);
625 this.Output.Append('~');
626 }
627
632 public override async Task Render(Strong Element)
633 {
634 this.Output.Append("**");
635 await this.RenderChildren(Element);
636 this.Output.Append("**");
637 }
638
643 public override async Task Render(SubScript Element)
644 {
645 this.Output.Append('[');
646 await this.RenderChildren(Element);
647 this.Output.Append(']');
648 }
649
654 public override async Task Render(SuperScript Element)
655 {
656 this.Output.Append("^[");
657 await this.RenderChildren(Element);
658 this.Output.Append(']');
659 }
660
665 public override async Task Render(Underline Element)
666 {
667 this.Output.Append('_');
668 await this.RenderChildren(Element);
669 this.Output.Append('_');
670 }
671
672 #endregion
673
674 #region Indentation
675
681 private Task PrefixedBlock(IEnumerable<MarkdownElement> Children, string Prefix)
682 {
683 return this.PrefixedBlock(Children, Prefix, Prefix);
684 }
685
692 private Task PrefixedBlock(MarkdownElement Child, string PrefixFirstRow, string PrefixNextRows)
693 {
694 return this.PrefixedBlock(new MarkdownElement[] { Child }, PrefixFirstRow, PrefixNextRows);
695 }
696
703 private async Task PrefixedBlock(IEnumerable<MarkdownElement> Children, string PrefixFirstRow, string PrefixNextRows)
704 {
706 {
707 foreach (MarkdownElement E in Children)
708 await E.Render(Renderer);
709
710 string s = Renderer.ToString().Replace("\r\n", "\n").Replace('\r', '\n');
711 string[] Rows = s.Split('\n');
712 int i, c = Rows.Length;
713
714 if (c > 0 && string.IsNullOrEmpty(Rows[c - 1]))
715 c--;
716
717 for (i = 0; i < c; i++)
718 {
719 this.Output.Append(PrefixFirstRow);
720 this.Output.AppendLine(Rows[i]);
721 PrefixFirstRow = PrefixNextRows;
722 }
723 }
724 }
725
731 private Task SuffixedBlock(IEnumerable<MarkdownElement> Children, string Suffix)
732 {
733 return this.SuffixedBlock(Children, Suffix, Suffix);
734 }
735
742 private async Task SuffixedBlock(IEnumerable<MarkdownElement> Children, string SuffixFirstRow, string SuffixNextRows)
743 {
745 {
746 foreach (MarkdownElement E in Children)
747 await E.Render(Renderer);
748
749 string s = Renderer.ToString().Replace("\r\n", "\n").Replace('\r', '\n');
750 string[] Rows = s.Split('\n');
751 int i, c = Rows.Length;
752
753 if (c > 0 && string.IsNullOrEmpty(Rows[c - 1]))
754 c--;
755
756 for (i = 0; i < c; i++)
757 {
758 this.Output.Append(Rows[i]);
759 this.Output.AppendLine(SuffixFirstRow);
760 SuffixFirstRow = SuffixNextRows;
761 }
762 }
763 }
764
771 private Task PrefixSuffixedBlock(IEnumerable<MarkdownElement> Children, string Prefix, string Suffix)
772 {
773 return this.PrefixSuffixedBlock(Children, Prefix, Prefix, Suffix, Suffix);
774 }
775
784 private async Task PrefixSuffixedBlock(IEnumerable<MarkdownElement> Children, string PrefixFirstRow, string PrefixNextRows,
785 string SuffixFirstRow, string SuffixNextRows)
786 {
788 {
789 foreach (MarkdownElement E in Children)
790 await E.Render(Renderer);
791
792 string s = Renderer.ToString().Replace("\r\n", "\n").Replace('\r', '\n');
793 string[] Rows = s.Split('\n');
794 int i, c = Rows.Length;
795
796 if (c > 0 && string.IsNullOrEmpty(Rows[c - 1]))
797 c--;
798
799 for (i = 0; i < c; i++)
800 {
801 this.Output.Append(PrefixFirstRow);
802 this.Output.Append(Rows[i]);
803 this.Output.AppendLine(SuffixFirstRow);
804 PrefixFirstRow = PrefixNextRows;
805 SuffixFirstRow = SuffixNextRows;
806 }
807 }
808 }
809
810 #endregion
811
812 #region Block elements
813
818 public override async Task Render(BlockQuote Element)
819 {
820 await this.PrefixedBlock(Element.Children, ">\t");
821 this.Output.AppendLine();
822 }
823
828 public override async Task Render(BulletList Element)
829 {
830 await this.RenderChildren(Element);
831 this.Output.AppendLine();
832 }
833
838 public override async Task Render(CenterAligned Element)
839 {
840 await this.PrefixSuffixedBlock(Element.Children, ">>", "<<");
841 this.Output.AppendLine();
842 }
843
848 public override async Task Render(CodeBlock Element)
849 {
850 if (this.portableSyntax)
851 {
853
854 if (!(Renderer is null))
855 {
856 try
857 {
858 if (await Renderer.RenderMarkdown(this, Element.Rows, Element.Language, Element.Indent, Element.Document))
859 return;
860 }
861 catch (Exception)
862 {
863 // Ignore
864 }
865 }
866 }
867
868 int Max = 2;
869
870 foreach (string Row in Element.Rows)
871 {
872 int i = 0;
873
874 foreach (char ch in Row)
875 {
876 if (ch == '`')
877 i++;
878 else
879 {
880 if (i > Max)
881 Max = i;
882
883 i = 0;
884 }
885 }
886
887 if (i > Max)
888 Max = i;
889 }
890
891 string s = new string('`', Max + 1);
892
893 this.Output.Append(s);
894 this.Output.AppendLine(Element.Language);
895
896 foreach (string Row in Element.Rows)
897 this.Output.AppendLine(Row);
898
899 this.Output.AppendLine(s);
900 this.Output.AppendLine();
901 }
902
907 public override Task Render(CommentBlock Element)
908 {
909 return Task.CompletedTask;
910 }
911
916 public override async Task Render(DefinitionDescriptions Element)
917 {
918 await this.PrefixedBlock(Element.Children, ":\t", ":\t");
919 this.Output.AppendLine();
920 }
921
926 public override async Task Render(DefinitionList Element)
927 {
928 await this.RenderChildren(Element);
929 this.Output.AppendLine();
930 }
931
936 public override async Task Render(DefinitionTerms Element)
937 {
938 foreach (MarkdownElement E in Element.Children)
939 {
940 await E.Render(this);
941 this.Output.AppendLine();
942 }
943 }
944
949 public override async Task Render(DeleteBlocks Element)
950 {
951 await this.PrefixedBlock(Element.Children, "->\t");
952 this.Output.AppendLine();
953 }
954
959 public override Task Render(Footnote Element)
960 {
961 return this.RenderChildren(Element);
962 }
963
968 public override async Task Render(Header Element)
969 {
970 if (Element.Prefix)
971 {
972 this.Output.Append(Element.Row);
973 this.Output.Append(' ');
974 }
975
976 await this.RenderChildren(Element);
977 this.Output.AppendLine();
978
979 if (!Element.Prefix)
980 this.Output.AppendLine(Element.Row);
981
982 this.Output.AppendLine();
983 }
984
989 public override Task Render(HorizontalRule Element)
990 {
991 this.Output.AppendLine(Element.Row);
992 this.Output.AppendLine();
993
994 return Task.CompletedTask;
995 }
996
1001 public override async Task Render(HtmlBlock Element)
1002 {
1003 await this.RenderChildren(Element);
1004 this.Output.AppendLine();
1005 }
1006
1011 public override async Task Render(InsertBlocks Element)
1012 {
1013 await this.PrefixedBlock(Element.Children, "+>\t");
1014 this.Output.AppendLine();
1015 }
1016
1021 public override Task Render(InvisibleBreak Element)
1022 {
1023 this.Output.AppendLine(Element.Row);
1024 this.Output.AppendLine();
1025
1026 return Task.CompletedTask;
1027 }
1028
1033 public override async Task Render(LeftAligned Element)
1034 {
1035 await this.PrefixedBlock(Element.Children, "<<");
1036 this.Output.AppendLine();
1037 }
1038
1043 public override async Task Render(MarginAligned Element)
1044 {
1045 await this.PrefixSuffixedBlock(Element.Children, "<<", ">>");
1046 this.Output.AppendLine();
1047 }
1048
1053 public override Task Render(NestedBlock Element)
1054 {
1055 return this.RenderChildren(Element);
1056 }
1057
1062 public override async Task Render(NumberedItem Element)
1063 {
1064 string Prefix;
1065
1066 if (Element.NumberExplicit)
1067 Prefix = Element.Number.ToString() + ".\t";
1068 else
1069 Prefix = "#.\t";
1070
1071 await this.PrefixedBlock(Element.Child, Prefix, "\t");
1072
1073 if (Element.Child.IsBlockElement)
1074 this.Output.AppendLine();
1075 }
1076
1081 public override async Task Render(NumberedList Element)
1082 {
1083 await this.RenderChildren(Element);
1084 this.Output.AppendLine();
1085 }
1086
1091 public override async Task Render(Paragraph Element)
1092 {
1093 await this.RenderChildren(Element);
1094
1095 this.Output.AppendLine();
1096 this.Output.AppendLine();
1097 }
1098
1103 public override async Task Render(RightAligned Element)
1104 {
1105 await this.SuffixedBlock(Element.Children, ">>");
1106 this.Output.AppendLine();
1107 }
1108
1113 public override Task Render(Sections Element)
1114 {
1115 if (!string.IsNullOrEmpty(Element.InitialRow))
1116 {
1117 this.Output.AppendLine(Element.InitialRow);
1118 this.Output.AppendLine();
1119 }
1120
1121 return this.RenderChildren(Element);
1122 }
1123
1128 public override Task Render(SectionSeparator Element)
1129 {
1130 this.Output.AppendLine(Element.Row);
1131 this.Output.AppendLine();
1132
1133 return Task.CompletedTask;
1134 }
1135
1140 public override async Task Render(Table Element)
1141 {
1142 int[] Widths = new int[Element.Columns];
1143 int i, c, d;
1144
1145 string[][] Headers = new string[c = Element.Headers.Length][];
1146 for (i = 0; i < c; i++)
1147 Headers[i] = await this.Render(Element.Headers[i], Element.HeaderCellAlignments[i], Widths, Element);
1148
1149 string[][] Rows = new string[d = Element.Rows.Length][];
1150 for (i = 0; i < d; i++)
1151 Rows[i] = await this.Render(Element.Rows[i], Element.RowCellAlignments[i], Widths, Element);
1152
1153 for (i = 0; i < c; i++)
1154 this.Render(Headers[i], Widths, Element);
1155
1156 foreach (string Headline in Element.ColumnAlignmentDefinitions)
1157 {
1158 this.Output.Append('|');
1159 this.Output.Append(Headline);
1160 }
1161
1162 this.Output.AppendLine("|");
1163
1164 for (i = 0; i < d; i++)
1165 this.Render(Rows[i], Widths, Element);
1166
1167 bool NewLine = false;
1168
1169 if (!string.IsNullOrEmpty(Element.Caption))
1170 {
1171 this.Output.Append('[');
1172 this.Output.Append(Element.Caption);
1173 this.Output.Append(']');
1174 NewLine = true;
1175 }
1176
1177 if (!string.IsNullOrEmpty(Element.Id))
1178 {
1179 this.Output.Append('[');
1180 this.Output.Append(Element.Id);
1181 this.Output.Append(']');
1182 NewLine = true;
1183 }
1184
1185 if (NewLine)
1186 this.Output.AppendLine();
1187
1188 this.Output.AppendLine();
1189 }
1190
1191 private void Render(string[] Elements, int[] Widths, Table Element)
1192 {
1193 string s;
1194 int i, j, k;
1195
1196 this.Output.Append('|');
1197
1198 for (i = 0; i < Element.Columns;)
1199 {
1200 s = Elements[i];
1201 if (s is null)
1202 continue;
1203
1204 this.Output.Append(' ');
1205 this.Output.Append(s);
1206 j = Widths[i] - s.Length;
1207 k = 1;
1208
1209 i++;
1210 while (i < Element.Columns && Elements[i] is null)
1211 {
1212 j += Widths[i++];
1213 k++;
1214 }
1215
1216 while (j-- > 0)
1217 this.Output.Append(' ');
1218
1219 while (k-- > 0)
1220 this.Output.Append('|');
1221 }
1222
1223 this.Output.AppendLine();
1224 }
1225
1226 private async Task<string[]> Render(MarkdownElement[] Elements, TextAlignment?[] Alignments, int[] Widths, Table Element)
1227 {
1229 {
1230 string[] Result = new string[Element.Columns];
1231 string s;
1233 TextAlignment? Alignment;
1234 int Len, LastLen;
1235 int i, j;
1236
1237 for (i = 0; i < Element.Columns; i++)
1238 {
1239 E = Elements[i];
1240 if (E is null)
1241 continue;
1242
1243 await E.Render(Renderer);
1244 s = Renderer.ToString();
1245 Renderer.Clear();
1246
1247 Alignment = Alignments[i];
1248 if (Alignment.HasValue)
1249 {
1250 switch (Alignment.Value)
1251 {
1252 case TextAlignment.Left:
1253 s = "<<" + s;
1254 break;
1255
1256 case TextAlignment.Right:
1257 s += ">>";
1258 break;
1259
1260 case TextAlignment.Center:
1261 s = ">>" + s + "<<";
1262 break;
1263 }
1264 }
1265
1266 Result[i] = s;
1267
1268 LastLen = s.Length + 2; // One space on each side of content.
1269 j = i + 1;
1270 while (j < Element.Columns && Elements[j] is null)
1271 {
1272 Result[j++] = null;
1273 LastLen++; // One additional pipe character
1274 }
1275
1276 j -= i;
1277
1278 Len = LastLen / j;
1279 LastLen -= (j - 1) * Len;
1280
1281 while (j-- > 1)
1282 {
1283 if (Widths[i] < Len)
1284 Widths[i] = Len;
1285
1286 i++;
1287 }
1288
1289 if (Widths[i] < LastLen)
1290 Widths[i] = LastLen;
1291 }
1292
1293 return Result;
1294 }
1295 }
1296
1301 public override async Task Render(TaskItem Element)
1302 {
1303 await this.PrefixedBlock(Element.Child, Element.IsChecked ? "[x]\t" : "[ ]\t", "\t");
1304
1305 if (Element.Child.IsBlockElement)
1306 this.Output.AppendLine();
1307 }
1308
1313 public override async Task Render(TaskList Element)
1314 {
1315 await this.RenderChildren(Element);
1316 this.Output.AppendLine();
1317 }
1318
1323 public override async Task Render(UnnumberedItem Element)
1324 {
1325 await this.PrefixedBlock(Element.Child, Element.Prefix + "\t", "\t");
1326
1327 if (Element.Child.IsBlockElement)
1328 this.Output.AppendLine();
1329 }
1330
1331 #endregion
1332
1333 }
1334}
Converts an element to a markdown string.
Definition: ToMarkdown.cs:22
static string ImageToMarkdown(SKImage Image)
Converts an image to Markdown.
Definition: ToMarkdown.cs:361
static string MatrixToMarkdown(IMatrix Matrix)
Converts a matrix to Markdown.
Definition: ToMarkdown.cs:85
static string PixelsToMarkdown(PixelInformation Pixels)
Converts pixels to Markdown.
Definition: ToMarkdown.cs:335
static string GraphToMarkdown(Graph Graph)
Converts a graph to Markdown.
Definition: ToMarkdown.cs:310
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.
static string Encode(string s)
Encodes all special characters in a string so that it can be included in a markdown document without ...
bool TryGetFootnote(string Key, out Footnote Footnote)
Tries to get a footnote, given its key.
IEnumerable< string > FootnoteOrder
Order of footnotes.
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
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
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
bool Prefix
If header is defined using a prefix.
Definition: Header.cs:124
string Row
Original Row generating the horizontal rule.
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
Represents a numbered item in an ordered list.
Definition: NumberedItem.cs:10
Represents a numbered list in a markdown document.
Definition: NumberedList.cs:11
Represents a paragraph in a markdown document.
Definition: Paragraph.cs:11
Represents a right-aligned set of blocks in a markdown document.
Definition: RightAligned.cs:11
Represents a sequence of sections.
Definition: Sections.cs:11
Represents a table in a markdown document.
Definition: Table.cs:11
MarkdownElement[][] Headers
Headers in table.
Definition: Table.cs:54
MarkdownElement[][] Rows
Rows in table.
Definition: Table.cs:59
Represents a task item in a task list.
Definition: TaskItem.cs:10
Represents a task list in a markdown document.
Definition: TaskList.cs:11
Represents an unnumbered item in an ordered list.
Abstract base class for all markdown elements.
abstract Task Render(IRenderer Output)
Renders the element.
int? Height
Height of media item, if available.
int? Width
Width of media item, if available.
string Delimiter
Delimiter string used to identify emoji.
Represents an HTML entity in Unicode format.
MultimediaItem[] Items
Multimedia items.
Definition: Multimedia.cs:40
Renders portable Markdown from a Markdown document.
override Task Render(CommentBlock Element)
Renders Element .
override Task Render(InlineHTML Element)
Renders Element .
override Task Render(InvisibleBreak Element)
Renders Element .
override async Task Render(MarginAligned Element)
Renders Element .
override async Task Render(Header Element)
Renders Element .
override async Task Render(Delete Element)
Renders Element .
override async Task RenderFootnotes()
Renders footnotes.
override async Task Render(FootnoteReference Element)
Renders Element .
override async Task Render(SuperScript Element)
Renders Element .
MarkdownRenderer(StringBuilder Output, MarkdownDocument Document)
Renders portable Markdown from a Markdown document.
override Task Render(InlineText Element)
Renders Element .
override async Task Render(Link Element)
Renders Element .
override Task Render(MultimediaReference Element)
Renders Element .
override Task Render(AutomaticLinkMail Element)
Renders Element .
override Task Render(HashTag Element)
Renders Element .
override async Task Render(Emphasize Element)
Renders Element .
override async Task Render(DefinitionDescriptions Element)
Renders Element .
MarkdownRenderer()
Renders portable Markdown from a Markdown document.
override async Task Render(DeleteBlocks Element)
Renders Element .
override Task Render(DetailsReference Element)
Renders Element .
override async Task Render(NumberedItem Element)
Renders Element .
async Task RenderObject(object Result, bool AloneInParagraph, Variables Variables)
Generates Markdown from Script output.
override Task Render(NestedBlock Element)
Renders Element .
override async Task Render(DefinitionList Element)
Renders Element .
MarkdownRenderer(StringBuilder Output)
Renders portable Markdown from a Markdown document.
override async Task Render(BulletList Element)
Renders Element .
override Task Render(Footnote Element)
Renders Element .
override Task Render(LineBreak Element)
Renders Element .
override async Task Render(Abbreviation Element)
Renders Element .
override async Task Render(TaskList Element)
Renders Element .
override async Task Render(InsertBlocks Element)
Renders Element .
override Task Render(AutomaticLinkUrl Element)
Renders Element .
override Task Render(InlineCode Element)
Renders Element .
override async Task Render(Underline Element)
Renders Element .
override Task Render(HorizontalRule Element)
Renders Element .
override async Task Render(Table Element)
Renders Element .
override async Task Render(RightAligned Element)
Renders Element .
override async Task Render(Insert Element)
Renders Element .
override async Task Render(UnnumberedItem Element)
Renders Element .
override async Task Render(Strong Element)
Renders Element .
override Task Render(HtmlEntity Element)
Renders Element .
override async Task Render(HtmlBlock Element)
Renders Element .
override Task Render(SectionSeparator Element)
Renders Element .
override async Task Render(StrikeThrough Element)
Renders Element .
bool PortableSyntax
If a portable syntax of markdown is to be generated (true), or if generated Markdown is to be process...
MarkdownRenderer(MarkdownDocument Document)
Renders portable Markdown from a Markdown document.
override Task Render(Sections Element)
Renders Element .
override Task Render(HtmlEntityUnicode Element)
Renders Element .
override async Task Render(CodeBlock Element)
Renders Element .
override async Task Render(SubScript Element)
Renders Element .
override async Task Render(BlockQuote Element)
Renders Element .
override Task Render(MetaReference Element)
Renders Element .
override async Task Render(InlineScript Element)
Renders Element .
override async Task Render(DefinitionTerms Element)
Renders Element .
override async Task Render(LinkReference Element)
Renders Element .
override Task Render(EmojiReference Element)
Renders Element .
override async Task Render(TaskItem Element)
Renders Element .
override Task Render(Model.SpanElements.Multimedia Element)
Renders Element .
override async Task Render(NumberedList Element)
Renders Element .
override async Task Render(Paragraph Element)
Renders Element .
override async Task Render(CenterAligned Element)
Renders Element .
override async Task Render(LeftAligned Element)
Renders Element .
Abstract base class for Markdown renderers.
Definition: Renderer.cs:14
readonly StringBuilder Output
Renderer output.
Definition: Renderer.cs:18
async Task RenderChildren(MarkdownElementChildren Element)
Renders the children of Element .
Definition: Renderer.cs:147
void Clear()
Clears the underlying StringBuilder.
Definition: Renderer.cs:138
virtual async Task RenderDocument(MarkdownDocument Document, bool Inclusion)
Renders a document.
Definition: Renderer.cs:75
override string ToString()
Returns the renderer output.
Definition: Renderer.cs:130
abstract Task Render(Abbreviation Element)
Renders Element .
MarkdownDocument Document
Reference to Markdown document being processed.
Definition: Renderer.cs:23
Renderer()
Abstract base class for Markdown renderers.
Definition: Renderer.cs:28
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 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
Base class for all types of elements.
Definition: Element.cs:13
Base class for graphs.
Definition: Graph.cs:79
Contains pixel information
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 multimedia content Markdown renderers.
Basic interface for matrices.
Definition: IMatrix.cs:9
Interface for objects that can be converted into matrices.
Definition: IToMatrix.cs:9
TextAlignment
Text alignment of contents.