├── .gitignore ├── .nuget ├── NuGet.Config ├── NuGet.exe └── NuGet.targets ├── LICENSE.md ├── MigraDoc.Extensions.sln ├── README.md ├── Rakefile.rb ├── dotnet.watchr.rb ├── sidekick.bat ├── sidekickapp.cs └── src ├── MigraDoc.Extensions.Html ├── HtmlConverter.cs ├── MigraDoc.Extensions.Html.csproj ├── Properties │ └── AssemblyInfo.cs ├── SectionExtensions.cs └── packages.config ├── MigraDoc.Extensions.Markdown ├── MarkdownConverter.cs ├── MigraDoc.Extensions.Markdown.csproj ├── Properties │ └── AssemblyInfo.cs ├── SectionExtensions.cs └── packages.config ├── MigraDoc.Extensions ├── FormattedTextExtensions.cs ├── IConverter.cs ├── MigraDoc.Extensions.csproj ├── ParagraphExtensions.cs ├── Properties │ └── AssemblyInfo.cs ├── SectionExtensions.cs └── packages.config ├── examples └── MigraDoc.Extensions.Html.Example │ ├── App.config │ ├── Example.html │ ├── Example.md │ ├── MigraDoc.Extensions.Html.Example.csproj │ ├── Program.cs │ ├── Properties │ └── AssemblyInfo.cs │ └── packages.config └── specs └── MigraDoc.Extensions.Html.Specs ├── DebuggerShim.cs ├── MigraDoc.Extensions.Html.Specs.csproj ├── Properties └── AssemblyInfo.cs ├── converting_tags.cs ├── define_htmlconverter.cs └── packages.config /.gitignore: -------------------------------------------------------------------------------- 1 | [Oo]bj 2 | [Bb]in 3 | *.user 4 | *.suo 5 | *.[Cc]ache 6 | *.bak 7 | *.ncb 8 | *.log 9 | *.DS_Store 10 | [Tt]humbs.db 11 | _ReSharper.* 12 | *.resharper 13 | Ankh.NoLoad 14 | tools 15 | packages 16 | artifacts 17 | sidekickapp.exe -------------------------------------------------------------------------------- /.nuget/NuGet.Config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.nuget/NuGet.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/benfoster/MigraDoc.Extensions/0839e82b2a17420d799a4b49bc9457ddf163c21f/.nuget/NuGet.exe -------------------------------------------------------------------------------- /.nuget/NuGet.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $(MSBuildProjectDirectory)\..\ 5 | 6 | 7 | false 8 | 9 | 10 | false 11 | 12 | 13 | true 14 | 15 | 16 | false 17 | 18 | 19 | 20 | 21 | 22 | 26 | 27 | 28 | 29 | 30 | $([System.IO.Path]::Combine($(SolutionDir), ".nuget")) 31 | $([System.IO.Path]::Combine($(ProjectDir), "packages.config")) 32 | 33 | 34 | 35 | 36 | $(SolutionDir).nuget 37 | packages.config 38 | 39 | 40 | 41 | 42 | $(NuGetToolsPath)\NuGet.exe 43 | @(PackageSource) 44 | 45 | "$(NuGetExePath)" 46 | mono --runtime=v4.0.30319 $(NuGetExePath) 47 | 48 | $(TargetDir.Trim('\\')) 49 | 50 | -RequireConsent 51 | -NonInteractive 52 | 53 | 54 | $(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)" $(NonInteractiveSwitch) $(RequireConsentSwitch) -solutionDir "$(SolutionDir) " 55 | $(NuGetCommand) pack "$(ProjectPath)" -Properties Configuration=$(Configuration) $(NonInteractiveSwitch) -OutputDirectory "$(PackageOutputDir)" -symbols 56 | 57 | 58 | 59 | RestorePackages; 60 | $(BuildDependsOn); 61 | 62 | 63 | 64 | 65 | $(BuildDependsOn); 66 | BuildPackage; 67 | 68 | 69 | 70 | 71 | 72 | 73 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 88 | 89 | 92 | 93 | 94 | 95 | 97 | 98 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 130 | 131 | 132 | 133 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2012 Ben Foster, United Kingdom 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /MigraDoc.Extensions.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2012 4 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{AF4177AE-AA2E-4434-AF32-46604508CBC7}" 5 | ProjectSection(SolutionItems) = preProject 6 | .nuget\NuGet.Config = .nuget\NuGet.Config 7 | .nuget\NuGet.exe = .nuget\NuGet.exe 8 | .nuget\NuGet.targets = .nuget\NuGet.targets 9 | EndProjectSection 10 | EndProject 11 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MigraDoc.Extensions.Html", "src\MigraDoc.Extensions.Html\MigraDoc.Extensions.Html.csproj", "{CA3F8535-EA5E-4362-8922-FFBD86DF498F}" 12 | EndProject 13 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "specs", "specs", "{668E5A7D-27EE-4351-922A-16902D13381F}" 14 | EndProject 15 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MigraDoc.Extensions.Html.Specs", "src\specs\MigraDoc.Extensions.Html.Specs\MigraDoc.Extensions.Html.Specs.csproj", "{CFBA7EB2-7A2F-4086-8EF7-7197DCDEE593}" 16 | EndProject 17 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "examples", "examples", "{22E2B3C0-7306-48B8-99C5-71796200CF86}" 18 | EndProject 19 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MigraDoc.Extensions.Html.Example", "src\examples\MigraDoc.Extensions.Html.Example\MigraDoc.Extensions.Html.Example.csproj", "{2383AE62-1D25-40DC-AF73-0CA020E96C7E}" 20 | EndProject 21 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MigraDoc.Extensions.Markdown", "src\MigraDoc.Extensions.Markdown\MigraDoc.Extensions.Markdown.csproj", "{EA990C7E-F7EC-4857-9A12-372FFE74B004}" 22 | EndProject 23 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MigraDoc.Extensions", "src\MigraDoc.Extensions\MigraDoc.Extensions.csproj", "{1863068F-975C-4F5B-ABA7-FBA344709A48}" 24 | EndProject 25 | Global 26 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 27 | Debug|Any CPU = Debug|Any CPU 28 | Release|Any CPU = Release|Any CPU 29 | EndGlobalSection 30 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 31 | {CA3F8535-EA5E-4362-8922-FFBD86DF498F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 32 | {CA3F8535-EA5E-4362-8922-FFBD86DF498F}.Debug|Any CPU.Build.0 = Debug|Any CPU 33 | {CA3F8535-EA5E-4362-8922-FFBD86DF498F}.Release|Any CPU.ActiveCfg = Release|Any CPU 34 | {CA3F8535-EA5E-4362-8922-FFBD86DF498F}.Release|Any CPU.Build.0 = Release|Any CPU 35 | {CFBA7EB2-7A2F-4086-8EF7-7197DCDEE593}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 36 | {CFBA7EB2-7A2F-4086-8EF7-7197DCDEE593}.Debug|Any CPU.Build.0 = Debug|Any CPU 37 | {CFBA7EB2-7A2F-4086-8EF7-7197DCDEE593}.Release|Any CPU.ActiveCfg = Release|Any CPU 38 | {CFBA7EB2-7A2F-4086-8EF7-7197DCDEE593}.Release|Any CPU.Build.0 = Release|Any CPU 39 | {2383AE62-1D25-40DC-AF73-0CA020E96C7E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 40 | {2383AE62-1D25-40DC-AF73-0CA020E96C7E}.Debug|Any CPU.Build.0 = Debug|Any CPU 41 | {2383AE62-1D25-40DC-AF73-0CA020E96C7E}.Release|Any CPU.ActiveCfg = Release|Any CPU 42 | {2383AE62-1D25-40DC-AF73-0CA020E96C7E}.Release|Any CPU.Build.0 = Release|Any CPU 43 | {EA990C7E-F7EC-4857-9A12-372FFE74B004}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 44 | {EA990C7E-F7EC-4857-9A12-372FFE74B004}.Debug|Any CPU.Build.0 = Debug|Any CPU 45 | {EA990C7E-F7EC-4857-9A12-372FFE74B004}.Release|Any CPU.ActiveCfg = Release|Any CPU 46 | {EA990C7E-F7EC-4857-9A12-372FFE74B004}.Release|Any CPU.Build.0 = Release|Any CPU 47 | {1863068F-975C-4F5B-ABA7-FBA344709A48}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 48 | {1863068F-975C-4F5B-ABA7-FBA344709A48}.Debug|Any CPU.Build.0 = Debug|Any CPU 49 | {1863068F-975C-4F5B-ABA7-FBA344709A48}.Release|Any CPU.ActiveCfg = Release|Any CPU 50 | {1863068F-975C-4F5B-ABA7-FBA344709A48}.Release|Any CPU.Build.0 = Release|Any CPU 51 | EndGlobalSection 52 | GlobalSection(SolutionProperties) = preSolution 53 | HideSolutionNode = FALSE 54 | EndGlobalSection 55 | GlobalSection(NestedProjects) = preSolution 56 | {CFBA7EB2-7A2F-4086-8EF7-7197DCDEE593} = {668E5A7D-27EE-4351-922A-16902D13381F} 57 | {2383AE62-1D25-40DC-AF73-0CA020E96C7E} = {22E2B3C0-7306-48B8-99C5-71796200CF86} 58 | EndGlobalSection 59 | EndGlobal 60 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MigraDoc.Extensions 2 | 3 | Extensions for [MigraDoc/PDFSharp](http://www.pdfsharp.net/Overview.ashx). 4 | 5 | ## Quick Start 6 | 7 | The biggest feature provided by this library is the ability to convert from HTML and Markdown to PDF, via MigraDoc's Document Object Model. 8 | 9 | MigraDoc.Extensions makes use of [MarkdownSharp](https://code.google.com/p/markdownsharp/) to convert from Markdown to HTML and the [Html Agility Pack](http://htmlagilitypack.codeplex.com/) to convert from HTML to PDF. 10 | 11 | Since the MigraDoc DOM is pretty basic, much of the conversion involves setting the `Style` of generated MigraDoc `Paragraph` instances. You can then configure these styles however you like. See the [example project](https://github.com/benfoster/MigraDoc.Extensions/blob/master/src/examples/MigraDoc.Extensions.Html.Example/Program.cs#L44) for more details. 12 | 13 | #### Converting from Markdown to PDF 14 | 15 | Import the `MigraDoc.Extensions.Markdown` namespace and call `AddMarkdown` on a MigraDoc `Section` instance: 16 | 17 | 18 | var markdown = @" 19 | # This is a heading 20 | 21 | This is some **bold** ass text with a [link](http://www.google.com). 22 | 23 | - List Item 1 24 | - List Item 2 25 | - List Item 3 26 | 27 | Pretty cool huh? 28 | "; 29 | 30 | section.AddMarkdown(markdown); 31 | 32 | 33 | #### Converting from HTML to PDF 34 | 35 | Import the `MigraDoc.Extensions.Html` namespace and call `AddHtml` on a MigraDoc `Section` instance: 36 | 37 | 38 | var html = @" 39 |

