mirror of
https://github.com/Nioux/AideDeJeu.git
synced 2025-10-30 06:56:10 +00:00
MardownView déplacé à l'intérieur du projet
This commit is contained in:
parent
4649c8f7b7
commit
888bcb110a
11 changed files with 890 additions and 12 deletions
|
|
@ -58,11 +58,11 @@
|
|||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SkiaSharp.Views.Forms">
|
||||
<PackageReference Include="SkiaSharp.Svg">
|
||||
<Version>1.60.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Xam.Forms.MarkdownView">
|
||||
<Version>0.0.0</Version>
|
||||
<PackageReference Include="SkiaSharp.Views.Forms">
|
||||
<Version>1.60.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Xamarin.Forms">
|
||||
<Version>3.1.0.583944</Version>
|
||||
|
|
|
|||
|
|
@ -175,13 +175,13 @@
|
|||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SkiaSharp.Svg">
|
||||
<Version>1.60.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="SkiaSharp.Views.Forms">
|
||||
<Version>1.60.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.NETCore.UniversalWindowsPlatform" Version="6.1.5" />
|
||||
<PackageReference Include="Xam.Forms.MarkdownView">
|
||||
<Version>0.0.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Xamarin.Forms">
|
||||
<Version>3.1.0.583944</Version>
|
||||
</PackageReference>
|
||||
|
|
|
|||
|
|
@ -111,11 +111,11 @@
|
|||
<Reference Include="Xamarin.iOS" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SkiaSharp.Views.Forms">
|
||||
<PackageReference Include="SkiaSharp.Svg">
|
||||
<Version>1.60.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Xam.Forms.MarkdownView">
|
||||
<Version>0.0.0</Version>
|
||||
<PackageReference Include="SkiaSharp.Views.Forms">
|
||||
<Version>1.60.0</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Xamarin.Forms">
|
||||
<Version>3.1.0.583944</Version>
|
||||
|
|
|
|||
|
|
@ -27,8 +27,8 @@
|
|||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Markdig" Version="0.15.0" />
|
||||
<PackageReference Include="SkiaSharp.Svg" Version="1.60.0" />
|
||||
<PackageReference Include="SkiaSharp.Views.Forms" Version="1.60.0" />
|
||||
<PackageReference Include="Xam.Forms.MarkdownView" Version="0.0.0" />
|
||||
<PackageReference Include="Xamarin.Forms" Version="3.1.0.583944" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
@ -49,6 +49,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<Folder Include="Data\" />
|
||||
<Folder Include="MarkdownView\" />
|
||||
<Folder Include="Services\" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
namespace Xam.Forms.Markdown
|
||||
{
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
/// <summary>
|
||||
/// A set o helper extensions for parsing Github common urls.
|
||||
/// </summary>
|
||||
public static class GithubExtensions
|
||||
{
|
||||
private static readonly Regex GithubRepoRegex = new Regex("http(s)?:\\/\\/github.com\\/([a-zA-Z0-9_-]+)\\/([a-zA-Z0-9_-]+)\\/((blob|tree)\\/([a-zA-Z0-9_-]+))?");
|
||||
|
||||
private const string GithubReadmeUrl = "https://raw.githubusercontent.com/{0}/{1}/{2}/README.md";
|
||||
|
||||
public static bool TryExtractGithubRawMarkdownUrl(string url, out string readmeUrl)
|
||||
{
|
||||
var match = GithubRepoRegex.Match(url);
|
||||
if(match.Success)
|
||||
{
|
||||
var user = match.Groups[2].Value;
|
||||
var repo = match.Groups[3].Value;
|
||||
var branch = match.Groups.Count > 6 ? match.Groups[6].Value : "master";
|
||||
readmeUrl = string.Format(GithubReadmeUrl, user, repo, branch);
|
||||
return true;
|
||||
}
|
||||
|
||||
readmeUrl = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
namespace Xam.Forms.Markdown.Extensions
|
||||
{
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using SkiaSharp;
|
||||
using Xamarin.Forms;
|
||||
using System.Diagnostics;
|
||||
|
||||
public static class ImageExtensions
|
||||
{
|
||||
public static void RenderSvg(this Image view, string uri)
|
||||
{
|
||||
try
|
||||
{
|
||||
var req = (HttpWebRequest)WebRequest.Create(uri);
|
||||
|
||||
var svg = new SkiaSharp.Extended.Svg.SKSvg();
|
||||
req.BeginGetResponse((ar) =>
|
||||
{
|
||||
var res = (ar.AsyncState as HttpWebRequest).EndGetResponse(ar) as HttpWebResponse;
|
||||
using (var stream = res.GetResponseStream())
|
||||
{
|
||||
if (stream != null)
|
||||
{
|
||||
var picture = svg.Load(stream);
|
||||
|
||||
using (var image = SKImage.FromPicture(picture, picture.CullRect.Size.ToSizeI()))
|
||||
using (var data = image.Encode(SKEncodedImageFormat.Jpeg, 80))
|
||||
{
|
||||
var ms = new MemoryStream();
|
||||
|
||||
if (data != null && !data.IsEmpty)
|
||||
{
|
||||
data.SaveTo(ms);
|
||||
ms.Seek(0, SeekOrigin.Begin);
|
||||
ms.Position = 0;
|
||||
view.Source = ImageSource.FromStream(() => ms);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, req);
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"Failed to render svg: {ex}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
21
AideDeJeu/AideDeJeu/MarkdownView/MarkdownStyle.cs
Normal file
21
AideDeJeu/AideDeJeu/MarkdownView/MarkdownStyle.cs
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
namespace Xam.Forms.Markdown
|
||||
{
|
||||
using Xamarin.Forms;
|
||||
|
||||
public class MarkdownStyle
|
||||
{
|
||||
public FontAttributes Attributes { get; set; } = FontAttributes.None;
|
||||
|
||||
public float FontSize { get; set; } = 12;
|
||||
|
||||
public Color ForegroundColor { get; set; } = Color.Black;
|
||||
|
||||
public Color BackgroundColor { get; set; } = Color.Transparent;
|
||||
|
||||
public Color BorderColor { get; set; }
|
||||
|
||||
public float BorderSize { get; set; }
|
||||
|
||||
public string FontFamily { get; set; }
|
||||
}
|
||||
}
|
||||
204
AideDeJeu/AideDeJeu/MarkdownView/MarkdownTheme.cs
Normal file
204
AideDeJeu/AideDeJeu/MarkdownView/MarkdownTheme.cs
Normal file
|
|
@ -0,0 +1,204 @@
|
|||
|
||||
namespace Xam.Forms.Markdown
|
||||
{
|
||||
using Xamarin.Forms;
|
||||
|
||||
public class MarkdownTheme
|
||||
{
|
||||
public MarkdownTheme()
|
||||
{
|
||||
this.Paragraph = new MarkdownStyle
|
||||
{
|
||||
Attributes = FontAttributes.None,
|
||||
BackgroundColor = Color.White,
|
||||
FontSize = 12,
|
||||
};
|
||||
|
||||
this.Heading1 = new MarkdownStyle
|
||||
{
|
||||
Attributes = FontAttributes.Bold,
|
||||
BorderSize = 1,
|
||||
FontSize = 26,
|
||||
};
|
||||
|
||||
this.Heading2 = new MarkdownStyle
|
||||
{
|
||||
Attributes = FontAttributes.Bold,
|
||||
BorderSize = 1,
|
||||
FontSize = 22,
|
||||
};
|
||||
|
||||
this.Heading3 = new MarkdownStyle
|
||||
{
|
||||
Attributes = FontAttributes.Bold,
|
||||
FontSize = 20,
|
||||
};
|
||||
|
||||
this.Heading4 = new MarkdownStyle
|
||||
{
|
||||
Attributes = FontAttributes.Bold,
|
||||
FontSize = 18,
|
||||
};
|
||||
|
||||
this.Heading5 = new MarkdownStyle
|
||||
{
|
||||
Attributes = FontAttributes.Bold,
|
||||
FontSize = 16,
|
||||
};
|
||||
|
||||
this.Heading6 = new MarkdownStyle
|
||||
{
|
||||
Attributes = FontAttributes.Bold,
|
||||
FontSize = 14,
|
||||
};
|
||||
|
||||
this.Link = new MarkdownStyle
|
||||
{
|
||||
Attributes = FontAttributes.None,
|
||||
FontSize = 12,
|
||||
};
|
||||
|
||||
this.Code = new MarkdownStyle
|
||||
{
|
||||
Attributes = FontAttributes.None,
|
||||
FontSize = 12,
|
||||
};
|
||||
|
||||
this.Quote = new MarkdownStyle
|
||||
{
|
||||
Attributes = FontAttributes.None,
|
||||
BorderSize = 4,
|
||||
FontSize = 12,
|
||||
BackgroundColor = Color.Gray.MultiplyAlpha(.1),
|
||||
};
|
||||
|
||||
this.Separator = new MarkdownStyle
|
||||
{
|
||||
BorderSize = 2,
|
||||
};
|
||||
|
||||
this.TableHeader = new MarkdownStyle
|
||||
{
|
||||
Attributes = FontAttributes.Bold,
|
||||
FontSize = 12,
|
||||
BorderSize = 1,
|
||||
ForegroundColor = Color.White,
|
||||
BackgroundColor = Color.Silver,
|
||||
};
|
||||
|
||||
// Platform specific properties
|
||||
switch (Device.RuntimePlatform)
|
||||
{
|
||||
case Device.iOS:
|
||||
Code.FontFamily = "Courier";
|
||||
break;
|
||||
|
||||
case Device.Android:
|
||||
Code.FontFamily = "monospace";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public Color BackgroundColor { get; set; }
|
||||
|
||||
public MarkdownStyle Paragraph { get; set; }
|
||||
|
||||
public MarkdownStyle Heading1 { get; set; }
|
||||
|
||||
public MarkdownStyle Heading2 { get; set; }
|
||||
|
||||
public MarkdownStyle Heading3 { get; set; }
|
||||
|
||||
public MarkdownStyle Heading4 { get; set; }
|
||||
|
||||
public MarkdownStyle Heading5 { get; set; }
|
||||
|
||||
public MarkdownStyle Heading6 { get; set; }
|
||||
|
||||
public MarkdownStyle Quote { get; set; }
|
||||
|
||||
public MarkdownStyle Separator { get; set; }
|
||||
|
||||
public MarkdownStyle Link { get; set; }
|
||||
|
||||
public MarkdownStyle Code { get; set; }
|
||||
|
||||
public MarkdownStyle TableHeader { get; set; }
|
||||
|
||||
public float Margin { get; set; } = 10;
|
||||
}
|
||||
|
||||
public class LightMarkdownTheme : MarkdownTheme
|
||||
{
|
||||
public LightMarkdownTheme()
|
||||
{
|
||||
this.BackgroundColor = DefaultBackgroundColor;
|
||||
this.Paragraph.ForegroundColor = DefaultTextColor;
|
||||
this.Heading1.ForegroundColor = DefaultTextColor;
|
||||
this.Heading1.BorderColor = DefaultSeparatorColor;
|
||||
this.Heading2.ForegroundColor = DefaultTextColor;
|
||||
this.Heading2.BorderColor = DefaultSeparatorColor;
|
||||
this.Heading3.ForegroundColor = DefaultTextColor;
|
||||
this.Heading4.ForegroundColor = DefaultTextColor;
|
||||
this.Heading5.ForegroundColor = DefaultTextColor;
|
||||
this.Heading6.ForegroundColor = DefaultTextColor;
|
||||
this.Link.ForegroundColor = DefaultAccentColor;
|
||||
this.Code.ForegroundColor = DefaultTextColor;
|
||||
this.Code.BackgroundColor = DefaultCodeBackground;
|
||||
this.Quote.ForegroundColor = DefaultQuoteTextColor;
|
||||
this.Quote.BorderColor = DefaultQuoteBorderColor;
|
||||
this.Separator.BorderColor = DefaultSeparatorColor;
|
||||
}
|
||||
|
||||
public static readonly Color DefaultBackgroundColor = Color.FromHex("#ffffff");
|
||||
|
||||
public static readonly Color DefaultAccentColor = Color.FromHex("#0366d6");
|
||||
|
||||
public static readonly Color DefaultTextColor = Color.FromHex("#24292e");
|
||||
|
||||
public static readonly Color DefaultCodeBackground = Color.FromHex("#f6f8fa");
|
||||
|
||||
public static readonly Color DefaultSeparatorColor = Color.FromHex("#eaecef");
|
||||
|
||||
public static readonly Color DefaultQuoteTextColor = Color.FromHex("#6a737d");
|
||||
|
||||
public static readonly Color DefaultQuoteBorderColor = Color.FromHex("#dfe2e5");
|
||||
}
|
||||
|
||||
public class DarkMarkdownTheme : MarkdownTheme
|
||||
{
|
||||
public DarkMarkdownTheme()
|
||||
{
|
||||
this.BackgroundColor = DefaultBackgroundColor;
|
||||
this.Paragraph.ForegroundColor = DefaultTextColor;
|
||||
this.Heading1.ForegroundColor = DefaultTextColor;
|
||||
this.Heading1.BorderColor = DefaultSeparatorColor;
|
||||
this.Heading2.ForegroundColor = DefaultTextColor;
|
||||
this.Heading2.BorderColor = DefaultSeparatorColor;
|
||||
this.Heading3.ForegroundColor = DefaultTextColor;
|
||||
this.Heading4.ForegroundColor = DefaultTextColor;
|
||||
this.Heading5.ForegroundColor = DefaultTextColor;
|
||||
this.Heading6.ForegroundColor = DefaultTextColor;
|
||||
this.Link.ForegroundColor = DefaultAccentColor;
|
||||
this.Code.ForegroundColor = DefaultTextColor;
|
||||
this.Code.BackgroundColor = DefaultCodeBackground;
|
||||
this.Quote.ForegroundColor = DefaultQuoteTextColor;
|
||||
this.Quote.BorderColor = DefaultQuoteBorderColor;
|
||||
this.Separator.BorderColor = DefaultSeparatorColor;
|
||||
}
|
||||
|
||||
public static readonly Color DefaultBackgroundColor = Color.FromHex("#2b303b");
|
||||
|
||||
public static readonly Color DefaultAccentColor = Color.FromHex("#d08770");
|
||||
|
||||
public static readonly Color DefaultTextColor = Color.FromHex("#eff1f5");
|
||||
|
||||
public static readonly Color DefaultCodeBackground = Color.FromHex("#4f5b66");
|
||||
|
||||
public static readonly Color DefaultSeparatorColor = Color.FromHex("#65737e");
|
||||
|
||||
public static readonly Color DefaultQuoteTextColor = Color.FromHex("#a7adba");
|
||||
|
||||
public static readonly Color DefaultQuoteBorderColor = Color.FromHex("#a7adba");
|
||||
}
|
||||
}
|
||||
570
AideDeJeu/AideDeJeu/MarkdownView/MarkdownView.cs
Normal file
570
AideDeJeu/AideDeJeu/MarkdownView/MarkdownView.cs
Normal file
|
|
@ -0,0 +1,570 @@
|
|||
namespace Xam.Forms.Markdown
|
||||
{
|
||||
using System.Linq;
|
||||
using Markdig.Syntax;
|
||||
using Markdig.Syntax.Inlines;
|
||||
using Xamarin.Forms;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using Extensions;
|
||||
using Markdig;
|
||||
|
||||
public class MarkdownView : ContentView
|
||||
{
|
||||
public Action<string> NavigateToLink { get; set; } = (s) => Device.OpenUri(new Uri(s));
|
||||
|
||||
public static MarkdownTheme Global = new LightMarkdownTheme();
|
||||
|
||||
public string Markdown
|
||||
{
|
||||
get { return (string)GetValue(MarkdownProperty); }
|
||||
set { SetValue(MarkdownProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly BindableProperty MarkdownProperty = BindableProperty.Create(nameof(Markdown), typeof(string), typeof(MarkdownView), null, propertyChanged: OnMarkdownChanged);
|
||||
|
||||
public string RelativeUrlHost
|
||||
{
|
||||
get { return (string)GetValue(RelativeUrlHostProperty); }
|
||||
set { SetValue(RelativeUrlHostProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly BindableProperty RelativeUrlHostProperty = BindableProperty.Create(nameof(RelativeUrlHost), typeof(string), typeof(MarkdownView), null, propertyChanged: OnMarkdownChanged);
|
||||
|
||||
public MarkdownTheme Theme
|
||||
{
|
||||
get { return (MarkdownTheme)GetValue(ThemeProperty); }
|
||||
set { SetValue(ThemeProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly BindableProperty ThemeProperty = BindableProperty.Create(nameof(Theme), typeof(MarkdownTheme), typeof(MarkdownView), Global, propertyChanged: OnMarkdownChanged);
|
||||
|
||||
private bool isQuoted;
|
||||
|
||||
private List<View> queuedViews = new List<View>();
|
||||
|
||||
static void OnMarkdownChanged(BindableObject bindable, object oldValue, object newValue)
|
||||
{
|
||||
var view = bindable as MarkdownView;
|
||||
view.RenderMarkdown();
|
||||
}
|
||||
|
||||
private StackLayout stack;
|
||||
|
||||
private List<KeyValuePair<string, string>> links = new List<KeyValuePair<string, string>>();
|
||||
|
||||
private void RenderMarkdown()
|
||||
{
|
||||
stack = new StackLayout()
|
||||
{
|
||||
Spacing = this.Theme.Margin,
|
||||
};
|
||||
|
||||
this.Padding = this.Theme.Margin;
|
||||
|
||||
this.BackgroundColor = this.Theme.BackgroundColor;
|
||||
|
||||
if(!string.IsNullOrEmpty(this.Markdown))
|
||||
{
|
||||
var pipeline = new Markdig.MarkdownPipelineBuilder().UsePipeTables().Build();
|
||||
var parsed = Markdig.Markdown.Parse(this.Markdown, pipeline);
|
||||
this.Render(parsed.AsEnumerable());
|
||||
}
|
||||
|
||||
this.Content = stack;
|
||||
|
||||
}
|
||||
|
||||
private void Render(IEnumerable<Block> blocks)
|
||||
{
|
||||
foreach (var block in blocks)
|
||||
{
|
||||
this.Render(block);
|
||||
}
|
||||
}
|
||||
|
||||
private void AttachLinks(View view)
|
||||
{
|
||||
if (links.Any())
|
||||
{
|
||||
var blockLinks = links;
|
||||
view.GestureRecognizers.Add(new TapGestureRecognizer
|
||||
{
|
||||
Command = new Command(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
if (blockLinks.Count > 1)
|
||||
{
|
||||
var result = await Application.Current.MainPage.DisplayActionSheet("Open link", "Cancel", null, blockLinks.Select(x => x.Key).ToArray());
|
||||
var link = blockLinks.FirstOrDefault(x => x.Key == result);
|
||||
NavigateToLink(link.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
NavigateToLink(blockLinks.First().Value);
|
||||
}
|
||||
}
|
||||
catch (Exception) { }
|
||||
}),
|
||||
});
|
||||
|
||||
links = new List<KeyValuePair<string, string>>();
|
||||
}
|
||||
}
|
||||
|
||||
#region Rendering blocks
|
||||
|
||||
private void Render(Block block)
|
||||
{
|
||||
switch (block)
|
||||
{
|
||||
case HeadingBlock heading:
|
||||
Render(heading);
|
||||
break;
|
||||
|
||||
case ParagraphBlock paragraph:
|
||||
Render(paragraph);
|
||||
break;
|
||||
|
||||
case QuoteBlock quote:
|
||||
Render(quote);
|
||||
break;
|
||||
|
||||
case CodeBlock code:
|
||||
Render(code);
|
||||
break;
|
||||
|
||||
case ListBlock list:
|
||||
Render(list);
|
||||
break;
|
||||
|
||||
case ThematicBreakBlock thematicBreak:
|
||||
Render(thematicBreak);
|
||||
break;
|
||||
|
||||
case HtmlBlock html:
|
||||
Render(html);
|
||||
break;
|
||||
|
||||
case Markdig.Extensions.Tables.Table table:
|
||||
Render(table);
|
||||
break;
|
||||
|
||||
default:
|
||||
Debug.WriteLine($"Can't render {block.GetType()} blocks.");
|
||||
break;
|
||||
}
|
||||
|
||||
if(queuedViews.Any())
|
||||
{
|
||||
foreach (var view in queuedViews)
|
||||
{
|
||||
this.stack.Children.Add(view);
|
||||
}
|
||||
queuedViews.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
private int listScope;
|
||||
|
||||
private void Render(ThematicBreakBlock block)
|
||||
{
|
||||
var style = this.Theme.Separator;
|
||||
|
||||
if (style.BorderSize > 0)
|
||||
{
|
||||
stack.Children.Add(new BoxView
|
||||
{
|
||||
HeightRequest = style.BorderSize,
|
||||
BackgroundColor = style.BorderColor,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void Render(ListBlock block)
|
||||
{
|
||||
listScope++;
|
||||
|
||||
for (int i = 0; i < block.Count(); i++)
|
||||
{
|
||||
var item = block.ElementAt(i);
|
||||
|
||||
if (item is ListItemBlock itemBlock)
|
||||
{
|
||||
this.Render(block, i + 1, itemBlock);
|
||||
}
|
||||
}
|
||||
|
||||
listScope--;
|
||||
}
|
||||
|
||||
private void Render(ListBlock parent, int index, ListItemBlock block)
|
||||
{
|
||||
var initialStack = this.stack;
|
||||
|
||||
this.stack = new StackLayout()
|
||||
{
|
||||
Spacing = this.Theme.Margin,
|
||||
};
|
||||
|
||||
this.Render(block.AsEnumerable());
|
||||
|
||||
var horizontalStack = new StackLayout
|
||||
{
|
||||
Orientation = StackOrientation.Horizontal,
|
||||
Margin = new Thickness(listScope * this.Theme.Margin, 0, 0, 0),
|
||||
};
|
||||
|
||||
View bullet;
|
||||
|
||||
if (parent.IsOrdered)
|
||||
{
|
||||
bullet = new Label
|
||||
{
|
||||
Text = $"{index}.",
|
||||
FontSize = this.Theme.Paragraph.FontSize,
|
||||
TextColor = this.Theme.Paragraph.ForegroundColor,
|
||||
VerticalOptions = LayoutOptions.Start,
|
||||
HorizontalOptions = LayoutOptions.End,
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
bullet = new BoxView
|
||||
{
|
||||
WidthRequest = 4,
|
||||
HeightRequest = 4,
|
||||
Margin = new Thickness(0, 6, 0, 0),
|
||||
BackgroundColor = this.Theme.Paragraph.ForegroundColor,
|
||||
VerticalOptions = LayoutOptions.Start,
|
||||
HorizontalOptions = LayoutOptions.Center,
|
||||
};
|
||||
}
|
||||
|
||||
horizontalStack.Children.Add(bullet);
|
||||
|
||||
|
||||
horizontalStack.Children.Add(this.stack);
|
||||
initialStack.Children.Add(horizontalStack);
|
||||
|
||||
this.stack = initialStack;
|
||||
}
|
||||
|
||||
private void Render(HeadingBlock block)
|
||||
{
|
||||
MarkdownStyle style;
|
||||
|
||||
switch (block.Level)
|
||||
{
|
||||
case 1:
|
||||
style = this.Theme.Heading1;
|
||||
break;
|
||||
case 2:
|
||||
style = this.Theme.Heading2;
|
||||
break;
|
||||
case 3:
|
||||
style = this.Theme.Heading3;
|
||||
break;
|
||||
case 4:
|
||||
style = this.Theme.Heading4;
|
||||
break;
|
||||
case 5:
|
||||
style = this.Theme.Heading5;
|
||||
break;
|
||||
default:
|
||||
style = this.Theme.Heading6;
|
||||
break;
|
||||
}
|
||||
|
||||
var foregroundColor = isQuoted ? this.Theme.Quote.ForegroundColor : style.ForegroundColor;
|
||||
|
||||
var label = new Label
|
||||
{
|
||||
FormattedText = CreateFormatted(block.Inline, style.FontFamily, style.Attributes, foregroundColor, style.BackgroundColor, style.FontSize),
|
||||
};
|
||||
|
||||
AttachLinks(label);
|
||||
|
||||
if (style.BorderSize > 0)
|
||||
{
|
||||
var headingStack = new StackLayout();
|
||||
headingStack.Children.Add(label);
|
||||
headingStack.Children.Add(new BoxView
|
||||
{
|
||||
HeightRequest = style.BorderSize,
|
||||
BackgroundColor = style.BorderColor,
|
||||
});
|
||||
stack.Children.Add(headingStack);
|
||||
}
|
||||
else
|
||||
{
|
||||
stack.Children.Add(label);
|
||||
}
|
||||
}
|
||||
|
||||
private void Render(ParagraphBlock block)
|
||||
{
|
||||
var style = this.Theme.Paragraph;
|
||||
var foregroundColor = isQuoted ? this.Theme.Quote.ForegroundColor : style.ForegroundColor;
|
||||
var label = new Label
|
||||
{
|
||||
FormattedText = CreateFormatted(block.Inline, style.FontFamily, style.Attributes, foregroundColor, style.BackgroundColor, style.FontSize),
|
||||
};
|
||||
AttachLinks(label);
|
||||
this.stack.Children.Add(label);
|
||||
}
|
||||
|
||||
private void Render(HtmlBlock block)
|
||||
{
|
||||
// ?
|
||||
}
|
||||
|
||||
private void Render(QuoteBlock block)
|
||||
{
|
||||
var initialIsQuoted = this.isQuoted;
|
||||
var initialStack = this.stack;
|
||||
|
||||
this.isQuoted = true;
|
||||
this.stack = new StackLayout()
|
||||
{
|
||||
Spacing = this.Theme.Margin,
|
||||
};
|
||||
|
||||
var style = this.Theme.Quote;
|
||||
|
||||
if (style.BorderSize > 0)
|
||||
{
|
||||
var horizontalStack = new StackLayout()
|
||||
{
|
||||
Orientation = StackOrientation.Horizontal,
|
||||
BackgroundColor = this.Theme.Quote.BackgroundColor,
|
||||
};
|
||||
|
||||
horizontalStack.Children.Add(new BoxView()
|
||||
{
|
||||
WidthRequest = style.BorderSize,
|
||||
BackgroundColor = style.BorderColor,
|
||||
});
|
||||
|
||||
horizontalStack.Children.Add(this.stack);
|
||||
initialStack.Children.Add(horizontalStack);
|
||||
}
|
||||
else
|
||||
{
|
||||
stack.BackgroundColor = this.Theme.Quote.BackgroundColor;
|
||||
initialStack.Children.Add(this.stack);
|
||||
}
|
||||
|
||||
this.Render(block.AsEnumerable());
|
||||
|
||||
this.isQuoted = initialIsQuoted;
|
||||
this.stack = initialStack;
|
||||
}
|
||||
|
||||
private void Render(CodeBlock block)
|
||||
{
|
||||
var style = this.Theme.Code;
|
||||
var label = new Label
|
||||
{
|
||||
TextColor = style.ForegroundColor,
|
||||
FontAttributes = style.Attributes,
|
||||
FontFamily = style.FontFamily,
|
||||
FontSize = style.FontSize,
|
||||
Text = string.Join(Environment.NewLine, block.Lines),
|
||||
};
|
||||
stack.Children.Add(new Frame()
|
||||
{
|
||||
CornerRadius = 3,
|
||||
HasShadow = false,
|
||||
Padding = this.Theme.Margin,
|
||||
BackgroundColor = style.BackgroundColor,
|
||||
Content = label
|
||||
});
|
||||
}
|
||||
|
||||
private void Render(Markdig.Extensions.Tables.Table tableBlock)
|
||||
{
|
||||
var scroll = new ScrollView() { HorizontalScrollBarVisibility = ScrollBarVisibility.Default, Orientation = ScrollOrientation.Horizontal };
|
||||
var grid = new Grid() { HorizontalOptions = LayoutOptions.Start, Margin = 0, Padding = 1, BackgroundColor = Theme.TableHeader.BackgroundColor, RowSpacing = 1, ColumnSpacing = 1 };
|
||||
|
||||
int top = 0;
|
||||
int maxColumns = 0;
|
||||
foreach (Markdig.Extensions.Tables.TableRow row in tableBlock)
|
||||
{
|
||||
int left = 0;
|
||||
foreach(Markdig.Extensions.Tables.TableCell cell in row)
|
||||
{
|
||||
foreach (var blockpar in cell)
|
||||
{
|
||||
var par = blockpar as Markdig.Syntax.ParagraphBlock;
|
||||
var style = row.IsHeader ? Theme.TableHeader : Theme.Paragraph;
|
||||
var frame = new Frame
|
||||
{
|
||||
BackgroundColor = style.BackgroundColor,
|
||||
Margin = 1,
|
||||
Padding = 5,
|
||||
};
|
||||
var label = new Label
|
||||
{
|
||||
FormattedText = CreateFormatted(par.Inline, style.FontFamily, style.Attributes, style.ForegroundColor, style.BackgroundColor, style.FontSize),
|
||||
HorizontalOptions = LayoutOptions.CenterAndExpand,
|
||||
BackgroundColor = style.BackgroundColor,
|
||||
VerticalTextAlignment = TextAlignment.Center,
|
||||
HorizontalTextAlignment = TextAlignment.Center,
|
||||
};
|
||||
frame.Content = label;
|
||||
AttachLinks(label);
|
||||
grid.Children.Add(frame, left, top);
|
||||
}
|
||||
|
||||
left++;
|
||||
maxColumns = Math.Max(maxColumns, left);
|
||||
}
|
||||
grid.RowDefinitions.Add(new RowDefinition { Height= GridLength.Auto });
|
||||
top++;
|
||||
}
|
||||
for (int i = 0; i < maxColumns; i++)
|
||||
{
|
||||
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
|
||||
}
|
||||
double? gridHeight = null;
|
||||
grid.SizeChanged += (object sender, EventArgs e) =>
|
||||
{
|
||||
if (gridHeight == null)
|
||||
{
|
||||
gridHeight = grid.HeightRequest = grid.Height;
|
||||
}
|
||||
else
|
||||
{
|
||||
grid.HeightRequest = gridHeight.Value;
|
||||
}
|
||||
};
|
||||
|
||||
//grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
|
||||
//grid.RowDefinitions.Add(new RowDefinition { Height= new GridLength(1, GridUnitType.Star) });
|
||||
stack.Children.Add(scroll);
|
||||
scroll.Content = grid;
|
||||
//grid.WidthRequest = 1000;
|
||||
scroll.ForceLayout();
|
||||
this.UpdateChildrenLayout();
|
||||
}
|
||||
|
||||
|
||||
private FormattedString CreateFormatted(ContainerInline inlines, string family, FontAttributes attributes, Color foregroundColor, Color backgroundColor, float size)
|
||||
{
|
||||
var fs = new FormattedString();
|
||||
|
||||
foreach (var inline in inlines)
|
||||
{
|
||||
var spans = CreateSpans(inline, family, attributes, foregroundColor, backgroundColor, size);
|
||||
if (spans != null)
|
||||
{
|
||||
foreach (var span in spans)
|
||||
{
|
||||
fs.Spans.Add(span);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return fs;
|
||||
}
|
||||
|
||||
private Span[] CreateSpans(Inline inline, string family, FontAttributes attributes, Color foregroundColor, Color backgroundColor, float size)
|
||||
{
|
||||
switch (inline)
|
||||
{
|
||||
case LiteralInline literal:
|
||||
return new[]
|
||||
{
|
||||
new Span
|
||||
{
|
||||
Text = literal.Content.Text.Substring(literal.Content.Start, literal.Content.Length),
|
||||
FontAttributes = attributes,
|
||||
ForegroundColor = foregroundColor,
|
||||
BackgroundColor = backgroundColor,
|
||||
FontSize = size,
|
||||
FontFamily = family,
|
||||
}
|
||||
};
|
||||
|
||||
case EmphasisInline emphasis:
|
||||
var childAttributes = attributes | (emphasis.IsDouble ? FontAttributes.Bold : FontAttributes.Italic);
|
||||
return emphasis.SelectMany(x => CreateSpans(x, family, childAttributes, foregroundColor, backgroundColor, size)).ToArray();
|
||||
|
||||
case LineBreakInline breakline:
|
||||
return new[] { new Span { Text = "\n" } };
|
||||
|
||||
case LinkInline link:
|
||||
|
||||
var url = link.Url;
|
||||
|
||||
if (!(url.StartsWith("http://") || url.StartsWith("https://")))
|
||||
{
|
||||
url = $"{this.RelativeUrlHost?.TrimEnd('/')}/{url.TrimStart('/')}";
|
||||
}
|
||||
|
||||
if(link.IsImage)
|
||||
{
|
||||
var image = new Image();
|
||||
|
||||
if(Path.GetExtension(url) == ".svg")
|
||||
{
|
||||
image.RenderSvg(url);
|
||||
}
|
||||
else
|
||||
{
|
||||
image.Source = url;
|
||||
}
|
||||
|
||||
queuedViews.Add(image);
|
||||
return new Span[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
var spans = link.SelectMany(x => CreateSpans(x, this.Theme.Link.FontFamily ?? family, this.Theme.Link.Attributes, this.Theme.Link.ForegroundColor, this.Theme.Link.BackgroundColor, size)).ToArray();
|
||||
links.Add(new KeyValuePair<string, string>(string.Join("",spans.Select(x => x.Text)), url));
|
||||
return spans;
|
||||
}
|
||||
|
||||
case CodeInline code:
|
||||
return new[]
|
||||
{
|
||||
new Span()
|
||||
{
|
||||
Text="\u2002",
|
||||
FontSize = size,
|
||||
FontFamily = this.Theme.Code.FontFamily,
|
||||
ForegroundColor = this.Theme.Code.ForegroundColor,
|
||||
BackgroundColor = this.Theme.Code.BackgroundColor
|
||||
},
|
||||
new Span
|
||||
{
|
||||
Text = code.Content,
|
||||
FontAttributes = this.Theme.Code.Attributes,
|
||||
FontSize = size,
|
||||
FontFamily = this.Theme.Code.FontFamily,
|
||||
ForegroundColor = this.Theme.Code.ForegroundColor,
|
||||
BackgroundColor = this.Theme.Code.BackgroundColor
|
||||
},
|
||||
new Span()
|
||||
{
|
||||
Text="\u2002",
|
||||
FontSize = size,
|
||||
FontFamily = this.Theme.Code.FontFamily,
|
||||
ForegroundColor = this.Theme.Code.ForegroundColor,
|
||||
BackgroundColor = this.Theme.Code.BackgroundColor
|
||||
},
|
||||
};
|
||||
|
||||
default:
|
||||
Debug.WriteLine($"Can't render {inline.GetType()} inlines.");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
xmlns:tools="clr-namespace:AideDeJeu.Tools"
|
||||
xmlns:skia="clr-namespace:SkiaSharp.Views.Forms;assembly=SkiaSharp.Views.Forms"
|
||||
xmlns:mdview="clr-namespace:Xam.Forms.Markdown;assembly=Xam.Forms.MarkdownView"
|
||||
xmlns:mdview="clr-namespace:Xam.Forms.Markdown"
|
||||
x:Class="AideDeJeu.Views.MonsterDetailPage"
|
||||
Title="{Binding Title}">
|
||||
<ContentPage.Resources>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
xmlns:tools="clr-namespace:AideDeJeu.Tools"
|
||||
xmlns:mdview="clr-namespace:Xam.Forms.Markdown;assembly=Xam.Forms.MarkdownView"
|
||||
xmlns:mdview="clr-namespace:Xam.Forms.Markdown"
|
||||
x:Class="AideDeJeu.Views.SpellDetailPage"
|
||||
Title="{Binding Title}">
|
||||
<ContentPage.Resources>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue