Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
XamarinFormsXamlRenderer.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;
16
18{
23 {
27 public readonly XmlWriter XmlOutput;
28
32 public readonly XamlSettings XamlSettings;
33
38
42 public bool Bold = false;
43
47 public bool Italic = false;
48
52 public bool StrikeThrough = false;
53
57 public bool Underline = false;
58
62 public bool Superscript = false;
63
67 public bool Subscript = false;
68
72 public bool Code = false;
73
77 public bool InLabel = false;
78
82 public string Hyperlink = null;
83
89 public XamarinFormsXamlRenderer(XmlWriterSettings XmlSettings, XamlSettings XamlSettings)
90 : base()
91 {
92 this.XamlSettings = XamlSettings;
93 this.XmlOutput = XmlWriter.Create(this.Output, XmlSettings);
94 }
95
102 public XamarinFormsXamlRenderer(StringBuilder Output, XmlWriterSettings XmlSettings, XamlSettings XamlSettings)
103 : base(Output)
104 {
105 this.XamlSettings = XamlSettings;
106 this.XmlOutput = XmlWriter.Create(this.Output, XmlSettings);
107 }
108
110 public override void Dispose()
111 {
112 base.Dispose();
113
114 this.XmlOutput.Dispose();
115 }
116
122 public override Task RenderDocument(MarkdownDocument Document, bool Inclusion)
123 {
124 this.Alignment = TextAlignment.Left;
125 this.Bold = false;
126 this.Italic = false;
127 this.StrikeThrough = false;
128 this.Underline = false;
129 this.Superscript = false;
130 this.Subscript = false;
131 this.Code = false;
132 this.InLabel = false;
133 this.Hyperlink = null;
134
135 return base.RenderDocument(Document, Inclusion);
136 }
137
141 public override Task RenderDocumentHeader()
142 {
143 this.XmlOutput.WriteStartElement("StackLayout", "http://xamarin.com/schemas/2014/forms");
144 this.XmlOutput.WriteAttributeString("xmlns", "x", null, "http://schemas.microsoft.com/winfx/2009/xaml");
145 this.XmlOutput.WriteAttributeString("Spacing", "0");
146
147 return Task.CompletedTask;
148 }
149
153 public override async Task RenderFootnotes()
154 {
156 string FootnoteMargin = "0," + this.XamlSettings.ParagraphMarginTop.ToString() + "," +
157 this.XamlSettings.FootnoteSeparator.ToString() + "," +
158 this.XamlSettings.ParagraphMarginBottom.ToString();
159 string Scale = CommonTypes.Encode(this.XamlSettings.SuperscriptScale);
160 string Offset = this.XamlSettings.SuperscriptOffset.ToString();
161 int Nr;
162 int Row = 0;
163
164 this.XmlOutput.WriteStartElement("BoxView");
165 this.XmlOutput.WriteAttributeString("HeightRequest", "1");
166 this.XmlOutput.WriteAttributeString("BackgroundColor", this.XamlSettings.TableCellBorderColor);
167 this.XmlOutput.WriteAttributeString("HorizontalOptions", "FillAndExpand");
168 this.XmlOutput.WriteAttributeString("Margin", this.XamlSettings.ParagraphMargins);
169 this.XmlOutput.WriteEndElement();
170
171 this.XmlOutput.WriteStartElement("Grid");
172 this.XmlOutput.WriteAttributeString("RowSpacing", "0");
173 this.XmlOutput.WriteAttributeString("ColumnSpacing", "0");
174
175 this.XmlOutput.WriteStartElement("Grid.ColumnDefinitions");
176
177 this.XmlOutput.WriteStartElement("ColumnDefinition");
178 this.XmlOutput.WriteAttributeString("Width", "Auto");
179 this.XmlOutput.WriteEndElement();
180
181 this.XmlOutput.WriteStartElement("ColumnDefinition");
182 this.XmlOutput.WriteAttributeString("Width", "*");
183 this.XmlOutput.WriteEndElement();
184
185 this.XmlOutput.WriteEndElement();
186 this.XmlOutput.WriteStartElement("Grid.RowDefinitions");
187
188 foreach (string Key in this.Document.FootnoteOrder)
189 {
190 if ((this.Document?.TryGetFootnoteNumber(Key, out Nr) ?? false) &&
191 (this.Document?.TryGetFootnote(Key, out Footnote) ?? false) &&
193 {
194 this.XmlOutput.WriteStartElement("RowDefinition");
195 this.XmlOutput.WriteAttributeString("Height", "Auto");
196 this.XmlOutput.WriteEndElement();
197 }
198 }
199
200 this.XmlOutput.WriteEndElement();
201
202 foreach (string Key in this.Document.FootnoteOrder)
203 {
204 if ((this.Document?.TryGetFootnoteNumber(Key, out Nr) ?? false) &&
205 (this.Document?.TryGetFootnote(Key, out Footnote) ?? false) &&
207 {
208 this.XmlOutput.WriteStartElement("ContentView");
209 this.XmlOutput.WriteAttributeString("Margin", FootnoteMargin);
210 this.XmlOutput.WriteAttributeString("Grid.Column", "0");
211 this.XmlOutput.WriteAttributeString("Grid.Row", Row.ToString());
212 this.XmlOutput.WriteAttributeString("Scale", Scale);
213 this.XmlOutput.WriteAttributeString("TranslationY", Offset);
214
215 this.XmlOutput.WriteStartElement("Label");
216 this.XmlOutput.WriteAttributeString("Text", Nr.ToString());
217 this.XmlOutput.WriteEndElement();
218 this.XmlOutput.WriteEndElement();
219
220 this.XmlOutput.WriteStartElement("ContentView");
221 this.XmlOutput.WriteAttributeString("Grid.Column", "1");
222 this.XmlOutput.WriteAttributeString("Grid.Row", Row.ToString());
223 await Footnote.Render(this);
224 this.XmlOutput.WriteEndElement();
225
226 Row++;
227 }
228 }
229
230 this.XmlOutput.WriteEndElement();
231 }
232
236 public override Task RenderDocumentFooter()
237 {
238 this.XmlOutput.WriteEndElement();
239 this.XmlOutput.Flush();
240
241 return Task.CompletedTask;
242 }
243
244 #region Span Elements
245
250 public override Task Render(Abbreviation Element)
251 {
252 return this.RenderChildren(Element);
253 }
254
259 public override Task Render(AutomaticLinkMail Element)
260 {
261 string Bak = this.Hyperlink;
262 this.Hyperlink = "mailto:" + Element.EMail;
263 this.RenderSpan(this.Hyperlink);
264 this.Hyperlink = Bak;
265
266 return Task.CompletedTask;
267 }
268
273 public override Task Render(AutomaticLinkUrl Element)
274 {
275 string Bak = this.Hyperlink;
276 this.Hyperlink = Element.URL;
277 this.RenderSpan(Element.URL);
278 this.Hyperlink = Bak;
279
280 return Task.CompletedTask;
281 }
282
287 public override async Task Render(Delete Element)
288 {
289 bool Bak = this.StrikeThrough;
290 this.StrikeThrough = true;
291
292 await this.RenderChildren(Element);
293
294 this.StrikeThrough = Bak;
295 }
296
301 public override Task Render(DetailsReference Element)
302 {
303 if (!(this.Document.Detail is null))
304 return this.RenderDocument(this.Document.Detail, false);
305 else
306 return this.Render((MetaReference)Element);
307 }
308
313 public override async Task Render(EmojiReference Element)
314 {
315 if (this.InLabel)
316 this.RenderSpan(Element.Emoji.Unicode);
317 else
318 {
319 IEmojiSource EmojiSource = this.Document.EmojiSource;
320
321 if (EmojiSource is null)
322 this.RenderSpan(Element.Delimiter + Element.Emoji.ShortName + Element.Delimiter);
323 else if (!EmojiSource.EmojiSupported(Element.Emoji))
324 this.RenderSpan(Element.Emoji.Unicode);
325 else
326 {
327 IImageSource Source = await this.Document.EmojiSource.GetImageSource(Element.Emoji, Element.Level);
328 await Multimedia.ImageContent.OutputXamarinForms(this.XmlOutput, Source);
329 }
330 }
331 }
332
337 public override async Task Render(Emphasize Element)
338 {
339 bool Bak = this.Italic;
340 this.Italic = true;
341
342 await this.RenderChildren(Element);
343
344 this.Italic = Bak;
345 }
346
351 public override async Task Render(FootnoteReference Element)
352 {
353 if (!(this.Document?.TryGetFootnote(Element.Key, out Footnote Footnote) ?? false))
354 Footnote = null;
355
356 if (Element.AutoExpand && !(Footnote is null))
357 await this.Render(Footnote);
358 else if (this.Document?.TryGetFootnoteNumber(Element.Key, out int Nr) ?? false)
359 {
360 bool Bak = this.Superscript;
361 this.Superscript = true;
362
363 this.RenderSpan(Nr.ToString());
364
365 this.Superscript = Bak;
366
367 if (!(Footnote is null))
368 Footnote.Referenced = true;
369 }
370 }
371
376 public override Task Render(HashTag Element)
377 {
378 this.RenderSpan(Element.Tag);
379 return Task.CompletedTask;
380 }
381
386 public override Task Render(HtmlEntity Element)
387 {
388 string s = Html.HtmlEntity.EntityToCharacter(Element.Entity);
389 if (!string.IsNullOrEmpty(s))
390 this.RenderSpan(s);
391
392 return Task.CompletedTask;
393 }
394
399 public override Task Render(HtmlEntityUnicode Element)
400 {
401 this.RenderSpan(new string((char)Element.Code, 1));
402 return Task.CompletedTask;
403 }
404
409 public override Task Render(InlineCode Element)
410 {
411 bool Bak = this.Code;
412 this.Code = true;
413
414 this.RenderSpan(Element.Code);
415
416 this.Code = Bak;
417
418 return Task.CompletedTask;
419 }
420
425 public override Task Render(InlineHTML Element)
426 {
427 this.XmlOutput.WriteComment(Element.HTML);
428 return Task.CompletedTask;
429 }
430
435 public override async Task Render(InlineScript Element)
436 {
437 object Result = await Element.EvaluateExpression();
438 await this.RenderObject(Result, Element.AloneInParagraph, Element.Variables);
439 }
440
447 public async Task RenderObject(object Result, bool AloneInParagraph, Variables Variables)
448 {
449 if (Result is null)
450 return;
451
452 string s;
453
454 if (Result is XmlDocument Xml)
455 Result = await MarkdownDocument.TransformXml(Xml, Variables);
456 else if (Result is IToMatrix ToMatrix)
457 Result = ToMatrix.ToMatrix();
458
459 if (this.InLabel)
460 {
461 s = Result?.ToString();
462 if (!string.IsNullOrEmpty(s))
463 this.RenderSpan(Result?.ToString() ?? string.Empty);
464
465 return;
466 }
467
468 if (Result is Graph G)
469 {
470 PixelInformation Pixels = G.CreatePixels();
471 byte[] Bin = Pixels.EncodeAsPng();
472
473 s = "data:image/png;base64," + Convert.ToBase64String(Bin, 0, Bin.Length);
474
475 await Multimedia.ImageContent.OutputXamarinForms(this.XmlOutput, new ImageSource()
476 {
477 Url = s,
478 Width = Pixels.Width,
479 Height = Pixels.Height
480 });
481 }
482 else if (Result is SKImage Img)
483 {
484 using (SKData Data = Img.Encode(SKEncodedImageFormat.Png, 100))
485 {
486 byte[] Bin = Data.ToArray();
487
488 s = "data:image/png;base64," + Convert.ToBase64String(Bin, 0, Bin.Length);
489
490 await Multimedia.ImageContent.OutputXamarinForms(this.XmlOutput, new ImageSource()
491 {
492 Url = s,
493 Width = Img.Width,
494 Height = Img.Height
495 });
496 }
497 }
498 else if (Result is MarkdownDocument Doc)
499 {
500 await this.RenderDocument(Doc, true); // Does not call ProcessAsyncTasks()
501 Doc.ProcessAsyncTasks();
502 }
503 else if (Result is MarkdownContent Markdown)
504 {
505 Doc = await MarkdownDocument.CreateAsync(Markdown.Markdown, Markdown.Settings ?? new MarkdownSettings());
506 await this.RenderDocument(Doc, true); // Does not call ProcessAsyncTasks()
507 Doc.ProcessAsyncTasks();
508 }
509 else if (Result is Exception ex)
510 {
511 ex = Log.UnnestException(ex);
512
513 if (ex is AggregateException ex2)
514 {
515 foreach (Exception ex3 in ex2.InnerExceptions)
516 {
517 this.RenderContentView();
518 this.XmlOutput.WriteStartElement("Label");
519 this.XmlOutput.WriteAttributeString("LineBreakMode", "WordWrap");
520 this.XmlOutput.WriteAttributeString("TextColor", "Red");
521 this.XmlOutput.WriteValue(ex3.Message);
522 this.XmlOutput.WriteEndElement();
523 this.XmlOutput.WriteEndElement();
524 }
525 }
526 else
527 {
528 if (AloneInParagraph)
529 this.RenderContentView();
530
531 this.XmlOutput.WriteStartElement("Label");
532 this.XmlOutput.WriteAttributeString("LineBreakMode", "WordWrap");
533 this.XmlOutput.WriteAttributeString("TextColor", "Red");
534 this.XmlOutput.WriteValue(ex.Message);
535 this.XmlOutput.WriteEndElement();
536
537 if (AloneInParagraph)
538 this.XmlOutput.WriteEndElement();
539 }
540 }
541 else
542 {
543 if (AloneInParagraph)
544 this.RenderContentView();
545
546 this.XmlOutput.WriteStartElement("Label");
547 this.XmlOutput.WriteAttributeString("LineBreakMode", "WordWrap");
548
550 this.XmlOutput.WriteValue(Result.ToString());
551 this.XmlOutput.WriteEndElement();
552
553 if (AloneInParagraph)
554 this.XmlOutput.WriteEndElement();
555 }
556 }
557
562 public override Task Render(InlineText Element)
563 {
564 this.RenderSpan(Element.Value);
565 return Task.CompletedTask;
566 }
567
572 public override async Task Render(Insert Element)
573 {
574 bool Bak = this.Underline;
575 this.Underline = true;
576
577 await this.RenderChildren(Element);
578
579 this.Underline = Bak;
580 }
581
586 public override Task Render(LineBreak Element)
587 {
588 this.RenderSpan(Environment.NewLine);
589 return Task.CompletedTask;
590 }
591
596 public override async Task Render(Link Element)
597 {
598 string Bak = this.Hyperlink;
599 this.Hyperlink = Element.Url;
600
601 await this.RenderChildren(Element);
602
603 this.Hyperlink = Bak;
604 }
605
610 public override async Task Render(LinkReference Element)
611 {
613
614 string Bak = this.Hyperlink;
615
616 if (!(Multimedia is null))
617 this.Hyperlink = Multimedia.Items[0].Url;
618
619 await this.RenderChildren(Element);
620
621 this.Hyperlink = Bak;
622 }
623
628 public override Task Render(MetaReference Element)
629 {
630 StringBuilder sb = new StringBuilder();
631 bool FirstOnRow = true;
632
633 if (Element.TryGetMetaData(out KeyValuePair<string, bool>[] Values))
634 {
635 foreach (KeyValuePair<string, bool> P in Values)
636 {
637 if (FirstOnRow)
638 FirstOnRow = false;
639 else
640 sb.Append(' ');
641
642 sb.Append(P.Key);
643 if (P.Value)
644 {
645 sb.Append(Environment.NewLine);
646 FirstOnRow = true;
647 }
648 }
649 }
650
651 this.RenderSpan(sb.ToString());
652
653 return Task.CompletedTask;
654 }
655
660 public override Task Render(Model.SpanElements.Multimedia Element)
661 {
663 if (Renderer is null)
664 return this.RenderChildren(Element);
665 else
666 return Renderer.RenderXamarinFormsXaml(this, Element.Items, Element.Children, Element.AloneInParagraph, Element.Document);
667 }
668
673 public override Task Render(MultimediaReference Element)
674 {
676
677 if (!(Multimedia is null))
678 {
680 if (!(Renderer is null))
681 return Renderer.RenderXamarinFormsXaml(this, Multimedia.Items, Element.Children, Element.AloneInParagraph, Element.Document);
682 }
683
684 return this.RenderChildren(Element);
685 }
686
691 public override async Task Render(StrikeThrough Element)
692 {
693 bool Bak = this.StrikeThrough;
694 this.StrikeThrough = true;
695
696 await this.RenderChildren(Element);
697
698 this.StrikeThrough = Bak;
699 }
700
705 public override async Task Render(Strong Element)
706 {
707 bool Bak = this.Bold;
708 this.Bold = true;
709
710 await this.RenderChildren(Element);
711
712 this.Bold = Bak;
713 }
714
719 public override async Task Render(SubScript Element)
720 {
721 bool Bak = this.Subscript;
722 this.Subscript = true;
723
724 await this.RenderChildren(Element);
725
726 this.Subscript = Bak;
727 }
728
733 public override async Task Render(SuperScript Element)
734 {
735 bool Bak = this.Superscript;
736 this.Superscript = true;
737
738 await this.RenderChildren(Element);
739
740 this.Superscript = Bak;
741 }
742
747 public override async Task Render(Underline Element)
748 {
749 bool Bak = this.Underline;
750 this.Underline = true;
751
752 await this.RenderChildren(Element);
753
754 this.Underline = Bak;
755 }
756
757 #endregion
758
759 #region Block elements
760
765 public override async Task Render(BlockQuote Element)
766 {
767 this.XmlOutput.WriteStartElement("ContentView");
768 this.XmlOutput.WriteAttributeString("Padding", this.XamlSettings.BlockQuoteMargin.ToString() + "," +
769 this.XamlSettings.ParagraphMarginTop.ToString() + ",0," + this.XamlSettings.ParagraphMarginBottom.ToString());
770
771 this.XmlOutput.WriteStartElement("Frame");
772 this.XmlOutput.WriteAttributeString("Padding", this.XamlSettings.BlockQuotePadding.ToString() +
773 ",0," + this.XamlSettings.BlockQuotePadding.ToString() + ",0");
774 this.XmlOutput.WriteAttributeString("BorderColor", this.XamlSettings.BlockQuoteBorderColor);
775 // TODO: Border thickness
776
777 this.XmlOutput.WriteStartElement("StackLayout");
778 this.XmlOutput.WriteAttributeString("Orientation", "Vertical");
779
780 await this.RenderChildren(Element);
781
782 this.XmlOutput.WriteEndElement();
783 this.XmlOutput.WriteEndElement();
784 this.XmlOutput.WriteEndElement();
785 }
786
791 public override async Task Render(BulletList Element)
792 {
793 int Row = 0;
794 bool ParagraphBullet;
795
796 this.XmlOutput.WriteStartElement("ContentView");
797 this.XmlOutput.WriteAttributeString("Padding", this.XamlSettings.ParagraphMargins);
798
799 this.XmlOutput.WriteStartElement("Grid");
800 this.XmlOutput.WriteAttributeString("RowSpacing", "0");
801 this.XmlOutput.WriteAttributeString("ColumnSpacing", "0");
802
803 this.XmlOutput.WriteStartElement("Grid.ColumnDefinitions");
804
805 this.XmlOutput.WriteStartElement("ColumnDefinition");
806 this.XmlOutput.WriteAttributeString("Width", "Auto");
807 this.XmlOutput.WriteEndElement();
808
809 this.XmlOutput.WriteStartElement("ColumnDefinition");
810 this.XmlOutput.WriteAttributeString("Width", "*");
811 this.XmlOutput.WriteEndElement();
812
813 this.XmlOutput.WriteEndElement();
814 this.XmlOutput.WriteStartElement("Grid.RowDefinitions");
815
816 foreach (MarkdownElement _ in Element.Children)
817 {
818 this.XmlOutput.WriteStartElement("RowDefinition");
819 this.XmlOutput.WriteAttributeString("Height", "Auto");
820 this.XmlOutput.WriteEndElement();
821 }
822
823 this.XmlOutput.WriteEndElement();
824
825 foreach (MarkdownElement E in Element.Children)
826 {
827 if (E is UnnumberedItem Item)
828 {
829 ParagraphBullet = !E.InlineSpanElement || E.OutsideParagraph;
830 this.GetMargins(E, out int TopMargin, out int BottomMargin);
831
832 this.RenderContentView("0," + TopMargin.ToString() + "," + this.XamlSettings.ListContentMargin.ToString() + "," +
833 BottomMargin.ToString());
834 this.XmlOutput.WriteAttributeString("Grid.Column", "0");
835 this.XmlOutput.WriteAttributeString("Grid.Row", Row.ToString());
836
837 this.XmlOutput.WriteElementString("Label", "•");
838 this.XmlOutput.WriteEndElement();
839
840 this.XmlOutput.WriteStartElement("StackLayout");
841 this.XmlOutput.WriteAttributeString("Grid.Column", "1");
842 this.XmlOutput.WriteAttributeString("Grid.Row", Row.ToString());
843 this.XmlOutput.WriteAttributeString("Orientation", "Vertical");
844
845 if (ParagraphBullet)
846 await E.Render(this);
847 else
848 await this.RenderLabel(Item, false);
849
850 this.XmlOutput.WriteEndElement();
851 }
852
853 Row++;
854 }
855
856 this.XmlOutput.WriteEndElement();
857 this.XmlOutput.WriteEndElement();
858 }
859
866 private void GetMargins(MarkdownElement Element, out int TopMargin, out int BottomMargin)
867 {
868 if (Element.InlineSpanElement && !Element.OutsideParagraph)
869 {
870 TopMargin = 0;
871 BottomMargin = 0;
872 }
873 else if (Element is NestedBlock NestedBlock)
874 {
875 bool First = true;
876
877 TopMargin = BottomMargin = 0;
878
880 {
881 if (First)
882 {
883 First = false;
884 this.GetMargins(E, out TopMargin, out BottomMargin);
885 }
886 else
887 this.GetMargins(E, out int _, out BottomMargin);
888 }
889 }
890 else if (Element is MarkdownElementSingleChild SingleChild)
891 this.GetMargins(SingleChild.Child, out TopMargin, out BottomMargin);
892 else
893 {
894 TopMargin = this.XamlSettings.ParagraphMarginTop;
895 BottomMargin = this.XamlSettings.ParagraphMarginBottom;
896 }
897 }
898
903 public override async Task Render(CenterAligned Element)
904 {
905 this.XmlOutput.WriteStartElement("StackLayout");
906 this.XmlOutput.WriteAttributeString("Orientation", "Vertical");
907
908 TextAlignment Bak = this.Alignment;
909 this.Alignment = TextAlignment.Center;
910
911 await this.RenderChildren(Element);
912
913 this.Alignment = Bak;
914 this.XmlOutput.WriteEndElement();
915 }
916
921 public override async Task Render(CodeBlock Element)
922 {
924
925 if (!(Renderer is null))
926 {
927 try
928 {
929 if (await Renderer.RenderXamarinFormsXaml(this, Element.Rows, Element.Language, Element.Indent, Element.Document))
930 return;
931 }
932 catch (Exception ex)
933 {
934 ex = Log.UnnestException(ex);
935
936 if (ex is AggregateException ex2)
937 {
938 foreach (Exception ex3 in ex2.InnerExceptions)
939 {
940 this.RenderContentView();
941 this.XmlOutput.WriteStartElement("Label");
942 this.XmlOutput.WriteAttributeString("LineBreakMode", "WordWrap");
943 this.XmlOutput.WriteAttributeString("TextColor", "Red");
944 this.XmlOutput.WriteValue(ex3.Message);
945 this.XmlOutput.WriteEndElement();
946 this.XmlOutput.WriteEndElement();
947 }
948 }
949 else
950 {
951 this.RenderContentView();
952 this.XmlOutput.WriteStartElement("Label");
953 this.XmlOutput.WriteAttributeString("LineBreakMode", "WordWrap");
954 this.XmlOutput.WriteAttributeString("TextColor", "Red");
955 this.XmlOutput.WriteValue(ex.Message);
956 this.XmlOutput.WriteEndElement();
957 this.XmlOutput.WriteEndElement();
958 }
959 }
960 }
961
962 this.RenderContentView();
963 this.XmlOutput.WriteStartElement("StackLayout");
964 this.XmlOutput.WriteAttributeString("Orientation", "Vertical");
965
966 int i;
967
968 for (i = Element.Start; i <= Element.End; i++)
969 {
970 this.XmlOutput.WriteStartElement("Label");
971 this.XmlOutput.WriteAttributeString("LineBreakMode", "NoWrap");
973 this.XmlOutput.WriteAttributeString("FontFamily", "Courier New");
974 this.XmlOutput.WriteAttributeString("Text", Element.Rows[i]);
975 this.XmlOutput.WriteEndElement();
976 }
977
978 this.XmlOutput.WriteEndElement();
979 this.XmlOutput.WriteEndElement();
980 }
981
986 public override Task Render(CommentBlock Element)
987 {
988 return Task.CompletedTask;
989 }
990
995 public override async Task Render(DefinitionDescriptions Element)
996 {
997 MarkdownElement Last = null;
998
999 foreach (MarkdownElement Description in Element.Children)
1000 Last = Description;
1001
1002 foreach (MarkdownElement Description in Element.Children)
1003 {
1004 if (Description.InlineSpanElement && !Description.OutsideParagraph)
1005 {
1006 this.RenderContentView();
1007
1008 this.XmlOutput.WriteStartElement("Label");
1009 this.XmlOutput.WriteAttributeString("LineBreakMode", "WordWrap");
1010 this.RenderLabelAlignment();
1011 this.XmlOutput.WriteAttributeString("TextType", "Html");
1012
1014 {
1015 XmlEntitiesOnly = true
1016 }, this.Document))
1017 {
1018 await Description.Render(Renderer);
1019 this.XmlOutput.WriteCData(Renderer.ToString());
1020 }
1021
1022 this.XmlOutput.WriteEndElement();
1023 this.XmlOutput.WriteEndElement();
1024 }
1025 else
1026 {
1027 this.XmlOutput.WriteStartElement("ContentView");
1028 this.XmlOutput.WriteAttributeString("Padding", this.XamlSettings.DefinitionMargin.ToString() + ",0,0," +
1029 (Description == Last ? this.XamlSettings.DefinitionSeparator : 0).ToString());
1030
1031 this.XmlOutput.WriteStartElement("StackLayout");
1032 await Description.Render(this);
1033 this.XmlOutput.WriteEndElement();
1034
1035 this.XmlOutput.WriteEndElement();
1036 }
1037 }
1038 }
1039
1044 public override Task Render(DefinitionList Element)
1045 {
1046 return this.RenderChildren(Element);
1047 }
1048
1053 public override async Task Render(DefinitionTerms Element)
1054 {
1055 int TopMargin = this.XamlSettings.ParagraphMarginTop;
1056
1057 foreach (MarkdownElement Term in Element.Children)
1058 {
1059 this.RenderContentView(this.XamlSettings.ParagraphMarginLeft.ToString() + "," + TopMargin.ToString() + "," +
1060 this.XamlSettings.ParagraphMarginRight.ToString() + ",0");
1061
1062 bool BoldBak = this.Bold;
1063 this.Bold = true;
1064
1065 await this.RenderLabel(Term, true);
1066
1067 this.Bold = BoldBak;
1068 this.XmlOutput.WriteEndElement();
1069
1070 TopMargin = 0;
1071 }
1072 }
1073
1078 public override async Task Render(DeleteBlocks Element)
1079 {
1080 this.XmlOutput.WriteStartElement("ContentView");
1081 this.XmlOutput.WriteAttributeString("Padding", this.XamlSettings.BlockQuoteMargin.ToString() + "," +
1082 this.XamlSettings.ParagraphMarginTop.ToString() + ",0," + this.XamlSettings.ParagraphMarginBottom.ToString());
1083
1084 this.XmlOutput.WriteStartElement("Frame");
1085 this.XmlOutput.WriteAttributeString("Padding", this.XamlSettings.BlockQuotePadding.ToString() +
1086 ",0," + this.XamlSettings.BlockQuotePadding.ToString() + ",0");
1087 this.XmlOutput.WriteAttributeString("BorderColor", this.XamlSettings.DeletedBlockQuoteBorderColor);
1088 // TODO: Border thickness
1089
1090 this.XmlOutput.WriteStartElement("StackLayout");
1091 this.XmlOutput.WriteAttributeString("Orientation", "Vertical");
1092
1093 foreach (MarkdownElement E in Element.Children)
1094 await E.Render(this);
1095
1096 this.XmlOutput.WriteEndElement();
1097 this.XmlOutput.WriteEndElement();
1098 this.XmlOutput.WriteEndElement();
1099 }
1100
1105 public override Task Render(Footnote Element)
1106 {
1107 return this.RenderChildren(Element);
1108 }
1109
1114 public override async Task Render(Header Element)
1115 {
1116 this.RenderContentView();
1117
1118 this.XmlOutput.WriteStartElement("Label");
1119 this.XmlOutput.WriteAttributeString("LineBreakMode", "WordWrap");
1120 this.RenderLabelAlignment();
1121
1122 if (Element.Level > 0 && Element.Level <= this.XamlSettings.HeaderFontSize.Length)
1123 {
1124 this.XmlOutput.WriteAttributeString("FontSize", this.XamlSettings.HeaderFontSize[Element.Level - 1].ToString());
1125 this.XmlOutput.WriteAttributeString("TextColor", this.XamlSettings.HeaderForegroundColor[Element.Level - 1].ToString());
1126 }
1127
1128 this.XmlOutput.WriteAttributeString("TextType", "Html");
1129
1131 {
1132 XmlEntitiesOnly = true
1133 }, this.Document))
1134 {
1135 await Renderer.RenderChildren(Element);
1136
1137 this.XmlOutput.WriteCData(Renderer.ToString());
1138 }
1139
1140 this.XmlOutput.WriteEndElement();
1141 this.XmlOutput.WriteEndElement();
1142 }
1143
1148 {
1149 switch (this.Alignment)
1150 {
1151 case TextAlignment.Left:
1152 this.XmlOutput.WriteAttributeString("HorizontalTextAlignment", "Start");
1153 break;
1154
1155 case TextAlignment.Right:
1156 this.XmlOutput.WriteAttributeString("HorizontalTextAlignment", "End");
1157 break;
1158
1159 case TextAlignment.Center:
1160 this.XmlOutput.WriteAttributeString("HorizontalTextAlignment", "Center");
1161 break;
1162 }
1163 }
1164
1169 public override Task Render(HorizontalRule Element)
1170 {
1171 this.XmlOutput.WriteStartElement("BoxView");
1172 this.XmlOutput.WriteAttributeString("HeightRequest", "1");
1173 this.XmlOutput.WriteAttributeString("BackgroundColor", this.XamlSettings.TableCellBorderColor);
1174 this.XmlOutput.WriteAttributeString("HorizontalOptions", "FillAndExpand");
1175 this.XmlOutput.WriteAttributeString("Margin", this.XamlSettings.ParagraphMargins);
1176 this.XmlOutput.WriteEndElement();
1177
1178 return Task.CompletedTask;
1179 }
1180
1185 public override async Task Render(HtmlBlock Element)
1186 {
1187 this.RenderContentView();
1188
1189 this.XmlOutput.WriteStartElement("Label");
1190 this.XmlOutput.WriteAttributeString("LineBreakMode", "WordWrap");
1191 this.RenderLabelAlignment();
1192 this.XmlOutput.WriteAttributeString("TextType", "Html");
1193
1195 {
1196 XmlEntitiesOnly = true
1197 }, this.Document))
1198 {
1199 await Renderer.RenderChildren(Element);
1200
1201 this.XmlOutput.WriteCData(Renderer.ToString());
1202
1203 this.XmlOutput.WriteEndElement();
1204 this.XmlOutput.WriteEndElement();
1205 }
1206 }
1207
1212 public override async Task Render(InsertBlocks Element)
1213 {
1214 this.XmlOutput.WriteStartElement("ContentView");
1215 this.XmlOutput.WriteAttributeString("Padding", this.XamlSettings.BlockQuoteMargin.ToString() + "," +
1216 this.XamlSettings.ParagraphMarginTop.ToString() + ",0," + this.XamlSettings.ParagraphMarginBottom.ToString());
1217
1218 this.XmlOutput.WriteStartElement("Frame");
1219 this.XmlOutput.WriteAttributeString("Padding", this.XamlSettings.BlockQuotePadding.ToString() +
1220 ",0," + this.XamlSettings.BlockQuotePadding.ToString() + ",0");
1221 this.XmlOutput.WriteAttributeString("BorderColor", this.XamlSettings.InsertedBlockQuoteBorderColor);
1222 // TODO: Border thickness
1223
1224 this.XmlOutput.WriteStartElement("StackLayout");
1225 this.XmlOutput.WriteAttributeString("Orientation", "Vertical");
1226
1227 await this.RenderChildren(Element);
1228
1229 this.XmlOutput.WriteEndElement();
1230 this.XmlOutput.WriteEndElement();
1231 this.XmlOutput.WriteEndElement();
1232 }
1233
1238 public override Task Render(InvisibleBreak Element)
1239 {
1240 return Task.CompletedTask;
1241 }
1242
1247 public override async Task Render(LeftAligned Element)
1248 {
1249 this.XmlOutput.WriteStartElement("StackLayout");
1250 this.XmlOutput.WriteAttributeString("Orientation", "Vertical");
1251
1252 TextAlignment Bak = this.Alignment;
1253 this.Alignment = TextAlignment.Left;
1254
1255 await this.RenderChildren(Element);
1256
1257 this.Alignment = Bak;
1258 this.XmlOutput.WriteEndElement();
1259 }
1260
1265 public override async Task Render(MarginAligned Element)
1266 {
1267 this.XmlOutput.WriteStartElement("StackLayout");
1268 this.XmlOutput.WriteAttributeString("Orientation", "Vertical");
1269
1270 TextAlignment Bak = this.Alignment;
1271 this.Alignment = TextAlignment.Left;
1272
1273 await this.RenderChildren(Element);
1274
1275 this.Alignment = Bak;
1276 this.XmlOutput.WriteEndElement();
1277 }
1278
1283 public override async Task Render(NestedBlock Element)
1284 {
1285 if (Element.HasOneChild)
1286 await Element.FirstChild.Render(this);
1287 else
1288 {
1289 HtmlSettings Settings = new HtmlSettings()
1290 {
1291 XmlEntitiesOnly = true
1292 };
1293 HtmlRenderer Html = null;
1294
1295 try
1296 {
1297 foreach (MarkdownElement E in Element.Children)
1298 {
1299 if (E.InlineSpanElement)
1300 {
1301 if (Html is null)
1302 Html = new HtmlRenderer(Settings, this.Document);
1303
1304 await E.Render(Html);
1305 }
1306 else
1307 {
1308 if (!(Html is null))
1309 {
1310 this.XmlOutput.WriteStartElement("Label");
1311 this.XmlOutput.WriteAttributeString("LineBreakMode", "WordWrap");
1312 this.RenderLabelAlignment();
1313 this.XmlOutput.WriteAttributeString("TextType", "Html");
1314 this.XmlOutput.WriteCData(Html.ToString());
1315 this.XmlOutput.WriteEndElement();
1316
1317 Html.Dispose();
1318 Html = null;
1319 }
1320
1321 await E.Render(this);
1322 }
1323 }
1324
1325 if (!(Html is null))
1326 {
1327 this.XmlOutput.WriteStartElement("Label");
1328 this.XmlOutput.WriteAttributeString("LineBreakMode", "WordWrap");
1329 this.RenderLabelAlignment();
1330 this.XmlOutput.WriteAttributeString("TextType", "Html");
1331 this.XmlOutput.WriteCData(Html.ToString());
1332 this.XmlOutput.WriteEndElement();
1333 }
1334 }
1335 finally
1336 {
1337 Html?.Dispose();
1338 }
1339 }
1340 }
1341
1346 public override Task Render(NumberedItem Element)
1347 {
1348 return this.RenderChild(Element);
1349 }
1350
1355 public override async Task Render(NumberedList Element)
1356 {
1357 int Expected = 0;
1358 int Row = 0;
1359 bool ParagraphBullet;
1360
1361 this.XmlOutput.WriteStartElement("ContentView");
1362 this.XmlOutput.WriteAttributeString("Padding", this.XamlSettings.ParagraphMargins);
1363
1364 this.XmlOutput.WriteStartElement("Grid");
1365 this.XmlOutput.WriteAttributeString("RowSpacing", "0");
1366 this.XmlOutput.WriteAttributeString("ColumnSpacing", "0");
1367
1368 this.XmlOutput.WriteStartElement("Grid.ColumnDefinitions");
1369
1370 this.XmlOutput.WriteStartElement("ColumnDefinition");
1371 this.XmlOutput.WriteAttributeString("Width", "Auto");
1372 this.XmlOutput.WriteEndElement();
1373
1374 this.XmlOutput.WriteStartElement("ColumnDefinition");
1375 this.XmlOutput.WriteAttributeString("Width", "*");
1376 this.XmlOutput.WriteEndElement();
1377
1378 this.XmlOutput.WriteEndElement();
1379 this.XmlOutput.WriteStartElement("Grid.RowDefinitions");
1380
1381 foreach (MarkdownElement _ in Element.Children)
1382 {
1383 this.XmlOutput.WriteStartElement("RowDefinition");
1384 this.XmlOutput.WriteAttributeString("Height", "Auto");
1385 this.XmlOutput.WriteEndElement();
1386 }
1387
1388 this.XmlOutput.WriteEndElement();
1389
1390 foreach (MarkdownElement E in Element.Children)
1391 {
1392 if (E is BlockElementSingleChild Item)
1393 {
1394 Expected++;
1395
1396 ParagraphBullet = !E.InlineSpanElement || E.OutsideParagraph;
1397 this.GetMargins(E, out int TopMargin, out int BottomMargin);
1398
1399 this.RenderContentView("0," + TopMargin.ToString() + "," + this.XamlSettings.ListContentMargin.ToString() + "," +
1400 BottomMargin.ToString());
1401 this.XmlOutput.WriteAttributeString("Grid.Column", "0");
1402 this.XmlOutput.WriteAttributeString("Grid.Row", Row.ToString());
1403
1404 this.XmlOutput.WriteStartElement("Label");
1405
1406 if (Item is NumberedItem NumberedItem)
1407 this.XmlOutput.WriteValue((Expected = NumberedItem.Number).ToString());
1408 else
1409 this.XmlOutput.WriteValue(Expected.ToString());
1410
1411 this.XmlOutput.WriteValue(".");
1412 this.XmlOutput.WriteEndElement();
1413 this.XmlOutput.WriteEndElement();
1414
1415 this.XmlOutput.WriteStartElement("StackLayout");
1416 this.XmlOutput.WriteAttributeString("Grid.Column", "1");
1417 this.XmlOutput.WriteAttributeString("Grid.Row", Row.ToString());
1418 this.XmlOutput.WriteAttributeString("Orientation", "Vertical");
1419
1420 if (ParagraphBullet)
1421 await E.Render(this);
1422 else
1423 await this.RenderLabel(Item, false);
1424
1425 this.XmlOutput.WriteEndElement();
1426 }
1427
1428 Row++;
1429 }
1430
1431 this.XmlOutput.WriteEndElement();
1432 this.XmlOutput.WriteEndElement();
1433 }
1434
1439 public override async Task Render(Paragraph Element)
1440 {
1441 this.RenderContentView();
1442 await this.RenderLabel(Element, false);
1443 this.XmlOutput.WriteEndElement();
1444 }
1445
1446 internal async Task RenderLabel(MarkdownElement Element, bool IncludeElement)
1447 {
1448 bool HasLink = !Element.ForEach((E, _) =>
1449 {
1450 return !(
1451 E is AutomaticLinkMail ||
1452 E is AutomaticLinkUrl ||
1453 E is Link ||
1454 E is LinkReference);
1455 }, null);
1456
1457 this.XmlOutput.WriteStartElement("Label");
1458 this.XmlOutput.WriteAttributeString("LineBreakMode", "WordWrap");
1459 this.RenderLabelAlignment();
1460
1461 if (HasLink)
1462 {
1463 if (this.InLabel)
1464 {
1465 if (IncludeElement)
1466 await Element.Render(this);
1467 else
1468 await this.RenderChildren(Element);
1469 }
1470 else
1471 {
1472 this.InLabel = true;
1473
1474 this.XmlOutput.WriteStartElement("Label.FormattedText");
1475 this.XmlOutput.WriteStartElement("FormattedString");
1476
1477 if (IncludeElement)
1478 await Element.Render(this);
1479 else
1480 await this.RenderChildren(Element);
1481
1482 this.XmlOutput.WriteEndElement();
1483 this.XmlOutput.WriteEndElement();
1484
1485 this.InLabel = false;
1486 }
1487 }
1488 else
1489 {
1490 this.XmlOutput.WriteAttributeString("TextType", "Html");
1491
1492 if (this.Bold)
1493 this.XmlOutput.WriteAttributeString("FontAttributes", "Bold");
1494
1496 {
1497 XmlEntitiesOnly = true
1498 }, this.Document))
1499 {
1500 if (IncludeElement)
1501 await Element.Render(Renderer);
1502 else
1503 await Renderer.RenderChildren(Element);
1504
1505 this.XmlOutput.WriteCData(Renderer.ToString());
1506 }
1507 }
1508
1509 this.XmlOutput.WriteEndElement();
1510 }
1511
1512 internal void RenderSpan(string Text)
1513 {
1514 if (!this.InLabel)
1515 {
1516 this.XmlOutput.WriteStartElement("Label");
1517 this.XmlOutput.WriteAttributeString("LineBreakMode", "WordWrap");
1518 this.RenderLabelAlignment();
1519 this.XmlOutput.WriteStartElement("Label.FormattedText");
1520 this.XmlOutput.WriteStartElement("FormattedString");
1521 }
1522
1523 this.XmlOutput.WriteStartElement("Span");
1524
1525 if (this.Superscript)
1526 Text = TextRenderer.ToSuperscript(Text);
1527 else if (this.Subscript)
1528 Text = TextRenderer.ToSubscript(Text);
1529
1530 this.XmlOutput.WriteAttributeString("Text", Text);
1531
1532 if (this.Bold && this.Italic)
1533 this.XmlOutput.WriteAttributeString("FontAttributes", "Italic, Bold");
1534 else if (this.Bold)
1535 this.XmlOutput.WriteAttributeString("FontAttributes", "Bold");
1536 else if (this.Italic)
1537 this.XmlOutput.WriteAttributeString("FontAttributes", "Italic");
1538
1539 if (this.StrikeThrough && this.Underline)
1540 this.XmlOutput.WriteAttributeString("TextDecorations", "Strikethrough, Underline");
1541 else if (this.StrikeThrough)
1542 this.XmlOutput.WriteAttributeString("TextDecorations", "Strikethrough");
1543 else if (this.Underline)
1544 this.XmlOutput.WriteAttributeString("TextDecorations", "Underline");
1545
1546 if (this.Code)
1547 this.XmlOutput.WriteAttributeString("FontFamily", "Courier New");
1548
1549 if (!(this.Hyperlink is null))
1550 {
1551 this.XmlOutput.WriteAttributeString("TextColor", "{Binding HyperlinkColor}");
1552
1553 this.XmlOutput.WriteStartElement("Span.GestureRecognizers");
1554 this.XmlOutput.WriteStartElement("TapGestureRecognizer");
1555 this.XmlOutput.WriteAttributeString("Command", "{Binding HyperlinkClicked}");
1556 this.XmlOutput.WriteAttributeString("CommandParameter", this.Hyperlink);
1557 this.XmlOutput.WriteEndElement();
1558 this.XmlOutput.WriteEndElement();
1559 }
1560
1561 if (!this.InLabel)
1562 {
1563 this.XmlOutput.WriteEndElement();
1564 this.XmlOutput.WriteEndElement();
1565 this.XmlOutput.WriteEndElement();
1566 }
1567
1568 this.XmlOutput.WriteEndElement();
1569 }
1570
1571 internal void RenderContentView()
1572 {
1573 this.RenderContentView(this.Alignment, this.XamlSettings.ParagraphMargins);
1574 }
1575
1576 internal void RenderContentView(string Margins)
1577 {
1578 this.RenderContentView(this.Alignment, Margins);
1579 }
1580
1581 internal void RenderContentView(TextAlignment Alignment, string Margins)
1582 {
1583 this.XmlOutput.WriteStartElement("ContentView");
1584 this.XmlOutput.WriteAttributeString("Padding", Margins);
1585
1586 switch (Alignment)
1587 {
1588 case TextAlignment.Center:
1589 this.XmlOutput.WriteAttributeString("HorizontalOptions", "Center");
1590 break;
1591
1592 case TextAlignment.Left:
1593 this.XmlOutput.WriteAttributeString("HorizontalOptions", "Start");
1594 break;
1595
1596 case TextAlignment.Right:
1597 this.XmlOutput.WriteAttributeString("HorizontalOptions", "End");
1598 break;
1599 }
1600 }
1601
1606 public override async Task Render(RightAligned Element)
1607 {
1608 this.XmlOutput.WriteStartElement("StackLayout");
1609 this.XmlOutput.WriteAttributeString("Orientation", "Vertical");
1610
1611 TextAlignment Bak = this.Alignment;
1612 this.Alignment = TextAlignment.Right;
1613
1614 await this.RenderChildren(Element);
1615
1616 this.Alignment = Bak;
1617 this.XmlOutput.WriteEndElement();
1618 }
1619
1624 public override Task Render(Sections Element)
1625 {
1626 return this.RenderChildren(Element);
1627 }
1628
1633 public override Task Render(SectionSeparator Element)
1634 {
1635 this.XmlOutput.WriteStartElement("BoxView");
1636 this.XmlOutput.WriteAttributeString("HeightRequest", "1");
1637 this.XmlOutput.WriteAttributeString("BackgroundColor", this.XamlSettings.TableCellBorderColor);
1638 this.XmlOutput.WriteAttributeString("HorizontalOptions", "FillAndExpand");
1639 this.XmlOutput.WriteAttributeString("Margin", this.XamlSettings.ParagraphMargins);
1640 this.XmlOutput.WriteEndElement();
1641
1642 return Task.CompletedTask;
1643 }
1644
1649 public override async Task Render(Table Element)
1650 {
1651 int Column;
1652 int Row, NrRows;
1653 int RowNr = 0;
1654
1655 this.XmlOutput.WriteStartElement("ContentView");
1656 this.XmlOutput.WriteAttributeString("Padding", this.XamlSettings.ParagraphMargins);
1657
1658 this.XmlOutput.WriteStartElement("Grid");
1659 this.XmlOutput.WriteAttributeString("RowSpacing", "-2");
1660 this.XmlOutput.WriteAttributeString("ColumnSpacing", "-2");
1661
1662 // TODO: Tooltip/caption
1663
1664 this.XmlOutput.WriteStartElement("Grid.ColumnDefinitions");
1665
1666 for (Column = 0; Column < Element.Columns; Column++)
1667 {
1668 this.XmlOutput.WriteStartElement("ColumnDefinition");
1669 this.XmlOutput.WriteAttributeString("Width", "Auto");
1670 this.XmlOutput.WriteEndElement();
1671 }
1672
1673 this.XmlOutput.WriteEndElement();
1674 this.XmlOutput.WriteStartElement("Grid.RowDefinitions");
1675
1676 for (Row = 0, NrRows = Element.Rows.Length + Element.Headers.Length; Row < NrRows; Row++)
1677 {
1678 this.XmlOutput.WriteStartElement("RowDefinition");
1679 this.XmlOutput.WriteAttributeString("Height", "Auto");
1680 this.XmlOutput.WriteEndElement();
1681 }
1682
1683 this.XmlOutput.WriteEndElement();
1684
1685 for (Row = 0, NrRows = Element.Headers.Length; Row < NrRows; Row++, RowNr++)
1686 await this.Render(Element.Headers[Row], Element.HeaderCellAlignments[Row], RowNr, true, Element);
1687
1688 for (Row = 0, NrRows = Element.Rows.Length; Row < NrRows; Row++, RowNr++)
1689 await this.Render(Element.Rows[Row], Element.RowCellAlignments[Row], RowNr, false, Element);
1690
1691 this.XmlOutput.WriteEndElement();
1692 this.XmlOutput.WriteEndElement();
1693 }
1694
1695 private void ClearState()
1696 {
1697 this.Alignment = TextAlignment.Left;
1698 this.Bold = false;
1699 this.Italic = false;
1700 this.StrikeThrough = false;
1701 this.Underline = false;
1702 this.Superscript = false;
1703 this.Subscript = false;
1704 this.Code = false;
1705 this.InLabel = false;
1706 this.Hyperlink = null;
1707 }
1708
1709 private StateBackup Backup()
1710 {
1711 return new StateBackup()
1712 {
1713 alignment = this.Alignment,
1714 bold = this.Bold,
1715 italic = this.Italic,
1716 strikeThrough = this.StrikeThrough,
1717 underline = this.Underline,
1718 superscript = this.Superscript,
1719 subscript = this.Subscript,
1720 code = this.Code,
1721 inLabel = this.InLabel,
1722 hyperlink = this.Hyperlink
1723 };
1724 }
1725
1726 private void Restore(StateBackup Backup)
1727 {
1728 this.Alignment = Backup.alignment;
1729 this.Bold = Backup.bold;
1730 this.Italic = Backup.italic;
1731 this.StrikeThrough = Backup.strikeThrough;
1732 this.Underline = Backup.underline;
1733 this.Superscript = Backup.superscript;
1734 this.Subscript = Backup.subscript;
1735 this.Code = Backup.code;
1736 this.InLabel = Backup.inLabel;
1737 this.Hyperlink = Backup.hyperlink;
1738 }
1739
1740 private class StateBackup
1741 {
1742 public TextAlignment alignment;
1743 public bool bold;
1744 public bool italic;
1745 public bool strikeThrough;
1746 public bool underline;
1747 public bool superscript;
1748 public bool subscript;
1749 public bool code;
1750 public bool inLabel;
1751 public string hyperlink;
1752 }
1753
1754 private async Task Render(MarkdownElement[] CurrentRow, TextAlignment?[] CellAlignments, int RowNr, bool Bold, Table Element)
1755 {
1758 int Column;
1759 int NrColumns = Element.Columns;
1760 int ColSpan;
1761 StateBackup Bak = this.Backup();
1762
1763 this.ClearState();
1764
1765 for (Column = 0; Column < NrColumns; Column++)
1766 {
1767 E = CurrentRow[Column];
1768 if (E is null)
1769 continue;
1770
1771 TextAlignment = CellAlignments[Column] ?? Element.ColumnAlignments[Column];
1772 ColSpan = Column + 1;
1773 while (ColSpan < NrColumns && CurrentRow[ColSpan] is null)
1774 ColSpan++;
1775
1776 ColSpan -= Column;
1777
1778 this.XmlOutput.WriteStartElement("Frame");
1779 this.XmlOutput.WriteAttributeString("Padding", "0,0,0,0");
1780 this.XmlOutput.WriteAttributeString("BorderColor", this.XamlSettings.TableCellBorderColor);
1781 // TODO: Table-cell border thickness
1782
1783 if ((RowNr & 1) == 0)
1784 {
1785 if (!string.IsNullOrEmpty(this.XamlSettings.TableCellRowBackgroundColor1))
1786 this.XmlOutput.WriteAttributeString("BackgroundColor", this.XamlSettings.TableCellRowBackgroundColor1);
1787 }
1788 else
1789 {
1790 if (!string.IsNullOrEmpty(this.XamlSettings.TableCellRowBackgroundColor2))
1791 this.XmlOutput.WriteAttributeString("BackgroundColor", this.XamlSettings.TableCellRowBackgroundColor2);
1792 }
1793
1794 this.XmlOutput.WriteAttributeString("Grid.Column", Column.ToString());
1795 this.XmlOutput.WriteAttributeString("Grid.Row", RowNr.ToString());
1796
1797 if (ColSpan > 1)
1798 this.XmlOutput.WriteAttributeString("Grid.ColumnSpan", ColSpan.ToString());
1799
1800 if (E.InlineSpanElement)
1801 {
1802 this.RenderContentView(TextAlignment, this.XamlSettings.TableCellPadding);
1803
1804 this.Bold = Bold;
1805 await this.RenderLabel(E, true);
1806 this.Bold = false;
1807
1808 this.XmlOutput.WriteEndElement(); // Paragraph
1809 }
1810 else
1811 {
1812 this.XmlOutput.WriteStartElement("ContentView");
1813 this.XmlOutput.WriteAttributeString("Padding", this.XamlSettings.TableCellPadding);
1814
1815 this.XmlOutput.WriteStartElement("StackLayout");
1816 await E.Render(this);
1817 this.XmlOutput.WriteEndElement(); // StackLayout
1818
1819 this.XmlOutput.WriteEndElement(); // ContentView
1820 }
1821
1822 this.XmlOutput.WriteEndElement(); // Frame
1823 }
1824
1825 this.Restore(Bak);
1826 }
1827
1832 public override Task Render(TaskItem Element)
1833 {
1834 return this.RenderChild(Element);
1835 }
1836
1841 public override async Task Render(TaskList Element)
1842 {
1843 int Row = 0;
1844 bool ParagraphBullet;
1845
1846 this.XmlOutput.WriteStartElement("ContentView");
1847 this.XmlOutput.WriteAttributeString("Padding", this.XamlSettings.ParagraphMargins);
1848
1849 this.XmlOutput.WriteStartElement("Grid");
1850 this.XmlOutput.WriteAttributeString("RowSpacing", "0");
1851 this.XmlOutput.WriteAttributeString("ColumnSpacing", "0");
1852
1853 this.XmlOutput.WriteStartElement("Grid.ColumnDefinitions");
1854
1855 this.XmlOutput.WriteStartElement("ColumnDefinition");
1856 this.XmlOutput.WriteAttributeString("Width", "Auto");
1857 this.XmlOutput.WriteEndElement();
1858
1859 this.XmlOutput.WriteStartElement("ColumnDefinition");
1860 this.XmlOutput.WriteAttributeString("Width", "*");
1861 this.XmlOutput.WriteEndElement();
1862
1863 this.XmlOutput.WriteEndElement();
1864 this.XmlOutput.WriteStartElement("Grid.RowDefinitions");
1865
1866 foreach (MarkdownElement _ in Element.Children)
1867 {
1868 this.XmlOutput.WriteStartElement("RowDefinition");
1869 this.XmlOutput.WriteAttributeString("Height", "Auto");
1870 this.XmlOutput.WriteEndElement();
1871 }
1872
1873 this.XmlOutput.WriteEndElement();
1874
1875 foreach (MarkdownElement E in Element.Children)
1876 {
1877 if (E is TaskItem TaskItem)
1878 {
1879 ParagraphBullet = !E.InlineSpanElement || E.OutsideParagraph;
1880 this.GetMargins(E, out int TopMargin, out int BottomMargin);
1881
1882 if (TaskItem.IsChecked)
1883 {
1884 this.RenderContentView("0," + TopMargin.ToString() + "," + this.XamlSettings.ListContentMargin.ToString() + "," +
1885 BottomMargin.ToString());
1886 this.XmlOutput.WriteAttributeString("Grid.Column", "0");
1887 this.XmlOutput.WriteAttributeString("Grid.Row", Row.ToString());
1888
1889 this.XmlOutput.WriteElementString("Label", "✓");
1890 this.XmlOutput.WriteEndElement();
1891 }
1892
1893 this.XmlOutput.WriteStartElement("StackLayout");
1894 this.XmlOutput.WriteAttributeString("Grid.Column", "1");
1895 this.XmlOutput.WriteAttributeString("Grid.Row", Row.ToString());
1896 this.XmlOutput.WriteAttributeString("Orientation", "Vertical");
1897
1898 if (ParagraphBullet)
1899 await E.Render(this);
1900 else
1901 await this.RenderLabel(TaskItem, false);
1902
1903 this.XmlOutput.WriteEndElement();
1904 }
1905
1906 Row++;
1907 }
1908
1909 this.XmlOutput.WriteEndElement();
1910 this.XmlOutput.WriteEndElement();
1911 }
1912
1917 public override Task Render(UnnumberedItem Element)
1918 {
1919 return this.RenderChild(Element);
1920 }
1921
1922 #endregion
1923
1924 }
1925}
Helps with parsing of commong data types.
Definition: CommonTypes.cs:13
static string Encode(bool x)
Encodes a Boolean for use in XML and other formats.
Definition: CommonTypes.cs:594
string ShortName
Emoji short name.
string Unicode
Unicode representation of emoji.
Contains information about an emoji image.
Definition: ImageSource.cs:9
int? Width
Width of image, if available.
Definition: ImageSource.cs:18
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.
IEnumerable< string > FootnoteOrder
Order of footnotes.
IEmojiSource EmojiSource
Source for emojis in the document.
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.
Abstract base class for block elements with one child.
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
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
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
TextAlignment[] ColumnAlignments
Table column alignments.
Definition: Table.cs:64
override IEnumerable< MarkdownElement > Children
Any children of the element.
Definition: Table.cs:100
MarkdownElement[][] Headers
Headers in table.
Definition: Table.cs:54
TextAlignment?[][] RowCellAlignments
Row cell alignments in table.
Definition: Table.cs:79
TextAlignment?[][] HeaderCellAlignments
Header cell alignments in table.
Definition: Table.cs:74
MarkdownElement[][] Rows
Rows in table.
Definition: Table.cs:59
Represents a task item in a task list.
Definition: TaskItem.cs:10
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.
bool HasOneChild
If the element has only one child.
MarkdownElement FirstChild
First child, or null if none.
Abstract base class for all markdown elements.
virtual bool ForEach(MarkdownElementHandler Callback, object State)
Loops through all child-elements for the element.
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.
virtual bool OutsideParagraph
If element, parsed as a span element, can stand outside of a paragraph if alone in it.
MarkdownDocument Document
Markdown document.
Abstract base class for all markdown elements with one child element.
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
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
override string ToString()
Returns the renderer output.
Definition: Renderer.cs:130
virtual void Dispose()
Disposes of the renderer.
Definition: Renderer.cs:65
MarkdownDocument Document
Reference to Markdown document being processed.
Definition: Renderer.cs:23
Renders plain text from a Markdown document.
Definition: TextRenderer.cs:16
static string ToSubscript(string s)
Converts a string to subscript (as far as it goes).
static string ToSuperscript(string s)
Converts a string to superscript (as far as it goes).
Renders XAML (Xamarin.Forms flavour) from a Markdown document.
override async Task Render(DefinitionTerms Element)
Renders Element .
override async Task Render(CodeBlock Element)
Renders Element .
override async Task Render(Header Element)
Renders Element .
override async Task Render(LeftAligned Element)
Renders Element .
override async Task Render(Table Element)
Renders Element .
override Task Render(NumberedItem Element)
Renders Element .
override Task Render(Model.SpanElements.Multimedia Element)
Renders Element .
XamarinFormsXamlRenderer(XmlWriterSettings XmlSettings, XamlSettings XamlSettings)
Renders XAML (Xamarin.Forms flavour) from a Markdown document.
void RenderLabelAlignment()
Writes a text-alignment attribute to a Xamarin.Forms label element.
override async Task Render(DefinitionDescriptions Element)
Renders Element .
override Task Render(HtmlEntity Element)
Renders Element .
override async Task Render(SuperScript Element)
Renders Element .
override async Task Render(InsertBlocks Element)
Renders Element .
async Task RenderObject(object Result, bool AloneInParagraph, Variables Variables)
Generates Xamarin.Forms XAML from Script output.
override Task Render(Abbreviation Element)
Renders Element .
override Task Render(HashTag Element)
Renders Element .
override async Task Render(HtmlBlock Element)
Renders Element .
override Task Render(InlineText Element)
Renders Element .
override Task Render(MetaReference Element)
Renders Element .
override async Task Render(Delete Element)
Renders Element .
override Task Render(AutomaticLinkMail Element)
Renders Element .
override async Task Render(LinkReference Element)
Renders Element .
override Task Render(DefinitionList Element)
Renders Element .
override async Task Render(Insert Element)
Renders Element .
override Task RenderDocumentFooter()
Renders the document header.
override Task Render(UnnumberedItem Element)
Renders Element .
override Task RenderDocument(MarkdownDocument Document, bool Inclusion)
Renders a document.
override Task Render(MultimediaReference Element)
Renders Element .
override async Task Render(InlineScript Element)
Renders Element .
override Task Render(LineBreak Element)
Renders Element .
override async Task Render(FootnoteReference Element)
Renders Element .
override async Task Render(Strong Element)
Renders Element .
override Task Render(Footnote Element)
Renders Element .
override Task Render(HorizontalRule Element)
Renders Element .
override async Task Render(CenterAligned Element)
Renders Element .
override async Task Render(NestedBlock Element)
Renders Element .
override Task Render(Sections Element)
Renders Element .
override Task Render(CommentBlock Element)
Renders Element .
override async Task Render(Underline Element)
Renders Element .
override Task Render(TaskItem Element)
Renders Element .
override Task Render(InlineCode Element)
Renders Element .
override Task Render(InlineHTML Element)
Renders Element .
override Task Render(InvisibleBreak Element)
Renders Element .
override async Task Render(SubScript Element)
Renders Element .
override async Task Render(BulletList Element)
Renders Element .
override async Task Render(NumberedList Element)
Renders Element .
override Task Render(SectionSeparator Element)
Renders Element .
override async Task Render(MarginAligned Element)
Renders Element .
override async Task Render(TaskList Element)
Renders Element .
override Task Render(AutomaticLinkUrl Element)
Renders Element .
override Task RenderDocumentHeader()
Renders the document header.
override async Task Render(StrikeThrough Element)
Renders Element .
override Task Render(DetailsReference Element)
Renders Element .
override async Task Render(Paragraph Element)
Renders Element .
override async Task Render(Link Element)
Renders Element .
override async Task Render(BlockQuote Element)
Renders Element .
string Hyperlink
Link, if rendering a hyperlink, null otherwise.
override async Task Render(Emphasize Element)
Renders Element .
override async Task Render(DeleteBlocks Element)
Renders Element .
override async Task Render(RightAligned Element)
Renders Element .
XamarinFormsXamlRenderer(StringBuilder Output, XmlWriterSettings XmlSettings, XamlSettings XamlSettings)
Renders XAML (Xamarin.Forms flavour) from a Markdown document.
override Task Render(HtmlEntityUnicode Element)
Renders Element .
override async Task Render(EmojiReference Element)
Renders Element .
Contains settings that the XAML export uses to customize XAML output.
Definition: XamlSettings.cs:10
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 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< IImageSource > GetImageSource(EmojiInfo Emoji)
Gets the image source of an emoji.
bool EmojiSupported(EmojiInfo Emoji)
If the emoji is supported by the emoji source.
Contains information about an emoji image.
Definition: IImageSource.cs:9
Interface for multimedia content Xamarin.Forms XAML renderers.
Interface for objects that can be converted into matrices.
Definition: IToMatrix.cs:9
TextAlignment
Text alignment of contents.