├── .gitattributes
├── .gitignore
├── LICENSE.md
├── NeoMarkdigXaml.sln
├── NeoMarkdigXaml
├── .editorconfig
├── MarkdigXaml.licenseheader
├── MarkdownXaml.Styles.cs
├── MarkdownXaml.cs
├── NeoMarkdigXaml.csproj
├── Properties
│ └── AssemblyInfo.cs
├── Renderers
│ ├── Extensions
│ │ ├── TableRenderer.cs
│ │ └── TaskListRenderer.cs
│ ├── XamlBlockRenderer.cs
│ ├── XamlInlineRenderer.cs
│ └── XamlMarkdownWriter.cs
└── Themes
│ └── generic.xaml
├── README.md
└── Tests
├── MarkdownCompare
├── App.config
├── Markdig-readme.md
├── MarkdigWpf.cs
├── MarkdigXaml.cs
├── MarkdownCompare.csproj
└── Program.cs
├── MarkdownWpfTest
├── App.config
├── App.xaml
├── App.xaml.cs
├── MainWindow.xaml
├── MainWindow.xaml.cs
├── MarkdownWpfTest.csproj
├── Properties
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ ├── Resources.resx
│ ├── Settings.Designer.cs
│ └── Settings.settings
└── Test
│ ├── Issue-6.md
│ └── Issue-9.md
└── MarkdownXamlTest
├── App.config
├── MarkdownXamlTest.csproj
├── Program.cs
└── Properties
└── AssemblyInfo.cs
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # User-specific files (MonoDevelop/Xamarin Studio)
11 | *.userprefs
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Dd]ebugPublic/
16 | [Rr]elease/
17 | [Rr]eleases/
18 | x64/
19 | x86/
20 | bld/
21 | [Bb]in/
22 | [Oo]bj/
23 | [Ll]og/
24 |
25 | # Visual Studio 2015 cache/options directory
26 | .vs/
27 | # Uncomment if you have tasks that create the project's static files in wwwroot
28 | #wwwroot/
29 |
30 | # MSTest test Results
31 | [Tt]est[Rr]esult*/
32 | [Bb]uild[Ll]og.*
33 |
34 | # NUNIT
35 | *.VisualState.xml
36 | TestResult.xml
37 |
38 | # Build Results of an ATL Project
39 | [Dd]ebugPS/
40 | [Rr]eleasePS/
41 | dlldata.c
42 |
43 | # DNX
44 | project.lock.json
45 | project.fragment.lock.json
46 | artifacts/
47 |
48 | *_i.c
49 | *_p.c
50 | *_i.h
51 | *.ilk
52 | *.meta
53 | *.obj
54 | *.pch
55 | *.pdb
56 | *.pgc
57 | *.pgd
58 | *.rsp
59 | *.sbr
60 | *.tlb
61 | *.tli
62 | *.tlh
63 | *.tmp
64 | *.tmp_proj
65 | *.log
66 | *.vspscc
67 | *.vssscc
68 | .builds
69 | *.pidb
70 | *.svclog
71 | *.scc
72 |
73 | # Chutzpah Test files
74 | _Chutzpah*
75 |
76 | # Visual C++ cache files
77 | ipch/
78 | *.aps
79 | *.ncb
80 | *.opendb
81 | *.opensdf
82 | *.sdf
83 | *.cachefile
84 | *.VC.db
85 | *.VC.VC.opendb
86 |
87 | # Visual Studio profiler
88 | *.psess
89 | *.vsp
90 | *.vspx
91 | *.sap
92 |
93 | # TFS 2012 Local Workspace
94 | $tf/
95 |
96 | # Guidance Automation Toolkit
97 | *.gpState
98 |
99 | # ReSharper is a .NET coding add-in
100 | _ReSharper*/
101 | *.[Rr]e[Ss]harper
102 | *.DotSettings.user
103 |
104 | # JustCode is a .NET coding add-in
105 | .JustCode
106 |
107 | # TeamCity is a build add-in
108 | _TeamCity*
109 |
110 | # DotCover is a Code Coverage Tool
111 | *.dotCover
112 |
113 | # NCrunch
114 | _NCrunch_*
115 | .*crunch*.local.xml
116 | nCrunchTemp_*
117 |
118 | # MightyMoose
119 | *.mm.*
120 | AutoTest.Net/
121 |
122 | # Web workbench (sass)
123 | .sass-cache/
124 |
125 | # Installshield output folder
126 | [Ee]xpress/
127 |
128 | # DocProject is a documentation generator add-in
129 | DocProject/buildhelp/
130 | DocProject/Help/*.HxT
131 | DocProject/Help/*.HxC
132 | DocProject/Help/*.hhc
133 | DocProject/Help/*.hhk
134 | DocProject/Help/*.hhp
135 | DocProject/Help/Html2
136 | DocProject/Help/html
137 |
138 | # Click-Once directory
139 | publish/
140 |
141 | # Publish Web Output
142 | *.[Pp]ublish.xml
143 | *.azurePubxml
144 | # TODO: Comment the next line if you want to checkin your web deploy settings
145 | # but database connection strings (with potential passwords) will be unencrypted
146 | #*.pubxml
147 | *.publishproj
148 |
149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
150 | # checkin your Azure Web App publish settings, but sensitive information contained
151 | # in these scripts will be unencrypted
152 | PublishScripts/
153 |
154 | # NuGet Packages
155 | *.nupkg
156 | # The packages folder can be ignored because of Package Restore
157 | **/packages/*
158 | # except build/, which is used as an MSBuild target.
159 | !**/packages/build/
160 | # Uncomment if necessary however generally it will be regenerated when needed
161 | #!**/packages/repositories.config
162 | # NuGet v3's project.json files produces more ignoreable files
163 | *.nuget.props
164 | *.nuget.targets
165 |
166 | # Microsoft Azure Build Output
167 | csx/
168 | *.build.csdef
169 |
170 | # Microsoft Azure Emulator
171 | ecf/
172 | rcf/
173 |
174 | # Windows Store app package directories and files
175 | AppPackages/
176 | BundleArtifacts/
177 | Package.StoreAssociation.xml
178 | _pkginfo.txt
179 |
180 | # Visual Studio cache files
181 | # files ending in .cache can be ignored
182 | *.[Cc]ache
183 | # but keep track of directories ending in .cache
184 | !*.[Cc]ache/
185 |
186 | # Others
187 | ClientBin/
188 | ~$*
189 | *~
190 | *.dbmdl
191 | *.dbproj.schemaview
192 | *.jfm
193 | *.pfx
194 | *.publishsettings
195 | node_modules/
196 | orleans.codegen.cs
197 |
198 | # Since there are multiple workflows, uncomment next line to ignore bower_components
199 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
200 | #bower_components/
201 |
202 | # RIA/Silverlight projects
203 | Generated_Code/
204 |
205 | # Backup & report files from converting an old project file
206 | # to a newer Visual Studio version. Backup files are not needed,
207 | # because we have git ;-)
208 | _UpgradeReport_Files/
209 | Backup*/
210 | UpgradeLog*.XML
211 | UpgradeLog*.htm
212 |
213 | # SQL Server files
214 | *.mdf
215 | *.ldf
216 |
217 | # Business Intelligence projects
218 | *.rdl.data
219 | *.bim.layout
220 | *.bim_*.settings
221 |
222 | # Microsoft Fakes
223 | FakesAssemblies/
224 |
225 | # GhostDoc plugin setting file
226 | *.GhostDoc.xml
227 |
228 | # Node.js Tools for Visual Studio
229 | .ntvs_analysis.dat
230 |
231 | # Visual Studio 6 build log
232 | *.plg
233 |
234 | # Visual Studio 6 workspace options file
235 | *.opt
236 |
237 | # Visual Studio LightSwitch build output
238 | **/*.HTMLClient/GeneratedArtifacts
239 | **/*.DesktopClient/GeneratedArtifacts
240 | **/*.DesktopClient/ModelManifest.xml
241 | **/*.Server/GeneratedArtifacts
242 | **/*.Server/ModelManifest.xml
243 | _Pvt_Extensions
244 |
245 | # Paket dependency manager
246 | .paket/paket.exe
247 | paket-files/
248 |
249 | # FAKE - F# Make
250 | .fake/
251 |
252 | # JetBrains Rider
253 | .idea/
254 | *.sln.iml
255 |
256 | # CodeRush
257 | .cr/
258 |
259 | # Python Tools for Visual Studio (PTVS)
260 | __pycache__/
261 | *.pyc
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright {yyyy} {name of copyright owner}
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/NeoMarkdigXaml.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.28307.271
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NeoMarkdigXaml", "NeoMarkdigXaml\NeoMarkdigXaml.csproj", "{005427DE-3693-4FB3-96A0-1037977D228E}"
7 | EndProject
8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Common", "Common", "{475A25FA-3F96-4640-BE39-1E56139045A9}"
9 | ProjectSection(SolutionItems) = preProject
10 | LICENSE.md = LICENSE.md
11 | README.md = README.md
12 | EndProjectSection
13 | EndProject
14 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{C994D1DA-027B-43D0-8CAC-9ED42D396197}"
15 | EndProject
16 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MarkdownWpfTest", "Tests\MarkdownWpfTest\MarkdownWpfTest.csproj", "{B884181B-0885-4BF6-87E5-A794EB12A807}"
17 | EndProject
18 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MarkdownXamlTest", "Tests\MarkdownXamlTest\MarkdownXamlTest.csproj", "{F1B116DA-1779-49DC-9E9D-094BDEBF2A49}"
19 | EndProject
20 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MarkdownCompare", "Tests\MarkdownCompare\MarkdownCompare.csproj", "{86DA9A8A-11E0-4A8B-94B8-E1A89208830B}"
21 | EndProject
22 | Global
23 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
24 | Debug|Any CPU = Debug|Any CPU
25 | Release|Any CPU = Release|Any CPU
26 | EndGlobalSection
27 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
28 | {005427DE-3693-4FB3-96A0-1037977D228E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
29 | {005427DE-3693-4FB3-96A0-1037977D228E}.Debug|Any CPU.Build.0 = Debug|Any CPU
30 | {005427DE-3693-4FB3-96A0-1037977D228E}.Release|Any CPU.ActiveCfg = Release|Any CPU
31 | {005427DE-3693-4FB3-96A0-1037977D228E}.Release|Any CPU.Build.0 = Release|Any CPU
32 | {B884181B-0885-4BF6-87E5-A794EB12A807}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
33 | {B884181B-0885-4BF6-87E5-A794EB12A807}.Debug|Any CPU.Build.0 = Debug|Any CPU
34 | {B884181B-0885-4BF6-87E5-A794EB12A807}.Release|Any CPU.ActiveCfg = Release|Any CPU
35 | {B884181B-0885-4BF6-87E5-A794EB12A807}.Release|Any CPU.Build.0 = Release|Any CPU
36 | {F1B116DA-1779-49DC-9E9D-094BDEBF2A49}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
37 | {F1B116DA-1779-49DC-9E9D-094BDEBF2A49}.Debug|Any CPU.Build.0 = Debug|Any CPU
38 | {F1B116DA-1779-49DC-9E9D-094BDEBF2A49}.Release|Any CPU.ActiveCfg = Release|Any CPU
39 | {F1B116DA-1779-49DC-9E9D-094BDEBF2A49}.Release|Any CPU.Build.0 = Release|Any CPU
40 | {86DA9A8A-11E0-4A8B-94B8-E1A89208830B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
41 | {86DA9A8A-11E0-4A8B-94B8-E1A89208830B}.Debug|Any CPU.Build.0 = Debug|Any CPU
42 | {86DA9A8A-11E0-4A8B-94B8-E1A89208830B}.Release|Any CPU.ActiveCfg = Release|Any CPU
43 | {86DA9A8A-11E0-4A8B-94B8-E1A89208830B}.Release|Any CPU.Build.0 = Release|Any CPU
44 | EndGlobalSection
45 | GlobalSection(SolutionProperties) = preSolution
46 | HideSolutionNode = FALSE
47 | EndGlobalSection
48 | GlobalSection(NestedProjects) = preSolution
49 | {B884181B-0885-4BF6-87E5-A794EB12A807} = {C994D1DA-027B-43D0-8CAC-9ED42D396197}
50 | {F1B116DA-1779-49DC-9E9D-094BDEBF2A49} = {C994D1DA-027B-43D0-8CAC-9ED42D396197}
51 | EndGlobalSection
52 | GlobalSection(ExtensibilityGlobals) = postSolution
53 | SolutionGuid = {CB3B2047-3563-4FD0-A891-3838E1664EBC}
54 | EndGlobalSection
55 | EndGlobal
56 |
--------------------------------------------------------------------------------
/NeoMarkdigXaml/.editorconfig:
--------------------------------------------------------------------------------
1 | # You can learn more about editorconfig here: https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-code-style-settings-reference
2 | [*.cs]
3 |
4 |
5 | #Core editorconfig formatting - indentation
6 |
7 | #use hard tabs for indentation
8 | indent_style = tab
9 |
10 | #Formatting - new line options
11 |
12 | #place else statements on a new line
13 | csharp_new_line_before_else = true
14 | #require braces to be on a new line for control_blocks, types, and methods (also known as "Allman" style)
15 | csharp_new_line_before_open_brace = control_blocks, types, methods
16 |
17 | #Formatting - organize using options
18 |
19 | #sort System.* using directives alphabetically, and place them before other usings
20 | dotnet_sort_system_directives_first = true
21 |
22 | #Formatting - spacing options
23 |
24 | #require NO space between a cast and the value
25 | csharp_space_after_cast = false
26 | #require a space before the colon for bases or interfaces in a type declaration
27 | csharp_space_after_colon_in_inheritance_clause = true
28 | #require a space after a keyword in a control flow statement such as a for loop
29 | csharp_space_after_keywords_in_control_flow_statements = true
30 | #require a space before the colon for bases or interfaces in a type declaration
31 | csharp_space_before_colon_in_inheritance_clause = true
32 | #remove space within empty argument list parentheses
33 | csharp_space_between_method_call_empty_parameter_list_parentheses = false
34 | #remove space between method call name and opening parenthesis
35 | csharp_space_between_method_call_name_and_opening_parenthesis = false
36 | #do not place space characters after the opening parenthesis and before the closing parenthesis of a method call
37 | csharp_space_between_method_call_parameter_list_parentheses = false
38 | #remove space within empty parameter list parentheses for a method declaration
39 | csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
40 | #place a space character after the opening parenthesis and before the closing parenthesis of a method declaration parameter list.
41 | csharp_space_between_method_declaration_parameter_list_parentheses = false
42 |
43 | #Formatting - wrapping options
44 |
45 | #leave code block on single line
46 | csharp_preserve_single_line_blocks = true
47 |
48 | #Style - Code block preferences
49 |
50 | #prefer no curly braces if allowed
51 | csharp_prefer_braces = false:suggestion
52 |
53 | #Style - expression bodied member options
54 |
55 | #prefer expression-bodied members for constructors
56 | csharp_style_expression_bodied_constructors = true:suggestion
57 | #prefer expression-bodied members for methods
58 | csharp_style_expression_bodied_methods = true:suggestion
59 | #prefer expression-bodied members for properties
60 | csharp_style_expression_bodied_properties = true:suggestion
61 |
62 | #Style - expression level options
63 |
64 | #prefer the type name for member access expressions, instead of the language keyword
65 | dotnet_style_predefined_type_for_member_access = false:suggestion
66 |
67 | #Style - Expression-level preferences
68 |
69 | #prefer objects to be initialized using object initializers when possible
70 | dotnet_style_object_initializer = true:suggestion
71 |
72 | #Style - implicit and explicit types
73 |
74 | #prefer var over explicit type in all cases, unless overridden by another code style rule
75 | csharp_style_var_elsewhere = true:suggestion
76 | #prefer var is used to declare variables with built-in system types such as int
77 | csharp_style_var_for_built_in_types = true:suggestion
78 | #prefer var when the type is already mentioned on the right-hand side of a declaration expression
79 | csharp_style_var_when_type_is_apparent = true:suggestion
80 |
81 | #Style - language keyword and framework type options
82 |
83 | #prefer the language keyword for local variables, method parameters, and class members, instead of the type name, for types that have a keyword to represent them
84 | dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
85 |
86 | #Style - modifier options
87 |
88 | #prefer accessibility modifiers to be declared except for public interface members. This will currently not differ from always and will act as future proofing for if C# adds default interface methods.
89 | dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion
90 |
91 | #Style - Modifier preferences
92 |
93 | #when this rule is set to a list of modifiers, prefer the specified ordering.
94 | csharp_preferred_modifier_order = public,protected,private,internal,static,override,sealed:suggestion
95 |
96 | #Style - Pattern matching
97 |
98 | #prefer pattern matching instead of is expression with type casts
99 | csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
100 |
101 | #Style - qualification options
102 |
103 | #prefer properties not to be prefaced with this. or Me. in Visual Basic
104 | dotnet_style_qualification_for_property = false:suggestion
105 |
--------------------------------------------------------------------------------
/NeoMarkdigXaml/MarkdigXaml.licenseheader:
--------------------------------------------------------------------------------
1 | extensions: designer.cs generated.cs
2 | extensions: .cs
3 | #region -- copyright --
4 | //
5 | // Licensed to the Apache Software Foundation (ASF) under one
6 | // or more contributor license agreements. See the NOTICE file
7 | // distributed with this work for additional information
8 | // regarding copyright ownership. The ASF licenses this file
9 | // to you under the Apache License, Version 2.0 (the
10 | // "License"); you may not use this file except in compliance
11 | // with the License. You may obtain a copy of the License at
12 | //
13 | // http://www.apache.org/licenses/LICENSE-2.0
14 | //
15 | // Unless required by applicable law or agreed to in writing,
16 | // software distributed under the License is distributed on an
17 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18 | // KIND, either express or implied. See the License for the
19 | // specific language governing permissions and limitations
20 | // under the License.
21 | //
22 | #endregion
23 | extensions: .vb
24 | #Region "-- copyright --"
25 | '
26 | ' Licensed to the Apache Software Foundation (ASF) under one
27 | ' or more contributor license agreements. See the NOTICE file
28 | ' distributed with this work for additional information
29 | ' regarding copyright ownership. The ASF licenses this file
30 | ' to you under the Apache License, Version 2.0 (the
31 | ' "License"); you may not use this file except in compliance
32 | ' with the License. You may obtain a copy of the License at
33 | '
34 | ' http://www.apache.org/licenses/LICENSE-2.0
35 | '
36 | ' Unless required by applicable law or agreed to in writing,
37 | ' software distributed under the License is distributed on an
38 | ' "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
39 | ' KIND, either express or implied. See the License for the
40 | ' specific language governing permissions and limitations
41 | ' under the License.
42 | '
43 | #End Region
--------------------------------------------------------------------------------
/NeoMarkdigXaml/MarkdownXaml.Styles.cs:
--------------------------------------------------------------------------------
1 | #region -- copyright --
2 | //
3 | // Licensed to the Apache Software Foundation (ASF) under one
4 | // or more contributor license agreements. See the NOTICE file
5 | // distributed with this work for additional information
6 | // regarding copyright ownership. The ASF licenses this file
7 | // to you under the Apache License, Version 2.0 (the
8 | // "License"); you may not use this file except in compliance
9 | // with the License. You may obtain a copy of the License at
10 | //
11 | // http://www.apache.org/licenses/LICENSE-2.0
12 | //
13 | // Unless required by applicable law or agreed to in writing,
14 | // software distributed under the License is distributed on an
15 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | // KIND, either express or implied. See the License for the
17 | // specific language governing permissions and limitations
18 | // under the License.
19 | //
20 | #endregion
21 | using System.ComponentModel;
22 | using System.Reflection;
23 | using System.Windows;
24 | using System.Windows.Input;
25 |
26 | namespace Neo.Markdig.Xaml
27 | {
28 | ///
29 | public enum MarkdownXamlStyle
30 | {
31 | /// Resource Key for the DocumentStyle.
32 | Document,
33 | /// Resource Key for the CodeStyle.
34 | Code,
35 | /// Resource Key for the CodeBlockStyle.
36 | CodeBlock,
37 | /// Resource Key for the Heading1Style.
38 | Heading1,
39 | /// Resource Key for the Heading2Style.
40 | Heading2,
41 | /// Resource Key for the Heading3Style.
42 | Heading3,
43 | /// Resource Key for the Heading4Style.
44 | Heading4,
45 | /// Resource Key for the Heading5Style.
46 | Heading5,
47 | /// Resource Key for the Heading6Style.
48 | Heading6,
49 | /// Resource Key for the ImageStyle.
50 | Image,
51 | /// Resource Key for the InsertedStyle.
52 | Inserted,
53 | /// Resource Key for the MarkedStyle.
54 | Marked,
55 | /// Resource Key for the QuoteBlockStyle.
56 | QuoteBlock,
57 | /// Resource Key for the StrikeThroughStyle.
58 | StrikeThrough,
59 | /// Resource Key for the SubscriptStyle.
60 | Subscript,
61 | /// Resource Key for the SuperscriptStyle.
62 | Superscript,
63 | /// Resource Key for the TableStyle.
64 | Table,
65 | /// Resource Key for the TableCellStyle.
66 | TableCell,
67 | /// Resource Key for the TableHeaderStyle.
68 | TableHeader,
69 | /// Resource Key for the TaskListStyle.
70 | TaskList,
71 | /// Resource Key for the ThematicBreakStyle.
72 | ThematicBreak,
73 | ///
74 | Hyperlink
75 | } // enum MarkdownXamlStyle
76 |
77 | public static partial class MarkdownXaml
78 | {
79 | #region -- class StyleResourceKey----------------------------------------------
80 |
81 | private sealed class StyleResourceKey : ResourceKey
82 | {
83 | public StyleResourceKey(string key)
84 | => Key = key;
85 |
86 | public override string ToString()
87 | => "XamlStyle: " + Key;
88 |
89 | public override bool Equals(object obj)
90 | => obj is StyleResourceKey srk ? Key.Equals(srk.Key) : base.Equals(obj);
91 |
92 | public override int GetHashCode()
93 | => Assembly.GetHashCode() ^ Key.GetHashCode();
94 |
95 | public string Key { get; }
96 | public override Assembly Assembly => typeof(StyleResourceKey).Assembly;
97 | } // class StyleResourceKey
98 |
99 | #endregion
100 |
101 | /// Resource Key for the DocumentStyle.
102 | [EditorBrowsable(EditorBrowsableState.Advanced)]
103 | public static ResourceKey DocumentStyleKey { get; } = new StyleResourceKey(nameof(DocumentStyleKey));
104 |
105 | /// Resource Key for the CodeStyle.
106 | [EditorBrowsable(EditorBrowsableState.Advanced)]
107 | public static ResourceKey CodeStyleKey { get; } = new StyleResourceKey(nameof(CodeStyleKey));
108 |
109 | /// Resource Key for the CodeBlockStyle.
110 | [EditorBrowsable(EditorBrowsableState.Advanced)]
111 | public static ResourceKey CodeBlockStyleKey { get; } = new StyleResourceKey(nameof(CodeBlockStyleKey));
112 |
113 | /// Resource Key for the Heading1Style.
114 | [EditorBrowsable(EditorBrowsableState.Advanced)]
115 | public static ResourceKey Heading1StyleKey { get; } = new StyleResourceKey(nameof(Heading1StyleKey));
116 |
117 | /// Resource Key for the Heading2Style.
118 | [EditorBrowsable(EditorBrowsableState.Advanced)]
119 | public static ResourceKey Heading2StyleKey { get; } = new StyleResourceKey(nameof(Heading2StyleKey));
120 |
121 | /// Resource Key for the Heading3Style.
122 | [EditorBrowsable(EditorBrowsableState.Advanced)]
123 | public static ResourceKey Heading3StyleKey { get; } = new StyleResourceKey(nameof(Heading3StyleKey));
124 |
125 | /// Resource Key for the Heading4Style.
126 | [EditorBrowsable(EditorBrowsableState.Advanced)]
127 | public static ResourceKey Heading4StyleKey { get; } = new StyleResourceKey(nameof(Heading4StyleKey));
128 |
129 | /// Resource Key for the Heading5Style.
130 | [EditorBrowsable(EditorBrowsableState.Advanced)]
131 | public static ResourceKey Heading5StyleKey { get; } = new StyleResourceKey(nameof(Heading5StyleKey));
132 |
133 | /// Resource Key for the Heading6Style.
134 | [EditorBrowsable(EditorBrowsableState.Advanced)]
135 | public static ResourceKey Heading6StyleKey { get; } = new StyleResourceKey(nameof(Heading6StyleKey));
136 |
137 | /// Resource Key for the ImageStyle.
138 | [EditorBrowsable(EditorBrowsableState.Advanced)]
139 | public static ResourceKey ImageStyleKey { get; } = new StyleResourceKey(nameof(ImageStyleKey));
140 |
141 | /// Resource Key for the InsertedStyle.
142 | [EditorBrowsable(EditorBrowsableState.Advanced)]
143 | public static ResourceKey InsertedStyleKey { get; } = new StyleResourceKey(nameof(InsertedStyleKey));
144 |
145 | /// Resource Key for the MarkedStyle.
146 | [EditorBrowsable(EditorBrowsableState.Advanced)]
147 | public static ResourceKey MarkedStyleKey { get; } = new StyleResourceKey(nameof(MarkedStyleKey));
148 |
149 | /// Resource Key for the QuoteBlockStyle.
150 | [EditorBrowsable(EditorBrowsableState.Advanced)]
151 | public static ResourceKey QuoteBlockStyleKey { get; } = new StyleResourceKey(nameof(QuoteBlockStyleKey));
152 |
153 | /// Resource Key for the StrikeThroughStyle.
154 | [EditorBrowsable(EditorBrowsableState.Advanced)]
155 | public static ResourceKey StrikeThroughStyleKey { get; } = new StyleResourceKey(nameof(StrikeThroughStyleKey));
156 |
157 | /// Resource Key for the SubscriptStyle.
158 | [EditorBrowsable(EditorBrowsableState.Advanced)]
159 | public static ResourceKey SubscriptStyleKey { get; } = new StyleResourceKey(nameof(SubscriptStyleKey));
160 |
161 | /// Resource Key for the SuperscriptStyle.
162 | [EditorBrowsable(EditorBrowsableState.Advanced)]
163 | public static ResourceKey SuperscriptStyleKey { get; } = new StyleResourceKey(nameof(SuperscriptStyleKey));
164 |
165 | /// Resource Key for the TableStyle.
166 | [EditorBrowsable(EditorBrowsableState.Advanced)]
167 | public static ResourceKey TableStyleKey { get; } = new StyleResourceKey(nameof(TableStyleKey));
168 |
169 | /// Resource Key for the TableCellStyle.
170 | [EditorBrowsable(EditorBrowsableState.Advanced)]
171 | public static ResourceKey TableCellStyleKey { get; } = new StyleResourceKey(nameof(TableCellStyleKey));
172 |
173 | /// Resource Key for the TableHeaderStyle.
174 | [EditorBrowsable(EditorBrowsableState.Advanced)]
175 | public static ResourceKey TableHeaderStyleKey { get; } = new StyleResourceKey(nameof(TableHeaderStyleKey));
176 |
177 | /// Resource Key for the TaskListStyle.
178 | [EditorBrowsable(EditorBrowsableState.Advanced)]
179 | public static ResourceKey TaskListStyleKey { get; } = new StyleResourceKey(nameof(TaskListStyleKey));
180 |
181 | /// Resource Key for the ThematicBreakStyle.
182 | [EditorBrowsable(EditorBrowsableState.Advanced)]
183 | public static ResourceKey ThematicBreakStyleKey { get; } = new StyleResourceKey(nameof(ThematicBreakStyleKey));
184 |
185 | ///
186 | [EditorBrowsable(EditorBrowsableState.Advanced)]
187 | public static ResourceKey HyperlinkStyleKey { get; } = new StyleResourceKey(nameof(HyperlinkStyleKey));
188 |
189 | /// Routed command for Hyperlink.
190 | public static RoutedCommand Hyperlink { get; } = new RoutedCommand(nameof(Hyperlink), typeof(MarkdownXaml));
191 | } // classs MarkdownXaml
192 | }
193 |
--------------------------------------------------------------------------------
/NeoMarkdigXaml/MarkdownXaml.cs:
--------------------------------------------------------------------------------
1 | #region -- copyright --
2 | //
3 | // Licensed to the Apache Software Foundation (ASF) under one
4 | // or more contributor license agreements. See the NOTICE file
5 | // distributed with this work for additional information
6 | // regarding copyright ownership. The ASF licenses this file
7 | // to you under the Apache License, Version 2.0 (the
8 | // "License"); you may not use this file except in compliance
9 | // with the License. You may obtain a copy of the License at
10 | //
11 | // http://www.apache.org/licenses/LICENSE-2.0
12 | //
13 | // Unless required by applicable law or agreed to in writing,
14 | // software distributed under the License is distributed on an
15 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | // KIND, either express or implied. See the License for the
17 | // specific language governing permissions and limitations
18 | // under the License.
19 | //
20 | #endregion
21 | using System;
22 | using System.IO;
23 | using System.Windows.Documents;
24 | using System.Xaml;
25 | using Markdig;
26 | using Neo.Markdig.Xaml.Renderers;
27 |
28 | namespace Neo.Markdig.Xaml
29 | {
30 | public static partial class MarkdownXaml
31 | {
32 | /// Converts a Markdown string to a FlowDocument.
33 | /// A Markdown text.
34 | /// The pipeline used for the conversion.
35 | /// Base uri for images and links.
36 | /// The result of the conversion
37 | /// if markdown variable is null
38 | public static FlowDocument ToFlowDocument(string markdown, MarkdownPipeline pipeline = null, Uri baseUri = null)
39 | {
40 | if (markdown == null)
41 | throw new ArgumentNullException(nameof(markdown));
42 | if (pipeline == null)
43 | pipeline = new MarkdownPipelineBuilder().Build();
44 |
45 | using (var writer = new XamlObjectWriter(System.Windows.Markup.XamlReader.GetWpfSchemaContext()))
46 | return (FlowDocument)ToXaml(markdown, writer, pipeline, baseUri);
47 | } // func ToFlowDocument
48 |
49 | /// Converts a Markdown string to XAML.
50 | /// A Markdown text.
51 | /// The pipeline used for the conversion.
52 | /// Base uri for images and links.
53 | /// The result of the conversion
54 | /// if markdown variable is null
55 | public static string ToXaml(string markdown, MarkdownPipeline pipeline = null, Uri baseUri = null)
56 | {
57 | if (markdown == null)
58 | throw new ArgumentNullException(nameof(markdown));
59 |
60 | using (var writer = new StringWriter())
61 | {
62 | ToXaml(markdown, writer, pipeline, baseUri);
63 | return writer.ToString();
64 | }
65 | } // func ToXaml
66 |
67 | /// Converts a Markdown string to XAML and output to the specified writer.
68 | /// A Markdown text.
69 | /// The destination that will receive the result of the conversion.
70 | /// The pipeline used for the conversion.
71 | /// Base uri for images and links.
72 | public static void ToXaml(string markdown, TextWriter writer, MarkdownPipeline pipeline = null, Uri baseUri = null)
73 | {
74 | if (markdown == null)
75 | throw new ArgumentNullException(nameof(markdown));
76 | if (writer == null)
77 | throw new ArgumentNullException(nameof(writer));
78 |
79 | using (var xamlWriter = new XamlXmlWriter(writer, System.Windows.Markup.XamlReader.GetWpfSchemaContext(), new XamlXmlWriterSettings() { CloseOutput = false }))
80 | {
81 | ToXaml(markdown, xamlWriter, pipeline, baseUri);
82 | xamlWriter.Flush();
83 | }
84 | } // func ToXaml
85 |
86 |
87 | /// Converts a Markdown string to XAML and output to the specified writer.
88 | /// A Markdown text.
89 | /// The destination that will receive the result of the conversion.
90 | /// The pipeline used for the conversion.
91 | /// Base uri for images and links.
92 | ///
93 | public static object ToXaml(string markdown, XamlWriter writer, MarkdownPipeline pipeline = null, Uri baseUri = null)
94 | {
95 | if (writer == null)
96 | throw new ArgumentNullException(nameof(writer));
97 | pipeline = pipeline ?? new MarkdownPipelineBuilder().Build();
98 |
99 | var renderer = new XamlMarkdownWriter(writer) { BaseUri = baseUri };
100 | pipeline.Setup(renderer);
101 |
102 | var document = Markdown.Parse(markdown, pipeline);
103 | return renderer.Render(document);
104 | } // proc ToXaml
105 |
106 | public static MarkdownPipelineBuilder UseXamlSupportedExtensions(this MarkdownPipelineBuilder pipeline)
107 | {
108 | if (pipeline == null)
109 | throw new ArgumentNullException(nameof(pipeline));
110 | return pipeline
111 | .UseEmphasisExtras()
112 | .UseGridTables()
113 | .UsePipeTables()
114 | .UseTaskLists()
115 | .UseAutoLinks();
116 | } // func UseXamlSupportedExtensions
117 | } // class MarkdownXaml
118 | }
119 |
--------------------------------------------------------------------------------
/NeoMarkdigXaml/NeoMarkdigXaml.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp3.1;net47
5 | Neo.Markdig.Xaml
6 | Neo.Markdig.Xaml
7 | Neolithos
8 | TecWare Gesellschaft für Softwareentwicklung mbH
9 | Xaml/wpf extension for lunet-io/markdig.
10 | TecWare Gesellschaft für Softwareentwicklung mbH
11 | https://github.com/neolithos/NeoMarkdigXaml/blob/master/LICENSE.md
12 | https://github.com/neolithos/NeoMarkdigXaml
13 | https://github.com/neolithos/NeoMarkdigXaml.git
14 | git
15 | markdig markdown xaml wpf
16 | true
17 | 1.0.10
18 | 1.0.10.0
19 | true
20 | 1.0.10.0
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/NeoMarkdigXaml/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 |
3 | [assembly: ThemeInfo(ResourceDictionaryLocation.SourceAssembly, ResourceDictionaryLocation.SourceAssembly)]
4 |
--------------------------------------------------------------------------------
/NeoMarkdigXaml/Renderers/Extensions/TableRenderer.cs:
--------------------------------------------------------------------------------
1 | #region -- copyright --
2 | //
3 | // Licensed to the Apache Software Foundation (ASF) under one
4 | // or more contributor license agreements. See the NOTICE file
5 | // distributed with this work for additional information
6 | // regarding copyright ownership. The ASF licenses this file
7 | // to you under the Apache License, Version 2.0 (the
8 | // "License"); you may not use this file except in compliance
9 | // with the License. You may obtain a copy of the License at
10 | //
11 | // http://www.apache.org/licenses/LICENSE-2.0
12 | //
13 | // Unless required by applicable law or agreed to in writing,
14 | // software distributed under the License is distributed on an
15 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | // KIND, either express or implied. See the License for the
17 | // specific language governing permissions and limitations
18 | // under the License.
19 | //
20 | #endregion
21 | using System.Windows;
22 | using Markdig.Extensions.Tables;
23 | using MdTable = Markdig.Extensions.Tables.Table;
24 | using MdTableCell = Markdig.Extensions.Tables.TableCell;
25 | using MdTableRow = Markdig.Extensions.Tables.TableRow;
26 | using WpfTable = System.Windows.Documents.Table;
27 | using WpfTableCell = System.Windows.Documents.TableCell;
28 | using WpfTableColumn = System.Windows.Documents.TableColumn;
29 | using WpfTableRow = System.Windows.Documents.TableRow;
30 | using WpfTableRowGroup = System.Windows.Documents.TableRowGroup;
31 |
32 | namespace Neo.Markdig.Xaml.Renderers.Extensions
33 | {
34 | #region -- class TableRenderer ----------------------------------------------------
35 |
36 | public class TableRenderer : XamlObjectRenderer
37 | {
38 | protected override void Write(XamlMarkdownWriter renderer, MdTable table)
39 | {
40 | renderer.WriteStartObject(typeof(WpfTable));
41 | renderer.WriteResourceMember(null, MarkdownXamlStyle.Table);
42 | var t = new WpfTable();
43 |
44 | renderer.WriteStartItems(nameof(WpfTable.Columns));
45 | foreach(var col in table.ColumnDefinitions)
46 | {
47 | renderer.WriteStartObject(typeof(WpfTableColumn));
48 | renderer.WriteMember(nameof(WpfTableColumn.Width),
49 | (col?.Width ?? 0) != 0
50 | ? new GridLength(col.Width, GridUnitType.Star)
51 | : GridLength.Auto
52 | );
53 | renderer.WriteEndObject();
54 | }
55 | renderer.WriteEndItems();
56 |
57 | renderer.WriteStartItems(nameof(WpfTable.RowGroups));
58 | renderer.WriteStartObject(typeof(WpfTableRowGroup));
59 | renderer.WriteStartItems(nameof(WpfTableRowGroup.Rows));
60 |
61 | foreach (var c in table)
62 | {
63 | var row = (MdTableRow)c;
64 | renderer.WriteStartObject(typeof(WpfTableRow));
65 | if (row.IsHeader)
66 | renderer.WriteResourceMember(null, MarkdownXamlStyle.TableHeader);
67 | renderer.WriteStartItems(nameof(WpfTableRow.Cells));
68 |
69 | for (var i = 0; i < row.Count; i++)
70 | {
71 | var cell = (MdTableCell)row[i];
72 | renderer.WriteStartObject(typeof(WpfTableCell));
73 | renderer.WriteResourceMember(null, MarkdownXamlStyle.TableCell);
74 |
75 | if (cell.ColumnSpan > 1)
76 | renderer.WriteMember(nameof(WpfTableCell.ColumnSpan), cell.ColumnSpan);
77 | if (cell.RowSpan > 1)
78 | renderer.WriteMember(nameof(WpfTableCell.RowSpan), cell.RowSpan);
79 |
80 | var columnIndex = cell.ColumnIndex < 0 || cell.ColumnIndex >= table.ColumnDefinitions.Count ? i : cell.ColumnIndex;
81 | columnIndex = columnIndex >= table.ColumnDefinitions.Count ? table.ColumnDefinitions.Count - 1 : columnIndex;
82 | var alignment = table.ColumnDefinitions[columnIndex].Alignment;
83 | if (alignment.HasValue)
84 | {
85 | switch (alignment)
86 | {
87 | case TableColumnAlign.Center:
88 | renderer.WriteMember(nameof(WpfTableCell.TextAlignment), TextAlignment.Center);
89 | break;
90 | case TableColumnAlign.Right:
91 | renderer.WriteMember(nameof(WpfTableCell.TextAlignment), TextAlignment.Right);
92 | break;
93 | case TableColumnAlign.Left:
94 | renderer.WriteMember(nameof(WpfTableCell.TextAlignment), TextAlignment.Left);
95 | break;
96 | }
97 | }
98 |
99 | renderer.WriteItems(cell);
100 |
101 | renderer.WriteEndObject();
102 | }
103 |
104 | renderer.WriteEndItems();
105 | renderer.WriteEndObject();
106 | }
107 |
108 | renderer.WriteEndItems();
109 | renderer.WriteEndObject();
110 | renderer.WriteEndItems();
111 |
112 | renderer.WriteEndObject();
113 | } // proc Write
114 | } // class TableRenderer
115 |
116 | #endregion
117 | }
118 |
--------------------------------------------------------------------------------
/NeoMarkdigXaml/Renderers/Extensions/TaskListRenderer.cs:
--------------------------------------------------------------------------------
1 | #region -- copyright --
2 | //
3 | // Licensed to the Apache Software Foundation (ASF) under one
4 | // or more contributor license agreements. See the NOTICE file
5 | // distributed with this work for additional information
6 | // regarding copyright ownership. The ASF licenses this file
7 | // to you under the Apache License, Version 2.0 (the
8 | // "License"); you may not use this file except in compliance
9 | // with the License. You may obtain a copy of the License at
10 | //
11 | // http://www.apache.org/licenses/LICENSE-2.0
12 | //
13 | // Unless required by applicable law or agreed to in writing,
14 | // software distributed under the License is distributed on an
15 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | // KIND, either express or implied. See the License for the
17 | // specific language governing permissions and limitations
18 | // under the License.
19 | //
20 | #endregion
21 | using Markdig.Extensions.TaskLists;
22 |
23 | namespace Neo.Markdig.Xaml.Renderers.Extensions
24 | {
25 | ///
26 | public class TaskListRenderer : XamlObjectRenderer
27 | {
28 | ///
29 | ///
30 | ///
31 | protected override void Write(XamlMarkdownWriter renderer, TaskList taskList)
32 | {
33 | //var checkBox = new CheckBox
34 | //{
35 | // IsEnabled = false,
36 | // IsChecked = taskList.Checked,
37 | //};
38 |
39 | //checkBox.SetResourceReference(FrameworkContentElement.StyleProperty, Styles.TaskListStyleKey);
40 | //renderer.WriteInline(new InlineUIContainer(checkBox));
41 | } // proc Write
42 | } // class TaskListRenderer
43 | }
44 |
--------------------------------------------------------------------------------
/NeoMarkdigXaml/Renderers/XamlBlockRenderer.cs:
--------------------------------------------------------------------------------
1 | #region -- copyright --
2 | //
3 | // Licensed to the Apache Software Foundation (ASF) under one
4 | // or more contributor license agreements. See the NOTICE file
5 | // distributed with this work for additional information
6 | // regarding copyright ownership. The ASF licenses this file
7 | // to you under the Apache License, Version 2.0 (the
8 | // "License"); you may not use this file except in compliance
9 | // with the License. You may obtain a copy of the License at
10 | //
11 | // http://www.apache.org/licenses/LICENSE-2.0
12 | //
13 | // Unless required by applicable law or agreed to in writing,
14 | // software distributed under the License is distributed on an
15 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | // KIND, either express or implied. See the License for the
17 | // specific language governing permissions and limitations
18 | // under the License.
19 | //
20 | #endregion
21 | using System.Windows;
22 | using System.Windows.Documents;
23 | using Markdig.Syntax;
24 |
25 | namespace Neo.Markdig.Xaml.Renderers
26 | {
27 | #region -- class ParagraphRenderer ------------------------------------------------
28 |
29 | public class ParagraphRenderer : XamlObjectRenderer
30 | {
31 | protected override void Write(XamlMarkdownWriter renderer, ParagraphBlock paragraph)
32 | {
33 | renderer.WriteStartObject(typeof(Paragraph));
34 | renderer.WriteItems(paragraph);
35 | renderer.WriteEndObject();
36 | } // proc Write
37 | } // class ParagraphRenderer
38 |
39 | #endregion
40 |
41 | #region -- class HeadingRenderer --------------------------------------------------
42 |
43 | public class HeadingRenderer : XamlObjectRenderer
44 | {
45 | private static MarkdownXamlStyle GetStyleKey(int level)
46 | {
47 | switch (level)
48 | {
49 | case 1:
50 | return MarkdownXamlStyle.Heading1;
51 | case 2:
52 | return MarkdownXamlStyle.Heading2;
53 | case 3:
54 | return MarkdownXamlStyle.Heading3;
55 | case 4:
56 | return MarkdownXamlStyle.Heading4;
57 | case 5:
58 | return MarkdownXamlStyle.Heading5;
59 | default:
60 | return MarkdownXamlStyle.Heading6;
61 | }
62 | } // func GetStyleKey
63 |
64 | protected override void Write(XamlMarkdownWriter renderer, HeadingBlock headingBlock)
65 | {
66 | renderer.WriteStartObject(typeof(Paragraph));
67 | renderer.WriteResourceMember(null, GetStyleKey(headingBlock.Level));
68 | renderer.WriteItems(headingBlock);
69 | renderer.WriteEndObject();
70 | } // proc Write
71 | } // class HeadingRenderer
72 |
73 | #endregion
74 |
75 | #region -- class CodeBlockRenderer ------------------------------------------------
76 |
77 | public class CodeBlockRenderer : XamlObjectRenderer
78 | {
79 | protected override void Write(XamlMarkdownWriter renderer, CodeBlock obj)
80 | {
81 | renderer.WriteStartObject(typeof(Paragraph));
82 | renderer.WriteResourceMember(null, MarkdownXamlStyle.CodeBlock);
83 | //if (obj is FencedCodeBlock f)
84 | // f.Info;
85 | renderer.WriteItems(obj, true);
86 | renderer.WriteEndObject();
87 | } // proc Write
88 | } // class CodeBlockRenderer
89 |
90 | #endregion
91 |
92 | #region -- class ListRenderer -----------------------------------------------------
93 |
94 | public class ListRenderer : XamlObjectRenderer
95 | {
96 | protected override void Write(XamlMarkdownWriter renderer, ListBlock listBlock)
97 | {
98 | renderer.WriteStartObject(typeof(List));
99 |
100 | if (listBlock.IsOrdered)
101 | {
102 | renderer.WriteMember(List.MarkerStyleProperty, TextMarkerStyle.Decimal);
103 |
104 | if (listBlock.OrderedStart != null && (listBlock.DefaultOrderedStart != listBlock.OrderedStart))
105 | renderer.WriteMember(List.StartIndexProperty, listBlock.OrderedStart);
106 | }
107 | else
108 | renderer.WriteMember(List.MarkerStyleProperty, TextMarkerStyle.Disc);
109 |
110 | renderer.WriteStartItems(nameof(List.ListItems));
111 |
112 | foreach (var cur in listBlock)
113 | {
114 | renderer.WriteStartObject(typeof(ListItem));
115 | renderer.WriteItems((ContainerBlock)cur);
116 | renderer.WriteEndObject();
117 | }
118 |
119 | renderer.WriteEndItems();
120 | renderer.WriteEndObject();
121 | } // proc Write
122 | } // class ListRenderer
123 |
124 | #endregion
125 |
126 | #region -- class QuoteBlockRenderer -----------------------------------------------
127 |
128 | public class QuoteBlockRenderer : XamlObjectRenderer
129 | {
130 | protected override void Write(XamlMarkdownWriter renderer, QuoteBlock block)
131 | {
132 | renderer.WriteStartObject(typeof(Section));
133 | renderer.WriteResourceMember(null, MarkdownXamlStyle.QuoteBlock);
134 |
135 | renderer.WriteItems(block);
136 |
137 | renderer.WriteEndObject();
138 | } // proc Write
139 | } // class QuoteBlockRenderer
140 |
141 | #endregion
142 |
143 | #region -- class ThematicBreakRenderer --------------------------------------------
144 |
145 | public class ThematicBreakRenderer : XamlObjectRenderer
146 | {
147 | protected override void Write(XamlMarkdownWriter renderer, ThematicBreakBlock obj)
148 | {
149 | renderer.WriteStartObject(typeof(Paragraph));
150 | renderer.WriteResourceMember(null, MarkdownXamlStyle.ThematicBreak);
151 | renderer.WriteEndObject();
152 |
153 | //var line = new System.Windows.Shapes.Line { X2 = 1 };
154 | //line.SetResourceReference(FrameworkContentElement.StyleProperty, Styles.ThematicBreakStyleKey);
155 |
156 | //var paragraph = new Paragraph
157 | //{
158 | // Inlines = { new InlineUIContainer(line) }
159 | //};
160 |
161 | //renderer.WriteBlock(paragraph);
162 | } // proc Write
163 | } // class ThematicBreakRenderer
164 |
165 | #endregion
166 | }
167 |
--------------------------------------------------------------------------------
/NeoMarkdigXaml/Renderers/XamlInlineRenderer.cs:
--------------------------------------------------------------------------------
1 | #region -- copyright --
2 | //
3 | // Licensed to the Apache Software Foundation (ASF) under one
4 | // or more contributor license agreements. See the NOTICE file
5 | // distributed with this work for additional information
6 | // regarding copyright ownership. The ASF licenses this file
7 | // to you under the Apache License, Version 2.0 (the
8 | // "License"); you may not use this file except in compliance
9 | // with the License. You may obtain a copy of the License at
10 | //
11 | // http://www.apache.org/licenses/LICENSE-2.0
12 | //
13 | // Unless required by applicable law or agreed to in writing,
14 | // software distributed under the License is distributed on an
15 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | // KIND, either express or implied. See the License for the
17 | // specific language governing permissions and limitations
18 | // under the License.
19 | //
20 | #endregion
21 | using System;
22 | using System.IO;
23 | using System.Runtime.CompilerServices;
24 | using System.Windows;
25 | using System.Windows.Controls;
26 | using System.Windows.Documents;
27 | using System.Xaml;
28 | using Markdig.Renderers.Html;
29 | using Markdig.Syntax.Inlines;
30 |
31 | namespace Neo.Markdig.Xaml.Renderers.Inlines
32 | {
33 | #region -- class AutolinkInlineRenderer -------------------------------------------
34 |
35 | public class AutolinkInlineRenderer : XamlObjectRenderer
36 | {
37 | protected override void Write(XamlMarkdownWriter renderer, AutolinkInline link)
38 | {
39 | var url = link.Url;
40 | var title = url;
41 |
42 | if (link.IsEmail)
43 | url = "mailto:" + url;
44 |
45 | LinkInlineRenderer.WriteStartHyperlink(renderer, url, title);
46 | renderer.WriteItems(title);
47 | LinkInlineRenderer.WriteEndHyperlink(renderer);
48 | } // proc Write
49 | } // class AutolinkInlineRenderer
50 |
51 | #endregion
52 |
53 | #region -- class CodeInlineRenderer -----------------------------------------------
54 |
55 | public class CodeInlineRenderer : XamlObjectRenderer
56 | {
57 | protected override void Write(XamlMarkdownWriter renderer, CodeInline code)
58 | {
59 | renderer.WriteStartObject(typeof(Span));
60 | renderer.WriteResourceMember(null, MarkdownXamlStyle.Code);
61 |
62 | renderer.WriteStartItems(nameof(Span.Inlines), true);
63 | renderer.WriteText(code.Content);
64 | renderer.WriteEndItems();
65 | renderer.WriteEndObject();
66 | } // proc Write
67 | } // proc class CodeInlineRenderer
68 |
69 | #endregion
70 |
71 | #region -- class DelimiterInlineRenderer ------------------------------------------
72 |
73 | public class DelimiterInlineRenderer : XamlObjectRenderer
74 | {
75 | protected override void Write(XamlMarkdownWriter renderer, DelimiterInline obj)
76 | {
77 | renderer.WriteText(obj.ToLiteral());
78 | renderer.WriteChildren(obj);
79 | } // proc Write
80 | } // class DelimiterInlineRenderer
81 |
82 | #endregion
83 |
84 | #region -- class EmphasisInlineRenderer -------------------------------------------
85 |
86 | public class EmphasisInlineRenderer : XamlObjectRenderer
87 | {
88 | private static bool WriteSpan(XamlMarkdownWriter renderer, EmphasisInline span)
89 | {
90 | switch (span.DelimiterChar)
91 | {
92 | case '*' when span.DelimiterCount == 2: // bold
93 | case '_' when span.DelimiterCount == 2: // bold
94 | renderer.WriteStartObject(typeof(Bold));
95 | return true;
96 | case '*': // italic
97 | case '_': // italic
98 | renderer.WriteStartObject(typeof(Italic));
99 | return true;
100 | case '~': // 2x strike through, 1x subscript
101 | renderer.WriteStartObject(typeof(Span));
102 | if (span.DelimiterCount == 2)
103 | renderer.WriteResourceMember(null, MarkdownXamlStyle.StrikeThrough);
104 | else
105 | renderer.WriteResourceMember(null, MarkdownXamlStyle.Subscript);
106 | return true;
107 | case '^': // 1x superscript
108 | renderer.WriteStartObject(typeof(Span));
109 | renderer.WriteResourceMember(null, MarkdownXamlStyle.Superscript);
110 | return true;
111 | case '+': // 2x underline
112 | renderer.WriteStartObject(typeof(Span));
113 | renderer.WriteResourceMember(null, MarkdownXamlStyle.Inserted);
114 | return true;
115 | case '=': // 2x Marked
116 | renderer.WriteStartObject(typeof(Span));
117 | renderer.WriteResourceMember(null, MarkdownXamlStyle.Marked);
118 | return true;
119 | default:
120 | return false;
121 | }
122 | } // proc WriteSpan
123 |
124 | protected override void Write(XamlMarkdownWriter renderer, EmphasisInline span)
125 | {
126 | if (WriteSpan(renderer, span))
127 | {
128 | renderer.WriteItems(span);
129 | renderer.WriteEndObject();
130 | }
131 | else
132 | renderer.WriteChildren(span);
133 | } // proc Write
134 | } // class EmphasisInlineRenderer
135 |
136 | #endregion
137 |
138 | #region -- class EntityInlineRenderer ---------------------------------------------
139 |
140 | public class EntityInlineRenderer : XamlObjectRenderer
141 | {
142 | protected override void Write(XamlMarkdownWriter renderer, HtmlEntityInline obj)
143 | {
144 | var txt = obj.Transcoded.Text.Substring(obj.Transcoded.Start, obj.Transcoded.Length);
145 | if (txt.Length == 0)
146 | return;
147 | if (txt[0] == '<')
148 | {
149 | using (var xaml = new XamlXmlReader(new StringReader(txt), new XamlXmlReaderSettings() { }))
150 | {
151 | while (xaml.Read())
152 | {
153 | switch (xaml.NodeType)
154 | {
155 | case XamlNodeType.NamespaceDeclaration:
156 | renderer.WriteNamespace(xaml.Namespace);
157 | break;
158 | case XamlNodeType.StartObject:
159 | renderer.WriteStartObject(xaml.Type);
160 | break;
161 | case XamlNodeType.GetObject:
162 | renderer.WriteGetObject();
163 | break;
164 | case XamlNodeType.EndObject:
165 | renderer.WriteEndObject();
166 | break;
167 |
168 | case XamlNodeType.StartMember:
169 | renderer.WriteStartMember(xaml.Member);
170 | break;
171 | case XamlNodeType.EndMember:
172 | renderer.WriteEndMember();
173 | break;
174 | case XamlNodeType.Value:
175 | if (xaml.Value is string text)
176 | renderer.WriteValue(text);
177 | else
178 | renderer.WriteValue(xaml.Value.ToString()); // todo: use xaml to text converter
179 | break;
180 | default:
181 | throw new InvalidOperationException();
182 | }
183 | }
184 | }
185 | }
186 | else
187 | renderer.WriteText(txt);
188 | } // proc Write
189 | } // class EntityInlineRenderer
190 |
191 | #endregion
192 |
193 | #region -- class LineBreakInlineRenderer ------------------------------------------
194 |
195 | public class LineBreakInlineRenderer : XamlObjectRenderer
196 | {
197 | protected override void Write(XamlMarkdownWriter renderer, LineBreakInline obj)
198 | {
199 | if (obj.IsHard)
200 | renderer.WriteLineBreak();
201 | else // Soft line break.
202 | renderer.WriteText(" ");
203 | } // proc Write
204 | } // class LineBreakInlineRenderer
205 |
206 | #endregion
207 |
208 | #region -- class LinkInlineRenderer -----------------------------------------------
209 |
210 | public class LinkInlineRenderer : XamlObjectRenderer
211 | {
212 | protected override void Write(XamlMarkdownWriter renderer, LinkInline link)
213 | {
214 | var url = link.GetDynamicUrl != null ? link.GetDynamicUrl() ?? link.Url : link.Url;
215 |
216 | if (link.IsImage)
217 | {
218 | if (!Uri.IsWellFormedUriString(url, UriKind.RelativeOrAbsolute))
219 | url = "#";
220 |
221 | renderer.WriteStartObject(typeof(Image));
222 | renderer.WriteResourceMember(null, MarkdownXamlStyle.Image);
223 | if (!String.IsNullOrEmpty(link.Title))
224 | renderer.WriteMember(ToolTipService.ToolTipProperty, link.Title);
225 | renderer.WriteMember(Image.SourceProperty, renderer.GetUri(new Uri(url, UriKind.RelativeOrAbsolute), false));
226 |
227 | var attr = link.TryGetAttributes();
228 | if (attr.TryGetPropertyInt32("width", out var width))
229 | renderer.WriteMember(FrameworkElement.WidthProperty, width);
230 | if (attr.TryGetPropertyInt32("height", out var height))
231 | renderer.WriteMember(FrameworkElement.HeightProperty, height);
232 |
233 | renderer.WriteEndObject();
234 | }
235 | else
236 | {
237 | WriteStartHyperlink(renderer, url, link.Title);
238 | renderer.WriteItems(link);
239 | WriteEndHyperlink(renderer);
240 | }
241 | } // proc Write
242 |
243 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
244 | internal static void WriteStartHyperlink(XamlMarkdownWriter renderer, string url, string linkTitle)
245 | {
246 | // check for valid url
247 | if (!url.StartsWith("#")
248 | && !Uri.IsWellFormedUriString(url, UriKind.RelativeOrAbsolute))
249 | url = "#";
250 |
251 | renderer.WriteStartObject(typeof(Hyperlink));
252 | renderer.WriteResourceMember(null, MarkdownXamlStyle.Hyperlink);
253 | //renderer.WriteMember(Hyperlink.CommandProperty, Commands.Hyperlink);
254 | //renderer.WriteMember(Hyperlink.CommandParameterProperty, url);
255 | renderer.WriteMember(Hyperlink.NavigateUriProperty, renderer.GetUri(new Uri(url, UriKind.RelativeOrAbsolute)));
256 | renderer.WriteMember(FrameworkContentElement.ToolTipProperty, String.IsNullOrEmpty(linkTitle) ? url : linkTitle);
257 | } // proc WriteStartHyperlink
258 |
259 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
260 | internal static void WriteEndHyperlink(XamlMarkdownWriter renderer)
261 | => renderer.WriteEndObject();
262 | } // class LinkInlineRenderer
263 |
264 | #endregion
265 |
266 | #region -- class LiteralInlineRenderer --------------------------------------------
267 |
268 | public class LiteralInlineRenderer : XamlObjectRenderer
269 | {
270 | protected override void Write(XamlMarkdownWriter renderer, LiteralInline obj)
271 | {
272 | if (obj.Content.IsEmpty)
273 | return;
274 |
275 | renderer.WriteText(ref obj.Content);
276 | } // proc Write
277 | } // class LiteralInlineRenderer
278 |
279 | #endregion
280 | }
281 |
--------------------------------------------------------------------------------
/NeoMarkdigXaml/Renderers/XamlMarkdownWriter.cs:
--------------------------------------------------------------------------------
1 | #region -- copyright --
2 | //
3 | // Licensed to the Apache Software Foundation (ASF) under one
4 | // or more contributor license agreements. See the NOTICE file
5 | // distributed with this work for additional information
6 | // regarding copyright ownership. The ASF licenses this file
7 | // to you under the Apache License, Version 2.0 (the
8 | // "License"); you may not use this file except in compliance
9 | // with the License. You may obtain a copy of the License at
10 | //
11 | // http://www.apache.org/licenses/LICENSE-2.0
12 | //
13 | // Unless required by applicable law or agreed to in writing,
14 | // software distributed under the License is distributed on an
15 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | // KIND, either express or implied. See the License for the
17 | // specific language governing permissions and limitations
18 | // under the License.
19 | //
20 | #endregion
21 | using System;
22 | using System.Collections.Generic;
23 | using System.Linq;
24 | using System.Reflection;
25 | using System.Runtime.CompilerServices;
26 | using System.Text;
27 | using System.Windows;
28 | using System.Windows.Documents;
29 | using System.Xaml;
30 | using Markdig.Helpers;
31 | using Markdig.Renderers;
32 | using Markdig.Renderers.Html;
33 | using Markdig.Syntax;
34 | using Markdig.Syntax.Inlines;
35 | using Neo.Markdig.Xaml.Renderers.Extensions;
36 | using Neo.Markdig.Xaml.Renderers.Inlines;
37 |
38 | namespace Neo.Markdig.Xaml.Renderers
39 | {
40 | #region -- class XamlMarkdownWriter -----------------------------------------------
41 |
42 | /// XAML token stream generator for a Markdown object.
43 | public class XamlMarkdownWriter : RendererBase, System.Windows.Markup.IUriContext
44 | {
45 | #region -- class StaticResourceKeyStoreInfo -----------------------------------
46 |
47 | private sealed class StaticResourceKeyStoreInfo
48 | {
49 | public StaticResourceKeyStoreInfo(Type type, string prefix)
50 | {
51 | Type = type ?? throw new ArgumentNullException(nameof(type));
52 | Prefix = prefix ?? throw new ArgumentNullException(nameof(prefix));
53 | } // ctor
54 |
55 | public Type Type { get; }
56 | public string Prefix { get; }
57 | } // class ResourceKeyStoreInfo
58 |
59 | #endregion
60 |
61 | #region -- struct StaticResourceKeyInfo ---------------------------------------
62 |
63 | private struct StaticResourceKeyInfo
64 | {
65 | public StaticResourceKeyInfo(StaticResourceKeyStoreInfo keyStoreInfo, string memberName)
66 | {
67 | KeyStore = keyStoreInfo ?? throw new ArgumentNullException(nameof(keyStoreInfo));
68 | MemberName = memberName ?? throw new ArgumentNullException(nameof(memberName));
69 | } // ctor
70 |
71 | public string MemberName { get; }
72 | public StaticResourceKeyStoreInfo KeyStore { get; }
73 | } // struct StaticResourceKeyInfo
74 |
75 | #endregion
76 |
77 | private readonly XamlWriter writer;
78 | private readonly Stack xamlTypes = new Stack();
79 |
80 | private readonly Dictionary staticResourceKeys = new Dictionary();
81 |
82 | private readonly XamlType runType;
83 | private readonly XamlMember runTextMember;
84 |
85 | private XamlMember currentContentMember = null; // start a _Items access before the next object
86 |
87 | private bool preserveWhitespace = false; // preserve current whitespaces
88 | private bool appendWhiteSpace = false;
89 | private bool firstCharOfBlock = true;
90 | private readonly StringBuilder textBuffer = new StringBuilder(); // current text buffer to collect all words
91 |
92 | #region -- Ctor/Dtor ----------------------------------------------------------
93 |
94 | /// Initializes a new instance of the class.
95 | /// Target for the xaml content.
96 | public XamlMarkdownWriter(XamlWriter writer)
97 | {
98 | this.writer = writer ?? throw new ArgumentNullException(nameof(writer));
99 |
100 | this.runType = SchemaContext.GetXamlType(typeof(Run)) ?? throw new ArgumentNullException(nameof(Run));
101 | this.runTextMember = runType.GetMember(nameof(Run.Text)) ?? throw new ArgumentNullException(nameof(Run.Text));
102 |
103 | // Default block renderers
104 | ObjectRenderers.Add(new CodeBlockRenderer());
105 | ObjectRenderers.Add(new ListRenderer());
106 | ObjectRenderers.Add(new HeadingRenderer());
107 | ObjectRenderers.Add(new ParagraphRenderer());
108 | ObjectRenderers.Add(new QuoteBlockRenderer());
109 | ObjectRenderers.Add(new ThematicBreakRenderer());
110 |
111 | // Default inline renderers
112 | ObjectRenderers.Add(new AutolinkInlineRenderer());
113 | ObjectRenderers.Add(new CodeInlineRenderer());
114 | ObjectRenderers.Add(new DelimiterInlineRenderer());
115 | ObjectRenderers.Add(new EmphasisInlineRenderer());
116 | ObjectRenderers.Add(new EntityInlineRenderer());
117 | ObjectRenderers.Add(new LineBreakInlineRenderer());
118 | ObjectRenderers.Add(new LinkInlineRenderer());
119 | ObjectRenderers.Add(new LiteralInlineRenderer());
120 |
121 | // Extension renderers
122 | ObjectRenderers.Add(new TableRenderer());
123 | ObjectRenderers.Add(new TaskListRenderer());
124 | } // ctor
125 |
126 | #endregion
127 |
128 | #region -- Primitives ---------------------------------------------------------
129 |
130 | ///
131 | ///
132 | ///
133 | public void WriteNamespace(string ns, string prefix)
134 | => WriteNamespace(new NamespaceDeclaration(ns, prefix));
135 |
136 | ///
137 | public void WriteNamespace(NamespaceDeclaration namespaceDeclaration)
138 | => writer.WriteNamespace(namespaceDeclaration);
139 |
140 | /// Start to write a xaml-object.
141 | ///
142 | public XamlType WriteStartObject(Type type)
143 | {
144 | var xamlType = SchemaContext.GetXamlType(type ?? throw new ArgumentNullException(nameof(type)))
145 | ?? throw new ArgumentOutOfRangeException(nameof(type), type, "Could not resolve xaml type.");
146 |
147 | return WriteStartObject(xamlType);
148 | } // proc WriteStartObject
149 |
150 | /// Start to write a xaml-object.
151 | ///
152 | ///
153 | public XamlType WriteStartObject(XamlType xamlType)
154 | {
155 | xamlTypes.Push(xamlType);
156 |
157 | // write pending elements
158 | WritePendingStartItems();
159 | WritePendingText(true);
160 |
161 | writer.WriteStartObject(xamlType);
162 |
163 | return xamlType;
164 | } // proc WriteStartObject
165 |
166 | /// Write GetObject
167 | public void WriteGetObject()
168 | => writer.WriteGetObject();
169 |
170 | /// Closes the current object.
171 | /// Current evaluated object or null.
172 | public object WriteEndObject()
173 | {
174 | // write pending text
175 | WritePendingText(false);
176 |
177 | xamlTypes.Pop();
178 | writer.WriteEndObject();
179 | return GetResult();
180 | } // proc WriteEndObject
181 |
182 | private object GetResult()
183 | => writer is XamlObjectWriter ow
184 | ? ow.Result
185 | : null;
186 |
187 | /// Get a xaml member to a member string.
188 | ///
189 | ///
190 | public XamlMember GetMember(string memberName)
191 | {
192 | var xamlType = xamlTypes.Peek();
193 | return xamlType.GetMember(memberName ?? throw new ArgumentNullException(nameof(memberName)));
194 | }
195 |
196 | /// Get a xaml member to a dependency property.
197 | ///
198 | ///
199 | public XamlMember GetMember(DependencyProperty property)
200 | {
201 | if (property == null)
202 | throw new ArgumentNullException(nameof(property));
203 |
204 | var xamlType = xamlTypes.Peek();
205 | if (property.OwnerType.IsAssignableFrom(xamlType.UnderlyingType))
206 | return xamlType.GetMember(property.Name);
207 | else
208 | {
209 | var type = SchemaContext.GetXamlType(property.OwnerType);
210 | return type.GetAttachableMember(property.Name);
211 | }
212 | }
213 |
214 | /// Start a member.
215 | ///
216 | public void WriteStartMember(string memberName)
217 | => WriteStartMember(GetMember(memberName));
218 |
219 | /// Start a member.
220 | ///
221 | public void WriteStartMember(DependencyProperty property)
222 | => WriteStartMember(GetMember(property));
223 |
224 | /// Start a member.
225 | ///
226 | public void WriteStartMember(XamlMember member)
227 | => writer.WriteStartMember(member ?? throw new ArgumentNullException(nameof(member)));
228 |
229 | /// End the current member.
230 | public void WriteEndMember()
231 | {
232 | WritePendingText(false);
233 | writer.WriteEndMember();
234 | } // proc WriteEndMember
235 |
236 | /// Start a items collection.
237 | ///
238 | ///
239 | public void WriteStartItems(string memberName, bool preserveSpaces = false)
240 | => WriteStartItems(GetMember(memberName), preserveSpaces);
241 |
242 | /// Start a items collection.
243 | ///
244 | ///
245 | public void WriteStartItems(DependencyProperty property, bool preserveSpaces = false)
246 | => WriteStartItems(GetMember(property), preserveSpaces);
247 |
248 | /// Start a items collection.
249 | ///
250 | ///
251 | public void WriteStartItems(XamlMember member, bool preserveSpaces = false)
252 | {
253 | if (currentContentMember != null)
254 | throw new InvalidOperationException();
255 |
256 | preserveWhitespace = preserveSpaces;
257 | appendWhiteSpace = false;
258 | firstCharOfBlock = true;
259 | currentContentMember = member;
260 | } // proc WriteStartItems
261 |
262 | private void WritePendingStartItems()
263 | {
264 | if (currentContentMember != null)
265 | {
266 | WriteStartMember(currentContentMember);
267 | writer.WriteGetObject();
268 | writer.WriteStartMember(XamlLanguage.Items);
269 |
270 | currentContentMember = null;
271 | }
272 | } // proc WritePendingStartItems
273 |
274 | /// End a items collection.
275 | public void WriteEndItems()
276 | {
277 | WritePendingText(false);
278 |
279 | if (currentContentMember == null)
280 | {
281 | writer.WriteEndMember();
282 | writer.WriteEndObject();
283 | writer.WriteEndMember();
284 | }
285 | else
286 | currentContentMember = null;
287 | }
288 |
289 | /// Write a complete member.
290 | ///
291 | ///
292 | public void WriteMember(string memberName, object value)
293 | {
294 | if (value != null)
295 | WriteMember(GetMember(memberName), value);
296 | } // proc WriteMember
297 |
298 | /// Write a complete member.
299 | ///
300 | ///
301 | public void WriteMember(DependencyProperty property, object value)
302 | {
303 | if (value != null)
304 | WriteMember(GetMember(property), value);
305 | } // proc WriteMember
306 |
307 | /// Write a complete member.
308 | ///
309 | ///
310 | public void WriteMember(XamlMember member, object value)
311 | {
312 | if (value == null)
313 | return;
314 | if (IsPendingText)
315 | throw new InvalidOperationException("Start member during text collection.");
316 |
317 | writer.WriteStartMember(member);
318 | if (writer is XamlObjectWriter)
319 | writer.WriteValue(value);
320 | else
321 | {
322 | if (!(value is string str))
323 | str = member.TypeConverter.ConverterInstance.ConvertToString(value);
324 |
325 | if (str != null)
326 | writer.WriteValue(str);
327 | }
328 | writer.WriteEndMember();
329 | } // proc WriteMember
330 |
331 | /// Write Inline LineBreak
332 | public void WriteLineBreak()
333 | {
334 | WriteStartObject(typeof(LineBreak));
335 | WriteEndObject();
336 | } // proc WriteLineBreak
337 |
338 | /// Write value
339 | ///
340 | public void WriteValue(string value)
341 | => WriteText(value);
342 |
343 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
344 | private void AppendChar(char c)
345 | {
346 | if (Char.IsWhiteSpace(c))
347 | appendWhiteSpace = true;
348 | else
349 | {
350 | if (appendWhiteSpace)
351 | {
352 | if (!firstCharOfBlock)
353 | textBuffer.Append(' ');
354 | appendWhiteSpace = false;
355 | }
356 |
357 | firstCharOfBlock = false;
358 | textBuffer.Append(c);
359 | }
360 | }
361 |
362 | /// Write normal text.
363 | ///
364 | public void WriteText(ref StringSlice slice)
365 | {
366 | if (slice.Start > slice.End)
367 | return;
368 |
369 | if (preserveWhitespace)
370 | textBuffer.Append(slice.Text, slice.Start, slice.Length);
371 | else
372 | {
373 | for (var i = slice.Start; i <= slice.End; i++)
374 | {
375 | var c = slice[i];
376 | AppendChar(c);
377 | }
378 | }
379 | } // proc WriteText
380 |
381 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
382 | internal void WriteText(string text)
383 | {
384 | if (preserveWhitespace)
385 | textBuffer.Append(text);
386 | else
387 | {
388 | var l = text.Length;
389 | for (var i = 0; i < l; i++)
390 | AppendChar(text[i]);
391 | }
392 | } // proc WriteText
393 |
394 | private void WritePendingText(bool onStartObject)
395 | {
396 | if (IsPendingText)
397 | {
398 | WritePendingStartItems();
399 |
400 | if (preserveWhitespace)
401 | {
402 | writer.WriteStartObject(runType);
403 | writer.WriteStartMember(runTextMember);
404 | writer.WriteValue(textBuffer.ToString());
405 | writer.WriteEndMember();
406 | writer.WriteEndObject();
407 | textBuffer.Length = 0;
408 | }
409 | else
410 | {
411 | if (appendWhiteSpace && onStartObject)
412 | {
413 | textBuffer.Append(' ');
414 | appendWhiteSpace = false;
415 | }
416 |
417 | writer.WriteValue(textBuffer.ToString());
418 | textBuffer.Length = 0;
419 | }
420 | }
421 | } // proc WritePendingText
422 |
423 | private XamlMember GetContentProperty()
424 | => xamlTypes.Peek().ContentProperty ?? throw new ArgumentNullException(nameof(XamlType.ContentProperty));
425 |
426 | /// Write inline stream in the current type.
427 | ///
428 | ///
429 | public void WriteItems(LeafBlock leafBlock, bool preserveSpaces = false)
430 | {
431 | if (leafBlock == null)
432 | throw new ArgumentNullException(nameof(leafBlock));
433 |
434 | WriteStartItems(GetContentProperty(), preserveSpaces);
435 |
436 | if (leafBlock.Inline != null)
437 | {
438 | WriteChildren(leafBlock.Inline);
439 | }
440 | else
441 | {
442 | var lineCount = leafBlock.Lines.Count;
443 | var first = true;
444 | for (var i = 0; i < lineCount; i++)
445 | {
446 | if (first)
447 | first = false;
448 | else if (preserveSpaces)
449 | WriteLineBreak();
450 | else
451 | AppendChar(' ');
452 |
453 | WriteText(ref leafBlock.Lines.Lines[i].Slice);
454 | }
455 | }
456 |
457 | WriteEndItems();
458 | } // proc WriteItems
459 |
460 | /// Write inline stream in the current type.
461 | ///
462 | ///
463 | public void WriteItems(ContainerInline inlines, bool preserveSpaces = false)
464 | {
465 | if (inlines == null)
466 | throw new ArgumentNullException(nameof(inlines));
467 |
468 | WriteStartItems(GetContentProperty(), preserveSpaces);
469 | WriteChildren(inlines);
470 | WriteEndItems();
471 | } // proc WriteItems
472 |
473 | /// Write block stream in the current type.
474 | ///
475 | ///
476 | public void WriteItems(ContainerBlock block, bool preserveSpaces = false)
477 | {
478 | if (block == null)
479 | throw new ArgumentNullException(nameof(block));
480 |
481 | WriteStartItems(GetContentProperty(), preserveSpaces);
482 | WriteChildren(block);
483 | WriteEndItems();
484 | } // proc WriteItems
485 |
486 | /// Write text as content in the current type.
487 | ///
488 | ///
489 | public void WriteItems(string text, bool preserveSpaces = false)
490 | {
491 | WriteStartItems(GetContentProperty(), preserveSpaces);
492 | WriteText(text);
493 | WriteEndItems();
494 | } // proc WriteItems
495 |
496 | private bool IsPendingText => textBuffer.Length > 0;
497 |
498 | #endregion
499 |
500 | #region -- Resources ----------------------------------------------------------
501 |
502 | protected void RegisterResourceKeys(Type resourceKeyStoreType, string prefix)
503 | {
504 | var resourceKeyStore = new StaticResourceKeyStoreInfo(resourceKeyStoreType, prefix);
505 | var itemsAdded = false;
506 |
507 | // register resources
508 | foreach (var pi in (from p in resourceKeyStoreType.GetRuntimeProperties() where p.CanRead && p.GetMethod.IsPublic && p.GetMethod.IsStatic && typeof(ResourceKey).IsAssignableFrom(p.PropertyType) select p))
509 | {
510 | var rk = (ResourceKey)pi.GetValue(null);
511 | staticResourceKeys.Add(rk, new StaticResourceKeyInfo(resourceKeyStore, pi.Name));
512 | itemsAdded = true;
513 | }
514 |
515 | // add name space
516 | if (itemsAdded)
517 | WriteNamespace("clr-namespace:" + resourceKeyStoreType.Assembly.GetName().Name + ";assembly=" + resourceKeyStoreType.Namespace, prefix);
518 | } // proc RegisterResourceKeys
519 |
520 | public void WriteResourceMember(XamlMember member, object value)
521 | {
522 | WriteStartMember(member ?? GetMember("Style"));
523 | WriteStartObject(typeof(StaticResourceExtension));
524 | WriteStartMember(XamlLanguage.PositionalParameters);
525 |
526 | WriteMemberValueCore(value);
527 |
528 | WriteEndMember();
529 | WriteEndObject();
530 | WriteEndMember();
531 | } // proc WriteResourceMember
532 |
533 | protected virtual void WriteMemberValueCore(object value)
534 | {
535 | if (value is MarkdownXamlStyle style)
536 | value = GetDefaultStyle(style);
537 |
538 | if (writer is XamlObjectWriter)
539 | writer.WriteValue(value);
540 | else if (!TryWriteResouceKey(value as ResourceKey))
541 | writer.WriteValue(value);
542 | } // proc WriteMemberValueCore
543 |
544 | public bool TryWriteResouceKey(ResourceKey resourceKey)
545 | {
546 | if (resourceKey != null && staticResourceKeys.TryGetValue(resourceKey, out var info)) // known resource key
547 | {
548 | WriteStartObject(XamlLanguage.Static);
549 | WriteStartMember(XamlLanguage.PositionalParameters);
550 |
551 | writer.WriteValue(info.KeyStore.Prefix + ":" + info.KeyStore.Type.Name + "." + info.MemberName);
552 |
553 | WriteEndMember();
554 | WriteEndObject();
555 |
556 | return true;
557 | }
558 | else
559 | return false;
560 | } // proc WriteResouceKey
561 |
562 | public virtual object GetDefaultStyle(MarkdownXamlStyle style)
563 | {
564 | switch (style)
565 | {
566 | case MarkdownXamlStyle.Document:
567 | return MarkdownXaml.DocumentStyleKey;
568 | case MarkdownXamlStyle.Code:
569 | return MarkdownXaml.CodeStyleKey;
570 | case MarkdownXamlStyle.CodeBlock:
571 | return MarkdownXaml.CodeBlockStyleKey;
572 | case MarkdownXamlStyle.Heading1:
573 | return MarkdownXaml.Heading1StyleKey;
574 | case MarkdownXamlStyle.Heading2:
575 | return MarkdownXaml.Heading2StyleKey;
576 | case MarkdownXamlStyle.Heading3:
577 | return MarkdownXaml.Heading3StyleKey;
578 | case MarkdownXamlStyle.Heading4:
579 | return MarkdownXaml.Heading4StyleKey;
580 | case MarkdownXamlStyle.Heading5:
581 | return MarkdownXaml.Heading5StyleKey;
582 | case MarkdownXamlStyle.Heading6:
583 | return MarkdownXaml.Heading6StyleKey;
584 | case MarkdownXamlStyle.Image:
585 | return MarkdownXaml.ImageStyleKey;
586 | case MarkdownXamlStyle.Inserted:
587 | return MarkdownXaml.InsertedStyleKey;
588 | case MarkdownXamlStyle.Marked:
589 | return MarkdownXaml.MarkedStyleKey;
590 | case MarkdownXamlStyle.QuoteBlock:
591 | return MarkdownXaml.QuoteBlockStyleKey;
592 | case MarkdownXamlStyle.StrikeThrough:
593 | return MarkdownXaml.StrikeThroughStyleKey;
594 | case MarkdownXamlStyle.Subscript:
595 | return MarkdownXaml.SubscriptStyleKey;
596 | case MarkdownXamlStyle.Superscript:
597 | return MarkdownXaml.SuperscriptStyleKey;
598 | case MarkdownXamlStyle.Table:
599 | return MarkdownXaml.TableStyleKey;
600 | case MarkdownXamlStyle.TableCell:
601 | return MarkdownXaml.TableCellStyleKey;
602 | case MarkdownXamlStyle.TableHeader:
603 | return MarkdownXaml.TableHeaderStyleKey;
604 | case MarkdownXamlStyle.TaskList:
605 | return MarkdownXaml.TaskListStyleKey;
606 | case MarkdownXamlStyle.ThematicBreak:
607 | return MarkdownXaml.ThematicBreakStyleKey;
608 | case MarkdownXamlStyle.Hyperlink:
609 | return MarkdownXaml.HyperlinkStyleKey;
610 | default:
611 | throw new ArgumentOutOfRangeException(nameof(style));
612 | }
613 | } // func GetDefaultStyle
614 |
615 | #endregion
616 |
617 | #region -- Render -------------------------------------------------------------
618 |
619 | protected virtual void WriteNamespaces()
620 | => RegisterResourceKeys(typeof(MarkdownXaml), "xmarkdig");
621 |
622 | protected virtual void WriteResources()
623 | {
624 | //WriteStartItems(nameof(FlowDocument.Resources));
625 | //WriteEndItems();
626 | } // proc WriteResources
627 |
628 | /// Render the markdown object in a XamlWriter.
629 | ///
630 | ///
631 | public override object Render(MarkdownObject markdownObject)
632 | {
633 | if (markdownObject is MarkdownDocument)
634 | {
635 | // emit namespaces
636 | WriteNamespace("http://schemas.microsoft.com/winfx/2006/xaml", "x");
637 | WriteNamespaces();
638 |
639 | // start flow document
640 | WriteStartObject(typeof(FlowDocument));
641 | WriteResources();
642 |
643 | WriteResourceMember(null, MarkdownXamlStyle.Document);
644 |
645 | WriteStartItems(nameof(FlowDocument.Blocks));
646 |
647 | Write(markdownObject);
648 |
649 | WriteEndItems();
650 | return WriteEndObject();
651 | }
652 | else
653 | {
654 | Write(markdownObject);
655 | return GetResult();
656 | }
657 | } // proc Render
658 |
659 | #endregion
660 |
661 | private object GetAbsoluteUri(Uri uri, bool enforceUri = true)
662 | {
663 | if (!enforceUri && uri.IsAbsoluteUri)
664 | {
665 | if (uri.Scheme == "file")
666 | return uri.AbsolutePath;
667 | else
668 | return uri;
669 | }
670 | else
671 | return uri;
672 | } // func GetAbsoluteUri
673 |
674 | public object GetUri(Uri uri, bool enforceUri = true)
675 | {
676 | if (uri == null)
677 | return null;
678 | else if (uri.IsAbsoluteUri)
679 | return GetAbsoluteUri(uri, enforceUri);
680 | else if (BaseUri != null)
681 | return GetAbsoluteUri(new Uri(BaseUri, uri), enforceUri);
682 | else
683 | return uri;
684 | } // func GetUri
685 |
686 | /// Define a BaseUri for the uri
687 | public Uri BaseUri { get; set; } = null;
688 | /// Acces to current schema context.
689 | public XamlSchemaContext SchemaContext => writer.SchemaContext;
690 | } // class XamlMarkdownWriter
691 |
692 | #endregion
693 |
694 | #region -- class XamlObjectRenderer -----------------------------------------------
695 |
696 | /// A base class for XAML rendering and Markdown objects.
697 | /// The type of the object.
698 | public abstract class XamlObjectRenderer : MarkdownObjectRenderer
699 | where TObject : MarkdownObject
700 | {
701 | } // class XamlObjectRenderer
702 |
703 | #endregion
704 |
705 | #region -- class Helper -----------------------------------------------------------
706 |
707 | internal static class Helper
708 | {
709 | public static bool TryGetProperty(this HtmlAttributes attributes, string name, out string value)
710 | {
711 | if (attributes != null)
712 | {
713 | var properties = attributes.Properties;
714 | for (var i = 0; i < properties.Count; i++)
715 | {
716 | if (properties[i].Key == name)
717 | {
718 | value = properties[i].Value;
719 | return true;
720 | }
721 | }
722 | }
723 | value = null;
724 | return false;
725 | } // func TryGetProperty
726 |
727 | public static bool TryGetPropertyInt32(this HtmlAttributes attributes, string name, out int value)
728 | {
729 | if (TryGetProperty(attributes, name, out var tmp) && Int32.TryParse(tmp, out value))
730 | return true;
731 | else
732 | {
733 | value = 0;
734 | return false;
735 | }
736 | } // func TryGetPropertyInt32
737 | } // class Helper
738 |
739 | #endregion
740 | }
741 |
--------------------------------------------------------------------------------
/NeoMarkdigXaml/Themes/generic.xaml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
9 |
13 |
17 |
21 |
25 |
30 |
35 |
40 |
46 |
49 |
52 |
56 |
62 |
67 |
71 |
74 |
77 |
83 |
86 |
89 |
92 |
95 |
98 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Neo.Markdig.Xaml
2 | ================
3 |
4 | Is a xaml/wpf extension for [lunet-io/markdig](https://github.com/lunet-io/markdig)
5 |
6 | With this library it is possible to create FlowDocument's
7 |
8 | ```C#
9 | var content = File.ReadAllText(@"..\..\..\..\Readme.md");
10 | var doc = MarkdownXaml.ToFlowDocument(content,
11 | new MarkdownPipelineBuilder()
12 | .UseXamlSupportedExtensions()
13 | .Build()
14 | );
15 | flowDocumentViewer.Document = doc;
16 | ```
17 |
18 | or Xaml-Source files.
19 |
20 | ```C#
21 | var content = File.ReadAllText(@"..\..\..\..\Readme.md");
22 | var xaml = MarkdownXaml.ToXaml(content,
23 | new MarkdownPipelineBuilder()
24 | .UseXamlSupportedExtensions()
25 | .Build()
26 | );
27 | ```
28 |
29 | ## Features
30 |
31 | Supports standard features from Markdig.
32 |
33 | Additionally, the following extensions are supported:
34 | - AutoLinks (such as )
35 | - Tables
36 | - Extra emphasis
37 |
38 | ## Styles
39 |
40 | It is possible to replace the default resource set.
41 |
42 | Inherit from `XamlMarkdownWriter` and override the method `GetDefaultStyle`.
43 |
44 | ## Difference to [markdig.wpf](https://github.com/Kryptos-FR/markdig.wpf)
45 |
46 | markdig.wpf implements **two** renderers, one for xaml-output and one for wpf-objects.
47 |
48 | This implementation has only **one** renderer, that has a xaml-token-stream as output.
49 | This stream can written with framework implemented `XamlXmlWriter` or the `XamlObjectWriter`.
50 |
51 | Numbers:
52 | ```
53 | Markdig.Wpf-toxaml : 109ms
54 | Markdig.Xaml-toxaml : 850ms
55 | Markdig.Wpf-towpf : 12.579ms
56 | Markdig.Xaml-towpf : 6.882ms
57 | ```
58 |
59 | If you want to create plain xaml text output, my library is a slower. The reason is, that my implementation
60 | validates the output against the wpf-object-schema. That is one expensive step more, but it ensures a
61 | valid wpf-xaml.
62 |
63 | The object creation should be always faster in Neo.Markdig.Xaml than the Markdig.Wpf approach, because
64 | Neo.Markdig.Xaml uses the internal wpf-object creation with all is caching and replay mechanism.
65 |
66 | Needs to prove: Neo.Markdig.Xaml should consume less memory on large documents in both cases.
67 |
68 | ## Links
69 | - Nuget [Neo.Markdig.Xaml](https://www.nuget.org/packages/Neo.Markdig.Xaml/)
70 | - [TecWare GmbH](https://www.tecware-gmbh.de/)
71 |
72 | ## What is missing
73 |
74 | Testing.
--------------------------------------------------------------------------------
/Tests/MarkdownCompare/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Tests/MarkdownCompare/Markdig-readme.md:
--------------------------------------------------------------------------------
1 | # Markdig [](https://ci.appveyor.com/project/xoofx/markdig) [](https://www.nuget.org/packages/Markdig/) [](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=FRGHXBTP442JL)
2 |
3 | | Tables | Are | Cool |
4 | | ------------- |:-------------:| -----:|
5 | | col 3 is | right-aligned | $1600 |
6 | | col 2 is | centered | $12 |
7 | | zebra stripes | are neat | $1 |
8 |
9 |
10 |
11 | Markdig is a fast, powerful, [CommonMark](http://commonmark.org/) compliant, extensible Markdown processor for .NET.
12 |
13 | > NOTE: The repository is under construction. There will be a dedicated website and proper documentation at some point!
14 |
15 | You can **try Markdig online** and compare it to other implementations on [babelmark3](https://babelmark.github.io/?text=Hello+**Markdig**!)
16 |
17 | ## Features
18 |
19 | - **Very fast parser and html renderer** (no-regexp), very lightweight in terms of GC pressure. See benchmarks
20 | - **Abstract Syntax Tree** with precise source code location for syntax tree, useful when building a Markdown editor.
21 | - Checkout [MarkdownEditor for Visual Studio](https://visualstudiogallery.msdn.microsoft.com/eaab33c3-437b-4918-8354-872dfe5d1bfe) powered by Markdig!
22 | - Converter to **HTML**
23 | - Passing more than **600+ tests** from the latest [CommonMark specs (0.28)](http://spec.commonmark.org/)
24 | - Includes all the core elements of CommonMark:
25 | - including **GFM fenced code blocks**.
26 | - **Extensible** architecture
27 | - Even the core Markdown/CommonMark parsing is pluggable, so it allows to disable builtin Markdown/Commonmark parsing (e.g [Disable HTML parsing](https://github.com/lunet-io/markdig/blob/7964bd0160d4c18e4155127a4c863d61ebd8944a/src/Markdig/MarkdownExtensions.cs#L306)) or change behaviour (e.g change matching `#` of a headers with `@`)
28 | - Built-in with **20+ extensions**, including:
29 | - 2 kind of tables:
30 | - [**Pipe tables**](https://github.com/lunet-io/markdig/blob/master/src/Markdig.Tests/Specs/PipeTableSpecs.md) (inspired from Github tables and [PanDoc - Pipe Tables](http://pandoc.org/README.html#extension-pipe_tables))
31 | - [**Grid tables**](https://github.com/lunet-io/markdig/blob/master/src/Markdig.Tests/Specs/GridTableSpecs.md) (inspired from [Pandoc - Grid Tables](http://pandoc.org/README.html#extension-grid_tables))
32 | - [**Extra emphasis**](https://github.com/lunet-io/markdig/blob/master/src/Markdig.Tests/Specs/EmphasisExtraSpecs.md) (inspired from [Pandoc - Emphasis](http://pandoc.org/README.html#strikeout) and [Markdown-it](https://markdown-it.github.io/))
33 | - strike through `~~`,
34 | - Subscript `~`
35 | - Superscript `^`
36 | - Inserted `++`
37 | - Marked `==`
38 | - [**Special attributes**](https://github.com/lunet-io/markdig/blob/master/src/Markdig.Tests/Specs/GenericAttributesSpecs.md) or attached HTML attributes (inspired from [PHP Markdown Extra - Special Attributes](https://michelf.ca/projects/php-markdown/extra/#spe-attr))
39 | - [**Definition lists**](https://github.com/lunet-io/markdig/blob/master/src/Markdig.Tests/Specs/DefinitionListSpecs.md) (inspired from [PHP Markdown Extra - Definitions Lists](https://michelf.ca/projects/php-markdown/extra/#def-list))
40 | - [**Footnotes**](https://github.com/lunet-io/markdig/blob/master/src/Markdig.Tests/Specs/FootnotesSpecs.md) (inspired from [PHP Markdown Extra - Footnotes](https://michelf.ca/projects/php-markdown/extra/#footnotes))
41 | - [**Auto-identifiers**](https://github.com/lunet-io/markdig/blob/master/src/Markdig.Tests/Specs/AutoIdentifierSpecs.md) for headings (similar to [Pandoc - Auto Identifiers](http://pandoc.org/README.html#extension-auto_identifiers))
42 | - [**Auto-links**](https://github.com/lunet-io/markdig/blob/master/src/Markdig.Tests/Specs/AutoLinks.md) generates links if a text starts with `http://` or `https://` or `ftp://` or `mailto:` or `www.xxx.yyy`
43 | - [**Task Lists**](https://github.com/lunet-io/markdig/blob/master/src/Markdig.Tests/Specs/TaskListSpecs.md) inspired from [Github Task lists](https://github.com/blog/1375-task-lists-in-gfm-issues-pulls-comments).
44 | - [**Extra bullet lists**](https://github.com/lunet-io/markdig/blob/master/src/Markdig.Tests/Specs/ListExtraSpecs.md), supporting alpha bullet `a.` `b.` and roman bullet (`i`, `ii`...etc.)
45 | - [**Media support**](https://github.com/lunet-io/markdig/blob/master/src/Markdig.Tests/Specs/MediaSpecs.md) for media url (youtube, vimeo, mp4...etc.) (inspired from this [CommonMark discussion](https://talk.commonmark.org/t/embedded-audio-and-video/441))
46 | - [**Abbreviations**](https://github.com/lunet-io/markdig/blob/master/src/Markdig.Tests/Specs/AbbreviationSpecs.md) (inspired from [PHP Markdown Extra - Abbreviations](https://michelf.ca/projects/php-markdown/extra/#abbr))
47 | - [**Citation**](https://github.com/lunet-io/markdig/blob/master/src/Markdig.Tests/Specs/FigureFooterAndCiteSpecs.md) text by enclosing `""...""` (inspired by this [CommonMark discussion ](https://talk.commonmark.org/t/referencing-creative-works-with-cite/892))
48 | - [**Custom containers**](https://github.com/lunet-io/markdig/blob/master/src/Markdig.Tests/Specs/CustomContainerSpecs.md) similar to fenced code block `:::` for generating a proper `
...
` instead (inspired by this [CommonMark discussion ](https://talk.commonmark.org/t/custom-container-for-block-and-inline/2051))
49 | - [**Figures**](https://github.com/lunet-io/markdig/blob/master/src/Markdig.Tests/Specs/FigureFooterAndCiteSpecs.md) (inspired from this [CommonMark discussion](https://talk.commonmark.org/t/image-tag-should-expand-to-figure-when-used-with-title/265/5))
50 | - [**Footers**](https://github.com/lunet-io/markdig/blob/master/src/Markdig.Tests/Specs/FigureFooterAndCiteSpecs.md) (inspired from this [CommonMark discussion](https://talk.commonmark.org/t/syntax-for-footer/2070))
51 | - [**Mathematics**](https://github.com/lunet-io/markdig/blob/master/src/Markdig.Tests/Specs/MathSpecs.md)/Latex extension by enclosing `$$` for block and `$` for inline math (inspired from this [CommonMark discussion](https://talk.commonmark.org/t/mathematics-extension/457/31))
52 | - [**Soft lines as hard lines**](https://github.com/lunet-io/markdig/blob/master/src/Markdig.Tests/Specs/HardlineBreakSpecs.md)
53 | - [**Emoji**](https://github.com/lunet-io/markdig/blob/master/src/Markdig.Tests/Specs/EmojiSpecs.md) support (inspired from [Markdown-it](https://markdown-it.github.io/))
54 | - [**SmartyPants**](https://github.com/lunet-io/markdig/blob/master/src/Markdig.Tests/Specs/SmartyPantsSpecs.md) (inspired from [Daring Fireball - SmartyPants](https://daringfireball.net/projects/smartypants/))
55 | - [**Bootstrap**](https://github.com/lunet-io/markdig/blob/master/src/Markdig.Tests/Specs/BootstrapSpecs.md) class (to output bootstrap class)
56 | - [**Diagrams**](https://github.com/lunet-io/markdig/blob/master/src/Markdig.Tests/Specs/DiagramsSpecs.md) extension whenever a fenced code block contains a special keyword, it will be converted to a div block with the content as-is (currently, supports only for [`mermaid` diagrams](https://knsv.github.io/mermaid/))
57 | - [**YAML frontmatter**](https://github.com/lunet-io/markdig/blob/master/src/Markdig.Tests/Specs/YamlSpecs.md) to parse without evaluating the frontmatter and to discard it from the HTML output (typically used for previewing without the frontmatter in MarkdownEditor)
58 | - [**JIRA links**](https://github.com/lunet-io/markdig/blob/master/src/Markdig.Tests/Specs/JiraLinks.md) to automatically generate links for JIRA project references (Thanks to @clarkd: https://github.com/clarkd/MarkdigJiraLinker)
59 | - Compatible with .NET 3.5, 4.0+ and .NET Core (`netstandard1.1+`)
60 |
61 | ## Documentation
62 |
63 | > The repository is under construction. There will be a dedicated website and proper documentation at some point!
64 |
65 | While there is not yet a dedicated documentation, you can find from the [specs documentation](https://github.com/lunet-io/markdig/blob/master/src/Markdig.Tests/Specs/readme.md) how to use these extensions.
66 |
67 | In the meantime, you can have a "behind the scene" article about Markdig in my blog post ["Implementing a Markdown Engine for .NET"](http://xoofx.com/blog/2016/06/13/implementing-a-markdown-processor-for-dotnet/)
68 |
69 | ## Download
70 |
71 | Markdig is available as a NuGet package: [](https://www.nuget.org/packages/Markdig/)
72 |
73 | Also [Markdig.Signed](https://www.nuget.org/packages/Markdig.Signed/) NuGet package provides signed assemblies.
74 |
75 | ## Usage
76 |
77 | The main entry point for the API is the `Markdig.Markdown` class:
78 |
79 | By default, without any options, Markdig is using the plain CommonMark parser:
80 |
81 | ```csharp
82 | var result = Markdown.ToHtml("This is a text with some *emphasis*");
83 | Console.WriteLine(result); // prints: