├── .gitignore
├── Documentation
├── Screenshot.png
├── Screenshot_dark.png
└── Screenshot_light.png
├── LICENSE
├── README.md
└── Sources
├── Droid
├── Assets
│ └── AboutAssets.txt
├── MainActivity.cs
├── MarkdownView.Samples.Droid.csproj
├── Properties
│ ├── AndroidManifest.xml
│ └── AssemblyInfo.cs
├── Resources
│ ├── AboutResources.txt
│ ├── Resource.designer.cs
│ ├── drawable-hdpi
│ │ └── icon.png
│ ├── drawable-xhdpi
│ │ └── icon.png
│ ├── drawable-xxhdpi
│ │ └── icon.png
│ ├── drawable
│ │ └── icon.png
│ ├── layout
│ │ ├── Tabbar.axml
│ │ └── Toolbar.axml
│ └── values
│ │ └── styles.xml
└── packages.config
├── MarkdownView.Portable
├── Extensions
│ ├── GithubExtensions.cs
│ └── ImageExtensions.cs
├── MarkdownStyle.cs
├── MarkdownTheme.cs
├── MarkdownView.cs
├── Xam.Forms.MarkdownView.csproj
└── packages.config
├── MarkdownView.Samples
├── App.xaml
├── App.xaml.cs
├── MarkdownView.Samples.csproj
├── MarkdownView.SamplesPage.xaml
├── MarkdownView.SamplesPage.xaml.cs
├── MenuPage.xaml
├── MenuPage.xaml.cs
└── packages.config
├── MarkdownView.sln
└── iOS
├── AppDelegate.cs
├── Assets.xcassets
├── AppIcon.appiconset
│ └── Contents.json
└── Contents.json
├── Entitlements.plist
├── Info.plist
├── LaunchScreen.storyboard
├── Main.cs
├── MarkdownView.Samples.iOS.csproj
└── packages.config
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.suo
8 | *.user
9 | *.userosscache
10 | *.sln.docstates
11 |
12 | # User-specific files (MonoDevelop/Xamarin Studio)
13 | *.userprefs
14 |
15 | # Build results
16 | [Dd]ebug/
17 | [Dd]ebugPublic/
18 | [Rr]elease/
19 | [Rr]eleases/
20 | x64/
21 | x86/
22 | bld/
23 | [Bb]in/
24 | [Oo]bj/
25 | [Ll]og/
26 |
27 | # Visual Studio 2015 cache/options directory
28 | .vs/
29 | # Uncomment if you have tasks that create the project's static files in wwwroot
30 | #wwwroot/
31 |
32 | # MSTest test Results
33 | [Tt]est[Rr]esult*/
34 | [Bb]uild[Ll]og.*
35 |
36 | # NUNIT
37 | *.VisualState.xml
38 | TestResult.xml
39 |
40 | # Build Results of an ATL Project
41 | [Dd]ebugPS/
42 | [Rr]eleasePS/
43 | dlldata.c
44 |
45 | # .NET Core
46 | project.lock.json
47 | project.fragment.lock.json
48 | artifacts/
49 | **/Properties/launchSettings.json
50 |
51 | *_i.c
52 | *_p.c
53 | *_i.h
54 | *.ilk
55 | *.meta
56 | *.obj
57 | *.pch
58 | *.pdb
59 | *.pgc
60 | *.pgd
61 | *.rsp
62 | *.sbr
63 | *.tlb
64 | *.tli
65 | *.tlh
66 | *.tmp
67 | *.tmp_proj
68 | *.log
69 | *.vspscc
70 | *.vssscc
71 | .builds
72 | *.pidb
73 | *.svclog
74 | *.scc
75 |
76 | # Chutzpah Test files
77 | _Chutzpah*
78 |
79 | # Visual C++ cache files
80 | ipch/
81 | *.aps
82 | *.ncb
83 | *.opendb
84 | *.opensdf
85 | *.sdf
86 | *.cachefile
87 | *.VC.db
88 | *.VC.VC.opendb
89 |
90 | # Visual Studio profiler
91 | *.psess
92 | *.vsp
93 | *.vspx
94 | *.sap
95 |
96 | # TFS 2012 Local Workspace
97 | $tf/
98 |
99 | # Guidance Automation Toolkit
100 | *.gpState
101 |
102 | # ReSharper is a .NET coding add-in
103 | _ReSharper*/
104 | *.[Rr]e[Ss]harper
105 | *.DotSettings.user
106 |
107 | # JustCode is a .NET coding add-in
108 | .JustCode
109 |
110 | # TeamCity is a build add-in
111 | _TeamCity*
112 |
113 | # DotCover is a Code Coverage Tool
114 | *.dotCover
115 |
116 | # Visual Studio code coverage results
117 | *.coverage
118 | *.coveragexml
119 |
120 | # NCrunch
121 | _NCrunch_*
122 | .*crunch*.local.xml
123 | nCrunchTemp_*
124 |
125 | # MightyMoose
126 | *.mm.*
127 | AutoTest.Net/
128 |
129 | # Web workbench (sass)
130 | .sass-cache/
131 |
132 | # Installshield output folder
133 | [Ee]xpress/
134 |
135 | # DocProject is a documentation generator add-in
136 | DocProject/buildhelp/
137 | DocProject/Help/*.HxT
138 | DocProject/Help/*.HxC
139 | DocProject/Help/*.hhc
140 | DocProject/Help/*.hhk
141 | DocProject/Help/*.hhp
142 | DocProject/Help/Html2
143 | DocProject/Help/html
144 |
145 | # Click-Once directory
146 | publish/
147 |
148 | # Publish Web Output
149 | *.[Pp]ublish.xml
150 | *.azurePubxml
151 | # TODO: Comment the next line if you want to checkin your web deploy settings
152 | # but database connection strings (with potential passwords) will be unencrypted
153 | *.pubxml
154 | *.publishproj
155 |
156 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
157 | # checkin your Azure Web App publish settings, but sensitive information contained
158 | # in these scripts will be unencrypted
159 | PublishScripts/
160 |
161 | # NuGet Packages
162 | *.nupkg
163 | # The packages folder can be ignored because of Package Restore
164 | **/packages/*
165 | # except build/, which is used as an MSBuild target.
166 | !**/packages/build/
167 | # Uncomment if necessary however generally it will be regenerated when needed
168 | #!**/packages/repositories.config
169 | # NuGet v3's project.json files produces more ignorable files
170 | *.nuget.props
171 | *.nuget.targets
172 |
173 | # Microsoft Azure Build Output
174 | csx/
175 | *.build.csdef
176 |
177 | # Microsoft Azure Emulator
178 | ecf/
179 | rcf/
180 |
181 | # Windows Store app package directories and files
182 | AppPackages/
183 | BundleArtifacts/
184 | Package.StoreAssociation.xml
185 | _pkginfo.txt
186 |
187 | # Visual Studio cache files
188 | # files ending in .cache can be ignored
189 | *.[Cc]ache
190 | # but keep track of directories ending in .cache
191 | !*.[Cc]ache/
192 |
193 | # Others
194 | ClientBin/
195 | ~$*
196 | *~
197 | *.dbmdl
198 | *.dbproj.schemaview
199 | *.jfm
200 | *.pfx
201 | *.publishsettings
202 | orleans.codegen.cs
203 |
204 | # Since there are multiple workflows, uncomment next line to ignore bower_components
205 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
206 | #bower_components/
207 |
208 | # RIA/Silverlight projects
209 | Generated_Code/
210 |
211 | # Backup & report files from converting an old project file
212 | # to a newer Visual Studio version. Backup files are not needed,
213 | # because we have git ;-)
214 | _UpgradeReport_Files/
215 | Backup*/
216 | UpgradeLog*.XML
217 | UpgradeLog*.htm
218 |
219 | # SQL Server files
220 | *.mdf
221 | *.ldf
222 | *.ndf
223 |
224 | # Business Intelligence projects
225 | *.rdl.data
226 | *.bim.layout
227 | *.bim_*.settings
228 |
229 | # Microsoft Fakes
230 | FakesAssemblies/
231 |
232 | # GhostDoc plugin setting file
233 | *.GhostDoc.xml
234 |
235 | # Node.js Tools for Visual Studio
236 | .ntvs_analysis.dat
237 | node_modules/
238 |
239 | # Typescript v1 declaration files
240 | typings/
241 |
242 | # Visual Studio 6 build log
243 | *.plg
244 |
245 | # Visual Studio 6 workspace options file
246 | *.opt
247 |
248 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
249 | *.vbw
250 |
251 | # Visual Studio LightSwitch build output
252 | **/*.HTMLClient/GeneratedArtifacts
253 | **/*.DesktopClient/GeneratedArtifacts
254 | **/*.DesktopClient/ModelManifest.xml
255 | **/*.Server/GeneratedArtifacts
256 | **/*.Server/ModelManifest.xml
257 | _Pvt_Extensions
258 |
259 | # Paket dependency manager
260 | .paket/paket.exe
261 | paket-files/
262 |
263 | # FAKE - F# Make
264 | .fake/
265 |
266 | # JetBrains Rider
267 | .idea/
268 | *.sln.iml
269 |
270 | # CodeRush
271 | .cr/
272 |
273 | # Python Tools for Visual Studio (PTVS)
274 | __pycache__/
275 | *.pyc
276 |
277 | # Cake - Uncomment if you are using it
278 | # tools/**
279 | # !tools/packages.config
280 |
281 | # Telerik's JustMock configuration file
282 | *.jmconfig
283 |
284 | # BizTalk build output
285 | *.btp.cs
286 | *.btm.cs
287 | *.odx.cs
288 | *.xsd.cs
289 |
--------------------------------------------------------------------------------
/Documentation/Screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dotnet-ad/MarkdownView/feea9069e8635336f323988994402bd9557445e5/Documentation/Screenshot.png
--------------------------------------------------------------------------------
/Documentation/Screenshot_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dotnet-ad/MarkdownView/feea9069e8635336f323988994402bd9557445e5/Documentation/Screenshot_dark.png
--------------------------------------------------------------------------------
/Documentation/Screenshot_light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dotnet-ad/MarkdownView/feea9069e8635336f323988994402bd9557445e5/Documentation/Screenshot_light.png
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # MarkdownView *for Xamarin.Forms*
2 |
3 | [](https://www.nuget.org/packages/Xam.Forms.MarkdownView/) [](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)
4 |
5 | A native Xamarin.Forms Markdown renderer.
6 |
7 | ## Gallery
8 |
9 | 
10 |
11 | ## Introduction
12 |
13 | 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)!
14 |
15 | This will produce a more reactive user interface, at the cost of rendering functionalities *(at the moment though!)*.
16 |
17 | ## Install
18 |
19 | Available on [NuGet](https://www.nuget.org/packages/Xam.Forms.MarkdownView/).
20 |
21 | ## Quickstart
22 |
23 | ```csharp
24 | var view = new MarkdownView();
25 | view.Markdown = "# Hello world\n\nThis is my first native markdown rendering";
26 | view.Theme = new DarkMarkdownTheme(); // Default is white, you also modify various values
27 | this.Content = view;
28 | ```
29 |
30 | ## Limitations
31 |
32 | Unfortunately, Xamarin.Forms string rendering has some limitations ...
33 |
34 | * **Inlined images aren't supported** (*Xamarin.Forms formatted strings doesn't support inlined views*) : They will be displayed after the block they are referenced from.
35 | * **Links are only clickable at a leaf block level** (*Xamarin.Forms formatted strings doesn't support span user interactions*) : if a leaf block contains more than one link, the user is prompted. This is almost a feature since text may be too small to be enough precise! ;)
36 | * **SVG rendering is very limited** (*The SVG rendering is based on SkiaSharp which doesn't seem to manage well all svg renderings*)
37 |
38 | ## Roadmap
39 |
40 | * **Customization**
41 | * [X] Styles
42 | * [X] Themes
43 | * **Leaf blocks**
44 | * [X] Headings
45 | * [X] Paragraphs
46 | * [ ] HTML Blocks (maybe partial and specific support)
47 | * [ ] Link reference definitions
48 | * [X] Code blocks
49 | * [X] Thematic breaks
50 | * **Container blocks**
51 | * [X] Block quote
52 | * [X] Lists
53 | * [ ] Numbers bullet formats
54 | * [ ] Custom bullets
55 | * **Inlines**
56 | * [X] Textual content
57 | * [X] Emphasis and string emphasis
58 | * [X] Code spans
59 | * [X] Links (partial, no interaction)
60 | * [X] Image blocks (partial, not inlined)
61 | * [X] SVG Rendering (Skia)
62 | * **Extensions**
63 | * [ ] Table blocks
64 | * [ ] Emojis (ascii)
65 | * [ ] Task lists
66 |
67 | ## Thanks
68 |
69 | * [lunet-io/markdig](https://github.com/lunet-io/markdig) : used for Markdown parsing
70 | * [mono/SkiaSharp](https://github.com/mono/SkiaSharp) : used for SVG rendering
71 |
72 | ## Contributions
73 |
74 | Contributions are welcome! If you find a bug please report it and if you want a feature please report it.
75 |
76 | 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.
77 |
78 | ## License
79 |
80 | MIT © [Aloïs Deniel](http://aloisdeniel.github.io)
81 |
--------------------------------------------------------------------------------
/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/Droid/MainActivity.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | using Android.App;
4 | using Android.Content;
5 | using Android.Content.PM;
6 | using Android.Runtime;
7 | using Android.Views;
8 | using Android.Widget;
9 | using Android.OS;
10 |
11 | namespace MarkdownView.Samples.Droid
12 | {
13 | [Activity(Label = "MarkdownView.Samples.Droid", Icon = "@drawable/icon", Theme = "@style/MyTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
14 | public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
15 | {
16 | protected override void OnCreate(Bundle bundle)
17 | {
18 | TabLayoutResource = Resource.Layout.Tabbar;
19 | ToolbarResource = Resource.Layout.Toolbar;
20 |
21 | base.OnCreate(bundle);
22 |
23 | global::Xamarin.Forms.Forms.Init(this, bundle);
24 |
25 | LoadApplication(new App());
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Sources/Droid/MarkdownView.Samples.Droid.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {5BD2DA5D-406C-4A82-9DBC-A4294B50738A}
8 | {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
9 | Library
10 | MarkdownView.Samples.Droid
11 | MarkdownView.Samples.Droid
12 | v7.1
13 | True
14 | Resources\Resource.designer.cs
15 | Resource
16 | Properties\AndroidManifest.xml
17 | Resources
18 | Assets
19 | true
20 |
21 |
22 | true
23 | full
24 | false
25 | bin\Debug
26 | DEBUG;
27 | prompt
28 | 4
29 | None
30 | arm64-v8a;armeabi;armeabi-v7a;x86
31 |
32 |
33 | true
34 | pdbonly
35 | true
36 | bin\Release
37 | prompt
38 | 4
39 | true
40 | false
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 | ..\packages\Xamarin.Android.Support.v4.23.3.0\lib\MonoAndroid403\Xamarin.Android.Support.v4.dll
49 |
50 |
51 | ..\packages\Xamarin.Android.Support.Vector.Drawable.23.3.0\lib\MonoAndroid403\Xamarin.Android.Support.Vector.Drawable.dll
52 |
53 |
54 | ..\packages\Xamarin.Android.Support.Animated.Vector.Drawable.23.3.0\lib\MonoAndroid403\Xamarin.Android.Support.Animated.Vector.Drawable.dll
55 |
56 |
57 | ..\packages\Xamarin.Android.Support.v7.AppCompat.23.3.0\lib\MonoAndroid403\Xamarin.Android.Support.v7.AppCompat.dll
58 |
59 |
60 | ..\packages\Xamarin.Android.Support.v7.RecyclerView.23.3.0\lib\MonoAndroid403\Xamarin.Android.Support.v7.RecyclerView.dll
61 |
62 |
63 | ..\packages\Xamarin.Android.Support.Design.23.3.0\lib\MonoAndroid43\Xamarin.Android.Support.Design.dll
64 |
65 |
66 | ..\packages\Xamarin.Android.Support.v7.CardView.23.3.0\lib\MonoAndroid403\Xamarin.Android.Support.v7.CardView.dll
67 |
68 |
69 | ..\packages\Xamarin.Android.Support.v7.MediaRouter.23.3.0\lib\MonoAndroid403\Xamarin.Android.Support.v7.MediaRouter.dll
70 |
71 |
72 |
73 |
74 |
75 | ..\packages\SkiaSharp.Svg.1.59.0\lib\netstandard1.3\SkiaSharp.Svg.dll
76 |
77 |
78 | ..\packages\Markdig.0.13.3\lib\netstandard1.1\Markdig.dll
79 |
80 |
81 | ..\packages\SkiaSharp.1.59.1\lib\MonoAndroid\SkiaSharp.dll
82 |
83 |
84 | ..\packages\Xamarin.Forms.2.4.0.269-pre2\lib\MonoAndroid10\FormsViewGroup.dll
85 |
86 |
87 | ..\packages\Xamarin.Forms.2.4.0.269-pre2\lib\MonoAndroid10\Xamarin.Forms.Core.dll
88 |
89 |
90 | ..\packages\Xamarin.Forms.2.4.0.269-pre2\lib\MonoAndroid10\Xamarin.Forms.Platform.Android.dll
91 |
92 |
93 | ..\packages\Xamarin.Forms.2.4.0.269-pre2\lib\MonoAndroid10\Xamarin.Forms.Platform.dll
94 |
95 |
96 | ..\packages\Xamarin.Forms.2.4.0.269-pre2\lib\MonoAndroid10\Xamarin.Forms.Xaml.dll
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 | {343F37AF-8929-4C43-90F6-57050218B243}
122 | MarkdownView.Samples
123 |
124 |
125 | {17728834-C586-4C2E-A1D7-F2E7AD1E1FBF}
126 | Xam.Forms.MarkdownView
127 |
128 |
129 |
130 |
131 |
132 |
--------------------------------------------------------------------------------
/Sources/Droid/Properties/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Sources/Droid/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using Android.App;
4 |
5 | // Information about this assembly is defined by the following attributes.
6 | // Change them to the values specific to your project.
7 |
8 | [assembly: AssemblyTitle("MarkdownView.Samples.Droid")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("")]
13 | [assembly: AssemblyCopyright("${AuthorCopyright}")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
18 | // The form "{Major}.{Minor}.*" will automatically update the build and revision,
19 | // and "{Major}.{Minor}.{Build}.*" will update just the revision.
20 |
21 | [assembly: AssemblyVersion("1.0.0")]
22 |
23 | // The following attributes are used to specify the signing key for the assembly,
24 | // if desired. See the Mono documentation for more information about signing.
25 |
26 | //[assembly: AssemblyDelaySign(false)]
27 | //[assembly: AssemblyKeyFile("")]
28 |
--------------------------------------------------------------------------------
/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/Droid/Resources/drawable-hdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dotnet-ad/MarkdownView/feea9069e8635336f323988994402bd9557445e5/Sources/Droid/Resources/drawable-hdpi/icon.png
--------------------------------------------------------------------------------
/Sources/Droid/Resources/drawable-xhdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dotnet-ad/MarkdownView/feea9069e8635336f323988994402bd9557445e5/Sources/Droid/Resources/drawable-xhdpi/icon.png
--------------------------------------------------------------------------------
/Sources/Droid/Resources/drawable-xxhdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dotnet-ad/MarkdownView/feea9069e8635336f323988994402bd9557445e5/Sources/Droid/Resources/drawable-xxhdpi/icon.png
--------------------------------------------------------------------------------
/Sources/Droid/Resources/drawable/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dotnet-ad/MarkdownView/feea9069e8635336f323988994402bd9557445e5/Sources/Droid/Resources/drawable/icon.png
--------------------------------------------------------------------------------
/Sources/Droid/Resources/layout/Tabbar.axml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/Sources/Droid/Resources/layout/Toolbar.axml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/Sources/Droid/Resources/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
24 |
27 |
28 |
--------------------------------------------------------------------------------
/Sources/Droid/packages.config:
--------------------------------------------------------------------------------
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 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/Sources/MarkdownView.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 | 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_-]+))?");
11 |
12 | private 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/MarkdownView.Portable/Extensions/ImageExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace Xam.Forms.Markdown.Extensions
2 | {
3 | using System;
4 | using System.IO;
5 | using System.Net;
6 | using SkiaSharp;
7 | using Xamarin.Forms;
8 | using System.Diagnostics;
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/MarkdownView.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 Color ForegroundColor { get; set; } = Color.Black;
12 |
13 | public Color BackgroundColor { get; set; } = Color.Transparent;
14 |
15 | public Color BorderColor { get; set; }
16 |
17 | public float BorderSize { get; set; }
18 |
19 | public string FontFamily { get; set; }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Sources/MarkdownView.Portable/MarkdownTheme.cs:
--------------------------------------------------------------------------------
1 |
2 | namespace Xam.Forms.Markdown
3 | {
4 | using Xamarin.Forms;
5 |
6 | public class MarkdownTheme
7 | {
8 | public MarkdownTheme()
9 | {
10 | this.Paragraph = new MarkdownStyle
11 | {
12 | Attributes = FontAttributes.None,
13 | FontSize = 12,
14 | };
15 |
16 | this.Heading1 = new MarkdownStyle
17 | {
18 | Attributes = FontAttributes.Bold,
19 | BorderSize = 1,
20 | FontSize = 26,
21 | };
22 |
23 | this.Heading2 = new MarkdownStyle
24 | {
25 | Attributes = FontAttributes.Bold,
26 | BorderSize = 1,
27 | FontSize = 22,
28 | };
29 |
30 | this.Heading3 = new MarkdownStyle
31 | {
32 | Attributes = FontAttributes.Bold,
33 | FontSize = 20,
34 | };
35 |
36 | this.Heading4 = new MarkdownStyle
37 | {
38 | Attributes = FontAttributes.Bold,
39 | FontSize = 18,
40 | };
41 |
42 | this.Heading5 = new MarkdownStyle
43 | {
44 | Attributes = FontAttributes.Bold,
45 | FontSize = 16,
46 | };
47 |
48 | this.Heading6 = new MarkdownStyle
49 | {
50 | Attributes = FontAttributes.Bold,
51 | FontSize = 14,
52 | };
53 |
54 | this.Link = new MarkdownStyle
55 | {
56 | Attributes = FontAttributes.None,
57 | FontSize = 12,
58 | };
59 |
60 | this.Code = new MarkdownStyle
61 | {
62 | Attributes = FontAttributes.None,
63 | FontSize = 12,
64 | };
65 |
66 | this.Quote = new MarkdownStyle
67 | {
68 | Attributes = FontAttributes.None,
69 | BorderSize = 4,
70 | FontSize = 12,
71 | BackgroundColor = Color.Gray.MultiplyAlpha(.1),
72 | };
73 |
74 | this.Separator = new MarkdownStyle
75 | {
76 | BorderSize = 2,
77 | };
78 |
79 | // Platform specific properties
80 | switch (Device.RuntimePlatform)
81 | {
82 | case Device.iOS:
83 | Code.FontFamily = "Courier";
84 | break;
85 |
86 | case Device.Android:
87 | Code.FontFamily = "monospace";
88 | break;
89 | }
90 | }
91 |
92 | public Color BackgroundColor { get; set; }
93 |
94 | public MarkdownStyle Paragraph { get; set; }
95 |
96 | public MarkdownStyle Heading1 { get; set; }
97 |
98 | public MarkdownStyle Heading2 { get; set; }
99 |
100 | public MarkdownStyle Heading3 { get; set; }
101 |
102 | public MarkdownStyle Heading4 { get; set; }
103 |
104 | public MarkdownStyle Heading5 { get; set; }
105 |
106 | public MarkdownStyle Heading6 { get; set; }
107 |
108 | public MarkdownStyle Quote { get; set; }
109 |
110 | public MarkdownStyle Separator { get; set; }
111 |
112 | public MarkdownStyle Link { get; set; }
113 |
114 | public MarkdownStyle Code { get; set; }
115 |
116 | public float Margin { get; set; } = 10;
117 | }
118 |
119 | public class LightMarkdownTheme : MarkdownTheme
120 | {
121 | public LightMarkdownTheme()
122 | {
123 | this.BackgroundColor = DefaultBackgroundColor;
124 | this.Paragraph.ForegroundColor = DefaultTextColor;
125 | this.Heading1.ForegroundColor = DefaultTextColor;
126 | this.Heading1.BorderColor = DefaultSeparatorColor;
127 | this.Heading2.ForegroundColor = DefaultTextColor;
128 | this.Heading2.BorderColor = DefaultSeparatorColor;
129 | this.Heading3.ForegroundColor = DefaultTextColor;
130 | this.Heading4.ForegroundColor = DefaultTextColor;
131 | this.Heading5.ForegroundColor = DefaultTextColor;
132 | this.Heading6.ForegroundColor = DefaultTextColor;
133 | this.Link.ForegroundColor = DefaultAccentColor;
134 | this.Code.ForegroundColor = DefaultTextColor;
135 | this.Code.BackgroundColor = DefaultCodeBackground;
136 | this.Quote.ForegroundColor = DefaultQuoteTextColor;
137 | this.Quote.BorderColor = DefaultQuoteBorderColor;
138 | this.Separator.BorderColor = DefaultSeparatorColor;
139 | }
140 |
141 | public static readonly Color DefaultBackgroundColor = Color.FromHex("#ffffff");
142 |
143 | public static readonly Color DefaultAccentColor = Color.FromHex("#0366d6");
144 |
145 | public static readonly Color DefaultTextColor = Color.FromHex("#24292e");
146 |
147 | public static readonly Color DefaultCodeBackground = Color.FromHex("#f6f8fa");
148 |
149 | public static readonly Color DefaultSeparatorColor = Color.FromHex("#eaecef");
150 |
151 | public static readonly Color DefaultQuoteTextColor = Color.FromHex("#6a737d");
152 |
153 | public static readonly Color DefaultQuoteBorderColor = Color.FromHex("#dfe2e5");
154 | }
155 |
156 | public class DarkMarkdownTheme : MarkdownTheme
157 | {
158 | public DarkMarkdownTheme()
159 | {
160 | this.BackgroundColor = DefaultBackgroundColor;
161 | this.Paragraph.ForegroundColor = DefaultTextColor;
162 | this.Heading1.ForegroundColor = DefaultTextColor;
163 | this.Heading1.BorderColor = DefaultSeparatorColor;
164 | this.Heading2.ForegroundColor = DefaultTextColor;
165 | this.Heading2.BorderColor = DefaultSeparatorColor;
166 | this.Heading3.ForegroundColor = DefaultTextColor;
167 | this.Heading4.ForegroundColor = DefaultTextColor;
168 | this.Heading5.ForegroundColor = DefaultTextColor;
169 | this.Heading6.ForegroundColor = DefaultTextColor;
170 | this.Link.ForegroundColor = DefaultAccentColor;
171 | this.Code.ForegroundColor = DefaultTextColor;
172 | this.Code.BackgroundColor = DefaultCodeBackground;
173 | this.Quote.ForegroundColor = DefaultQuoteTextColor;
174 | this.Quote.BorderColor = DefaultQuoteBorderColor;
175 | this.Separator.BorderColor = DefaultSeparatorColor;
176 | }
177 |
178 | public static readonly Color DefaultBackgroundColor = Color.FromHex("#2b303b");
179 |
180 | public static readonly Color DefaultAccentColor = Color.FromHex("#d08770");
181 |
182 | public static readonly Color DefaultTextColor = Color.FromHex("#eff1f5");
183 |
184 | public static readonly Color DefaultCodeBackground = Color.FromHex("#4f5b66");
185 |
186 | public static readonly Color DefaultSeparatorColor = Color.FromHex("#65737e");
187 |
188 | public static readonly Color DefaultQuoteTextColor = Color.FromHex("#a7adba");
189 |
190 | public static readonly Color DefaultQuoteBorderColor = Color.FromHex("#a7adba");
191 | }
192 | }
193 |
--------------------------------------------------------------------------------
/Sources/MarkdownView.Portable/MarkdownView.cs:
--------------------------------------------------------------------------------
1 | namespace Xam.Forms.Markdown
2 | {
3 | using System.Linq;
4 | using Markdig.Syntax;
5 | using Markdig.Syntax.Inlines;
6 | using Xamarin.Forms;
7 | using System;
8 | using System.Collections.Generic;
9 | using System.Diagnostics;
10 | using System.IO;
11 | using Extensions;
12 |
13 | public class MarkdownView : ContentView
14 | {
15 | public Action NavigateToLink { get; set; } = (s) => Device.OpenUri(new Uri(s));
16 |
17 | public static MarkdownTheme Global = new LightMarkdownTheme();
18 |
19 | public string Markdown
20 | {
21 | get { return (string)GetValue(MarkdownProperty); }
22 | set { SetValue(MarkdownProperty, value); }
23 | }
24 |
25 | public static readonly BindableProperty MarkdownProperty = BindableProperty.Create(nameof(Markdown), typeof(string), typeof(MarkdownView), null, propertyChanged: OnMarkdownChanged);
26 |
27 | public string RelativeUrlHost
28 | {
29 | get { return (string)GetValue(RelativeUrlHostProperty); }
30 | set { SetValue(RelativeUrlHostProperty, value); }
31 | }
32 |
33 | public static readonly BindableProperty RelativeUrlHostProperty = BindableProperty.Create(nameof(RelativeUrlHost), typeof(string), typeof(MarkdownView), null, propertyChanged: OnMarkdownChanged);
34 |
35 | public MarkdownTheme Theme
36 | {
37 | get { return (MarkdownTheme)GetValue(ThemeProperty); }
38 | set { SetValue(ThemeProperty, value); }
39 | }
40 |
41 | public static readonly BindableProperty ThemeProperty = BindableProperty.Create(nameof(Theme), typeof(MarkdownTheme), typeof(MarkdownView), Global, propertyChanged: OnMarkdownChanged);
42 |
43 | private bool isQuoted;
44 |
45 | private List queuedViews = new List();
46 |
47 | static void OnMarkdownChanged(BindableObject bindable, object oldValue, object newValue)
48 | {
49 | var view = bindable as MarkdownView;
50 | view.RenderMarkdown();
51 | }
52 |
53 | private StackLayout stack;
54 |
55 | private List> links = new List>();
56 |
57 | private void RenderMarkdown()
58 | {
59 | stack = new StackLayout()
60 | {
61 | Spacing = this.Theme.Margin,
62 | };
63 |
64 | this.Padding = this.Theme.Margin;
65 |
66 | this.BackgroundColor = this.Theme.BackgroundColor;
67 |
68 | if(!string.IsNullOrEmpty(this.Markdown))
69 | {
70 | var parsed = Markdig.Markdown.Parse(this.Markdown);
71 | this.Render(parsed.AsEnumerable());
72 | }
73 |
74 | this.Content = stack;
75 | }
76 |
77 | private void Render(IEnumerable blocks)
78 | {
79 | foreach (var block in blocks)
80 | {
81 | this.Render(block);
82 | }
83 | }
84 |
85 | private void AttachLinks(View view)
86 | {
87 | if (links.Any())
88 | {
89 | var blockLinks = links;
90 | view.GestureRecognizers.Add(new TapGestureRecognizer
91 | {
92 | Command = new Command(async () =>
93 | {
94 | try
95 | {
96 | if (blockLinks.Count > 1)
97 | {
98 | var result = await Application.Current.MainPage.DisplayActionSheet("Open link", "Cancel", null, blockLinks.Select(x => x.Key).ToArray());
99 | var link = blockLinks.FirstOrDefault(x => x.Key == result);
100 | NavigateToLink(link.Value);
101 | }
102 | else
103 | {
104 | NavigateToLink(blockLinks.First().Value);
105 | }
106 | }
107 | catch (Exception) { }
108 | }),
109 | });
110 |
111 | links = new List>();
112 | }
113 | }
114 |
115 | #region Rendering blocks
116 |
117 | private void Render(Block block)
118 | {
119 | switch (block)
120 | {
121 | case HeadingBlock heading:
122 | Render(heading);
123 | break;
124 |
125 | case ParagraphBlock paragraph:
126 | Render(paragraph);
127 | break;
128 |
129 | case QuoteBlock quote:
130 | Render(quote);
131 | break;
132 |
133 | case CodeBlock code:
134 | Render(code);
135 | break;
136 |
137 | case ListBlock list:
138 | Render(list);
139 | break;
140 |
141 | case ThematicBreakBlock thematicBreak:
142 | Render(thematicBreak);
143 | break;
144 |
145 | case HtmlBlock html:
146 | Render(html);
147 | break;
148 |
149 | default:
150 | Debug.WriteLine($"Can't render {block.GetType()} blocks.");
151 | break;
152 | }
153 |
154 | if(queuedViews.Any())
155 | {
156 | foreach (var view in queuedViews)
157 | {
158 | this.stack.Children.Add(view);
159 | }
160 | queuedViews.Clear();
161 | }
162 | }
163 |
164 | private int listScope;
165 |
166 | private void Render(ThematicBreakBlock block)
167 | {
168 | var style = this.Theme.Separator;
169 |
170 | if (style.BorderSize > 0)
171 | {
172 | stack.Children.Add(new BoxView
173 | {
174 | HeightRequest = style.BorderSize,
175 | BackgroundColor = style.BorderColor,
176 | });
177 | }
178 | }
179 |
180 | private void Render(ListBlock block)
181 | {
182 | listScope++;
183 |
184 | for (int i = 0; i < block.Count(); i++)
185 | {
186 | var item = block.ElementAt(i);
187 |
188 | if (item is ListItemBlock itemBlock)
189 | {
190 | this.Render(block, i + 1, itemBlock);
191 | }
192 | }
193 |
194 | listScope--;
195 | }
196 |
197 | private void Render(ListBlock parent, int index, ListItemBlock block)
198 | {
199 | var initialStack = this.stack;
200 |
201 | this.stack = new StackLayout()
202 | {
203 | Spacing = this.Theme.Margin,
204 | };
205 |
206 | this.Render(block.AsEnumerable());
207 |
208 | var horizontalStack = new StackLayout
209 | {
210 | Orientation = StackOrientation.Horizontal,
211 | Margin = new Thickness(listScope * this.Theme.Margin, 0, 0, 0),
212 | };
213 |
214 | View bullet;
215 |
216 | if (parent.IsOrdered)
217 | {
218 | bullet = new Label
219 | {
220 | Text = $"{index}.",
221 | FontSize = this.Theme.Paragraph.FontSize,
222 | TextColor = this.Theme.Paragraph.ForegroundColor,
223 | VerticalOptions = LayoutOptions.Start,
224 | HorizontalOptions = LayoutOptions.End,
225 | };
226 | }
227 | else
228 | {
229 | bullet = new BoxView
230 | {
231 | WidthRequest = 4,
232 | HeightRequest = 4,
233 | Margin = new Thickness(0, 6, 0, 0),
234 | BackgroundColor = this.Theme.Paragraph.ForegroundColor,
235 | VerticalOptions = LayoutOptions.Start,
236 | HorizontalOptions = LayoutOptions.Center,
237 | };
238 | }
239 |
240 | horizontalStack.Children.Add(bullet);
241 |
242 |
243 | horizontalStack.Children.Add(this.stack);
244 | initialStack.Children.Add(horizontalStack);
245 |
246 | this.stack = initialStack;
247 | }
248 |
249 | private void Render(HeadingBlock block)
250 | {
251 | MarkdownStyle style;
252 |
253 | switch (block.Level)
254 | {
255 | case 1:
256 | style = this.Theme.Heading1;
257 | break;
258 | case 2:
259 | style = this.Theme.Heading2;
260 | break;
261 | case 3:
262 | style = this.Theme.Heading3;
263 | break;
264 | case 4:
265 | style = this.Theme.Heading4;
266 | break;
267 | case 5:
268 | style = this.Theme.Heading5;
269 | break;
270 | default:
271 | style = this.Theme.Heading6;
272 | break;
273 | }
274 |
275 | var foregroundColor = isQuoted ? this.Theme.Quote.ForegroundColor : style.ForegroundColor;
276 |
277 | var label = new Label
278 | {
279 | FormattedText = CreateFormatted(block.Inline, style.FontFamily, style.Attributes, foregroundColor, style.BackgroundColor, style.FontSize),
280 | };
281 |
282 | AttachLinks(label);
283 |
284 | if (style.BorderSize > 0)
285 | {
286 | var headingStack = new StackLayout();
287 | headingStack.Children.Add(label);
288 | headingStack.Children.Add(new BoxView
289 | {
290 | HeightRequest = style.BorderSize,
291 | BackgroundColor = style.BorderColor,
292 | });
293 | stack.Children.Add(headingStack);
294 | }
295 | else
296 | {
297 | stack.Children.Add(label);
298 | }
299 | }
300 |
301 | private void Render(ParagraphBlock block)
302 | {
303 | var style = this.Theme.Paragraph;
304 | var foregroundColor = isQuoted ? this.Theme.Quote.ForegroundColor : style.ForegroundColor;
305 | var label = new Label
306 | {
307 | FormattedText = CreateFormatted(block.Inline, style.FontFamily, style.Attributes, foregroundColor, style.BackgroundColor, style.FontSize),
308 | };
309 | AttachLinks(label);
310 | this.stack.Children.Add(label);
311 | }
312 |
313 | private void Render(HtmlBlock block)
314 | {
315 | // ?
316 | }
317 |
318 | private void Render(QuoteBlock block)
319 | {
320 | var initialIsQuoted = this.isQuoted;
321 | var initialStack = this.stack;
322 |
323 | this.isQuoted = true;
324 | this.stack = new StackLayout()
325 | {
326 | Spacing = this.Theme.Margin,
327 | };
328 |
329 | var style = this.Theme.Quote;
330 |
331 | if (style.BorderSize > 0)
332 | {
333 | var horizontalStack = new StackLayout()
334 | {
335 | Orientation = StackOrientation.Horizontal,
336 | BackgroundColor = this.Theme.Quote.BackgroundColor,
337 | };
338 |
339 | horizontalStack.Children.Add(new BoxView()
340 | {
341 | WidthRequest = style.BorderSize,
342 | BackgroundColor = style.BorderColor,
343 | });
344 |
345 | horizontalStack.Children.Add(this.stack);
346 | initialStack.Children.Add(horizontalStack);
347 | }
348 | else
349 | {
350 | stack.BackgroundColor = this.Theme.Quote.BackgroundColor;
351 | initialStack.Children.Add(this.stack);
352 | }
353 |
354 | this.Render(block.AsEnumerable());
355 |
356 | this.isQuoted = initialIsQuoted;
357 | this.stack = initialStack;
358 | }
359 |
360 | private void Render(CodeBlock block)
361 | {
362 | var style = this.Theme.Code;
363 | var label = new Label
364 | {
365 | TextColor = style.ForegroundColor,
366 | FontAttributes = style.Attributes,
367 | FontFamily = style.FontFamily,
368 | FontSize = style.FontSize,
369 | Text = string.Join(Environment.NewLine, block.Lines),
370 | };
371 | stack.Children.Add(new Frame()
372 | {
373 | CornerRadius = 3,
374 | HasShadow = false,
375 | Padding = this.Theme.Margin,
376 | BackgroundColor = style.BackgroundColor,
377 | Content = label
378 | });
379 | }
380 |
381 | private FormattedString CreateFormatted(ContainerInline inlines, string family, FontAttributes attributes, Color foregroundColor, Color backgroundColor, float size)
382 | {
383 | var fs = new FormattedString();
384 |
385 | foreach (var inline in inlines)
386 | {
387 | var spans = CreateSpans(inline, family, attributes, foregroundColor, backgroundColor, size);
388 | if (spans != null)
389 | {
390 | foreach (var span in spans)
391 | {
392 | fs.Spans.Add(span);
393 | }
394 | }
395 | }
396 |
397 | return fs;
398 | }
399 |
400 | private Span[] CreateSpans(Inline inline, string family, FontAttributes attributes, Color foregroundColor, Color backgroundColor, float size)
401 | {
402 | switch (inline)
403 | {
404 | case LiteralInline literal:
405 | return new[]
406 | {
407 | new Span
408 | {
409 | Text = literal.Content.Text.Substring(literal.Content.Start, literal.Content.Length),
410 | FontAttributes = attributes,
411 | ForegroundColor = foregroundColor,
412 | BackgroundColor = backgroundColor,
413 | FontSize = size,
414 | FontFamily = family,
415 | }
416 | };
417 |
418 | case EmphasisInline emphasis:
419 | var childAttributes = attributes | (emphasis.IsDouble ? FontAttributes.Bold : FontAttributes.Italic);
420 | return emphasis.SelectMany(x => CreateSpans(x, family, childAttributes, foregroundColor, backgroundColor, size)).ToArray();
421 |
422 | case LineBreakInline breakline:
423 | return new[] { new Span { Text = "\n" } };
424 |
425 | case LinkInline link:
426 |
427 | var url = link.Url;
428 |
429 | if (!(url.StartsWith("http://") || url.StartsWith("https://")))
430 | {
431 | url = $"{this.RelativeUrlHost?.TrimEnd('/')}/{url.TrimStart('/')}";
432 | }
433 |
434 | if(link.IsImage)
435 | {
436 | var image = new Image();
437 |
438 | if(Path.GetExtension(url) == ".svg")
439 | {
440 | image.RenderSvg(url);
441 | }
442 | else
443 | {
444 | image.Source = url;
445 | }
446 |
447 | queuedViews.Add(image);
448 | return new Span[0];
449 | }
450 | else
451 | {
452 | 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();
453 | links.Add(new KeyValuePair(string.Join("",spans.Select(x => x.Text)), url));
454 | return spans;
455 | }
456 |
457 | case CodeInline code:
458 | return new[]
459 | {
460 | new Span()
461 | {
462 | Text="\u2002",
463 | FontSize = size,
464 | FontFamily = this.Theme.Code.FontFamily,
465 | ForegroundColor = this.Theme.Code.ForegroundColor,
466 | BackgroundColor = this.Theme.Code.BackgroundColor
467 | },
468 | new Span
469 | {
470 | Text = code.Content,
471 | FontAttributes = this.Theme.Code.Attributes,
472 | FontSize = size,
473 | FontFamily = this.Theme.Code.FontFamily,
474 | ForegroundColor = this.Theme.Code.ForegroundColor,
475 | BackgroundColor = this.Theme.Code.BackgroundColor
476 | },
477 | new Span()
478 | {
479 | Text="\u2002",
480 | FontSize = size,
481 | FontFamily = this.Theme.Code.FontFamily,
482 | ForegroundColor = this.Theme.Code.ForegroundColor,
483 | BackgroundColor = this.Theme.Code.BackgroundColor
484 | },
485 | };
486 |
487 | default:
488 | Debug.WriteLine($"Can't render {inline.GetType()} inlines.");
489 | return null;
490 | }
491 | }
492 |
493 | #endregion
494 | }
495 | }
496 |
--------------------------------------------------------------------------------
/Sources/MarkdownView.Portable/Xam.Forms.MarkdownView.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | netstandard2.0
6 |
7 |
8 |
9 | 0.0.0.0
10 | 0.0.0.0
11 | 0.0.0.0
12 | 0.0.0.0
13 | $(AssemblyName) ($(TargetFramework))
14 | Aloïs Deniel
15 | Xam.Forms.MarkdownView
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
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/aloisdeniel/MarkdownView
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/Sources/MarkdownView.Portable/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/Sources/MarkdownView.Samples/App.xaml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/Sources/MarkdownView.Samples/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using Xamarin.Forms;
2 |
3 | namespace MarkdownView.Samples
4 | {
5 | public partial class App : Application
6 | {
7 | public App()
8 | {
9 | InitializeComponent();
10 |
11 | MainPage = new MasterDetailPage()
12 | {
13 | Master = new MenuPage() { Title = "Menu"},
14 | Detail = new MarkdownView_SamplesPage()
15 | };
16 | }
17 |
18 | protected override void OnStart()
19 | {
20 | // Handle when your app starts
21 | }
22 |
23 | protected override void OnSleep()
24 | {
25 | // Handle when your app sleeps
26 | }
27 |
28 | protected override void OnResume()
29 | {
30 | // Handle when your app resumes
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Sources/MarkdownView.Samples/MarkdownView.Samples.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | netstandard2.0
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | App.xaml
19 |
20 |
21 | MarkdownView.SamplesPage.xaml
22 |
23 |
24 | MenuPage.xaml
25 |
26 |
27 |
28 |
29 |
30 | MSBuild:UpdateDesignTimeXaml
31 |
32 |
33 | MSBuild:UpdateDesignTimeXaml
34 |
35 |
36 | MSBuild:UpdateDesignTimeXaml
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/Sources/MarkdownView.Samples/MarkdownView.SamplesPage.xaml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/Sources/MarkdownView.Samples/MarkdownView.SamplesPage.xaml.cs:
--------------------------------------------------------------------------------
1 | using Xamarin.Forms;
2 | using System.Net;
3 | using System.IO;
4 | using System.Linq;
5 | using Xam.Forms.Markdown;
6 | using System.Diagnostics;
7 |
8 | namespace MarkdownView.Samples
9 | {
10 | public partial class MarkdownView_SamplesPage : ContentPage
11 | {
12 | const string embedded = "# An exhibit of Markdown\n\nThis note demonstrates some of what [Markdown][1] is capable of doing.\n\n*Note: Feel free to play with this page. Unlike regular notes, this doesn't automatically save itself.*\n\n## Basic formatting\n\nParagraphs can be written like so. A paragraph is the basic block of Markdown. A paragraph is what text will turn into when there is no reason it should become anything else.\n\nParagraphs must be separated by a blank line. Basic formatting of *italics* and **bold** is supported. This *can be **nested** like* so.\n\n## Lists\n\n### Ordered list\n\n1. Item 1\n2. A second item\n3. Number 3\n4. Ⅳ\n\n*Note: the fourth item uses the Unicode character for [Roman numeral four][2].*\n\n### Unordered list\n\n* An item\n* Another item\n* Yet another item\n* And there's more...\n\n## Paragraph modifiers\n\n### Code block\n\n Code blocks are very useful for developers and other people who look at code or other things that are written in plain text. As you can see, it uses a fixed-width font.\n\nYou can also make `inline code` to add code into other things.\n\n### Quote\n\n> Here is a quote. What this is should be self explanatory. Quotes are automatically indented when they are used.\n\n## Headings\n\nThere are six levels of headings. They correspond with the six levels of HTML headings. You've probably noticed them already in the page. Each level down uses one more hash character.\n\n### Headings *can* also contain **formatting**\n\n### They can even contain `inline code`\n\nOf course, demonstrating what headings look like messes up the structure of the page.\n\nI don't recommend using more than three or four levels of headings here, because, when you're smallest heading isn't too small, and you're largest heading isn't too big, and you want each size up to look noticeably larger and more important, there there are only so many sizes that you can use.\n\n## URLs\n\nURLs can be made in a handful of ways:\n\n* A named link to [MarkItDown][3]. The easiest way to do these is to select what you want to make a link and hit `Ctrl+L`.\n* Another named link to [MarkItDown](http://www.markitdown.net/)\n\n## Horizontal rule\n\nA horizontal rule is a line that goes across the middle of the page.\n\n---\n\nIt's sometimes handy for breaking things up.\n\n## Images\n\nMarkdown can also contain images. I'll need to add something here sometime.\n\n## Finally\n\nThere's actually a lot more to Markdown than this. See the official [introduction][4] and [syntax][5] for more information. However, be aware that this is not using the official implementation, and this might work subtly differently in some of the little things.\n\n [1]: http://daringfireball.net/projects/markdown/\n [2]: http://www.fileformat.info/info/unicode/char/2163/index.htm\n [3]: http://www.markitdown.net/\n [4]: http://daringfireball.net/projects/markdown/basics\n [5]: http://daringfireball.net/projects/markdown/syntax";
13 |
14 | public MarkdownView_SamplesPage()
15 | {
16 | InitializeComponent();
17 | var mdView = new Xam.Forms.Markdown.MarkdownView();
18 | mdView.Markdown = embedded;
19 | mdView.RelativeUrlHost = "";
20 | this.Content = new ScrollView() { Content = mdView };
21 |
22 | MessagingCenter.Subscribe(this, "theme", (s, arg) =>
23 | {
24 | mdView.Theme = arg == "dark" ? (MarkdownTheme)new DarkMarkdownTheme() : new LightMarkdownTheme();
25 | });
26 |
27 | MessagingCenter.Subscribe(this, "new_md", async (s, arg) => {
28 | if(arg == "")
29 | {
30 | mdView.Markdown = embedded;
31 | mdView.RelativeUrlHost = "";
32 | }
33 | else
34 | {
35 | try
36 | {
37 | var urlSplits = arg.Split('/');
38 | var ghUser = urlSplits.ElementAtOrDefault(3);
39 | var ghRepo = urlSplits.ElementAtOrDefault(4);
40 | var ghBranch = urlSplits.ElementAtOrDefault(5);
41 | mdView.RelativeUrlHost = $"https://raw.githubusercontent.com/{ghUser}/{ghRepo}/{ghBranch}";
42 |
43 | var req = WebRequest.Create(arg);
44 | var res = await req.GetResponseAsync();
45 | using (var stream = res.GetResponseStream())
46 | using (var ms = new MemoryStream())
47 | {
48 | await stream.CopyToAsync(ms);
49 | ms.Seek(0, SeekOrigin.Begin);
50 | ms.Position = 0;
51 | using (var reader = new StreamReader(ms))
52 | mdView.Markdown = reader.ReadToEnd();
53 | }
54 | }
55 | catch (System.Exception ex)
56 | {
57 | Debug.WriteLine(ex.ToString());
58 | }
59 | }
60 | });
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/Sources/MarkdownView.Samples/MenuPage.xaml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/Sources/MarkdownView.Samples/MenuPage.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | using Xamarin.Forms;
5 |
6 | namespace MarkdownView.Samples
7 | {
8 | public partial class MenuPage : ContentPage
9 | {
10 | public class Item
11 | {
12 | public Item(string title, string url)
13 | {
14 | this.Title = title;
15 | this.Url = url;
16 | }
17 | public string Title { get; }
18 |
19 | public string Url { get; }
20 | }
21 |
22 | public Item[] Items { get; } =
23 | {
24 | new Item("Embedded", ""),
25 | new Item("MarkdownView", "https://raw.githubusercontent.com/aloisdeniel/MarkdownView/master/README.md"),
26 | new Item("Markdig", "https://raw.githubusercontent.com/lunet-io/markdig/master/readme.md"),
27 | new Item("Xamarin.Forms", "https://raw.githubusercontent.com/xamarin/Xamarin.Forms/master/README.md"),
28 | };
29 |
30 | public MenuPage()
31 | {
32 | InitializeComponent();
33 | this.BindingContext = this;
34 | }
35 |
36 | void Handle_Toggled(object sender, Xamarin.Forms.ToggledEventArgs e)
37 | {
38 | MessagingCenter.Send(this, "theme", e.Value ? "dark" : "light");
39 | }
40 |
41 | void Handle_ItemSelected(object sender, Xamarin.Forms.SelectedItemChangedEventArgs e)
42 | {
43 | var item = e.SelectedItem as Item;
44 | MessagingCenter.Send(this, "new_md", item.Url);
45 | ((MasterDetailPage)Application.Current.MainPage).IsPresented = false;
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/Sources/MarkdownView.Samples/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/Sources/MarkdownView.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 2012
4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xam.Forms.MarkdownView", "MarkdownView.Portable\Xam.Forms.MarkdownView.csproj", "{17728834-C586-4C2E-A1D7-F2E7AD1E1FBF}"
5 | EndProject
6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{BD895E94-AF92-409F-8D79-A5DAD7556CC0}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MarkdownView.Samples", "MarkdownView.Samples\MarkdownView.Samples.csproj", "{343F37AF-8929-4C43-90F6-57050218B243}"
9 | EndProject
10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MarkdownView.Samples.iOS", "iOS\MarkdownView.Samples.iOS.csproj", "{49523DF2-73C7-4149-AD32-34B6669B72B8}"
11 | EndProject
12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MarkdownView.Samples.Droid", "Droid\MarkdownView.Samples.Droid.csproj", "{5BD2DA5D-406C-4A82-9DBC-A4294B50738A}"
13 | EndProject
14 | Global
15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
16 | Debug|Any CPU = Debug|Any CPU
17 | Release|Any CPU = Release|Any CPU
18 | Debug|iPhoneSimulator = Debug|iPhoneSimulator
19 | Release|iPhone = Release|iPhone
20 | Release|iPhoneSimulator = Release|iPhoneSimulator
21 | Debug|iPhone = Debug|iPhone
22 | EndGlobalSection
23 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
24 | {17728834-C586-4C2E-A1D7-F2E7AD1E1FBF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
25 | {17728834-C586-4C2E-A1D7-F2E7AD1E1FBF}.Debug|Any CPU.Build.0 = Debug|Any CPU
26 | {17728834-C586-4C2E-A1D7-F2E7AD1E1FBF}.Release|Any CPU.ActiveCfg = Release|Any CPU
27 | {17728834-C586-4C2E-A1D7-F2E7AD1E1FBF}.Release|Any CPU.Build.0 = Release|Any CPU
28 | {17728834-C586-4C2E-A1D7-F2E7AD1E1FBF}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
29 | {17728834-C586-4C2E-A1D7-F2E7AD1E1FBF}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
30 | {17728834-C586-4C2E-A1D7-F2E7AD1E1FBF}.Release|iPhone.ActiveCfg = Release|Any CPU
31 | {17728834-C586-4C2E-A1D7-F2E7AD1E1FBF}.Release|iPhone.Build.0 = Release|Any CPU
32 | {17728834-C586-4C2E-A1D7-F2E7AD1E1FBF}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
33 | {17728834-C586-4C2E-A1D7-F2E7AD1E1FBF}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
34 | {17728834-C586-4C2E-A1D7-F2E7AD1E1FBF}.Debug|iPhone.ActiveCfg = Debug|Any CPU
35 | {17728834-C586-4C2E-A1D7-F2E7AD1E1FBF}.Debug|iPhone.Build.0 = Debug|Any CPU
36 | {343F37AF-8929-4C43-90F6-57050218B243}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
37 | {343F37AF-8929-4C43-90F6-57050218B243}.Debug|Any CPU.Build.0 = Debug|Any CPU
38 | {343F37AF-8929-4C43-90F6-57050218B243}.Release|Any CPU.ActiveCfg = Release|Any CPU
39 | {343F37AF-8929-4C43-90F6-57050218B243}.Release|Any CPU.Build.0 = Release|Any CPU
40 | {343F37AF-8929-4C43-90F6-57050218B243}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
41 | {343F37AF-8929-4C43-90F6-57050218B243}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
42 | {343F37AF-8929-4C43-90F6-57050218B243}.Release|iPhone.ActiveCfg = Release|Any CPU
43 | {343F37AF-8929-4C43-90F6-57050218B243}.Release|iPhone.Build.0 = Release|Any CPU
44 | {343F37AF-8929-4C43-90F6-57050218B243}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
45 | {343F37AF-8929-4C43-90F6-57050218B243}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
46 | {343F37AF-8929-4C43-90F6-57050218B243}.Debug|iPhone.ActiveCfg = Debug|Any CPU
47 | {343F37AF-8929-4C43-90F6-57050218B243}.Debug|iPhone.Build.0 = Debug|Any CPU
48 | {49523DF2-73C7-4149-AD32-34B6669B72B8}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator
49 | {49523DF2-73C7-4149-AD32-34B6669B72B8}.Debug|Any CPU.Build.0 = Debug|iPhoneSimulator
50 | {49523DF2-73C7-4149-AD32-34B6669B72B8}.Release|Any CPU.ActiveCfg = Release|iPhone
51 | {49523DF2-73C7-4149-AD32-34B6669B72B8}.Release|Any CPU.Build.0 = Release|iPhone
52 | {49523DF2-73C7-4149-AD32-34B6669B72B8}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
53 | {49523DF2-73C7-4149-AD32-34B6669B72B8}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
54 | {49523DF2-73C7-4149-AD32-34B6669B72B8}.Release|iPhone.ActiveCfg = Release|iPhone
55 | {49523DF2-73C7-4149-AD32-34B6669B72B8}.Release|iPhone.Build.0 = Release|iPhone
56 | {49523DF2-73C7-4149-AD32-34B6669B72B8}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
57 | {49523DF2-73C7-4149-AD32-34B6669B72B8}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
58 | {49523DF2-73C7-4149-AD32-34B6669B72B8}.Debug|iPhone.ActiveCfg = Debug|iPhone
59 | {49523DF2-73C7-4149-AD32-34B6669B72B8}.Debug|iPhone.Build.0 = Debug|iPhone
60 | {5BD2DA5D-406C-4A82-9DBC-A4294B50738A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
61 | {5BD2DA5D-406C-4A82-9DBC-A4294B50738A}.Debug|Any CPU.Build.0 = Debug|Any CPU
62 | {5BD2DA5D-406C-4A82-9DBC-A4294B50738A}.Release|Any CPU.ActiveCfg = Release|Any CPU
63 | {5BD2DA5D-406C-4A82-9DBC-A4294B50738A}.Release|Any CPU.Build.0 = Release|Any CPU
64 | {5BD2DA5D-406C-4A82-9DBC-A4294B50738A}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
65 | {5BD2DA5D-406C-4A82-9DBC-A4294B50738A}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
66 | {5BD2DA5D-406C-4A82-9DBC-A4294B50738A}.Release|iPhone.ActiveCfg = Release|Any CPU
67 | {5BD2DA5D-406C-4A82-9DBC-A4294B50738A}.Release|iPhone.Build.0 = Release|Any CPU
68 | {5BD2DA5D-406C-4A82-9DBC-A4294B50738A}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
69 | {5BD2DA5D-406C-4A82-9DBC-A4294B50738A}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
70 | {5BD2DA5D-406C-4A82-9DBC-A4294B50738A}.Debug|iPhone.ActiveCfg = Debug|Any CPU
71 | {5BD2DA5D-406C-4A82-9DBC-A4294B50738A}.Debug|iPhone.Build.0 = Debug|Any CPU
72 | EndGlobalSection
73 | GlobalSection(NestedProjects) = preSolution
74 | {343F37AF-8929-4C43-90F6-57050218B243} = {BD895E94-AF92-409F-8D79-A5DAD7556CC0}
75 | {49523DF2-73C7-4149-AD32-34B6669B72B8} = {BD895E94-AF92-409F-8D79-A5DAD7556CC0}
76 | {5BD2DA5D-406C-4A82-9DBC-A4294B50738A} = {BD895E94-AF92-409F-8D79-A5DAD7556CC0}
77 | EndGlobalSection
78 | EndGlobal
79 |
--------------------------------------------------------------------------------
/Sources/iOS/AppDelegate.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 |
5 | using Foundation;
6 | using UIKit;
7 |
8 | namespace MarkdownView.Samples.iOS
9 | {
10 | [Register("AppDelegate")]
11 | public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
12 | {
13 | public override bool FinishedLaunching(UIApplication app, NSDictionary options)
14 | {
15 | global::Xamarin.Forms.Forms.Init();
16 |
17 | LoadApplication(new App());
18 |
19 | return base.FinishedLaunching(app, options);
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/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/iOS/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Sources/iOS/Entitlements.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/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/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/Main.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 |
5 | using Foundation;
6 | using UIKit;
7 |
8 | namespace MarkdownView.Samples.iOS
9 | {
10 | public class Application
11 | {
12 | // This is the main entry point of the application.
13 | static void Main(string[] args)
14 | {
15 | // if you want to use a different Application Delegate class from "AppDelegate"
16 | // you can specify it here.
17 | UIApplication.Main(args, null, "AppDelegate");
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Sources/iOS/MarkdownView.Samples.iOS.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | iPhoneSimulator
7 | {49523DF2-73C7-4149-AD32-34B6669B72B8}
8 | {FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
9 | Exe
10 | MarkdownView.Samples.iOS
11 | MarkdownView.Samples.iOS
12 | Resources
13 |
14 |
15 | true
16 | full
17 | false
18 | bin\iPhoneSimulator\Debug
19 | DEBUG;ENABLE_TEST_CLOUD;
20 | prompt
21 | 4
22 | iPhone Developer
23 | true
24 | true
25 | true
26 | 13752
27 | SdkOnly
28 | i386, x86_64
29 | HttpClientHandler
30 | false
31 |
32 |
33 | pdbonly
34 | true
35 | bin\iPhone\Release
36 |
37 | prompt
38 | 4
39 | iPhone Developer
40 | true
41 | Entitlements.plist
42 | SdkOnly
43 | ARMv7, ARM64
44 | HttpClientHandler
45 |
46 |
47 | pdbonly
48 | true
49 | bin\iPhoneSimulator\Release
50 |
51 | prompt
52 | 4
53 | iPhone Developer
54 | true
55 | None
56 | i386, x86_64
57 | HttpClientHandler
58 |
59 |
60 | true
61 | full
62 | false
63 | bin\iPhone\Debug
64 | DEBUG;ENABLE_TEST_CLOUD;
65 | prompt
66 | 4
67 | iPhone Developer
68 | true
69 | true
70 | true
71 | true
72 | true
73 | Entitlements.plist
74 | 46039
75 | SdkOnly
76 | ARMv7, ARM64
77 | HttpClientHandler
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 | ..\packages\Xamarin.Forms.3.0.0.530893\lib\Xamarin.iOS10\Xamarin.Forms.Core.dll
89 |
90 |
91 | ..\packages\Xamarin.Forms.3.0.0.530893\lib\Xamarin.iOS10\Xamarin.Forms.Platform.dll
92 |
93 |
94 | ..\packages\Xamarin.Forms.3.0.0.530893\lib\Xamarin.iOS10\Xamarin.Forms.Platform.iOS.dll
95 |
96 |
97 | ..\packages\Xamarin.Forms.3.0.0.530893\lib\Xamarin.iOS10\Xamarin.Forms.Xaml.dll
98 |
99 |
100 | ..\packages\Markdig.0.15.0\lib\netstandard1.1\Markdig.dll
101 |
102 |
103 | ..\packages\SkiaSharp.1.60.0\lib\XamariniOS\SkiaSharp.dll
104 |
105 |
106 | ..\packages\SkiaSharp.Svg.1.60.0\lib\netstandard2.0\SkiaSharp.Extended.Svg.dll
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 | {343F37AF-8929-4C43-90F6-57050218B243}
131 | MarkdownView.Samples
132 |
133 |
134 | {17728834-C586-4C2E-A1D7-F2E7AD1E1FBF}
135 | Xam.Forms.MarkdownView
136 |
137 |
138 |
139 |
140 |
--------------------------------------------------------------------------------
/Sources/iOS/packages.config:
--------------------------------------------------------------------------------
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 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------