This is a heading

40 | 41 |

This is some **bold** ass text with a link.

42 | 43 |

48 | 49 |

Pretty cool huh?

50 | "; 51 | 52 | section.AddHtml(html); 53 | 54 | #### What is supported? 55 | 56 | The HTML converter currently supports the following: 57 | 58 | - Headings (H1 -> H6) - Sets a "HeadingX" style on the generated paragraph 59 | - Paragraphs 60 | - Hyperlinks containing plain text or supported inline elements 61 | - Lists - Adds a paragraph with style "ListStart" before the list and one with style "ListEnd" after the list. 62 | - Unordered Lists - Each list item has the style "UnorderedList" 63 | - Ordered Lists - Each list item has the style "Ordered List" 64 | - Line breaks 65 | - Inline elements ``, ``, ``, `` 66 | - Horizontal Rules - Adds a paragraph with style "HorizontalRule" 67 | 68 | For more details, check out the [specs](https://github.com/benfoster/MigraDoc.Extensions/blob/master/src/specs/MigraDoc.Extensions.Html.Specs/converting_tags.cs). 69 | 70 | 71 | #### Extending the HTML converter 72 | 73 | To add a custom handler, create a new instance of `HtmlConverter` and add to its `NodeHandlers` dictionary. The key is the HTML element you wish to handle and the value is a `Func` element: 78 | 79 | nodeHandlers.Add("strong", (node, parent) => { 80 | var format = TextFormat.Bold; 81 | 82 | var formattedText = parent as FormattedText; 83 | if (formattedText != null) 84 | { 85 | return formattedText.Format(format); 86 | } 87 | 88 | // otherwise parent is paragraph or section 89 | return GetParagraph(parent).AddFormattedText(format); 90 | }); 91 | 92 | In the above handler, we need to cater for nested format tags (e.g. `some text`) so we first attempt to cast the parent as `FormattedText`, otherwise fall back to adding formatted text to a `Paragraph`. Unfortunately such type checks are fairly frequent due to the limited relationships between objects in the MigraDoc DOM. 93 | 94 | To use a custom converter instance use the `Section.Add(string content, IConverter converter)` extension in the `MigraDoc.Extensions` namespace. 95 | 96 | Note that an element handler should not process any inner HTML. For example the handler for a `

