├── Documentation
├── Screenshot.png
├── Screenshot_dark.png
├── Screenshot_light.png
└── wiki
│ ├── youtube_preview.png
│ └── link_actionsheet.png
├── .github
└── FUNDING.yml
├── Sources
├── iOS
│ ├── Assets.xcassets
│ │ ├── Contents.json
│ │ └── AppIcon.appiconset
│ │ │ └── Contents.json
│ ├── Entitlements.plist
│ ├── Main.cs
│ ├── AppDelegate.cs
│ ├── LaunchScreen.storyboard
│ ├── Info.plist
│ ├── packages.config
│ └── Markdown.Samples.iOS.csproj
├── Droid
│ ├── Resources
│ │ ├── drawable
│ │ │ └── icon.png
│ │ ├── drawable-hdpi
│ │ │ └── icon.png
│ │ ├── drawable-xhdpi
│ │ │ └── icon.png
│ │ ├── drawable-xxhdpi
│ │ │ └── icon.png
│ │ ├── layout
│ │ │ ├── Toolbar.axml
│ │ │ └── Tabbar.axml
│ │ ├── values
│ │ │ └── styles.xml
│ │ └── AboutResources.txt
│ ├── Properties
│ │ ├── AndroidManifest.xml
│ │ └── AssemblyInfo.cs
│ ├── Assets
│ │ └── AboutAssets.txt
│ ├── MainActivity.cs
│ ├── packages.config
│ └── Markdown.Samples.Droid.csproj
├── Markdown.Samples
│ ├── FodyWeavers.xml
│ ├── App.xaml
│ ├── packages.config
│ ├── Controls
│ │ ├── SettingsCard.xaml.cs
│ │ └── SettingsCard.xaml
│ ├── ViewModels
│ │ ├── BaseViewModel.cs
│ │ ├── SettingsCardViewModel.cs
│ │ ├── SettingsItemViewModel.cs
│ │ └── SamplePageViewModel.cs
│ ├── App.xaml.cs
│ ├── Utils
│ │ └── LayoutOptionsWrapper.cs
│ ├── Views
│ │ ├── SamplesPage.xaml.cs
│ │ └── SamplesPage.xaml
│ ├── Selectors
│ │ └── SettingsItemSelector.cs
│ ├── Markdown.Samples.csproj
│ └── FodyWeavers.xsd
├── Markdown.Portable
│ ├── VideoPreviewDescriptor.cs
│ ├── packages.config
│ ├── Xam.Forms.Markdown.nuspec
│ ├── MarkdownStyle.cs
│ ├── Extensions
│ │ ├── GithubExtensions.cs
│ │ └── ImageExtensions.cs
│ ├── LinkStyle.cs
│ ├── ListStyle.cs
│ ├── Xam.Forms.Markdown.csproj
│ ├── MarkdownTheme.cs
│ └── MarkdownView.cs
├── Settings.XamlStyler
├── .editorconfig
└── MarkdownView.sln
├── LICENSE
├── README.md
├── CHANGELOG.md
└── .gitignore
/Documentation/Screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bares43/MarkdownView/HEAD/Documentation/Screenshot.png
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | custom: https://www.buymeacoffee.com/bares43
4 |
--------------------------------------------------------------------------------
/Documentation/Screenshot_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bares43/MarkdownView/HEAD/Documentation/Screenshot_dark.png
--------------------------------------------------------------------------------
/Sources/iOS/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Documentation/Screenshot_light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bares43/MarkdownView/HEAD/Documentation/Screenshot_light.png
--------------------------------------------------------------------------------
/Documentation/wiki/youtube_preview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bares43/MarkdownView/HEAD/Documentation/wiki/youtube_preview.png
--------------------------------------------------------------------------------
/Documentation/wiki/link_actionsheet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bares43/MarkdownView/HEAD/Documentation/wiki/link_actionsheet.png
--------------------------------------------------------------------------------
/Sources/Droid/Resources/drawable/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bares43/MarkdownView/HEAD/Sources/Droid/Resources/drawable/icon.png
--------------------------------------------------------------------------------
/Sources/Droid/Resources/drawable-hdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bares43/MarkdownView/HEAD/Sources/Droid/Resources/drawable-hdpi/icon.png
--------------------------------------------------------------------------------
/Sources/Droid/Resources/drawable-xhdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bares43/MarkdownView/HEAD/Sources/Droid/Resources/drawable-xhdpi/icon.png
--------------------------------------------------------------------------------
/Sources/Droid/Resources/drawable-xxhdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bares43/MarkdownView/HEAD/Sources/Droid/Resources/drawable-xxhdpi/icon.png
--------------------------------------------------------------------------------
/Sources/Markdown.Samples/FodyWeavers.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Sources/iOS/Entitlements.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/Sources/Markdown.Portable/VideoPreviewDescriptor.cs:
--------------------------------------------------------------------------------
1 | namespace Xam.Forms.Markdown
2 | {
3 | public class VideoPreviewDescriptor
4 | {
5 | public string Code { get; set; }
6 | public string VideoUrl { get; set; }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/Sources/Markdown.Samples/App.xaml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/Sources/Droid/Resources/layout/Toolbar.axml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/Sources/Droid/Properties/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Sources/iOS/Main.cs:
--------------------------------------------------------------------------------
1 | using UIKit;
2 |
3 | namespace MarkdownView.Samples.iOS
4 | {
5 | public class Application
6 | {
7 | // This is the main entry point of the application.
8 | static void Main(string[] args)
9 | {
10 | // if you want to use a different Application Delegate class from "AppDelegate"
11 | // you can specify it here.
12 | UIApplication.Main(args, null, "AppDelegate");
13 | }
14 | }
15 | }
--------------------------------------------------------------------------------
/Sources/Markdown.Samples/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/Sources/Markdown.Portable/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/Sources/Droid/Resources/layout/Tabbar.axml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/Sources/Markdown.Samples/Controls/SettingsCard.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | using Xamarin.Forms;
8 | using Xamarin.Forms.Xaml;
9 |
10 | namespace Markdown.Samples.Controls
11 | {
12 | [XamlCompilation(XamlCompilationOptions.Compile)]
13 | public partial class SettingsCard : ContentView
14 | {
15 | public SettingsCard()
16 | {
17 | InitializeComponent();
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/Sources/Markdown.Samples/ViewModels/BaseViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Text;
5 |
6 | namespace Markdown.Samples.ViewModels
7 | {
8 | public class BaseViewModel : INotifyPropertyChanged
9 | {
10 | public event PropertyChangedEventHandler PropertyChanged;
11 |
12 | public void RaisePropertyChanged(string propertyName)
13 | {
14 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Sources/iOS/AppDelegate.cs:
--------------------------------------------------------------------------------
1 | using Foundation;
2 | using UIKit;
3 |
4 | namespace MarkdownView.Samples.iOS
5 | {
6 | [Register("AppDelegate")]
7 | public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
8 | {
9 | public override bool FinishedLaunching(UIApplication app, NSDictionary options)
10 | {
11 | global::Xamarin.Forms.Forms.Init();
12 |
13 | LoadApplication(new App());
14 |
15 | return base.FinishedLaunching(app, options);
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/Sources/Droid/Assets/AboutAssets.txt:
--------------------------------------------------------------------------------
1 | Any raw assets you want to be deployed with your application can be placed in
2 | this directory (and child directories) and given a Build Action of "AndroidAsset".
3 |
4 | These files will be deployed with your package and will be accessible using Android's
5 | AssetManager, like this:
6 |
7 | public class ReadAsset : Activity
8 | {
9 | protected override void OnCreate (Bundle bundle)
10 | {
11 | base.OnCreate (bundle);
12 |
13 | InputStream input = Assets.Open ("my_asset.txt");
14 | }
15 | }
16 |
17 | Additionally, some Android functions will automatically load asset files:
18 |
19 | Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf");
20 |
--------------------------------------------------------------------------------
/Sources/Markdown.Samples/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using Markdown.Samples.Views;
2 | using Xamarin.Forms;
3 |
4 | namespace MarkdownView.Samples
5 | {
6 | public partial class App : Application
7 | {
8 | public App()
9 | {
10 | InitializeComponent();
11 |
12 | MainPage = new SamplesPage();
13 | }
14 |
15 | protected override void OnStart()
16 | {
17 | // Handle when your app starts
18 | }
19 |
20 | protected override void OnSleep()
21 | {
22 | // Handle when your app sleeps
23 | }
24 |
25 | protected override void OnResume()
26 | {
27 | // Handle when your app resumes
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Sources/Markdown.Portable/Xam.Forms.Markdown.nuspec:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Xam.Forms.Markdown
5 | 1.5.2
6 | Xam.Forms.Markdown
7 | bares43
8 | bares43
9 | https://github.com/bares43/MarkdownView
10 | false
11 | Actively developed (2021) native markdown rendering for Xamarin.Forms.
12 |
13 | https://github.com/bares43/MarkdownView/blob/dev/CHANGELOG.md
14 |
15 | Copyright 2021
16 | xamarin ios android md markdown native xamarin.forms
17 |
18 |
--------------------------------------------------------------------------------
/Sources/Markdown.Samples/Utils/LayoutOptionsWrapper.cs:
--------------------------------------------------------------------------------
1 | using Xamarin.Forms;
2 |
3 | namespace Markdown.Samples.Utils
4 | {
5 | public class LayoutOptionsWrapper
6 | {
7 | public LayoutOptions LayoutOptions { get; }
8 |
9 | public LayoutOptionsWrapper(LayoutOptions layoutOptions)
10 | {
11 | LayoutOptions = layoutOptions;
12 | }
13 | public override string ToString()
14 | {
15 | var name = LayoutOptions.Alignment.ToString();
16 |
17 | if (LayoutOptions.Expands)
18 | {
19 | name += "AndExpand";
20 | }
21 |
22 | return name;
23 | }
24 |
25 | public override bool Equals(object obj) => LayoutOptions.Equals((obj as LayoutOptionsWrapper).LayoutOptions);
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Sources/Droid/MainActivity.cs:
--------------------------------------------------------------------------------
1 | using Android.App;
2 | using Android.Content.PM;
3 | using Android.OS;
4 |
5 | namespace MarkdownView.Samples.Droid
6 | {
7 | [Activity(Label = "MarkdownView.Samples.Droid", Icon = "@drawable/icon", Theme = "@style/MyTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
8 | public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
9 | {
10 | protected override void OnCreate(Bundle bundle)
11 | {
12 | TabLayoutResource = Resource.Layout.Tabbar;
13 | ToolbarResource = Resource.Layout.Toolbar;
14 |
15 | base.OnCreate(bundle);
16 |
17 | global::Xamarin.Forms.Forms.Init(this, bundle);
18 |
19 | LoadApplication(new App());
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Sources/Markdown.Samples/ViewModels/SettingsCardViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Collections.ObjectModel;
4 | using System.Text;
5 | using System.Windows.Input;
6 | using Xamarin.Forms;
7 |
8 | namespace Markdown.Samples.ViewModels
9 | {
10 | public class SettingsCardViewModel : BaseViewModel
11 | {
12 | public string Name { get; set; }
13 | public bool IsOpened { get; set; }
14 | public ICommand ToggleCommand { get; set; }
15 | public ObservableCollection Items { get; set; } = new ObservableCollection();
16 |
17 | public SettingsCardViewModel(string name)
18 | {
19 | Name = name;
20 | ToggleCommand = new Command(() =>
21 | {
22 | IsOpened = !IsOpened;
23 | });
24 | }
25 |
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Sources/Markdown.Portable/MarkdownStyle.cs:
--------------------------------------------------------------------------------
1 | namespace Xam.Forms.Markdown
2 | {
3 | using Xamarin.Forms;
4 |
5 | public class MarkdownStyle
6 | {
7 | public FontAttributes Attributes { get; set; } = FontAttributes.None;
8 |
9 | public float FontSize { get; set; } = 12;
10 |
11 | public float LineHeight { get; set; } = -1;
12 |
13 | public Color ForegroundColor { get; set; } = Color.Black;
14 |
15 | public Color BackgroundColor { get; set; } = Color.Transparent;
16 |
17 | public Color BorderColor { get; set; }
18 |
19 | public float BorderSize { get; set; }
20 |
21 | public string FontFamily { get; set; }
22 |
23 | public TextAlignment HorizontalTextAlignment { get; set; } = TextAlignment.Start;
24 | public TextAlignment VerticalTextAlignment { get; set; } = TextAlignment.Center;
25 |
26 | public TextDecorations TextDecorations { get; set; } = TextDecorations.None;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Sources/Droid/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 |
3 | // Information about this assembly is defined by the following attributes.
4 | // Change them to the values specific to your project.
5 |
6 | [assembly: AssemblyTitle("MarkdownView.Samples.Droid")]
7 | [assembly: AssemblyDescription("")]
8 | [assembly: AssemblyConfiguration("")]
9 | [assembly: AssemblyCompany("")]
10 | [assembly: AssemblyProduct("")]
11 | [assembly: AssemblyCopyright("${AuthorCopyright}")]
12 | [assembly: AssemblyTrademark("")]
13 | [assembly: AssemblyCulture("")]
14 |
15 | // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
16 | // The form "{Major}.{Minor}.*" will automatically update the build and revision,
17 | // and "{Major}.{Minor}.{Build}.*" will update just the revision.
18 |
19 | [assembly: AssemblyVersion("1.0.0")]
20 |
21 | // The following attributes are used to specify the signing key for the assembly,
22 | // if desired. See the Mono documentation for more information about signing.
23 |
24 | //[assembly: AssemblyDelaySign(false)]
25 | //[assembly: AssemblyKeyFile("")]
26 |
--------------------------------------------------------------------------------
/Sources/Markdown.Samples/Views/SamplesPage.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | using Xamarin.Forms;
8 | using Xamarin.Forms.Xaml;
9 |
10 | namespace Markdown.Samples.Views
11 | {
12 | [XamlCompilation(XamlCompilationOptions.Compile)]
13 | public partial class SamplesPage : ContentPage
14 | {
15 | public SamplesPage()
16 | {
17 | InitializeComponent();
18 | }
19 |
20 | private void SettingsButton_Clicked(object sender, EventArgs e)
21 | {
22 | Device.BeginInvokeOnMainThread(async () =>
23 | {
24 | await scrollView.ScrollToAsync(settings, ScrollToPosition.Start, true);
25 | });
26 | }
27 |
28 | private void SourceButton_Clicked(object sender, EventArgs e)
29 | {
30 | Device.BeginInvokeOnMainThread(async () =>
31 | {
32 | await scrollView.ScrollToAsync(source, ScrollToPosition.Start, true);
33 | });
34 | }
35 | }
36 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Aloïs Deniel
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Sources/Markdown.Portable/Extensions/GithubExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace Xam.Forms.Markdown
2 | {
3 | using System.Text.RegularExpressions;
4 |
5 | ///
6 | /// A set o helper extensions for parsing Github common urls.
7 | ///
8 | public static class GithubExtensions
9 | {
10 | static readonly Regex githubRepoRegex = new Regex("http(s)?:\\/\\/github.com\\/([a-zA-Z0-9_-]+)\\/([a-zA-Z0-9_-]+)\\/((blob|tree)\\/([a-zA-Z0-9_-]+))?");
11 |
12 | const string githubReadmeUrl = "https://raw.githubusercontent.com/{0}/{1}/{2}/README.md";
13 |
14 | public static bool TryExtractGithubRawMarkdownUrl(string url, out string readmeUrl)
15 | {
16 | var match = githubRepoRegex.Match(url);
17 | if (match.Success)
18 | {
19 | var user = match.Groups[2].Value;
20 | var repo = match.Groups[3].Value;
21 | var branch = match.Groups.Count > 6 ? match.Groups[6].Value : "master";
22 | readmeUrl = string.Format(githubReadmeUrl, user, repo, branch);
23 | return true;
24 | }
25 |
26 | readmeUrl = null;
27 | return false;
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Sources/Markdown.Portable/LinkStyle.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using Xamarin.Forms;
5 |
6 | namespace Xam.Forms.Markdown
7 | {
8 | public class LinkStyle : MarkdownStyle
9 | {
10 | public string OpenLinkSheetTitle { get; set; } = "Open link";
11 | public string OpenLinkSheetCancel { get; set; } = "Cancel";
12 | public Action> CustomTapHandler { get; set; }
13 | public List ExternalProtocols = new List { "http://", "https://", "mailto:", "tel:" };
14 | public bool LoadYouTubePreview { get; set; }
15 | public YouTubePreview YouTubePreview { get; set; }
16 | public bool UseAutolinksExtension { get; set; }
17 | }
18 |
19 | public class LinkData
20 | {
21 | public string Text { get; set; }
22 | public string Link { get; set; }
23 | }
24 |
25 | public class YouTubePreview
26 | {
27 | public Func GenerateLoadImageUrl { get; set; }
28 | public Func CustomLoadImage { get; set; }
29 | public Func TransformView { get; set; }
30 | }
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/Sources/Markdown.Portable/ListStyle.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Markdig.Syntax;
3 | using Xamarin.Forms;
4 |
5 | namespace Xam.Forms.Markdown
6 | {
7 | public class ListStyle
8 | {
9 | public float Indentation { get; set; } = 10;
10 | public float? Spacing { get; set; }
11 | public float ItemsVerticalSpacing { get; set; } = 10;
12 | public Thickness ListMargin { get; set; } = new Thickness(0);
13 | public ListStyleType BulletStyleType { get; set; }
14 | public int BulletSize { get; set; } = 4;
15 | public float? BulletFontSize { get; set; }
16 | public float? BulletLineHeight { get; set; }
17 | public Color? BulletColor { get; set; }
18 | public FontAttributes BulletFontAttributes { get; set; } = FontAttributes.None;
19 | public LayoutOptions BulletVerticalOptions { get; set; }
20 | public LayoutOptions ItemVerticalOptions { get; set; }
21 | public string Symbol { get; set; }
22 | public Func CustomCallback { get; set; }
23 | }
24 |
25 | public enum ListStyleType
26 | {
27 | Square,
28 | Circle,
29 | None,
30 | Symbol,
31 | Decimal,
32 | Custom
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/Sources/Markdown.Samples/Selectors/SettingsItemSelector.cs:
--------------------------------------------------------------------------------
1 | using Markdown.Samples.ViewModels;
2 | using Xamarin.Forms;
3 |
4 | namespace Markdown.Samples.Selectors
5 | {
6 | public class SettingsItemSelector : DataTemplateSelector
7 | {
8 | protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
9 | {
10 | var list = (StackLayout)container;
11 |
12 | if (item is SwitchSettingsItemViewModel)
13 | {
14 | return (DataTemplate)list.Resources["Switch"];
15 | }
16 |
17 | if (item is EntrySettingsItemViewModel)
18 | {
19 | return (DataTemplate)list.Resources["Entry"];
20 | }
21 |
22 | if (item is StepperSettingsItemViewModel)
23 | {
24 | return (DataTemplate)list.Resources["Stepper"];
25 | }
26 |
27 | if (item is PickerSettingsViewModel)
28 | {
29 | return (DataTemplate)list.Resources["Picker"];
30 | }
31 |
32 | if (item is EditorSettingsItemViewModel)
33 | {
34 | return (DataTemplate)list.Resources["Editor"];
35 | }
36 |
37 | return null;
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Sources/Droid/Resources/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
24 |
27 |
28 |
--------------------------------------------------------------------------------
/Sources/iOS/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/Sources/iOS/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDisplayName
6 | MarkdownView
7 | CFBundleName
8 | MarkdownView
9 | CFBundleIdentifier
10 | com.MarkdownView
11 | CFBundleShortVersionString
12 | 1.0
13 | CFBundleVersion
14 | 1.0
15 | LSRequiresIPhoneOS
16 |
17 | MinimumOSVersion
18 | 8.0
19 | UIDeviceFamily
20 |
21 | 1
22 | 2
23 |
24 | UILaunchStoryboardName
25 | LaunchScreen
26 | UIRequiredDeviceCapabilities
27 |
28 | armv7
29 |
30 | UISupportedInterfaceOrientations
31 |
32 | UIInterfaceOrientationPortrait
33 | UIInterfaceOrientationLandscapeLeft
34 | UIInterfaceOrientationLandscapeRight
35 |
36 | UISupportedInterfaceOrientations~ipad
37 |
38 | UIInterfaceOrientationPortrait
39 | UIInterfaceOrientationPortraitUpsideDown
40 | UIInterfaceOrientationLandscapeLeft
41 | UIInterfaceOrientationLandscapeRight
42 |
43 | XSAppIconAssets
44 | Assets.xcassets/AppIcon.appiconset
45 |
46 |
47 |
--------------------------------------------------------------------------------
/Sources/Markdown.Samples/Markdown.Samples.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | netstandard2.0
6 |
7 |
8 |
9 |
10 | all
11 | runtime; build; native; contentfiles; analyzers; buildtransitive
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | App.xaml
25 |
26 |
27 | SamplesPage.xaml
28 |
29 |
30 |
31 |
32 |
33 | MSBuild:UpdateDesignTimeXaml
34 |
35 |
36 | MSBuild:UpdateDesignTimeXaml
37 |
38 |
39 | MSBuild:UpdateDesignTimeXaml
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/Sources/Markdown.Portable/Xam.Forms.Markdown.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | netstandard2.0
6 |
7 |
8 |
9 | 0.0.0.0
10 | 0.0.0.0
11 | 1.0.0.0
12 | 0.0.0.0
13 | $(AssemblyName) ($(TargetFramework))
14 | bares43
15 | Xam.Forms.Markdown
16 | MarkdownView for Xamarin.Forms
17 | Native markdown rendering for Xamarin.Forms.
18 | Native markdown rendering for Xamarin.Forms.
19 | xamarin, ios, android, md, markdown, native, xamarin.forms
20 | Aloïs Deniel
21 | true
22 | en
23 | https://raw.githubusercontent.com/aloisdeniel/MarkdownView/master/Documentation/Logo.png
24 | https://github.com/aloisdeniel/MarkdownView/blob/master/LICENSE
25 | https://github.com/bares43/MarkdownView
26 | Xam.Forms.Markdown
27 | Xam.Forms.Markdown
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/Sources/Droid/Resources/AboutResources.txt:
--------------------------------------------------------------------------------
1 | Images, layout descriptions, binary blobs and string dictionaries can be included
2 | in your application as resource files. Various Android APIs are designed to
3 | operate on the resource IDs instead of dealing with images, strings or binary blobs
4 | directly.
5 |
6 | For example, a sample Android app that contains a user interface layout (main.axml),
7 | an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png)
8 | would keep its resources in the "Resources" directory of the application:
9 |
10 | Resources/
11 | drawable/
12 | icon.png
13 |
14 | layout/
15 | main.axml
16 |
17 | values/
18 | strings.xml
19 |
20 | In order to get the build system to recognize Android resources, set the build action to
21 | "AndroidResource". The native Android APIs do not operate directly with filenames, but
22 | instead operate on resource IDs. When you compile an Android application that uses resources,
23 | the build system will package the resources for distribution and generate a class called "R"
24 | (this is an Android convention) that contains the tokens for each one of the resources
25 | included. For example, for the above Resources layout, this is what the R class would expose:
26 |
27 | public class R {
28 | public class drawable {
29 | public const int icon = 0x123;
30 | }
31 |
32 | public class layout {
33 | public const int main = 0x456;
34 | }
35 |
36 | public class strings {
37 | public const int first_string = 0xabc;
38 | public const int second_string = 0xbcd;
39 | }
40 | }
41 |
42 | You would then use R.drawable.icon to reference the drawable/icon.png file, or R.layout.main
43 | to reference the layout/main.axml file, or R.strings.first_string to reference the first
44 | string in the dictionary file values/strings.xml.
45 |
--------------------------------------------------------------------------------
/Sources/Markdown.Portable/Extensions/ImageExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace Xam.Forms.Markdown.Extensions
2 | {
3 | using System;
4 | using System.Diagnostics;
5 | using System.IO;
6 | using System.Net;
7 | using SkiaSharp;
8 | using Xamarin.Forms;
9 |
10 | public static class ImageExtensions
11 | {
12 | public static void RenderSvg(this Image view, string uri)
13 | {
14 | try
15 | {
16 | var req = (HttpWebRequest)WebRequest.Create(uri);
17 |
18 | var svg = new SkiaSharp.Extended.Svg.SKSvg();
19 | req.BeginGetResponse((ar) =>
20 | {
21 | var res = (ar.AsyncState as HttpWebRequest).EndGetResponse(ar) as HttpWebResponse;
22 | using (var stream = res.GetResponseStream())
23 | {
24 | if (stream != null)
25 | {
26 | var picture = svg.Load(stream);
27 |
28 | using (var image = SKImage.FromPicture(picture, picture.CullRect.Size.ToSizeI()))
29 | using (var data = image.Encode(SKEncodedImageFormat.Jpeg, 80))
30 | {
31 | var ms = new MemoryStream();
32 |
33 | if (data != null && !data.IsEmpty)
34 | {
35 | data.SaveTo(ms);
36 | ms.Seek(0, SeekOrigin.Begin);
37 | ms.Position = 0;
38 | view.Source = ImageSource.FromStream(() => ms);
39 | }
40 | }
41 | }
42 | }
43 | }, req);
44 |
45 | }
46 | catch (Exception ex)
47 | {
48 | Debug.WriteLine($"Failed to render svg: {ex}");
49 | }
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/Sources/Settings.XamlStyler:
--------------------------------------------------------------------------------
1 | {
2 | "AttributesTolerance": 2,
3 | "KeepFirstAttributeOnSameLine": false,
4 | "MaxAttributeCharactersPerLine": 0,
5 | "MaxAttributesPerLine": 1,
6 | "NewlineExemptionElements": "RadialGradientBrush, GradientStop, LinearGradientBrush, ScaleTransform, SkewTransform, RotateTransform, TranslateTransform, Trigger, Condition, Setter",
7 | "SeparateByGroups": false,
8 | "AttributeIndentation": 0,
9 | "AttributeIndentationStyle": 1,
10 | "RemoveDesignTimeReferences": false,
11 | "EnableAttributeReordering": true,
12 | "AttributeOrderingRuleGroups": [
13 | "x:Class",
14 | "xmlns, xmlns:x, xmlns:d, xmlns:mc, mc:Ignorable",
15 | "xmlns:*",
16 | "prism:*",
17 | "x:Key, Key, x:Name, Name, x:Uid, Uid, Title, ControlTemplate",
18 | "Grid.Row, Grid.RowSpan, Grid.Column, Grid.ColumnSpan, RowSpacing, ColumnSpacing, Spacing, AbsoluteLayout.LayoutFlags, AbsoluteLayout.LayoutBounds",
19 | "BindingContext",
20 | "Text, Command, CommandParameter",
21 | "IsRefreshing, RefreshColor",
22 | "BindableLayout.ItemsSource, BindableLayout.ItemTemplateSelector",
23 | "IsVisible, WidthRequest, HeightRequest, MinimumWidthRequest, MinimumHeightRequest",
24 | "Margin, Padding, HorizontalOptions, VerticalOptions, HorizontalTextAlignment, VerticalTextAlignment",
25 | "FontSize, TextColor, BackgroundColor, CornerRadius",
26 | "*:*, *"
27 | ],
28 | "FirstLineAttributes": "x:Name, AutomationId",
29 | "OrderAttributesByName": true,
30 | "PutEndingBracketOnNewLine": false,
31 | "RemoveEndingTagOfEmptyElement": true,
32 | "SpaceBeforeClosingSlash": true,
33 | "RootElementLineBreakRule": 0,
34 | "ReorderVSM": 2,
35 | "ReorderGridChildren": true,
36 | "ReorderCanvasChildren": false,
37 | "ReorderSetters": 0,
38 | "FormatMarkupExtension": true,
39 | "NoNewLineMarkupExtensions": "x:Bind, Binding",
40 | "ThicknessSeparator": 2,
41 | "ThicknessAttributes": "Margin, Padding, BorderThickness, ThumbnailClipMargin",
42 | "FormatOnSave": true,
43 | "CommentPadding": 2,
44 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Markdown *for Xamarin.Forms*
2 |
3 | [](https://www.nuget.org/packages/Xam.Forms.Markdown/) [](https://www.buymeacoffee.com/bares43)
4 | You can also support author of original package here [](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=ZJZKXPPGBKKAY&lc=US&item_name=GitHub&item_number=0000001¤cy_code=USD&bn=PP%2dDonationsBF%3abtn_donate_SM%2egif%3aNonHosted)
5 |
6 | A native Xamarin.Forms Markdown renderer.
7 |
8 | Fork of original repository https://github.com/dotnet-ad/MarkdownView with some improvements.
9 |
10 | ## Gallery
11 |
12 | 
13 |
14 | ## Introduction
15 |
16 | Compared to a majority of solutions, MarkdownView will render every component as **a native Xamarin.Forms view instead of via an HTML backend.** The Markdown is directly translated from a syntax tree to a hierarchy of Xamarin.Forms views, : no HTML is being produced at all (hurray)!
17 |
18 | This will produce a more reactive user interface, at the cost of rendering functionalities *(at the moment though!)*.
19 |
20 | ## Install
21 |
22 | Available on [NuGet](https://www.nuget.org/packages/Xam.Forms.Markdown/).
23 |
24 | ## Quickstart
25 |
26 | See [documentation](https://github.com/bares43/MarkdownView/wiki#basic-usage).
27 |
28 | ## Thanks
29 |
30 | * [dotnet-ad/MarkdownView](https://github.com/dotnet-ad/MarkdownView) : original package
31 | * [lunet-io/markdig](https://github.com/lunet-io/markdig) : used for Markdown parsing
32 | * [mono/SkiaSharp](https://github.com/mono/SkiaSharp) : used for SVG rendering
33 |
34 | ## Contributions
35 |
36 | Contributions are welcome! If you find a bug please report it and if you want a feature please report it.
37 |
38 | If you want to contribute code please file an issue and create a branch off of the current dev branch and file a pull request.
39 |
40 | ## License
41 |
42 | MIT © [bares43](https://janbares.cz/en/), [Aloïs Deniel](http://aloisdeniel.github.io)
43 |
--------------------------------------------------------------------------------
/Sources/Markdown.Samples/Views/SamplesPage.xaml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/Sources/iOS/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images": [
3 | {
4 | "idiom": "iphone",
5 | "size": "29x29",
6 | "scale": "1x"
7 | },
8 | {
9 | "idiom": "iphone",
10 | "size": "29x29",
11 | "scale": "2x"
12 | },
13 | {
14 | "idiom": "iphone",
15 | "size": "29x29",
16 | "scale": "3x"
17 | },
18 | {
19 | "idiom": "iphone",
20 | "size": "40x40",
21 | "scale": "2x"
22 | },
23 | {
24 | "idiom": "iphone",
25 | "size": "40x40",
26 | "scale": "3x"
27 | },
28 | {
29 | "idiom": "iphone",
30 | "size": "57x57",
31 | "scale": "1x"
32 | },
33 | {
34 | "idiom": "iphone",
35 | "size": "57x57",
36 | "scale": "2x"
37 | },
38 | {
39 | "idiom": "iphone",
40 | "size": "60x60",
41 | "scale": "2x"
42 | },
43 | {
44 | "idiom": "iphone",
45 | "size": "60x60",
46 | "scale": "3x"
47 | },
48 | {
49 | "idiom": "ipad",
50 | "size": "29x29",
51 | "scale": "1x"
52 | },
53 | {
54 | "idiom": "ipad",
55 | "size": "29x29",
56 | "scale": "2x"
57 | },
58 | {
59 | "idiom": "ipad",
60 | "size": "40x40",
61 | "scale": "1x"
62 | },
63 | {
64 | "idiom": "ipad",
65 | "size": "40x40",
66 | "scale": "2x"
67 | },
68 | {
69 | "idiom": "ipad",
70 | "size": "50x50",
71 | "scale": "1x"
72 | },
73 | {
74 | "idiom": "ipad",
75 | "size": "50x50",
76 | "scale": "2x"
77 | },
78 | {
79 | "idiom": "ipad",
80 | "size": "72x72",
81 | "scale": "1x"
82 | },
83 | {
84 | "idiom": "ipad",
85 | "size": "72x72",
86 | "scale": "2x"
87 | },
88 | {
89 | "idiom": "ipad",
90 | "size": "76x76",
91 | "scale": "1x"
92 | },
93 | {
94 | "idiom": "ipad",
95 | "size": "76x76",
96 | "scale": "2x"
97 | },
98 | {
99 | "size": "24x24",
100 | "idiom": "watch",
101 | "scale": "2x",
102 | "role": "notificationCenter",
103 | "subtype": "38mm"
104 | },
105 | {
106 | "size": "27.5x27.5",
107 | "idiom": "watch",
108 | "scale": "2x",
109 | "role": "notificationCenter",
110 | "subtype": "42mm"
111 | },
112 | {
113 | "size": "29x29",
114 | "idiom": "watch",
115 | "role": "companionSettings",
116 | "scale": "2x"
117 | },
118 | {
119 | "size": "29x29",
120 | "idiom": "watch",
121 | "role": "companionSettings",
122 | "scale": "3x"
123 | },
124 | {
125 | "size": "40x40",
126 | "idiom": "watch",
127 | "scale": "2x",
128 | "role": "appLauncher",
129 | "subtype": "38mm"
130 | },
131 | {
132 | "size": "44x44",
133 | "idiom": "watch",
134 | "scale": "2x",
135 | "role": "longLook",
136 | "subtype": "42mm"
137 | },
138 | {
139 | "size": "86x86",
140 | "idiom": "watch",
141 | "scale": "2x",
142 | "role": "quickLook",
143 | "subtype": "38mm"
144 | },
145 | {
146 | "size": "98x98",
147 | "idiom": "watch",
148 | "scale": "2x",
149 | "role": "quickLook",
150 | "subtype": "42mm"
151 | }
152 | ],
153 | "info": {
154 | "version": 1,
155 | "author": "xcode"
156 | }
157 | }
--------------------------------------------------------------------------------
/Sources/Markdown.Samples/Controls/SettingsCard.xaml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
10 |
15 |
16 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
--------------------------------------------------------------------------------
/Sources/Markdown.Samples/ViewModels/SettingsItemViewModel.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace Markdown.Samples.ViewModels
6 | {
7 | public abstract class SettingsItemViewModel : BaseViewModel
8 | {
9 | protected readonly SamplePageViewModel vm;
10 | public string Label { get; set; }
11 | public bool IsVisible { get; set; } = true;
12 | public SettingsItemViewModel(SamplePageViewModel vm, string label)
13 | {
14 | this.vm = vm;
15 | Label = label;
16 | }
17 | }
18 |
19 | public class SwitchSettingsItemViewModel : SettingsItemViewModel
20 | {
21 | public SwitchSettingsItemViewModel(SamplePageViewModel vm, string label) : base(vm, label)
22 | {
23 | }
24 |
25 | public bool IsToggled { get; set; }
26 |
27 | public Action Action { get; set; }
28 |
29 | public void OnIsToggledChanged()
30 | {
31 | Action?.Invoke(IsToggled);
32 | vm.RaisePropertyChanged(nameof(SamplePageViewModel.Theme));
33 | }
34 | }
35 |
36 | public class EntrySettingsItemViewModel : SettingsItemViewModel
37 | {
38 | public EntrySettingsItemViewModel(SamplePageViewModel vm, string label, string value) : base(vm, label)
39 | {
40 | Value = value;
41 | }
42 |
43 | public string Value { get; set; }
44 |
45 | public Action Action { get; set; }
46 |
47 | public void OnValueChanged()
48 | {
49 | Action?.Invoke(Value);
50 | vm.RaisePropertyChanged(nameof(SamplePageViewModel.Theme));
51 | }
52 | }
53 |
54 | public class EditorSettingsItemViewModel : SettingsItemViewModel
55 | {
56 | public EditorSettingsItemViewModel(SamplePageViewModel vm, string label, string value) : base(vm, label)
57 | {
58 | Value = value;
59 | }
60 |
61 | public string Value { get; set; }
62 |
63 | public Action Action { get; set; }
64 |
65 | public void OnValueChanged()
66 | {
67 | Action?.Invoke(Value);
68 | vm?.RaisePropertyChanged(nameof(SamplePageViewModel.Theme));
69 | }
70 | }
71 |
72 | public class StepperSettingsItemViewModel : SettingsItemViewModel
73 | {
74 | public StepperSettingsItemViewModel(SamplePageViewModel vm, string label, int defaultValue) : base(vm, label)
75 | {
76 | Value = defaultValue;
77 | }
78 |
79 | public int Value { get; set; }
80 |
81 | public Action Action { get; set; }
82 |
83 | public void OnValueChanged()
84 | {
85 | Action?.Invoke(Value);
86 | vm.RaisePropertyChanged(nameof(SamplePageViewModel.Theme));
87 | }
88 | }
89 |
90 | public class PickerSettingsViewModel : SettingsItemViewModel
91 | {
92 | public PickerSettingsViewModel(SamplePageViewModel vm, string label, List