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;
4using System.Text;
5using System.Threading.Tasks;
6using System.Xml;
12using Waher.Events;
14using Waher.Script;
17
19{
24 {
28 public readonly XmlWriter XmlOutput;
29
33 public readonly XamlSettings XamlSettings;
34
39
43 public bool Bold = false;
44
48 public bool Italic = false;
49
53 public bool StrikeThrough = false;
54
58 public bool Underline = false;
59
63 public bool Superscript = false;
64
68 public bool Subscript = false;
69
73 public bool Code = false;
74
78 public bool InLabel = false;
79
83 public string Hyperlink = null;
84
90 public XamarinFormsXamlRenderer(XmlWriterSettings XmlSettings, XamlSettings XamlSettings)
91 : base()
92 {
93 this.XamlSettings = XamlSettings;
94 this.XmlOutput = XmlWriter.Create(this.Output, XmlSettings);
95 }
96
103 public XamarinFormsXamlRenderer(StringBuilder Output, XmlWriterSettings XmlSettings, XamlSettings XamlSettings)
104 : base(Output)
105 {
106 this.XamlSettings = XamlSettings;
107 this.XmlOutput = XmlWriter.Create(this.Output, XmlSettings);
108 }
109
111 public override void Dispose()
112 {
113 base.Dispose();
114
115 this.XmlOutput.Dispose();
116 }
117
123 public override Task RenderDocument(MarkdownDocument Document, bool Inclusion)
124 {
125 this.Alignment = TextAlignment.Left;
126 this.Bold = false;
127 this.Italic = false;
128 this.StrikeThrough = false;
129 this.Underline = false;
130 this.Superscript = false;
131 this.Subscript = false;
132 this.Code = false;
133 this.InLabel = false;
134 this.Hyperlink = null;
135
136 return base.RenderDocument(Document, Inclusion);
137 }
138
142 public override Task RenderDocumentHeader()
143 {
144 this.XmlOutput.WriteStartElement("StackLayout", "http://xamarin.com/schemas/2014/forms");
145 this.XmlOutput.WriteAttributeString("xmlns", "x", null, "http://schemas.microsoft.com/winfx/2009/xaml");
146 this.XmlOutput.WriteAttributeString("Spacing", "0");
147
148 return Task.CompletedTask;
149 }
150
154 public override async Task RenderFootnotes()
155 {
157 string FootnoteMargin = "0," + this.XamlSettings.ParagraphMarginTop.ToString() + "," +
158 this.XamlSettings.FootnoteSeparator.ToString() + "," +
159 this.XamlSettings.ParagraphMarginBottom.ToString();
160 string Scale = CommonTypes.Encode(this.XamlSettings.SuperscriptScale);
161 string Offset = this.XamlSettings.SuperscriptOffset.ToString();
162 int Nr;
163 int Row = 0;
164
165 this.XmlOutput.WriteStartElement("BoxView");
166 this.XmlOutput.WriteAttributeString("HeightRequest", "1");
167 this.XmlOutput.WriteAttributeString("BackgroundColor", this.XamlSettings.TableCellBorderColor);
168 this.XmlOutput.WriteAttributeString("HorizontalOptions", "FillAndExpand");
169 this.XmlOutput.WriteAttributeString("Margin", this.XamlSettings.ParagraphMargins);
170 this.XmlOutput.WriteEndElement();
171
172 this.XmlOutput.WriteStartElement("Grid");
173 this.XmlOutput.WriteAttributeString("RowSpacing", "0");
174 this.XmlOutput.WriteAttributeString("ColumnSpacing", "0");
175
176 this.XmlOutput.WriteStartElement("Grid.ColumnDefinitions");
177
178 this.XmlOutput.WriteStartElement("ColumnDefinition");
179 this.XmlOutput.WriteAttributeString("Width", "Auto");
180 this.XmlOutput.WriteEndElement();
181
182 this.XmlOutput.WriteStartElement("ColumnDefinition");
183 this.XmlOutput.WriteAttributeString("Width", "*");
184 this.XmlOutput.WriteEndElement();
185
186 this.XmlOutput.WriteEndElement();
187 this.XmlOutput.WriteStartElement("Grid.RowDefinitions");
188
189 foreach (string Key in this.Document.FootnoteOrder)
190 {
191 if ((this.Document?.TryGetFootnoteNumber(Key, out Nr) ?? false) &&
192 (this.Document?.TryGetFootnote(Key, out Footnote) ?? false) &&
194 {
195 this.XmlOutput.WriteStartElement("RowDefinition");
196 this.XmlOutput.WriteAttributeString("Height", "Auto");
197 this.XmlOutput.WriteEndElement();
198 }
199 }
200
201 this.XmlOutput.WriteEndElement();
202
203 foreach (string Key in this.Document.FootnoteOrder)
204 {
205 if ((this.Document?.TryGetFootnoteNumber(Key, out Nr) ?? false) &&
206 (this.Document?.TryGetFootnote(Key, out Footnote) ?? false) &&
208 {
209 this.XmlOutput.WriteStartElement("ContentView");
210 this.XmlOutput.WriteAttributeString("Margin", FootnoteMargin);
211 this.XmlOutput.WriteAttributeString("Grid.Column", "0");
212 this.XmlOutput.WriteAttributeString("Grid.Row", Row.ToString());
213 this.XmlOutput.WriteAttributeString("Scale", Scale);
214 this.XmlOutput.WriteAttributeString("TranslationY", Offset);
215
216 this.XmlOutput.WriteStartElement("Label");
217 this.XmlOutput.WriteAttributeString("Text", Nr.ToString());
218 this.XmlOutput.WriteEndElement();
219 this.XmlOutput.WriteEndElement();
220
221 this.XmlOutput.WriteStartElement("ContentView");
222 this.XmlOutput.WriteAttributeString("Grid.Column", "1");
223 this.XmlOutput.WriteAttributeString("Grid.Row", Row.ToString());
224 await Footnote.Render(this);
225 this.XmlOutput.WriteEndElement();
226
227 Row++;
228 }
229 }
230
231 this.XmlOutput.WriteEndElement();
232 }
233
237 public override Task RenderDocumentFooter()
238 {
239 this.XmlOutput.WriteEndElement();
240 this.XmlOutput.Flush();
241
242 return Task.CompletedTask;
243 }
244
245 #region Span Elements
246
251 public override Task Render(Abbreviation Element)
252 {
253 return this.RenderChildren(Element);
254 }
255
260 public override Task Render(AutomaticLinkMail Element)
261 {
262 string Bak = this.Hyperlink;
263 this.Hyperlink = "mailto:" + Element.EMail;
264 this.RenderSpan(this.Hyperlink);
265 this.Hyperlink = Bak;
266
267 return Task.CompletedTask;
268 }
269
274 public override Task Render(AutomaticLinkUrl Element)
275 {
276 string Bak = this.Hyperlink;
277 this.Hyperlink = Element.URL;
278 this.RenderSpan(Element.URL);
279 this.Hyperlink = Bak;
280
281 return Task.CompletedTask;
282 }
283
288 public override async Task Render(Delete Element)
289 {
290 bool Bak = this.StrikeThrough;
291 this.StrikeThrough = true;
292
293 await this.RenderChildren(Element);
294
295 this.StrikeThrough = Bak;
296 }
297
302 public override Task Render(DetailsReference Element)
303 {
304 if (!(this.Document.Detail is null))
305 return this.RenderDocument(this.Document.Detail, false);
306 else
307 return this.Render((MetaReference)Element);
308 }
309
314 public override async Task Render(EmojiReference Element)
315 {
316 if (this.InLabel)
317 this.RenderSpan(Element.Emoji.Unicode);
318 else
319 {
320 IEmojiSource EmojiSource = this.Document.EmojiSource;
321
322 if (EmojiSource is null)
323 this.RenderSpan(Element.Delimiter + Element.Emoji.ShortName + Element.Delimiter);
324 else if (!EmojiSource.EmojiSupported(Element.Emoji))
325 this.RenderSpan(Element.Emoji.Unicode);
326 else
327 {
328 IImageSource Source = await this.Document.EmojiSource.GetImageSource(Element.Emoji, Element.Level);
329 await Multimedia.ImageContent.OutputXamarinForms(this.XmlOutput, Source);
330 }
331 }
332 }
333
338 public override async Task Render(Emphasize Element)
339 {
340 bool Bak = this.Italic;
341 this.Italic = true;
342
343 await this.RenderChildren(Element);
344
345 this.Italic = Bak;
346 }
347
352 public override async Task Render(FootnoteReference Element)
353 {
354 if (!(this.Document?.TryGetFootnote(Element.Key, out Footnote Footnote) ?? false))
355 Footnote = null;
356
357 if (Element.AutoExpand && !(Footnote is null))
358 await this.Render(Footnote);
359 else if (this.Document?.TryGetFootnoteNumber(Element.Key, out int Nr) ?? false)
360 {
361 bool Bak = this.Superscript;
362 this.Superscript = true;
363
364 this.RenderSpan(Nr.ToString());
365
366 this.Superscript = Bak;
367
368 if (!(Footnote is null))
369 Footnote.Referenced = true;
370 }
371 }
372
377 public override Task Render(HashTag Element)
378 {
379 this.RenderSpan(Element.Tag);
380 return Task.CompletedTask;
381 }
382
387 public override Task Render(HtmlEntity Element)
388 {
389 string s = Html.HtmlEntity.EntityToCharacter(Element.Entity);
390 if (!string.IsNullOrEmpty(s))
391 this.RenderSpan(s);
392
393 return Task.CompletedTask;
394 }
395
400 public override Task Render(HtmlEntityUnicode Element)
401 {
402 this.RenderSpan(new string((char)Element.Code, 1));
403 return Task.CompletedTask;
404 }
405
410 public override Task Render(InlineCode Element)
411 {
412 bool Bak = this.Code;
413 this.Code = true;
414
415 this.RenderSpan(Element.Code);
416
417 this.Code = Bak;
418
419 return Task.CompletedTask;
420 }
421
426 public override Task Render(InlineHTML Element)
427 {
428 this.XmlOutput.WriteComment(Element.HTML);
429 return Task.CompletedTask;
430 }
431
436 public override async Task Render(InlineScript Element)
437 {
438 object Result = await Element.EvaluateExpression();
439 await this.RenderObject(Result, Element.AloneInParagraph, Element.Variables);
440 }
441
448 public async Task RenderObject(object Result, bool AloneInParagraph, Variables Variables)
449 {
450 if (Result is null)
451 return;
452
453 string s;
454
455 if (Result is XmlDocument Xml)
456 Result = await MarkdownDocument.TransformXml(Xml, Variables);
457 else if (Result is IToMatrix ToMatrix)
458 Result = ToMatrix.ToMatrix();
459
460 if (this.InLabel)
461 {
462 s = Result?.ToString();
463 if (!string.IsNullOrEmpty(s))
464 this.RenderSpan(Result?.ToString() ?? string.Empty);
465
466 return;
467 }
468
469 if (Result is Graph G)
470 {
471 PixelInformation Pixels = G.CreatePixels();
472 byte[] Bin = Pixels.EncodeAsPng();
473
474 s = "data:image/png;base64," + Convert.ToBase64String(Bin, 0, Bin.Length);
475
476 await Multimedia.ImageContent.OutputXamarinForms(this.XmlOutput, new ImageSource()
477 {
478 Url = s,
479 Width = Pixels.Width,
480 Height = Pixels.Height
481 });
482 }
483 else if (Result is SKImage Img)
484 {
485 using (SKData Data = Img.Encode(SKEncodedImageFormat.Png, 100))
486 {
487 byte[] Bin = Data.ToArray();
488
489 s = "data:image/png;base64," + Convert.ToBase64String(Bin, 0, Bin.Length);
490
491 await Multimedia.ImageContent.OutputXamarinForms(this.XmlOutput, new ImageSource()
492 {
493 Url = s,
494 Width = Img.Width,
495 Height = Img.Height
496 });
497 }
498 }
499 else if (Result is MarkdownDocument Doc)
500 {
501 await this.RenderDocument(Doc, true); // Does not call ProcessAsyncTasks()
502 Doc.ProcessAsyncTasks();
503 }
504 else if (Result is MarkdownContent Markdown)
505 {
506 Doc = await MarkdownDocument.CreateAsync(Markdown.Markdown, Markdown.Settings ?? new MarkdownSettings());
507 await this.RenderDocument(Doc, true); // Does not call ProcessAsyncTasks()
508 Doc.ProcessAsyncTasks();
509 }
510 else if (Result is Exception ex)
511 {
512 ex = Log.UnnestException(ex);
513
514 if (ex is AggregateException ex2)
515 {
516 foreach (Exception ex3 in ex2.InnerExceptions)
517 {
518 this.RenderContentView();
519 this.XmlOutput.WriteStartElement("Label");
520 this.XmlOutput.WriteAttributeString("LineBreakMode", "WordWrap");
521 this.XmlOutput.WriteAttributeString("TextColor", "Red");
522 this.XmlOutput.WriteValue(ex3.Message);
523 this.XmlOutput.WriteEndElement();
524 this.XmlOutput.WriteEndElement();
525 }
526 }
527 else
528 {
529 if (AloneInParagraph)
530 this.RenderContentView();
531
532 this.XmlOutput.WriteStartElement("Label");
533 this.XmlOutput.WriteAttributeString("LineBreakMode", "WordWrap");
534 this.XmlOutput.WriteAttributeString("TextColor", "Red");
535 this.XmlOutput.WriteValue(ex.Message);
536 this.XmlOutput.WriteEndElement();
537
538 if (AloneInParagraph)
539 this.XmlOutput.WriteEndElement();
540 }
541 }
542 else
543 {
544 if (AloneInParagraph)
545 this.RenderContentView();
546
547 this.XmlOutput.WriteStartElement("Label");
548 this.XmlOutput.WriteAttributeString("LineBreakMode", "WordWrap");
549
551 this.XmlOutput.WriteValue(Result.ToString());
552 this.XmlOutput.WriteEndElement();
553
554 if (AloneInParagraph)
555 this.XmlOutput.WriteEndElement();
556 }
557 }
558
563 public override Task Render(InlineText Element)
564 {
565 this.RenderSpan(Element.Value);
566 return Task.CompletedTask;
567 }
568
573 public override async Task Render(Insert Element)
574 {
575 bool Bak = this.Underline;
576 this.Underline = true;
577
578 await this.RenderChildren(Element);
579
580 this.Underline = Bak;
581 }
582
587 public override Task Render(LineBreak Element)
588 {
589 this.RenderSpan(Environment.NewLine);
590 return Task.CompletedTask;
591 }
592
597 public override async Task Render(Link Element)
598 {
599 string Bak = this.Hyperlink;
600 this.Hyperlink = Element.Url;
601
602 await this.RenderChildren(Element);
603
604 this.Hyperlink = Bak;
605 }
606
611 public override async Task Render(LinkReference Element)
612 {
614
615 string Bak = this.Hyperlink;
616
617 if (!(Multimedia is null))
618 this.Hyperlink = Multimedia.Items[0].Url;
619
620 await this.RenderChildren(Element);
621
622 this.Hyperlink = Bak;
623 }
624
629 public override Task Render(MetaReference Element)
630 {
631 StringBuilder sb = new StringBuilder();
632 bool FirstOnRow = true;
633
634 if (Element.TryGetMetaData(out KeyValuePair<string, bool>[] Values))
635 {
636 foreach (KeyValuePair<string, bool> P in Values)
637 {
638 if (FirstOnRow)
639 FirstOnRow = false;
640 else
641 sb.Append(' ');
642
643 sb.Append(P.Key);
644 if (P.Value)
645 {
646 sb.Append(Environment.NewLine);
647 FirstOnRow = true;
648 }
649 }
650 }
651
652 this.RenderSpan(sb.ToString());
653
654 return Task.CompletedTask;
655 }
656
661 public override Task Render(Model.SpanElements.Multimedia Element)
662 {
664 if (Renderer is null)
665 return this.RenderChildren(Element);
666 else
667 return Renderer.RenderXamarinFormsXaml(this, Element.Items, Element.Children, Element.AloneInParagraph, Element.Document);
668 }
669
674 public override Task Render(MultimediaReference Element)
675 {
677
678 if (!(Multimedia is null))
679 {
681 if (!(Renderer is null))
682 return Renderer.RenderXamarinFormsXaml(this, Multimedia.Items, Element.Children, Element.AloneInParagraph, Element.Document);
683 }
684
685 return this.RenderChildren(Element);
686 }
687
692 public override async Task Render(StrikeThrough Element)
693 {
694 bool Bak = this.StrikeThrough;
695 this.StrikeThrough = true;
696
697 await this.RenderChildren(Element);
698
699 this.StrikeThrough = Bak;
700 }
701
706 public override async Task Render(Strong Element)
707 {
708 bool Bak = this.Bold;
709 this.Bold = true;
710
711 await this.RenderChildren(Element);
712
713 this.Bold = Bak;
714 }
715
720 public override async Task Render(SubScript Element)
721 {
722 bool Bak = this.Subscript;
723 this.Subscript = true;
724
725 await this.RenderChildren(Element);
726
727 this.Subscript = Bak;
728 }
729
734 public override async Task Render(SuperScript Element)
735 {
736 bool Bak = this.Superscript;
737 this.Superscript = true;
738
739 await this.RenderChildren(Element);
740
741 this.Superscript = Bak;
742 }
743
748 public override async Task Render(Underline Element)
749 {
750 bool Bak = this.Underline;
751 this.Underline = true;
752
753 await this.RenderChildren(Element);
754
755 this.Underline = Bak;
756 }
757
758 #endregion
759
760 #region Block elements
761
766 public override async Task Render(BlockQuote Element)
767 {
768 this.XmlOutput.WriteStartElement("ContentView");
769 this.XmlOutput.WriteAttributeString("Padding", this.XamlSettings.BlockQuoteMargin.ToString() + "," +
770 this.XamlSettings.ParagraphMarginTop.ToString() + ",0," + this.XamlSettings.ParagraphMarginBottom.ToString());
771
772 this.XmlOutput.WriteStartElement("Frame");
773 this.XmlOutput.WriteAttributeString("Padding", this.XamlSettings.BlockQuotePadding.ToString() +
774 ",0," + this.XamlSettings.BlockQuotePadding.ToString() + ",0");
775 this.XmlOutput.WriteAttributeString("BorderColor", this.XamlSettings.BlockQuoteBorderColor);
776 // TODO: Border thickness
777
778 this.XmlOutput.WriteStartElement("StackLayout");
779 this.XmlOutput.WriteAttributeString("Orientation", "Vertical");
780
781 await this.RenderChildren(Element);
782
783 this.XmlOutput.WriteEndElement();
784 this.XmlOutput.WriteEndElement();
785 this.XmlOutput.WriteEndElement();
786 }
787
792 public override async Task Render(BulletList Element)
793 {
794 int Row = 0;
795 bool ParagraphBullet;
796 int i, c;
797
798 this.XmlOutput.WriteStartElement("ContentView");
799 this.XmlOutput.WriteAttributeString("Padding", this.XamlSettings.ParagraphMargins);
800
801 this.XmlOutput.WriteStartElement("Grid");
802 this.XmlOutput.WriteAttributeString("RowSpacing", "0");
803 this.XmlOutput.WriteAttributeString("ColumnSpacing", "0");
804
805 this.XmlOutput.WriteStartElement("Grid.ColumnDefinitions");
806
807 this.XmlOutput.WriteStartElement("ColumnDefinition");
808 this.XmlOutput.WriteAttributeString("Width", "Auto");
809 this.XmlOutput.WriteEndElement();
810
811 this.XmlOutput.WriteStartElement("ColumnDefinition");
812 this.XmlOutput.WriteAttributeString("Width", "*");
813 this.XmlOutput.WriteEndElement();
814
815 this.XmlOutput.WriteEndElement();
816 this.XmlOutput.WriteStartElement("Grid.RowDefinitions");
817
818 for (i = 0, c = Element.Children.Count; i < c; i++)
819 {
820 this.XmlOutput.WriteStartElement("RowDefinition");
821 this.XmlOutput.WriteAttributeString("Height", "Auto");
822 this.XmlOutput.WriteEndElement();
823 }
824
825 this.XmlOutput.WriteEndElement();
826
829
830 while (!(Loop is null))
831 {
832 for (i = Loop.Start, c = Loop.Pos; i < c; i++)
833 {
834 E = Loop[i];
835
836 ParagraphBullet = !E.InlineSpanElement || E.OutsideParagraph;
837 this.GetMargins(E, out int TopMargin, out int BottomMargin);
838
839 this.RenderContentView("0," + TopMargin.ToString() + "," + this.XamlSettings.ListContentMargin.ToString() + "," +
840 BottomMargin.ToString());
841 this.XmlOutput.WriteAttributeString("Grid.Column", "0");
842 this.XmlOutput.WriteAttributeString("Grid.Row", Row.ToString());
843
844 this.XmlOutput.WriteElementString("Label", "•");
845 this.XmlOutput.WriteEndElement();
846
847 this.XmlOutput.WriteStartElement("StackLayout");
848 this.XmlOutput.WriteAttributeString("Grid.Column", "1");
849 this.XmlOutput.WriteAttributeString("Grid.Row", Row.ToString());
850 this.XmlOutput.WriteAttributeString("Orientation", "Vertical");
851
852 if (ParagraphBullet)
853 await E.Render(this);
854 else
855 await this.RenderLabel(E, false);
856
857 this.XmlOutput.WriteEndElement();
858
859 Row++;
860 }
861
862 Loop = Loop.Next;
863 }
864
865 this.XmlOutput.WriteEndElement();
866 this.XmlOutput.WriteEndElement();
867 }
868
875 private void GetMargins(MarkdownElement Element, out int TopMargin, out int BottomMargin)
876 {
877 if (Element.InlineSpanElement && !Element.OutsideParagraph)
878 {
879 TopMargin = 0;
880 BottomMargin = 0;
881 }
882 else if (Element is NestedBlock NestedBlock)
883 {
886 int i, c;
887 bool First = true;
888
889 TopMargin = BottomMargin = 0;
890
891 while (!(Loop is null))
892 {
893 for (i = Loop.Start, c = Loop.Pos; i < c; i++)
894 {
895 E = Loop[i];
896
897 if (First)
898 {
899 First = false;
900 this.GetMargins(E, out TopMargin, out BottomMargin);
901 }
902 else
903 this.GetMargins(E, out int _, out BottomMargin);
904 }
905
906 Loop = Loop.Next;
907 }
908 }
909 else if (Element is MarkdownElementSingleChild SingleChild)
910 this.GetMargins(SingleChild.Child, out TopMargin, out BottomMargin);
911 else
912 {
913 TopMargin = this.XamlSettings.ParagraphMarginTop;
914 BottomMargin = this.XamlSettings.ParagraphMarginBottom;
915 }
916 }
917
922 public override async Task Render(CenterAligned Element)
923 {
924 this.XmlOutput.WriteStartElement("StackLayout");
925 this.XmlOutput.WriteAttributeString("Orientation", "Vertical");
926
927 TextAlignment Bak = this.Alignment;
928 this.Alignment = TextAlignment.Center;
929
930 await this.RenderChildren(Element);
931
932 this.Alignment = Bak;
933 this.XmlOutput.WriteEndElement();
934 }
935
940 public override async Task Render(CodeBlock Element)
941 {
943
944 if (!(Renderer is null))
945 {
946 try
947 {
948 if (await Renderer.RenderXamarinFormsXaml(this, Element.Rows, Element.Language, Element.Indent, Element.Document))
949 return;
950 }
951 catch (Exception ex)
952 {
953 ex = Log.UnnestException(ex);
954
955 if (ex is AggregateException ex2)
956 {
957 foreach (Exception ex3 in ex2.InnerExceptions)
958 {
959 this.RenderContentView();
960 this.XmlOutput.WriteStartElement("Label");
961 this.XmlOutput.WriteAttributeString("LineBreakMode", "WordWrap");
962 this.XmlOutput.WriteAttributeString("TextColor", "Red");
963 this.XmlOutput.WriteValue(ex3.Message);
964 this.XmlOutput.WriteEndElement();
965 this.XmlOutput.WriteEndElement();
966 }
967 }
968 else
969 {
970 this.RenderContentView();
971 this.XmlOutput.WriteStartElement("Label");
972 this.XmlOutput.WriteAttributeString("LineBreakMode", "WordWrap");
973 this.XmlOutput.WriteAttributeString("TextColor", "Red");
974 this.XmlOutput.WriteValue(ex.Message);
975 this.XmlOutput.WriteEndElement();
976 this.XmlOutput.WriteEndElement();
977 }
978 }
979 }
980
981 this.RenderContentView();
982 this.XmlOutput.WriteStartElement("StackLayout");
983 this.XmlOutput.WriteAttributeString("Orientation", "Vertical");
984
985 int i;
986
987 for (i = Element.Start; i <= Element.End; i++)
988 {
989 this.XmlOutput.WriteStartElement("Label");
990 this.XmlOutput.WriteAttributeString("LineBreakMode", "NoWrap");
992 this.XmlOutput.WriteAttributeString("FontFamily", "Courier New");
993 this.XmlOutput.WriteAttributeString("Text", Element.Rows[i]);
994 this.XmlOutput.WriteEndElement();
995 }
996
997 this.XmlOutput.WriteEndElement();
998 this.XmlOutput.WriteEndElement();
999 }
1000
1005 public override Task Render(CommentBlock Element)
1006 {
1007 return Task.CompletedTask;
1008 }
1009
1014 public override async Task Render(DefinitionDescriptions Element)
1015 {
1016 MarkdownElement Last = Element.Children.HasLastItem ? Element.Children.LastItem : null;
1019 int i, c;
1020
1021 while (!(Loop is null))
1022 {
1023 for (i = Loop.Start, c = Loop.Pos; i < c; i++)
1024 {
1025 E = Loop[i];
1026
1028 {
1029 this.RenderContentView();
1030
1031 this.XmlOutput.WriteStartElement("Label");
1032 this.XmlOutput.WriteAttributeString("LineBreakMode", "WordWrap");
1033 this.RenderLabelAlignment();
1034 this.XmlOutput.WriteAttributeString("TextType", "Html");
1035
1037 {
1038 XmlEntitiesOnly = true
1039 }, this.Document))
1040 {
1041 await E.Render(Renderer);
1042 this.XmlOutput.WriteCData(Renderer.ToString());
1043 }
1044
1045 this.XmlOutput.WriteEndElement();
1046 this.XmlOutput.WriteEndElement();
1047 }
1048 else
1049 {
1050 this.XmlOutput.WriteStartElement("ContentView");
1051 this.XmlOutput.WriteAttributeString("Padding", this.XamlSettings.DefinitionMargin.ToString() + ",0,0," +
1052 (E == Last ? this.XamlSettings.DefinitionSeparator : 0).ToString());
1053
1054 this.XmlOutput.WriteStartElement("StackLayout");
1055 await E.Render(this);
1056 this.XmlOutput.WriteEndElement();
1057
1058 this.XmlOutput.WriteEndElement();
1059 }
1060 }
1061
1062 Loop = Loop.Next;
1063 }
1064 }
1065
1070 public override Task Render(DefinitionList Element)
1071 {
1072 return this.RenderChildren(Element);
1073 }
1074
1079 public override async Task Render(DefinitionTerms Element)
1080 {
1081 int TopMargin = this.XamlSettings.ParagraphMarginTop;
1083 int i, c;
1084
1085 while (!(Loop is null))
1086 {
1087 for (i = Loop.Start, c = Loop.Pos; i < c; i++)
1088 {
1089 this.RenderContentView(this.XamlSettings.ParagraphMarginLeft.ToString() + "," + TopMargin.ToString() + "," +
1090 this.XamlSettings.ParagraphMarginRight.ToString() + ",0");
1091
1092 bool BoldBak = this.Bold;
1093 this.Bold = true;
1094
1095 await this.RenderLabel(Loop[i], true);
1096
1097 this.Bold = BoldBak;
1098 this.XmlOutput.WriteEndElement();
1099
1100 TopMargin = 0;
1101 }
1102
1103 Loop = Loop.Next;
1104 }
1105 }
1106
1111 public override async Task Render(DeleteBlocks Element)
1112 {
1113 this.XmlOutput.WriteStartElement("ContentView");
1114 this.XmlOutput.WriteAttributeString("Padding", this.XamlSettings.BlockQuoteMargin.ToString() + "," +
1115 this.XamlSettings.ParagraphMarginTop.ToString() + ",0," + this.XamlSettings.ParagraphMarginBottom.ToString());
1116
1117 this.XmlOutput.WriteStartElement("Frame");
1118 this.XmlOutput.WriteAttributeString("Padding", this.XamlSettings.BlockQuotePadding.ToString() +
1119 ",0," + this.XamlSettings.BlockQuotePadding.ToString() + ",0");
1120 this.XmlOutput.WriteAttributeString("BorderColor", this.XamlSettings.DeletedBlockQuoteBorderColor);
1121 // TODO: Border thickness
1122
1123 this.XmlOutput.WriteStartElement("StackLayout");
1124 this.XmlOutput.WriteAttributeString("Orientation", "Vertical");
1125
1126 await this.RenderChildren(Element);
1127
1128 this.XmlOutput.WriteEndElement();
1129 this.XmlOutput.WriteEndElement();
1130 this.XmlOutput.WriteEndElement();
1131 }
1132
1137 public override Task Render(Footnote Element)
1138 {
1139 return this.RenderChildren(Element);
1140 }
1141
1146 public override async Task Render(Header Element)
1147 {
1148 this.RenderContentView();
1149
1150 this.XmlOutput.WriteStartElement("Label");
1151 this.XmlOutput.WriteAttributeString("LineBreakMode", "WordWrap");
1152 this.RenderLabelAlignment();
1153
1154 if (Element.Level > 0 && Element.Level <= this.XamlSettings.HeaderFontSize.Length)
1155 {
1156 this.XmlOutput.WriteAttributeString("FontSize", this.XamlSettings.HeaderFontSize[Element.Level - 1].ToString());
1157 this.XmlOutput.WriteAttributeString("TextColor", this.XamlSettings.HeaderForegroundColor[Element.Level - 1].ToString());
1158 }
1159
1160 this.XmlOutput.WriteAttributeString("TextType", "Html");
1161
1163 {
1164 XmlEntitiesOnly = true
1165 }, this.Document))
1166 {
1167 await Renderer.RenderChildren(Element);
1168
1169 this.XmlOutput.WriteCData(Renderer.ToString());
1170 }
1171
1172 this.XmlOutput.WriteEndElement();
1173 this.XmlOutput.WriteEndElement();
1174 }
1175
1180 {
1181 switch (this.Alignment)
1182 {
1183 case TextAlignment.Left:
1184 this.XmlOutput.WriteAttributeString("HorizontalTextAlignment", "Start");
1185 break;
1186
1187 case TextAlignment.Right:
1188 this.XmlOutput.WriteAttributeString("HorizontalTextAlignment", "End");
1189 break;
1190
1191 case TextAlignment.Center:
1192 this.XmlOutput.WriteAttributeString("HorizontalTextAlignment", "Center");
1193 break;
1194 }
1195 }
1196
1201 public override Task Render(HorizontalRule Element)
1202 {
1203 this.XmlOutput.WriteStartElement("BoxView");
1204 this.XmlOutput.WriteAttributeString("HeightRequest", "1");
1205 this.XmlOutput.WriteAttributeString("BackgroundColor", this.XamlSettings.TableCellBorderColor);
1206 this.XmlOutput.WriteAttributeString("HorizontalOptions", "FillAndExpand");
1207 this.XmlOutput.WriteAttributeString("Margin", this.XamlSettings.ParagraphMargins);
1208 this.XmlOutput.WriteEndElement();
1209
1210 return Task.CompletedTask;
1211 }
1212
1217 public override async Task Render(HtmlBlock Element)
1218 {
1219 this.RenderContentView();
1220
1221 this.XmlOutput.WriteStartElement("Label");
1222 this.XmlOutput.WriteAttributeString("LineBreakMode", "WordWrap");
1223 this.RenderLabelAlignment();
1224 this.XmlOutput.WriteAttributeString("TextType", "Html");
1225
1227 {
1228 XmlEntitiesOnly = true
1229 }, this.Document))
1230 {
1231 await Renderer.RenderChildren(Element);
1232
1233 this.XmlOutput.WriteCData(Renderer.ToString());
1234
1235 this.XmlOutput.WriteEndElement();
1236 this.XmlOutput.WriteEndElement();
1237 }
1238 }
1239
1244 public override async Task Render(InsertBlocks Element)
1245 {
1246 this.XmlOutput.WriteStartElement("ContentView");
1247 this.XmlOutput.WriteAttributeString("Padding", this.XamlSettings.BlockQuoteMargin.ToString() + "," +
1248 this.XamlSettings.ParagraphMarginTop.ToString() + ",0," + this.XamlSettings.ParagraphMarginBottom.ToString());
1249
1250 this.XmlOutput.WriteStartElement("Frame");
1251 this.XmlOutput.WriteAttributeString("Padding", this.XamlSettings.BlockQuotePadding.ToString() +
1252 ",0," + this.XamlSettings.BlockQuotePadding.ToString() + ",0");
1253 this.XmlOutput.WriteAttributeString("BorderColor", this.XamlSettings.InsertedBlockQuoteBorderColor);
1254 // TODO: Border thickness
1255
1256 this.XmlOutput.WriteStartElement("StackLayout");
1257 this.XmlOutput.WriteAttributeString("Orientation", "Vertical");
1258
1259 await this.RenderChildren(Element);
1260
1261 this.XmlOutput.WriteEndElement();
1262 this.XmlOutput.WriteEndElement();
1263 this.XmlOutput.WriteEndElement();
1264 }
1265
1270 public override Task Render(InvisibleBreak Element)
1271 {
1272 return Task.CompletedTask;
1273 }
1274
1279 public override async Task Render(LeftAligned Element)
1280 {
1281 this.XmlOutput.WriteStartElement("StackLayout");
1282 this.XmlOutput.WriteAttributeString("Orientation", "Vertical");
1283
1284 TextAlignment Bak = this.Alignment;
1285 this.Alignment = TextAlignment.Left;
1286
1287 await this.RenderChildren(Element);
1288
1289 this.Alignment = Bak;
1290 this.XmlOutput.WriteEndElement();
1291 }
1292
1297 public override async Task Render(MarginAligned Element)
1298 {
1299 this.XmlOutput.WriteStartElement("StackLayout");
1300 this.XmlOutput.WriteAttributeString("Orientation", "Vertical");
1301
1302 TextAlignment Bak = this.Alignment;
1303 this.Alignment = TextAlignment.Left;
1304
1305 await this.RenderChildren(Element);
1306
1307 this.Alignment = Bak;
1308 this.XmlOutput.WriteEndElement();
1309 }
1310
1315 public override async Task Render(NestedBlock Element)
1316 {
1317 if (Element.HasOneChild)
1318 await Element.FirstChild.Render(this);
1319 else
1320 {
1321 HtmlSettings Settings = new HtmlSettings()
1322 {
1323 XmlEntitiesOnly = true
1324 };
1325 HtmlRenderer Html = null;
1326
1327 try
1328 {
1331 int i, c;
1332
1333 while (!(Loop is null))
1334 {
1335 for (i = Loop.Start, c = Loop.Pos; i < c; i++)
1336 {
1337 E = Loop[i];
1338
1339 if (E.InlineSpanElement)
1340 {
1341 if (Html is null)
1342 Html = new HtmlRenderer(Settings, this.Document);
1343
1344 await E.Render(Html);
1345 }
1346 else
1347 {
1348 if (!(Html is null))
1349 {
1350 this.XmlOutput.WriteStartElement("Label");
1351 this.XmlOutput.WriteAttributeString("LineBreakMode", "WordWrap");
1352 this.RenderLabelAlignment();
1353 this.XmlOutput.WriteAttributeString("TextType", "Html");
1354 this.XmlOutput.WriteCData(Html.ToString());
1355 this.XmlOutput.WriteEndElement();
1356
1357 Html.Dispose();
1358 Html = null;
1359 }
1360
1361 await E.Render(this);
1362 }
1363 }
1364
1365 Loop = Loop.Next;
1366 }
1367
1368 if (!(Html is null))
1369 {
1370 this.XmlOutput.WriteStartElement("Label");
1371 this.XmlOutput.WriteAttributeString("LineBreakMode", "WordWrap");
1372 this.RenderLabelAlignment();
1373 this.XmlOutput.WriteAttributeString("TextType", "Html");
1374 this.XmlOutput.WriteCData(Html.ToString());
1375 this.XmlOutput.WriteEndElement();
1376 }
1377 }
1378 finally
1379 {
1380 Html?.Dispose();
1381 }
1382 }
1383 }
1384
1389 public override Task Render(NumberedItem Element)
1390 {
1391 return this.RenderChild(Element);
1392 }
1393
1398 public override async Task Render(NumberedList Element)
1399 {
1400 int Expected = 0;
1401 int Row = 0;
1402 bool ParagraphBullet;
1403 int i, c;
1404
1405 this.XmlOutput.WriteStartElement("ContentView");
1406 this.XmlOutput.WriteAttributeString("Padding", this.XamlSettings.ParagraphMargins);
1407
1408 this.XmlOutput.WriteStartElement("Grid");
1409 this.XmlOutput.WriteAttributeString("RowSpacing", "0");
1410 this.XmlOutput.WriteAttributeString("ColumnSpacing", "0");
1411
1412 this.XmlOutput.WriteStartElement("Grid.ColumnDefinitions");
1413
1414 this.XmlOutput.WriteStartElement("ColumnDefinition");
1415 this.XmlOutput.WriteAttributeString("Width", "Auto");
1416 this.XmlOutput.WriteEndElement();
1417
1418 this.XmlOutput.WriteStartElement("ColumnDefinition");
1419 this.XmlOutput.WriteAttributeString("Width", "*");
1420 this.XmlOutput.WriteEndElement();
1421
1422 this.XmlOutput.WriteEndElement();
1423 this.XmlOutput.WriteStartElement("Grid.RowDefinitions");
1424
1425 for (i = 0, c = Element.Children.Count; i < c; i++)
1426 {
1427 this.XmlOutput.WriteStartElement("RowDefinition");
1428 this.XmlOutput.WriteAttributeString("Height", "Auto");
1429 this.XmlOutput.WriteEndElement();
1430 }
1431
1432 this.XmlOutput.WriteEndElement();
1433
1436
1437 while (!(Loop is null))
1438 {
1439 for (i = Loop.Start, c = Loop.Pos; i < c; i++)
1440 {
1441 E = Loop[i];
1442 Expected++;
1443
1444 ParagraphBullet = !E.InlineSpanElement || E.OutsideParagraph;
1445 this.GetMargins(E, out int TopMargin, out int BottomMargin);
1446
1447 this.RenderContentView("0," + TopMargin.ToString() + "," + this.XamlSettings.ListContentMargin.ToString() + "," +
1448 BottomMargin.ToString());
1449 this.XmlOutput.WriteAttributeString("Grid.Column", "0");
1450 this.XmlOutput.WriteAttributeString("Grid.Row", Row.ToString());
1451
1452 this.XmlOutput.WriteStartElement("Label");
1453
1454 if (E is NumberedItem NumberedItem)
1455 this.XmlOutput.WriteValue((Expected = NumberedItem.Number).ToString());
1456 else
1457 this.XmlOutput.WriteValue(Expected.ToString());
1458
1459 this.XmlOutput.WriteValue(".");
1460 this.XmlOutput.WriteEndElement();
1461 this.XmlOutput.WriteEndElement();
1462
1463 this.XmlOutput.WriteStartElement("StackLayout");
1464 this.XmlOutput.WriteAttributeString("Grid.Column", "1");
1465 this.XmlOutput.WriteAttributeString("Grid.Row", Row.ToString());
1466 this.XmlOutput.WriteAttributeString("Orientation", "Vertical");
1467
1468 if (ParagraphBullet)
1469 await E.Render(this);
1470 else
1471 await this.RenderLabel(E, false);
1472
1473 this.XmlOutput.WriteEndElement();
1474
1475 Row++;
1476 }
1477
1478 Loop = Loop.Next;
1479 }
1480
1481 this.XmlOutput.WriteEndElement();
1482 this.XmlOutput.WriteEndElement();
1483 }
1484
1489 public override async Task Render(Paragraph Element)
1490 {
1491 this.RenderContentView();
1492 await this.RenderLabel(Element, false);
1493 this.XmlOutput.WriteEndElement();
1494 }
1495
1496 internal async Task RenderLabel(MarkdownElement Element, bool IncludeElement)
1497 {
1498 bool HasLink = !Element.ForEach((E, _) =>
1499 {
1500 return !(
1501 E is AutomaticLinkMail ||
1502 E is AutomaticLinkUrl ||
1503 E is Link ||
1504 E is LinkReference);
1505 }, null);
1506
1507 this.XmlOutput.WriteStartElement("Label");
1508 this.XmlOutput.WriteAttributeString("LineBreakMode", "WordWrap");
1509 this.RenderLabelAlignment();
1510
1511 if (HasLink)
1512 {
1513 if (this.InLabel)
1514 {
1515 if (IncludeElement)
1516 await Element.Render(this);
1517 else
1518 await this.RenderChildren(Element);
1519 }
1520 else
1521 {
1522 this.InLabel = true;
1523
1524 this.XmlOutput.WriteStartElement("Label.FormattedText");
1525 this.XmlOutput.WriteStartElement("FormattedString");
1526
1527 if (IncludeElement)
1528 await Element.Render(this);
1529 else
1530 await this.RenderChildren(Element);
1531
1532 this.XmlOutput.WriteEndElement();
1533 this.XmlOutput.WriteEndElement();
1534
1535 this.InLabel = false;
1536 }
1537 }
1538 else
1539 {
1540 this.XmlOutput.WriteAttributeString("TextType", "Html");
1541
1542 if (this.Bold)
1543 this.XmlOutput.WriteAttributeString("FontAttributes", "Bold");
1544
1546 {
1547 XmlEntitiesOnly = true
1548 }, this.Document))
1549 {
1550 if (IncludeElement)
1551 await Element.Render(Renderer);
1552 else
1553 await Renderer.RenderChildren(Element);
1554
1555 this.XmlOutput.WriteCData(Renderer.ToString());
1556 }
1557 }
1558
1559 this.XmlOutput.WriteEndElement();
1560 }
1561
1562 internal void RenderSpan(string Text)
1563 {
1564 if (!this.InLabel)
1565 {
1566 this.XmlOutput.WriteStartElement("Label");
1567 this.XmlOutput.WriteAttributeString("LineBreakMode", "WordWrap");
1568 this.RenderLabelAlignment();
1569 this.XmlOutput.WriteStartElement("Label.FormattedText");
1570 this.XmlOutput.WriteStartElement("FormattedString");
1571 }
1572
1573 this.XmlOutput.WriteStartElement("Span");
1574
1575 if (this.Superscript)
1576 Text = TextRenderer.ToSuperscript(Text);
1577 else if (this.Subscript)
1578 Text = TextRenderer.ToSubscript(Text);
1579
1580 this.XmlOutput.WriteAttributeString("Text", Text);
1581
1582 if (this.Bold && this.Italic)
1583 this.XmlOutput.WriteAttributeString("FontAttributes", "Italic, Bold");
1584 else if (this.Bold)
1585 this.XmlOutput.WriteAttributeString("FontAttributes", "Bold");
1586 else if (this.Italic)
1587 this.XmlOutput.WriteAttributeString("FontAttributes", "Italic");
1588
1589 if (this.StrikeThrough && this.Underline)
1590 this.XmlOutput.WriteAttributeString("TextDecorations", "Strikethrough, Underline");
1591 else if (this.StrikeThrough)
1592 this.XmlOutput.WriteAttributeString("TextDecorations", "Strikethrough");
1593 else if (this.Underline)
1594 this.XmlOutput.WriteAttributeString("TextDecorations", "Underline");
1595
1596 if (this.Code)
1597 this.XmlOutput.WriteAttributeString("FontFamily", "Courier New");
1598
1599 if (!(this.Hyperlink is null))
1600 {
1601 this.XmlOutput.WriteAttributeString("TextColor", "{Binding HyperlinkColor}");
1602
1603 this.XmlOutput.WriteStartElement("Span.GestureRecognizers");
1604 this.XmlOutput.WriteStartElement("TapGestureRecognizer");
1605 this.XmlOutput.WriteAttributeString("Command", "{Binding HyperlinkClicked}");
1606 this.XmlOutput.WriteAttributeString("CommandParameter", this.Hyperlink);
1607 this.XmlOutput.WriteEndElement();
1608 this.XmlOutput.WriteEndElement();
1609 }
1610
1611 if (!this.InLabel)
1612 {
1613 this.XmlOutput.WriteEndElement();
1614 this.XmlOutput.WriteEndElement();
1615 this.XmlOutput.WriteEndElement();
1616 }
1617
1618 this.XmlOutput.WriteEndElement();
1619 }
1620
1621 internal void RenderContentView()
1622 {
1623 this.RenderContentView(this.Alignment, this.XamlSettings.ParagraphMargins);
1624 }
1625
1626 internal void RenderContentView(string Margins)
1627 {
1628 this.RenderContentView(this.Alignment, Margins);
1629 }
1630
1631 internal void RenderContentView(TextAlignment Alignment, string Margins)
1632 {
1633 this.XmlOutput.WriteStartElement("ContentView");
1634 this.XmlOutput.WriteAttributeString("Padding", Margins);
1635
1636 switch (Alignment)
1637 {
1638 case TextAlignment.Center:
1639 this.XmlOutput.WriteAttributeString("HorizontalOptions", "Center");
1640 break;
1641
1642 case TextAlignment.Left:
1643 this.XmlOutput.WriteAttributeString("HorizontalOptions", "Start");
1644 break;
1645
1646 case TextAlignment.Right:
1647 this.XmlOutput.WriteAttributeString("HorizontalOptions", "End");
1648 break;
1649 }
1650 }
1651
1656 public override async Task Render(RightAligned Element)
1657 {
1658 this.XmlOutput.WriteStartElement("StackLayout");
1659 this.XmlOutput.WriteAttributeString("Orientation", "Vertical");
1660
1661 TextAlignment Bak = this.Alignment;
1662 this.Alignment = TextAlignment.Right;
1663
1664 await this.RenderChildren(Element);
1665
1666 this.Alignment = Bak;
1667 this.XmlOutput.WriteEndElement();
1668 }
1669
1674 public override Task Render(Sections Element)
1675 {
1676 return this.RenderChildren(Element);
1677 }
1678
1683 public override Task Render(SectionSeparator Element)
1684 {
1685 this.XmlOutput.WriteStartElement("BoxView");
1686 this.XmlOutput.WriteAttributeString("HeightRequest", "1");
1687 this.XmlOutput.WriteAttributeString("BackgroundColor", this.XamlSettings.TableCellBorderColor);
1688 this.XmlOutput.WriteAttributeString("HorizontalOptions", "FillAndExpand");
1689 this.XmlOutput.WriteAttributeString("Margin", this.XamlSettings.ParagraphMargins);
1690 this.XmlOutput.WriteEndElement();
1691
1692 return Task.CompletedTask;
1693 }
1694
1699 public override async Task Render(Table Element)
1700 {
1701 int Column;
1702 int Row, NrRows;
1703 int RowNr = 0;
1704
1705 this.XmlOutput.WriteStartElement("ContentView");
1706 this.XmlOutput.WriteAttributeString("Padding", this.XamlSettings.ParagraphMargins);
1707
1708 this.XmlOutput.WriteStartElement("Grid");
1709 this.XmlOutput.WriteAttributeString("RowSpacing", "-2");
1710 this.XmlOutput.WriteAttributeString("ColumnSpacing", "-2");
1711
1712 // TODO: Tooltip/caption
1713
1714 this.XmlOutput.WriteStartElement("Grid.ColumnDefinitions");
1715
1716 for (Column = 0; Column < Element.Columns; Column++)
1717 {
1718 this.XmlOutput.WriteStartElement("ColumnDefinition");
1719 this.XmlOutput.WriteAttributeString("Width", "Auto");
1720 this.XmlOutput.WriteEndElement();
1721 }
1722
1723 this.XmlOutput.WriteEndElement();
1724 this.XmlOutput.WriteStartElement("Grid.RowDefinitions");
1725
1726 for (Row = 0, NrRows = Element.Rows.Length + Element.Headers.Length; Row < NrRows; Row++)
1727 {
1728 this.XmlOutput.WriteStartElement("RowDefinition");
1729 this.XmlOutput.WriteAttributeString("Height", "Auto");
1730 this.XmlOutput.WriteEndElement();
1731 }
1732
1733 this.XmlOutput.WriteEndElement();
1734
1735 for (Row = 0, NrRows = Element.Headers.Length; Row < NrRows; Row++, RowNr++)
1736 await this.Render(Element.Headers[Row], Element.HeaderCellAlignments[Row], RowNr, true, Element);
1737
1738 for (Row = 0, NrRows = Element.Rows.Length; Row < NrRows; Row++, RowNr++)
1739 await this.Render(Element.Rows[Row], Element.RowCellAlignments[Row], RowNr, false, Element);
1740
1741 this.XmlOutput.WriteEndElement();
1742 this.XmlOutput.WriteEndElement();
1743 }
1744
1745 private void ClearState()
1746 {
1747 this.Alignment = TextAlignment.Left;
1748 this.Bold = false;
1749 this.Italic = false;
1750 this.StrikeThrough = false;
1751 this.Underline = false;
1752 this.Superscript = false;
1753 this.Subscript = false;
1754 this.Code = false;
1755 this.InLabel = false;
1756 this.Hyperlink = null;
1757 }
1758
1759 private StateBackup Backup()
1760 {
1761 return new StateBackup()
1762 {
1763 alignment = this.Alignment,
1764 bold = this.Bold,
1765 italic = this.Italic,
1766 strikeThrough = this.StrikeThrough,
1767 underline = this.Underline,
1768 superscript = this.Superscript,
1769 subscript = this.Subscript,
1770 code = this.Code,
1771 inLabel = this.InLabel,
1772 hyperlink = this.Hyperlink
1773 };
1774 }
1775
1776 private void Restore(StateBackup Backup)
1777 {
1778 this.Alignment = Backup.alignment;
1779 this.Bold = Backup.bold;
1780 this.Italic = Backup.italic;
1781 this.StrikeThrough = Backup.strikeThrough;
1782 this.Underline = Backup.underline;
1783 this.Superscript = Backup.superscript;
1784 this.Subscript = Backup.subscript;
1785 this.Code = Backup.code;
1786 this.InLabel = Backup.inLabel;
1787 this.Hyperlink = Backup.hyperlink;
1788 }
1789
1790 private class StateBackup
1791 {
1792 public TextAlignment alignment;
1793 public bool bold;
1794 public bool italic;
1795 public bool strikeThrough;
1796 public bool underline;
1797 public bool superscript;
1798 public bool subscript;
1799 public bool code;
1800 public bool inLabel;
1801 public string hyperlink;
1802 }
1803
1804 private async Task Render(MarkdownElement[] CurrentRow, TextAlignment?[] CellAlignments, int RowNr, bool Bold, Table Element)
1805 {
1808 int Column;
1809 int NrColumns = Element.Columns;
1810 int ColSpan;
1811 StateBackup Bak = this.Backup();
1812
1813 this.ClearState();
1814
1815 for (Column = 0; Column < NrColumns; Column++)
1816 {
1817 E = CurrentRow[Column];
1818 if (E is null)
1819 continue;
1820
1821 TextAlignment = CellAlignments[Column] ?? Element.ColumnAlignments[Column];
1822 ColSpan = Column + 1;
1823 while (ColSpan < NrColumns && CurrentRow[ColSpan] is null)
1824 ColSpan++;
1825
1826 ColSpan -= Column;
1827
1828 this.XmlOutput.WriteStartElement("Frame");
1829 this.XmlOutput.WriteAttributeString("Padding", "0,0,0,0");
1830 this.XmlOutput.WriteAttributeString("BorderColor", this.XamlSettings.TableCellBorderColor);
1831 // TODO: Table-cell border thickness
1832
1833 if ((RowNr & 1) == 0)
1834 {
1835 if (!string.IsNullOrEmpty(this.XamlSettings.TableCellRowBackgroundColor1))
1836 this.XmlOutput.WriteAttributeString("BackgroundColor", this.XamlSettings.TableCellRowBackgroundColor1);
1837 }
1838 else
1839 {
1840 if (!string.IsNullOrEmpty(this.XamlSettings.TableCellRowBackgroundColor2))
1841 this.XmlOutput.WriteAttributeString("BackgroundColor", this.XamlSettings.TableCellRowBackgroundColor2);
1842 }
1843
1844 this.XmlOutput.WriteAttributeString("Grid.Column", Column.ToString());
1845 this.XmlOutput.WriteAttributeString("Grid.Row", RowNr.ToString());
1846
1847 if (ColSpan > 1)
1848 this.XmlOutput.WriteAttributeString("Grid.ColumnSpan", ColSpan.ToString());
1849
1850 if (E.InlineSpanElement)
1851 {
1852 this.RenderContentView(TextAlignment, this.XamlSettings.TableCellPadding);
1853
1854 this.Bold = Bold;
1855 await this.RenderLabel(E, true);
1856 this.Bold = false;
1857
1858 this.XmlOutput.WriteEndElement(); // Paragraph
1859 }
1860 else
1861 {
1862 this.XmlOutput.WriteStartElement("ContentView");
1863 this.XmlOutput.WriteAttributeString("Padding", this.XamlSettings.TableCellPadding);
1864
1865 this.XmlOutput.WriteStartElement("StackLayout");
1866 await E.Render(this);
1867 this.XmlOutput.WriteEndElement(); // StackLayout
1868
1869 this.XmlOutput.WriteEndElement(); // ContentView
1870 }
1871
1872 this.XmlOutput.WriteEndElement(); // Frame
1873 }
1874
1875 this.Restore(Bak);
1876 }
1877
1882 public override Task Render(TaskItem Element)
1883 {
1884 return this.RenderChild(Element);
1885 }
1886
1891 public override async Task Render(TaskList Element)
1892 {
1893 int Row = 0;
1894 bool ParagraphBullet;
1895 int i, c;
1896
1897 this.XmlOutput.WriteStartElement("ContentView");
1898 this.XmlOutput.WriteAttributeString("Padding", this.XamlSettings.ParagraphMargins);
1899
1900 this.XmlOutput.WriteStartElement("Grid");
1901 this.XmlOutput.WriteAttributeString("RowSpacing", "0");
1902 this.XmlOutput.WriteAttributeString("ColumnSpacing", "0");
1903
1904 this.XmlOutput.WriteStartElement("Grid.ColumnDefinitions");
1905
1906 this.XmlOutput.WriteStartElement("ColumnDefinition");
1907 this.XmlOutput.WriteAttributeString("Width", "Auto");
1908 this.XmlOutput.WriteEndElement();
1909
1910 this.XmlOutput.WriteStartElement("ColumnDefinition");
1911 this.XmlOutput.WriteAttributeString("Width", "*");
1912 this.XmlOutput.WriteEndElement();
1913
1914 this.XmlOutput.WriteEndElement();
1915 this.XmlOutput.WriteStartElement("Grid.RowDefinitions");
1916
1917 for (i = 0, c = Element.Children.Count; i < c; i++)
1918 {
1919 this.XmlOutput.WriteStartElement("RowDefinition");
1920 this.XmlOutput.WriteAttributeString("Height", "Auto");
1921 this.XmlOutput.WriteEndElement();
1922 }
1923
1924 this.XmlOutput.WriteEndElement();
1925
1928
1929 while (!(Loop is null))
1930 {
1931 for (i = Loop.Start, c = Loop.Pos; i < c; i++)
1932 {
1933 E = Loop[i];
1934
1935 ParagraphBullet = !E.InlineSpanElement || E.OutsideParagraph;
1936 this.GetMargins(E, out int TopMargin, out int BottomMargin);
1937
1938 if (E is TaskItem Item && Item.IsChecked)
1939 {
1940 this.RenderContentView("0," + TopMargin.ToString() + "," + this.XamlSettings.ListContentMargin.ToString() + "," +
1941 BottomMargin.ToString());
1942 this.XmlOutput.WriteAttributeString("Grid.Column", "0");
1943 this.XmlOutput.WriteAttributeString("Grid.Row", Row.ToString());
1944
1945 this.XmlOutput.WriteElementString("Label", "✓");
1946 this.XmlOutput.WriteEndElement();
1947 }
1948
1949 this.XmlOutput.WriteStartElement("StackLayout");
1950 this.XmlOutput.WriteAttributeString("Grid.Column", "1");
1951 this.XmlOutput.WriteAttributeString("Grid.Row", Row.ToString());
1952 this.XmlOutput.WriteAttributeString("Orientation", "Vertical");
1953
1954 if (ParagraphBullet)
1955 await E.Render(this);
1956 else
1957 await this.RenderLabel(E, false);
1958
1959 this.XmlOutput.WriteEndElement();
1960
1961 Row++;
1962 }
1963
1964 Loop = Loop.Next;
1965 }
1966
1967 this.XmlOutput.WriteEndElement();
1968 this.XmlOutput.WriteEndElement();
1969 }
1970
1975 public override Task Render(UnnumberedItem Element)
1976 {
1977 return this.RenderChild(Element);
1978 }
1979
1980 #endregion
1981
1982 }
1983}
Helps with parsing of commong data types.
Definition: CommonTypes.cs:15
static string Encode(bool x)
Encodes a Boolean for use in XML and other formats.
Definition: CommonTypes.cs:596
string ShortName
Emoji short name.
string Unicode
Unicode representation of emoji.
Contains information about an emoji image.
Definition: ImageSource.cs:7
int? Width
Width of image, if available.
Definition: ImageSource.cs:16
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.
Represents a block quote in a markdown document.
Definition: BlockQuote.cs:11
Represents a bullet list in a markdown document.
Definition: BulletList.cs:11
Represents a center-aligned set of blocks in a markdown document.
Represents a code block in a markdown document.
Definition: CodeBlock.cs:17
Represents a comment block in a markdown document.
Definition: CommentBlock.cs:10
Represents a definition list in a markdown document.
Represents inserted blocks in a markdown document.
Definition: DeleteBlocks.cs:11
override Task Render(IRenderer Output)
Renders the element.
bool Referenced
If the Footnote has been referenced during rendering, and therefore needs to be shown at the end of t...
Definition: Footnote.cs:51
Represents a header in a markdown document.
Definition: Header.cs:15
Represents a block of HTML in a markdown document.
Definition: HtmlBlock.cs:11
Represents inserted blocks in a markdown document.
Definition: InsertBlocks.cs:11
Represents a left-aligned set of blocks in a markdown document.
Definition: LeftAligned.cs:11
Represents a margin-aligned set of blocks in a markdown document.
Represents a nested block with no special formatting rules in a markdown document.
Definition: NestedBlock.cs:12
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:65
MarkdownElement[][] Headers
Headers in table.
Definition: Table.cs:55
TextAlignment?[][] RowCellAlignments
Row cell alignments in table.
Definition: Table.cs:80
TextAlignment?[][] HeaderCellAlignments
Header cell alignments in table.
Definition: Table.cs:75
MarkdownElement[][] Rows
Rows in table.
Definition: Table.cs:60
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 ChunkedList< 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.
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.
virtual ChunkedList< MarkdownElement > Children
Any children of the element.
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:41
bool AloneInParagraph
If the element is alone in a paragraph.
Renders HTML from a Markdown document.
Definition: HtmlRenderer.cs:25
Contains settings that the HTML export uses to customize HTML output.
Definition: HtmlSettings.cs:7
Abstract base class for Markdown renderers.
Definition: Renderer.cs:15
readonly StringBuilder Output
Renderer output.
Definition: Renderer.cs:19
Task RenderChild(MarkdownElementSingleChild Element)
Renders the child of Element .
Definition: Renderer.cs:178
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:66
MarkdownDocument Document
Reference to Markdown document being processed.
Definition: Renderer.cs:24
Renders plain text from a Markdown document.
Definition: TextRenderer.cs:18
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:14
static Exception UnnestException(Exception Exception)
Unnests an exception, to extract the relevant inner exception.
Definition: Log.cs:828
Node referencing a chunk in a ChunkedList<T>
Definition: ChunkNode.cs:11
ChunkNode< T > Next
Next chunk
Definition: ChunkNode.cs:26
int Pos
Index after the last element in chunk.
Definition: ChunkNode.cs:51
int Start
Index of first element in chunk.
Definition: ChunkNode.cs:46
ChunkNode< T > FirstChunk
First chunk
Definition: ChunkedList.cs:259
int Count
Number of elements in collection.
Definition: ChunkedList.cs:68
Base class for graphs.
Definition: Graph.cs:88
Contains pixel information
virtual byte[] EncodeAsPng()
Encodes the pixels into a binary PNG image.
ToMatrix(ScriptNode Operand, bool NullCheck, int Start, int Length, Expression Expression)
To-Matrix operator.
Definition: ToMatrix.cs:22
Collection of variables.
Definition: Variables.cs:25
Interface for Emoji sources. Emoji sources provide emojis to content providers.
Definition: IEmojiSource.cs:10
Task< 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:7
Interface for multimedia content Xamarin.Forms XAML renderers.
Interface for objects that can be converted into matrices.
Definition: IToMatrix.cs:9
Definition: ImplTypes.g.cs:58
TextAlignment
Text alignment of contents.