` tag only adds a paragraph with a the style "Heading1", it does not add the text (there is a separate handler for processing text nodes). 97 | 98 | 99 | ## License 100 | 101 | Licensed under the MIT License. -------------------------------------------------------------------------------- /Rakefile.rb: -------------------------------------------------------------------------------- 1 | @msbuild_path = "#{ENV['SystemRoot']}\\Microsoft.NET\\Framework\\v4.0.30319\\msbuild.exe" 2 | 3 | def build_command(sln) 4 | return "\"#{@msbuild_path}\" \"#{sln}\" /verbosity:quiet /nologo" 5 | end 6 | 7 | task :default do 8 | sh build_command("MigraDoc.Extensions.sln") 9 | end 10 | 11 | task :tests do 12 | sh ".\\packages\\nspec.0.9.66\\tools\\NSpecRunner.exe .\\src\\specs\\MigraDoc.Extensions.Html.Specs\\bin\\Debug\\MigraDoc.Extensions.Html.Specs.dll" 13 | end 14 | -------------------------------------------------------------------------------- /dotnet.watchr.rb: -------------------------------------------------------------------------------- 1 | class GrowlNotifier 2 | def self.growl_path 3 | @@growl_path 4 | end 5 | 6 | def self.growl_path= value 7 | @@growl_path = value 8 | end 9 | 10 | def execute title, text, color 11 | return unless GrowlNotifier.growl_path 12 | 13 | text.gsub!('"', "''") 14 | 15 | text = text + "\n\n---" 16 | 17 | opts = ["\"#{GrowlNotifier.growl_path}\"", "\"#{text}\"", "/t:\"#{title}\""] 18 | 19 | opts << "/i:\"#{File.expand_path("#{color}.png")}\"" 20 | 21 | `#{opts.join ' '}` 22 | end 23 | end 24 | 25 | class CommandShell 26 | def execute cmd 27 | puts cmd + "\n\n" 28 | 29 | str="" 30 | STDOUT.sync = true # That's all it takes... 31 | IO.popen(cmd+" 2>&1") do |pipe| # Redirection is performed using operators 32 | pipe.sync = true 33 | while s = pipe.gets 34 | str+=s # This is synchronous! 35 | end 36 | end 37 | 38 | puts str + "\n\n" 39 | 40 | str 41 | end 42 | end 43 | 44 | @growl = GrowlNotifier.new 45 | @sh = CommandShell.new 46 | 47 | GrowlNotifier.growl_path = 48 | 'C:\program files (x86)\Growl for Windows\growlnotify.exe' 49 | 50 | def build_succeeded? results 51 | return !(/: error/.match results) 52 | end 53 | 54 | def file_changed full_path 55 | if full_path =~ /.*.\.cs$/ 56 | puts full_path 57 | results = @sh.execute "rake" 58 | 59 | if(!build_succeeded? results) 60 | errors = results.each_line.find { |l| l =~ /: error/ } 61 | puts errors 62 | 63 | @growl.execute "sad panda", errors, "red" 64 | else 65 | results = @sh.execute "rake tests" 66 | 67 | if(results =~ /FAILURES/) 68 | @growl.execute "failed", results.split("**** FAILURES ****").last, "red" 69 | else 70 | @growl.execute "passed", "all tests passed", "green" 71 | end 72 | end 73 | end 74 | end 75 | 76 | def tutorial 77 | puts "in dotnet.watchr.rb, update the file_changed method to execute rake tasks" 78 | end 79 | 80 | method_to_run = ARGV[0] #get the first argument from the command line and act accordingly 81 | 82 | case method_to_run 83 | when "tutorial" 84 | tutorial 85 | when "file_changed" 86 | puts ARGV 87 | file_changed ARGV[1].gsub("\\", "\/")[1..-1] #run the file_changed routine giving it a shell compatible file name 88 | else 89 | puts "I dont know how to run: " + method_to_run 90 | end 91 | -------------------------------------------------------------------------------- /sidekick.bat: -------------------------------------------------------------------------------- 1 | ECHO ON 2 | C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe sidekickapp.cs 3 | sidekickapp.exe 4 | -------------------------------------------------------------------------------- /sidekickapp.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.IO; 6 | using System.Diagnostics; 7 | 8 | namespace SyncDeploy 9 | { 10 | class Program 11 | { 12 | static string path = null; 13 | static FileSystemWatcher watcher; 14 | 15 | static void Main(string[] args) 16 | { 17 | path = Directory.GetCurrentDirectory(); 18 | watcher = new FileSystemWatcher(path, "*.*"); 19 | watcher.IncludeSubdirectories = true; 20 | watcher.EnableRaisingEvents = true; 21 | watcher.NotifyFilter = NotifyFilters.LastWrite; 22 | watcher.Changed += new FileSystemEventHandler(watcher_Changed); 23 | watcher.Created += new FileSystemEventHandler(watcher_Changed); 24 | Console.WriteLine("Watching " + path + " for changes, press Enter to stop..."); 25 | Shell("tutorial"); 26 | Console.ReadLine(); 27 | 28 | } 29 | 30 | static void Shell(params string[] args) 31 | { 32 | ProcessStartInfo processStartInfo = new ProcessStartInfo("ruby", "dotnet.watchr.rb " + string.Join(" ", args)); 33 | processStartInfo.UseShellExecute = false; 34 | processStartInfo.ErrorDialog = false; 35 | processStartInfo.RedirectStandardError = true; 36 | processStartInfo.RedirectStandardInput = true; 37 | processStartInfo.RedirectStandardOutput = true; 38 | Process process = new Process(); 39 | process.EnableRaisingEvents = true; 40 | process.StartInfo = processStartInfo; 41 | process.OutputDataReceived += (sender, args1) => System.Console.WriteLine(args1.Data); 42 | process.ErrorDataReceived += (sender, args2) => System.Console.WriteLine(args2.Data); 43 | 44 | bool processStarted = process.Start(); 45 | process.BeginOutputReadLine(); 46 | process.BeginErrorReadLine(); 47 | 48 | process.WaitForExit(); 49 | System.Console.WriteLine("---"); 50 | } 51 | 52 | static void watcher_Changed(object sender, FileSystemEventArgs e) 53 | { 54 | watcher.EnableRaisingEvents = false; 55 | var relativeFile = e.FullPath.Replace(Directory.GetCurrentDirectory(), ""); 56 | System.Console.WriteLine("Changed: " + relativeFile); 57 | Shell("file_changed", relativeFile); 58 | watcher.EnableRaisingEvents = true; 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/MigraDoc.Extensions.Html/HtmlConverter.cs: -------------------------------------------------------------------------------- 1 | using HtmlAgilityPack; 2 | using MigraDoc.DocumentObjectModel; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Net; 7 | 8 | namespace MigraDoc.Extensions.Html 9 | { 10 | public class HtmlConverter : IConverter 11 | { 12 | private IDictionary> nodeHandlers 13 | = new Dictionary>(); 14 | 15 | public HtmlConverter() 16 | { 17 | AddDefaultNodeHandlers(); 18 | } 19 | 20 | public IDictionary> NodeHandlers 21 | { 22 | get 23 | { 24 | return nodeHandlers; 25 | } 26 | } 27 | 28 | public Action
Convert(string contents) 29 | { 30 | return section => ConvertHtml(contents, section); 31 | } 32 | 33 | private void ConvertHtml(string html, Section section) 34 | { 35 | if (string.IsNullOrEmpty(html)) 36 | { 37 | throw new ArgumentNullException("html"); 38 | } 39 | 40 | if (section == null) 41 | { 42 | throw new ArgumentNullException("section"); 43 | } 44 | 45 | var doc = new HtmlDocument(); 46 | doc.LoadHtml(html); 47 | ConvertHtmlNodes(doc.DocumentNode.ChildNodes, section); 48 | } 49 | 50 | private void ConvertHtmlNodes(HtmlNodeCollection nodes, DocumentObject section, DocumentObject current = null) 51 | { 52 | foreach (var node in nodes) 53 | { 54 | Func nodeHandler; 55 | if (nodeHandlers.TryGetValue(node.Name, out nodeHandler)) 56 | { 57 | // pass the current container or section 58 | var result = nodeHandler(node, current ?? section); 59 | 60 | if (node.HasChildNodes) 61 | { 62 | ConvertHtmlNodes(node.ChildNodes, section, result); 63 | } 64 | } 65 | else 66 | { 67 | if (node.HasChildNodes) 68 | { 69 | ConvertHtmlNodes(node.ChildNodes, section, current); 70 | } 71 | } 72 | } 73 | } 74 | 75 | private void AddDefaultNodeHandlers() 76 | { 77 | // Block Elements 78 | 79 | // could do with a predicate/regex matcher so we could just use one handler for all headings 80 | nodeHandlers.Add("h1", AddHeading); 81 | nodeHandlers.Add("h2", AddHeading); 82 | nodeHandlers.Add("h3", AddHeading); 83 | nodeHandlers.Add("h4", AddHeading); 84 | nodeHandlers.Add("h5", AddHeading); 85 | nodeHandlers.Add("h6", AddHeading); 86 | 87 | nodeHandlers.Add("p", (node, parent) => 88 | { 89 | return ((Section)parent).AddParagraph(); 90 | }); 91 | 92 | // Inline Elements 93 | 94 | nodeHandlers.Add("strong", (node, parent) => AddFormattedText(node, parent, TextFormat.Bold)); 95 | nodeHandlers.Add("i", (node, parent) => AddFormattedText(node, parent, TextFormat.Italic)); 96 | nodeHandlers.Add("em", (node, parent) => AddFormattedText(node, parent, TextFormat.Italic)); 97 | nodeHandlers.Add("u", (node, parent) => AddFormattedText(node, parent, TextFormat.Underline)); 98 | nodeHandlers.Add("a", (node, parent) => 99 | { 100 | return GetParagraph(parent).AddHyperlink(node.GetAttributeValue("href", ""), HyperlinkType.Web); 101 | }); 102 | nodeHandlers.Add("hr", (node, parent) => GetParagraph(parent).SetStyle("HorizontalRule")); 103 | nodeHandlers.Add("br", (node, parent) => { 104 | if (parent is FormattedText) 105 | { 106 | // inline elements can contain line breaks 107 | ((FormattedText)parent).AddLineBreak(); 108 | return parent; 109 | } 110 | 111 | var paragraph = GetParagraph(parent); 112 | paragraph.AddLineBreak(); 113 | return paragraph; 114 | }); 115 | 116 | nodeHandlers.Add("li", (node, parent) => 117 | { 118 | var listStyle = node.ParentNode.Name == "ul" 119 | ? "UnorderedList" 120 | : "OrderedList"; 121 | 122 | var section = (Section)parent; 123 | var isFirst = node.ParentNode.Elements("li").First() == node; 124 | var isLast = node.ParentNode.Elements("li").Last() == node; 125 | 126 | // if this is the first item add the ListStart paragraph 127 | if (isFirst) 128 | { 129 | section.AddParagraph().SetStyle("ListStart"); 130 | } 131 | 132 | var listItem = section.AddParagraph().SetStyle(listStyle); 133 | 134 | // disable continuation if this is the first list item 135 | listItem.Format.ListInfo.ContinuePreviousList = !isFirst; 136 | 137 | // if the this is the last item add the ListEnd paragraph 138 | if (isLast) 139 | { 140 | section.AddParagraph().SetStyle("ListEnd"); 141 | } 142 | 143 | return listItem; 144 | }); 145 | 146 | nodeHandlers.Add("#text", (node, parent) => 147 | { 148 | // remove line breaks 149 | var innerText = node.InnerText.Replace("\r", "").Replace("\n", ""); 150 | 151 | if (string.IsNullOrWhiteSpace(innerText)) 152 | { 153 | return parent; 154 | } 155 | 156 | // decode escaped HTML 157 | innerText = WebUtility.HtmlDecode(innerText); 158 | 159 | // text elements must be wrapped in a paragraph but this could also be FormattedText or a Hyperlink!! 160 | // this needs some work 161 | if (parent is FormattedText) 162 | { 163 | return ((FormattedText)parent).AddText(innerText); 164 | } 165 | if (parent is Hyperlink) 166 | { 167 | return ((Hyperlink)parent).AddText(innerText); 168 | } 169 | 170 | // otherwise a section or paragraph 171 | return GetParagraph(parent).AddText(innerText); 172 | }); 173 | } 174 | 175 | private static DocumentObject AddFormattedText(HtmlNode node, DocumentObject parent, TextFormat format) 176 | { 177 | var formattedText = parent as FormattedText; 178 | if (formattedText != null) 179 | { 180 | return formattedText.Format(format); 181 | } 182 | 183 | // otherwise parent is paragraph or section 184 | return GetParagraph(parent).AddFormattedText(format); 185 | } 186 | 187 | private static DocumentObject AddHeading(HtmlNode node, DocumentObject parent) 188 | { 189 | return ((Section)parent).AddParagraph().SetStyle("Heading" + node.Name[1]); 190 | } 191 | 192 | private static Paragraph GetParagraph(DocumentObject parent) 193 | { 194 | return parent as Paragraph ?? ((Section)parent).AddParagraph(); 195 | } 196 | 197 | private static Paragraph AddParagraphWithStyle(DocumentObject parent, string style) 198 | { 199 | return ((Section)parent).AddParagraph().SetStyle(style); 200 | } 201 | } 202 | } 203 | -------------------------------------------------------------------------------- /src/MigraDoc.Extensions.Html/MigraDoc.Extensions.Html.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {CA3F8535-EA5E-4362-8922-FFBD86DF498F} 8 | Library 9 | Properties 10 | MigraDoc.Extensions.Html 11 | MigraDoc.Extensions.Html 12 | v4.0 13 | 512 14 | ..\..\ 15 | true 16 | 17 | 18 | 19 | true 20 | full 21 | false 22 | bin\Debug\ 23 | DEBUG;TRACE 24 | prompt 25 | 4 26 | 27 | 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | 35 | 36 | 37 | ..\..\packages\HtmlAgilityPack.1.4.6\lib\Net40\HtmlAgilityPack.dll 38 | 39 | 40 | ..\..\packages\PDFsharp-MigraDoc-GDI.1.32.3879.0\lib\net20\MigraDoc.DocumentObjectModel.dll 41 | 42 | 43 | ..\..\packages\PDFsharp-MigraDoc-GDI.1.32.3879.0\lib\net20\MigraDoc.Rendering.dll 44 | 45 | 46 | ..\..\packages\PDFsharp-MigraDoc-GDI.1.32.3879.0\lib\net20\MigraDoc.RtfRendering.dll 47 | 48 | 49 | ..\..\packages\PDFsharp-MigraDoc-GDI.1.32.3879.0\lib\net20\PdfSharp.dll 50 | 51 | 52 | ..\..\packages\PDFsharp-MigraDoc-GDI.1.32.3879.0\lib\net20\PdfSharp.Charting.dll 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | {1863068f-975c-4f5b-aba7-fba344709a48} 74 | MigraDoc.Extensions 75 | 76 | 77 | 78 | 79 | 86 | -------------------------------------------------------------------------------- /src/MigraDoc.Extensions.Html/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("MigraDoc.Extensions.Html")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("MigraDoc.Extensions.Html")] 13 | [assembly: AssemblyCopyright("Copyright © 2013")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("666a8f9c-11cc-41b6-a709-57a5beb2df69")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /src/MigraDoc.Extensions.Html/SectionExtensions.cs: -------------------------------------------------------------------------------- 1 | using MigraDoc.DocumentObjectModel; 2 | using MigraDoc.Extensions.Html; 3 | using System; 4 | 5 | namespace MigraDoc.Extensions.Html 6 | { 7 | public static class SectionExtensions 8 | { 9 | public static Section AddHtml(this Section section, string html) 10 | { 11 | return section.Add(html, new HtmlConverter()); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/MigraDoc.Extensions.Html/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/MigraDoc.Extensions.Markdown/MarkdownConverter.cs: -------------------------------------------------------------------------------- 1 | using MarkdownSharp; 2 | using MigraDoc.DocumentObjectModel; 3 | using MigraDoc.Extensions.Html; 4 | using System; 5 | 6 | namespace MigraDoc.Extensions.Markdown 7 | { 8 | public class MarkdownConverter : IConverter 9 | { 10 | private readonly MarkdownOptions options; 11 | 12 | public MarkdownConverter() 13 | { 14 | options = new MarkdownOptions 15 | { 16 | LinkEmails = true 17 | }; 18 | } 19 | 20 | public MarkdownConverter(MarkdownOptions options) 21 | { 22 | if (options == null) 23 | { 24 | throw new ArgumentNullException("options"); 25 | } 26 | 27 | this.options = options; 28 | } 29 | 30 | public Action
Convert(string contents) 31 | { 32 | var converter = new MarkdownSharp.Markdown(options); 33 | var html = converter.Transform(contents); 34 | 35 | var htmlConverter = new HtmlConverter(); 36 | return htmlConverter.Convert(html); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/MigraDoc.Extensions.Markdown/MigraDoc.Extensions.Markdown.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {EA990C7E-F7EC-4857-9A12-372FFE74B004} 8 | Library 9 | Properties 10 | MigraDoc.Extensions.Markdown 11 | MigraDoc.Extensions.Markdown 12 | v4.0 13 | 512 14 | ..\..\ 15 | true 16 | 17 | 18 | 19 | true 20 | full 21 | false 22 | bin\Debug\ 23 | DEBUG;TRACE 24 | prompt 25 | 4 26 | 27 | 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | 35 | 36 | 37 | ..\..\packages\MarkdownSharp.1.13.0.0\lib\35\MarkdownSharp.dll 38 | 39 | 40 | False 41 | ..\..\packages\PDFsharp-MigraDoc-GDI.1.32.3879.0\lib\net20\MigraDoc.DocumentObjectModel.dll 42 | 43 | 44 | ..\..\packages\PDFsharp-MigraDoc-GDI.1.32.3879.0\lib\net20\MigraDoc.Rendering.dll 45 | 46 | 47 | ..\..\packages\PDFsharp-MigraDoc-GDI.1.32.3879.0\lib\net20\MigraDoc.RtfRendering.dll 48 | 49 | 50 | ..\..\packages\PDFsharp-MigraDoc-GDI.1.32.3879.0\lib\net20\PdfSharp.dll 51 | 52 | 53 | ..\..\packages\PDFsharp-MigraDoc-GDI.1.32.3879.0\lib\net20\PdfSharp.Charting.dll 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | {ca3f8535-ea5e-4362-8922-ffbd86df498f} 72 | MigraDoc.Extensions.Html 73 | 74 | 75 | {1863068f-975c-4f5b-aba7-fba344709a48} 76 | MigraDoc.Extensions 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 91 | -------------------------------------------------------------------------------- /src/MigraDoc.Extensions.Markdown/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("MigraDoc.Extensions.Markdown")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("MigraDoc.Extensions.Markdown")] 13 | [assembly: AssemblyCopyright("Copyright © 2013")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("4cfa7343-7e37-4b98-a989-1d74db70107d")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /src/MigraDoc.Extensions.Markdown/SectionExtensions.cs: -------------------------------------------------------------------------------- 1 | using MigraDoc.DocumentObjectModel; 2 | using MigraDoc.Extensions.Html; 3 | using System; 4 | 5 | namespace MigraDoc.Extensions.Markdown 6 | { 7 | public static class SectionExtensions 8 | { 9 | public static Section AddMarkdown(this Section section, string markdown) 10 | { 11 | return section.Add(markdown, new MarkdownConverter()); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/MigraDoc.Extensions.Markdown/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/MigraDoc.Extensions/FormattedTextExtensions.cs: -------------------------------------------------------------------------------- 1 | using MigraDoc.DocumentObjectModel; 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | namespace MigraDoc.Extensions 6 | { 7 | public static class FormattedTextExtensions 8 | { 9 | private static Dictionary> formats 10 | = new Dictionary> 11 | { 12 | { TextFormat.Bold, text => text.Bold = true }, 13 | { TextFormat.NotBold, text => text.Bold = false }, 14 | { TextFormat.Italic, text => text.Italic = true }, 15 | { TextFormat.NotItalic, text => text.Italic = false }, 16 | { TextFormat.Underline, text => text.Underline = Underline.Single }, 17 | { TextFormat.NoUnderline, text => text.Underline = Underline.None } 18 | }; 19 | 20 | public static FormattedText Format(this FormattedText formattedText, TextFormat textFormat) 21 | { 22 | if (formattedText == null) 23 | { 24 | throw new ArgumentNullException("formattedText"); 25 | } 26 | 27 | Action formatter; 28 | if (formats.TryGetValue(textFormat, out formatter)) 29 | { 30 | formatter(formattedText); 31 | } 32 | 33 | return formattedText; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/MigraDoc.Extensions/IConverter.cs: -------------------------------------------------------------------------------- 1 | using MigraDoc.DocumentObjectModel; 2 | using System; 3 | 4 | namespace MigraDoc.Extensions 5 | { 6 | public interface IConverter 7 | { 8 | Action
Convert(string contents); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/MigraDoc.Extensions/MigraDoc.Extensions.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {1863068F-975C-4F5B-ABA7-FBA344709A48} 8 | Library 9 | Properties 10 | MigraDoc.Extensions 11 | MigraDoc.Extensions 12 | v4.0 13 | 512 14 | ..\..\ 15 | true 16 | 17 | 18 | 19 | true 20 | full 21 | false 22 | bin\Debug\ 23 | DEBUG;TRACE 24 | prompt 25 | 4 26 | 27 | 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | 35 | 36 | 37 | ..\..\packages\PDFsharp-MigraDoc-GDI.1.32.3879.0\lib\net20\MigraDoc.DocumentObjectModel.dll 38 | 39 | 40 | ..\..\packages\PDFsharp-MigraDoc-GDI.1.32.3879.0\lib\net20\MigraDoc.Rendering.dll 41 | 42 | 43 | ..\..\packages\PDFsharp-MigraDoc-GDI.1.32.3879.0\lib\net20\MigraDoc.RtfRendering.dll 44 | 45 | 46 | ..\..\packages\PDFsharp-MigraDoc-GDI.1.32.3879.0\lib\net20\PdfSharp.dll 47 | 48 | 49 | ..\..\packages\PDFsharp-MigraDoc-GDI.1.32.3879.0\lib\net20\PdfSharp.Charting.dll 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 79 | -------------------------------------------------------------------------------- /src/MigraDoc.Extensions/ParagraphExtensions.cs: -------------------------------------------------------------------------------- 1 | using MigraDoc.DocumentObjectModel; 2 | using System; 3 | 4 | namespace MigraDoc.Extensions 5 | { 6 | public static class ParagraphExtensions 7 | { 8 | public static Paragraph SetStyle(this Paragraph paragraph, string style) 9 | { 10 | if (paragraph == null) 11 | { 12 | throw new ArgumentNullException("paragraph"); 13 | } 14 | if (string.IsNullOrEmpty(style)) 15 | { 16 | throw new ArgumentNullException("style"); 17 | } 18 | 19 | paragraph.Style = style; 20 | return paragraph; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/MigraDoc.Extensions/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("MigraDoc.Extensions")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("MigraDoc.Extensions")] 13 | [assembly: AssemblyCopyright("Copyright © 2013")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("65c350e6-85a0-4da2-9182-26287195266c")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /src/MigraDoc.Extensions/SectionExtensions.cs: -------------------------------------------------------------------------------- 1 | using MigraDoc.DocumentObjectModel; 2 | using System; 3 | 4 | namespace MigraDoc.Extensions 5 | { 6 | public static class SectionExtensions 7 | { 8 | public static Section Add(this Section section, string contents, IConverter converter) 9 | { 10 | if (string.IsNullOrEmpty(contents)) 11 | { 12 | throw new ArgumentNullException("contents"); 13 | } 14 | if (converter == null) 15 | { 16 | throw new ArgumentNullException("converter"); 17 | } 18 | 19 | var addAction = converter.Convert(contents); 20 | addAction(section); 21 | return section; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/MigraDoc.Extensions/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /src/examples/MigraDoc.Extensions.Html.Example/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/examples/MigraDoc.Extensions.Html.Example/Example.html: -------------------------------------------------------------------------------- 1 | 
2 |

This is a heading 1

3 |

4 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin dapibus convallis nisi quis volutpat. In in felis id felis venenatis venenatis.
5 | Mauris sit amet consequat mi. Proin gravida gravida tellus, eget tristique leo pharetra sed. Proin nec quam at ligula viverra sollicitudin. Donec sit amet neque ac nisi adipiscing porta. Suspendisse mollis mi id nulla condimentum lobortis. 6 |

7 |

8 | Etiam sem arcu, imperdiet sed rhoncus in, rhoncus posuere nulla. Pellentesque sit amet urna non elit suscipit imperdiet. Ut at auctor felis. 9 |

10 | 11 |

This is a heading 2

12 |

13 | Fusce augue turpis, convallis eget facilisis eget, scelerisque in odio. Sed in suscipit elit. Morbi ipsum tortor, aliquam sit amet mattis sit amet, ullamcorper vitae eros. Proin ut enim a eros dignissim iaculis. 14 |

15 |
    16 |
  • Strong
  • 17 |
  • Italic
  • 18 |
  • Underline
  • 19 |
  • Strong Italic
  • 20 |
  • Strong Underline
  • 21 |
  • All the styles
  • 22 |
23 |
24 |

This is a heading 3

25 |

26 | Fusce augue turpis, convallis eget facilisis eget, scelerisque in odio. Sed in suscipit elit. Morbi ipsum tortor, aliquam sit amet mattis sit amet, ullamcorper vitae eros. Proin ut enim a eros dignissim iaculis. 27 |

28 |
    29 |
  1. One
  2. 30 |
  3. Two
  4. 31 |
  5. Three
  6. 32 |
  7. Four
  8. 33 |
  9. Five
  10. 34 |
35 |

36 | Fusce augue turpis, convallis eget facilisis eget, scelerisque in odio. Sed in suscipit elit. Morbi ipsum tortor, aliquam sit amet mattis sit amet, ullamcorper vitae eros. Proin ut enim a eros dignissim iaculis. 37 |

38 |
    39 |
  1. One
  2. 40 |
  3. Two
  4. 41 |
  5. Three
  6. 42 |
  7. Four
  8. 43 |
  9. Five
  10. 44 |
45 |
46 | -------------------------------------------------------------------------------- /src/examples/MigraDoc.Extensions.Html.Example/Example.md: -------------------------------------------------------------------------------- 1 | # This is markdown 2 | 3 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque laoreet nibh sit amet lacus ultrices in mollis sapien eleifend. 4 | Mauris congue luctus elit sit amet elementum. Integer nisl sapien, tristique et venenatis nec, auctor ac risus. Pellentesque et nisl eu risus pretium elementum. 5 | 6 | This 7 | should 8 | collapse 9 | to 10 | one 11 | line 12 | 13 | --- 14 | 15 | Sed non eros metus, in posuere dui. Nunc lobortis tellus vitae dolor sodales quis aliquet augue malesuada. Donec orci sem, imperdiet a suscipit eu, interdum sed ipsum. Donec ullamcorper consequat mauris, non faucibus elit placerat sed. Etiam luctus commodo tristique. 16 | 17 | - **strong** 18 | - *italic* 19 | - ***strong italic*** 20 | 21 | ## This is a secondary heading 22 | 23 | Curabitur fringilla rhoncus pellentesque. Morbi at diam metus. Sed ac ultricies orci. Sed eu felis enim. Integer molestie libero elementum ligula hendrerit eleifend. 24 | 25 | 1. One 26 | 2. Two 27 | 3. Three 28 | 4. Four 29 | 5. Five 30 | 31 | Curabitur fringilla rhoncus pellentesque. Morbi at diam metus. Sed ac ultricies orci. Sed eu felis enim. Integer molestie libero elementum ligula [hendrerit eleifend](http://www.google.com). -------------------------------------------------------------------------------- /src/examples/MigraDoc.Extensions.Html.Example/MigraDoc.Extensions.Html.Example.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {2383AE62-1D25-40DC-AF73-0CA020E96C7E} 8 | Exe 9 | Properties 10 | MigraDoc.Extensions.Html.Example 11 | MigraDoc.Extensions.Html.Example 12 | v4.5 13 | 512 14 | ..\..\..\ 15 | true 16 | 17 | 18 | AnyCPU 19 | true 20 | full 21 | false 22 | bin\Debug\ 23 | DEBUG;TRACE 24 | prompt 25 | 4 26 | 27 | 28 | AnyCPU 29 | pdbonly 30 | true 31 | bin\Release\ 32 | TRACE 33 | prompt 34 | 4 35 | 36 | 37 | 38 | ..\..\..\packages\PDFsharp-MigraDoc-GDI.1.32.3879.0\lib\net20\MigraDoc.DocumentObjectModel.dll 39 | 40 | 41 | ..\..\..\packages\PDFsharp-MigraDoc-GDI.1.32.3879.0\lib\net20\MigraDoc.Rendering.dll 42 | 43 | 44 | ..\..\..\packages\PDFsharp-MigraDoc-GDI.1.32.3879.0\lib\net20\MigraDoc.RtfRendering.dll 45 | 46 | 47 | ..\..\..\packages\PDFsharp-MigraDoc-GDI.1.32.3879.0\lib\net20\PdfSharp.dll 48 | 49 | 50 | ..\..\..\packages\PDFsharp-MigraDoc-GDI.1.32.3879.0\lib\net20\PdfSharp.Charting.dll 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | {ca3f8535-ea5e-4362-8922-ffbd86df498f} 72 | MigraDoc.Extensions.Html 73 | 74 | 75 | {ea990c7e-f7ec-4857-9a12-372ffe74b004} 76 | MigraDoc.Extensions.Markdown 77 | 78 | 79 | {1863068f-975c-4f5b-aba7-fba344709a48} 80 | MigraDoc.Extensions 81 | 82 | 83 | 84 | 85 | Always 86 | 87 | 88 | Always 89 | 90 | 91 | 92 | 93 | 100 | -------------------------------------------------------------------------------- /src/examples/MigraDoc.Extensions.Html.Example/Program.cs: -------------------------------------------------------------------------------- 1 | using MigraDoc.DocumentObjectModel; 2 | using MigraDoc.Extensions.Markdown; 3 | using MigraDoc.Rendering; 4 | using System.Diagnostics; 5 | using System.IO; 6 | 7 | namespace MigraDoc.Extensions.Html.Example 8 | { 9 | class Program 10 | { 11 | static void Main(string[] args) 12 | { 13 | new Program().Run(); 14 | } 15 | 16 | private string outputName = "output.pdf"; 17 | 18 | void Run() 19 | { 20 | if (File.Exists(outputName)) 21 | { 22 | File.Delete(outputName); 23 | } 24 | 25 | 26 | var doc = new Document(); 27 | StyleDoc(doc); 28 | var section = doc.AddSection(); 29 | 30 | var html = File.ReadAllText("example.html"); 31 | section.AddHtml(html); 32 | 33 | var markdown = File.ReadAllText("example.md"); 34 | section.AddMarkdown(markdown); 35 | 36 | var renderer = new PdfDocumentRenderer(); 37 | renderer.Document = doc; 38 | renderer.RenderDocument(); 39 | 40 | renderer.Save(outputName); 41 | Process.Start(outputName); 42 | } 43 | 44 | private void StyleDoc(Document doc) 45 | { 46 | Color green = new Color(108, 179, 63), 47 | brown = new Color(88, 71, 76), 48 | lightbrown = new Color(150, 132, 126); 49 | 50 | var body = doc.Styles["Normal"]; 51 | 52 | body.Font.Size = Unit.FromPoint(10); 53 | body.Font.Color = new Color(51, 51, 51); 54 | 55 | body.ParagraphFormat.LineSpacingRule = LineSpacingRule.Multiple; 56 | body.ParagraphFormat.LineSpacing = 1.25; 57 | body.ParagraphFormat.SpaceAfter = 10; 58 | 59 | var footer = doc.Styles["Footer"]; 60 | footer.Font.Size = Unit.FromPoint(9); 61 | footer.Font.Color = lightbrown; 62 | 63 | var h1 = doc.Styles["Heading1"]; 64 | h1.Font.Color = brown; 65 | h1.Font.Bold = true; 66 | h1.Font.Size = Unit.FromPoint(15); 67 | 68 | var h2 = doc.Styles["Heading2"]; 69 | h2.Font.Color = green; 70 | h2.Font.Bold = true; 71 | h2.Font.Size = Unit.FromPoint(13); 72 | 73 | var h3 = doc.Styles["Heading3"]; 74 | h3.Font.Bold = true; 75 | h3.Font.Color = Colors.Black; 76 | h3.Font.Size = Unit.FromPoint(11); 77 | 78 | var links = doc.Styles["Hyperlink"]; 79 | links.Font.Color = green; 80 | 81 | var unorderedlist = doc.AddStyle("UnorderedList", "Normal"); 82 | var listInfo = new ListInfo(); 83 | listInfo.ListType = ListType.BulletList1; 84 | unorderedlist.ParagraphFormat.ListInfo = listInfo; 85 | unorderedlist.ParagraphFormat.LeftIndent = "1cm"; 86 | unorderedlist.ParagraphFormat.FirstLineIndent = "-0.5cm"; 87 | unorderedlist.ParagraphFormat.SpaceAfter = 0; 88 | 89 | var orderedlist = doc.AddStyle("OrderedList", "UnorderedList"); 90 | orderedlist.ParagraphFormat.ListInfo.ListType = ListType.NumberList1; 91 | 92 | // for list spacing (since MigraDoc doesn't provide a list object that we can target) 93 | var listStart = doc.AddStyle("ListStart", "Normal"); 94 | listStart.ParagraphFormat.SpaceAfter = 0; 95 | listStart.ParagraphFormat.LineSpacing = 0.5; 96 | var listEnd = doc.AddStyle("ListEnd", "ListStart"); 97 | listEnd.ParagraphFormat.LineSpacing = 1; 98 | 99 | var hr = doc.AddStyle("HorizontalRule", "Normal"); 100 | var hrBorder = new Border(); 101 | hrBorder.Width = "1pt"; 102 | hrBorder.Color = Colors.DarkGray; 103 | hr.ParagraphFormat.Borders.Bottom = hrBorder; 104 | hr.ParagraphFormat.LineSpacing = 0; 105 | hr.ParagraphFormat.SpaceBefore = 15; 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/examples/MigraDoc.Extensions.Html.Example/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("MigraDoc.Extensions.Html.Example")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("MigraDoc.Extensions.Html.Example")] 13 | [assembly: AssemblyCopyright("Copyright © 2013")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("67875b3e-3554-4630-ac8e-75af46368ce8")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /src/examples/MigraDoc.Extensions.Html.Example/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /src/specs/MigraDoc.Extensions.Html.Specs/DebuggerShim.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Reflection; 3 | using NSpec; 4 | using NSpec.Domain; 5 | using NSpec.Domain.Formatters; 6 | 7 | /* 8 | * Howdy, 9 | * 10 | * This is NSpec's DebuggerShim. It will allow you to use TestDriven.Net or Resharper's test runner to run 11 | * NSpec tests that are in the same Assembly as this class. 12 | * 13 | * It's DEFINITELY worth trying specwatchr (http://nspec.org/continuoustesting). Specwatchr automatically 14 | * runs tests for you. 15 | * 16 | * If you ever want to debug a test when using Specwatchr, simply put the following line in your test: 17 | * 18 | * System.Diagnostics.Debugger.Launch() 19 | * 20 | * Visual Studio will detect this and will give you a window which you can use to attach a debugger. 21 | */ 22 | 23 | //[TestFixture] 24 | public class DebuggerShim 25 | { 26 | //[Test] 27 | public void debug() 28 | { 29 | var tagOrClassName = ""; 30 | 31 | var types = GetType().Assembly.GetTypes(); 32 | // OR 33 | // var types = new Type[]{typeof(Some_Type_Containg_some_Specs)}; 34 | var finder = new SpecFinder(types, ""); 35 | var builder = new ContextBuilder(finder, new Tags().Parse(tagOrClassName), new DefaultConventions()); 36 | var runner = new ContextRunner(builder, new ConsoleFormatter(), false); 37 | var results = runner.Run(builder.Contexts().Build()); 38 | 39 | //assert that there aren't any failures 40 | results.Failures().Count().should_be(0); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/specs/MigraDoc.Extensions.Html.Specs/MigraDoc.Extensions.Html.Specs.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {CFBA7EB2-7A2F-4086-8EF7-7197DCDEE593} 8 | Library 9 | Properties 10 | MigraDoc.Extensions.Html.Specs 11 | MigraDoc.Extensions.Html.Specs 12 | v4.5 13 | 512 14 | ..\..\..\ 15 | true 16 | 17 | 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | 36 | False 37 | ..\..\..\packages\HtmlAgilityPack.1.4.6\lib\Net45\HtmlAgilityPack.dll 38 | 39 | 40 | ..\..\..\packages\PDFsharp-MigraDoc-GDI.1.32.3879.0\lib\net20\MigraDoc.DocumentObjectModel.dll 41 | 42 | 43 | ..\..\..\packages\PDFsharp-MigraDoc-GDI.1.32.3879.0\lib\net20\MigraDoc.Rendering.dll 44 | 45 | 46 | ..\..\..\packages\PDFsharp-MigraDoc-GDI.1.32.3879.0\lib\net20\MigraDoc.RtfRendering.dll 47 | 48 | 49 | False 50 | ..\..\..\packages\nspec.0.9.66\lib\NSpec.dll 51 | 52 | 53 | ..\..\..\packages\NUnit.2.6.2\lib\nunit.framework.dll 54 | 55 | 56 | ..\..\..\packages\PDFsharp-MigraDoc-GDI.1.32.3879.0\lib\net20\PdfSharp.dll 57 | 58 | 59 | ..\..\..\packages\PDFsharp-MigraDoc-GDI.1.32.3879.0\lib\net20\PdfSharp.Charting.dll 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | {ca3f8535-ea5e-4362-8922-ffbd86df498f} 82 | MigraDoc.Extensions.Html 83 | 84 | 85 | {1863068f-975c-4f5b-aba7-fba344709a48} 86 | MigraDoc.Extensions 87 | 88 | 89 | 90 | 91 | 98 | -------------------------------------------------------------------------------- /src/specs/MigraDoc.Extensions.Html.Specs/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("MigraDoc.Extensions.Html.Specs")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("MigraDoc.Extensions.Html.Specs")] 13 | [assembly: AssemblyCopyright("Copyright © 2013")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("d4d20e01-5345-4fa4-adae-ba5b0c8916c0")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /src/specs/MigraDoc.Extensions.Html.Specs/converting_tags.cs: -------------------------------------------------------------------------------- 1 | using MigraDoc.DocumentObjectModel; 2 | using NSpec; 3 | using System; 4 | 5 | namespace MigraDoc.Extensions.Html.Specs 6 | { 7 | class converting_tags : nspec 8 | { 9 | Section pdf; 10 | 11 | string html; 12 | 13 | void before_each() 14 | { 15 | pdf = new Section(); 16 | } 17 | 18 | void act_each() 19 | { 20 | pdf.AddHtml(html); 21 | } 22 | 23 | void plain_text() 24 | { 25 | before = () => html = "test"; 26 | it["adds a paragraph to the pdf containing the provided text"] = () 27 | => pdf.LastParagraph.should_not_be_null() 28 | .Elements[0].should_cast_to() 29 | .Content.should_be("test"); 30 | } 31 | 32 | void html_encoded_text() 33 | { 34 | before = () => html = "<Me & You>"; 35 | 36 | it["decodes the html"] = () 37 | => pdf.LastParagraph.Elements[0].should_cast_to() 38 | .Content.should_be(""); 39 | } 40 | 41 | void paragraph_tag() 42 | { 43 | context["when the tag is empty"] = () => 44 | { 45 | before = () => html = "

"; 46 | it["adds an empty paragraph to the pdf"] = () 47 | => pdf.LastParagraph.Elements.Count.should_be(0); 48 | }; 49 | 50 | context["when the tag contains plain text"] = () => 51 | { 52 | before = () => html = "

test

"; 53 | it["adds a paragraph to the pdf containing the provided text"] = () 54 | => pdf.LastParagraph.Elements[0].should_cast_to() 55 | .Content.should_be("test"); 56 | }; 57 | } 58 | 59 | void heading_tags() 60 | { 61 | new[] { 1, 2, 3, 4, 5, 6 }.Do(x => 62 | { 63 | context["heading{0} tag".With(x)] = () => 64 | { 65 | pdf = new Section(); 66 | pdf.AddHtml("".With(x)); 67 | 68 | it["adds a paragraph with the style 'Heading{0}'".With(x)] = () 69 | => pdf.LastParagraph.Style = "Heading{0}".With(x); 70 | }; 71 | }); 72 | } 73 | 74 | void strong_tag() 75 | { 76 | before = () => html = "test"; 77 | it["adds a paragraph with bold text"] = () 78 | => pdf.LastParagraph.should_not_be_null() 79 | .Elements[0].should_cast_to() 80 | .Bold.should_be_true(); 81 | } 82 | 83 | // edge case 84 | void line_break_within_strong_tag() 85 | { 86 | before = () => html = "test
test2
"; 87 | it["adds bold text with a line break"] = () 88 | => pdf.LastParagraph.Elements[0].should_cast_to() 89 | .Elements[1].should_cast_to() 90 | .SymbolName.should_be(SymbolName.LineBreak); 91 | } 92 | 93 | void italic_tag() 94 | { 95 | before = () => html = "test"; 96 | it["adds a paragraph with italic text"] = () 97 | => pdf.LastParagraph.should_not_be_null() 98 | .Elements[0].should_cast_to() 99 | .Italic.should_be_true(); 100 | } 101 | 102 | void emphasis_tag() 103 | { 104 | before = () => html = "test"; 105 | it["adds a paragraph with italic text"] = () 106 | => pdf.LastParagraph.should_not_be_null() 107 | .Elements[0].should_cast_to() 108 | .Italic.should_be_true(); 109 | } 110 | 111 | void underline_tag() 112 | { 113 | before = () => html = "test"; 114 | it["adds a paragraph with underlined text"] = () 115 | => pdf.LastParagraph.should_not_be_null() 116 | .Elements[0].should_cast_to() 117 | .Underline.should_be(Underline.Single); 118 | } 119 | 120 | void nested_bold_italic_and_underline_tags() 121 | { 122 | FormattedText text = null; 123 | before = () => html = "test"; 124 | 125 | act = () => 126 | { 127 | text = pdf.LastParagraph.Elements[0] as FormattedText; 128 | }; 129 | 130 | it["adds a paragraph with formatted text"] = () 131 | => text.should_not_be_null(); 132 | 133 | it["the text is bold"] = () => text.Bold.should_be_true(); 134 | it["the text is italic"] = () => text.Italic.should_be_true(); 135 | it["the text is underlined"] = () => text.Underline.should_be(Underline.Single); 136 | } 137 | 138 | void anchor_tag() 139 | { 140 | Hyperlink link = null; 141 | 142 | before = () => html = "test"; 143 | 144 | act = () => link = pdf.LastParagraph.Elements[0] as Hyperlink; 145 | 146 | it["adds a hyperlink"] = () => link.should_not_be_null(); 147 | it["sets the link to the anchor's href"] = () => link.Name.should_be("http://www.google.com"); 148 | it["contains the anchor text"] = () 149 | => link.Elements[0].should_cast_to() 150 | .Content.should_be("test"); 151 | } 152 | 153 | void div_tag() 154 | { 155 | before = () => html = "

test

"; 156 | 157 | it["processes the inner html as normal"] = () 158 | => pdf.LastParagraph.Elements[0].should_cast_to() 159 | .Elements[0].should_cast_to() 160 | .Content.should_be("test"); 161 | } 162 | 163 | void heading_followed_by_a_paragraph() 164 | { 165 | before = () => html = "

Heading

Content

"; 166 | 167 | it["adds a heading paragraph"] = () 168 | => pdf.Elements[0].should_cast_to() 169 | .Style.should_be("Heading1"); 170 | 171 | it["adds a text paragraph"] = () 172 | => pdf.LastParagraph.Elements[0].should_cast_to() 173 | .Content.should_be("Content"); 174 | } 175 | 176 | void whitespace_between_tags() 177 | { 178 | before = () => html = @" 179 |

One

180 | 181 | 182 |

Two

183 | "; 184 | 185 | it["removes the whitespace"] = () 186 | => pdf.Elements.Count.should_be(2); 187 | } 188 | 189 | void line_breaks_between_text_elements() 190 | { 191 | before = () => html = "this\nshould\nbe\ncollapsed"; 192 | 193 | it["removes the line breaks"] = () 194 | => pdf.LastParagraph.Elements.Count.should_be(1); 195 | } 196 | 197 | void unordered_list() 198 | { 199 | before = () => html = @" 200 |
    201 |
  • Item 1
  • 202 |
  • Item 2
  • 203 |
  • Item 3
  • 204 |
205 | "; 206 | 207 | it["adds an opening paragraph to the start of the list with style 'ListStart'"] = () 208 | => pdf.Elements[0].should_cast_to().Style.should_be("ListStart"); 209 | 210 | it["adds a paragraph for each list item with the style 'UnorderedList'"] = () 211 | => 212 | { 213 | pdf.Elements.Count.should_be(5); // including the start/close paragraphs 214 | for (int i = 1, j = pdf.Elements.Count - 1; i < j; i++) 215 | { 216 | var li = pdf.Elements[i] as Paragraph; 217 | li.Style.should_be("UnorderedList"); 218 | } 219 | }; 220 | 221 | it["adds a closing paragraph to the end of the list with style 'ListEnd'"] = () 222 | => pdf.LastParagraph.Style.should_be("ListEnd"); 223 | } 224 | 225 | void ordered_list() 226 | { 227 | before = () => html = @" 228 |
    229 |
  1. Item 1
  2. 230 |
  3. Item 2
  4. 231 |
  5. Item 3
  6. 232 |
233 | "; 234 | 235 | it["adds an opening paragraph to the start of the list with style 'ListStart'"] = () 236 | => pdf.Elements[0].should_cast_to().Style.should_be("ListStart"); 237 | 238 | it["adds a paragraph for each list item with the style 'OrderedList'"] = () 239 | => 240 | { 241 | pdf.Elements.Count.should_be(5); 242 | for (int i = 1, j = pdf.Elements.Count - 1; i < j; i++) 243 | { 244 | var li = pdf.Elements[i] as Paragraph; 245 | li.Style.should_be("OrderedList"); 246 | } 247 | }; 248 | 249 | it["adds a closing paragraph to the end of the list with style 'ListEnd'"] = () 250 | => pdf.LastParagraph.Style.should_be("ListEnd"); 251 | } 252 | 253 | void multiple_ordered_lists() 254 | { 255 | before = () => html = @" 256 |
    257 |
  1. Item 1
  2. 258 |
  3. Item 2
  4. 259 |
  5. Item 3
  6. 260 |
261 |
    262 |
  1. Item 1
  2. 263 |
  3. Item 2
  4. 264 |
  5. Item 3
  6. 265 |
266 | "; 267 | 268 | it["restarts numbering for each list"] = () => 269 | { 270 | pdf.Elements[1].should_cast_to() 271 | .Format.ListInfo.ContinuePreviousList.should_be_false(); 272 | 273 | pdf.Elements[2].should_cast_to() 274 | .Format.ListInfo.ContinuePreviousList.should_be_true(); 275 | 276 | // first item in the second list should not continue numbering 277 | pdf.Elements[4].should_cast_to() 278 | .Format.ListInfo.ContinuePreviousList.should_be_false(); 279 | }; 280 | 281 | it["still adds the 'ListEnd' paragraph"] = () 282 | => pdf.LastParagraph.Style.should_be("ListEnd"); 283 | } 284 | 285 | void horizontal_rule_tag() 286 | { 287 | before = () => html = "
"; 288 | 289 | it["adds a paragraph with the style 'HorizontalRule'"] = () 290 | => pdf.LastParagraph.Style.should_be("HorizontalRule"); 291 | } 292 | 293 | void line_break() 294 | { 295 | before = () => html = "
"; 296 | 297 | it["adds a line break to the paragraph"] = () 298 | => pdf.LastParagraph.Elements[0].should_cast_to() 299 | .SymbolName.should_be(SymbolName.LineBreak); 300 | } 301 | } 302 | } 303 | -------------------------------------------------------------------------------- /src/specs/MigraDoc.Extensions.Html.Specs/define_htmlconverter.cs: -------------------------------------------------------------------------------- 1 | using MigraDoc.DocumentObjectModel; 2 | using NSpec; 3 | 4 | namespace MigraDoc.Extensions.Html.Specs 5 | { 6 | class define_htmlconverter : nspec 7 | { 8 | HtmlConverter converter; 9 | Section pdf; 10 | 11 | void before_each() 12 | { 13 | converter = new HtmlConverter(); 14 | pdf = new Section(); 15 | } 16 | 17 | void adding_custom_handlers() 18 | { 19 | before = () => converter.NodeHandlers.Add( 20 | "img", (node, parent) => ((Section)parent).AddParagraph() 21 | ); 22 | 23 | act = () => pdf.Add("", converter); 24 | 25 | it["adds the handler to the converter"] = () 26 | => converter.NodeHandlers["img"].should_not_be_null(); 27 | 28 | it["uses the handler when processing"] = () 29 | => pdf.LastParagraph.should_not_be_null(); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/specs/MigraDoc.Extensions.Html.Specs/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | --------------------------------------------------------------------------------