Table of Contents

HTML

DocWright reads HTML the way a browser does, recovering from malformed markup, and applies a documented subset of CSS. It writes HTML as a single self-contained file, or as a page with linked images and a stylesheet.

HTML to PDF and Word

HTML goes through the same calls as a Word document. .html, .htm and .xhtml are detected automatically:

using DocWright;

// HTML, RTF and Markdown convert like any Word document.
foreach (string file in new[] { "article.html", "article.rtf" })
{
    using FileStream input = File.OpenRead(file);
    using FileStream output = File.Create(Path.ChangeExtension(file, ".pdf").Replace("article", Path.GetExtension(file)[1..]));
    converter.Convert(input, output);
}
article.html → html.pdf
An HTML article rendered to PDF with headings, paragraphs, a list and a table

Load it with converter.Load(stream, FormatDetection.Html) to edit it or save it as .docx.

Word to HTML

converter.Save(document, stream, ".html") writes self-contained HTML: inline CSS and images as data: URIs, one file. For a web page with separate files, configure the writer:

using DocWright.Core.Diagnostics;
using DocWright.Core.Formats;
using DocWright.Formats.Html;

// Linked HTML: images and one stylesheet written as separate files.
var html = new HtmlWriter(new HtmlWriteOptions
{
    Mode = HtmlOutputMode.Linked,
    ResourceWriter = new FolderResourceWriter("letterhead_files"),
    StylesheetWriter = new FolderResourceWriter("letterhead_files"),
    Title = "Letterhead",
    NewLine = "\n",
});

using (FileStream output = File.Create("letterhead-linked.html"))
{
    html.Write(document, output, new DocumentWriteOptions(), NullConversionDiagnostics.Instance);
}

The resource writer decides where each file goes and returns the URL the HTML should use:

using DocWright.Formats.Html;

/// <summary>Writes each image the HTML refers to into a folder, and returns its URL.</summary>
internal sealed class FolderResourceWriter(string folder) : IHtmlResourceWriter
{
    public string? Write(string suggestedFileName, string contentType, byte[] data)
    {
        Directory.CreateDirectory(folder);
        File.WriteAllBytes(Path.Combine(folder, suggestedFileName), data);
        return $"{folder}/{suggestedFileName}";      // the src/href the HTML will use
    }
}
HtmlWriteOptions Default Meaning
Mode SelfContained Or Linked, with a ResourceWriter.
StylesheetWriter null Write CSS to one shared file instead of inline.
WriteDocumentShell true false writes only the body's contents, to embed in a page you own.
XhtmlSyntax false Well-formed XML output.
WriteDirectionAttribute false dir="rtl" instead of a CSS direction.
Title null The <title>.
Indent false Pretty-printing. Leave it off if you'll read the HTML back: indentation adds whitespace.
NewLine "\n" "\n" or "\r\n".

Nothing is fetched

The HTML reader never downloads anything. Images and stylesheets referenced by URL or path are reported (DXP2004) and skipped. An image falls back to its alt text. Only data: URIs are used, because their bytes are already in the file. <script> is removed.

A document that names a URL is untrusted input telling your server where to send a request. If you want resources fetched, implement IHtmlResourceResolver with your own allow-list and set it on HtmlReadOptions.ResourceResolver. You own the risk.

Reader options

HtmlReadOptions Default Meaning
ResourceResolver null Your fetcher, for images and stylesheets.
BaseUri null Resolves relative references when the page has no <base href>.
ApplyStyleElements true false ignores <style> blocks and uses only inline style="".
MapHeadingsToStyles true <h1> becomes the Heading 1 style, so the outline survives.
MaxNestingDepth 256 Refuses absurdly deep markup with an exception instead of a crash.

What survives

  • HTML to Word keeps block structure, inline formatting, lists, tables with spans, links, bookmarks and embedded images. It drops float, position, display, media queries, and attribute and pseudo-class selectors, reporting each once. Table spacing, vertical alignment and font sizes follow Word's own HTML import, measured against Word rather than a browser.
  • Word to HTML keeps paragraphs, headings, formatting, lists, tables, links and images. HTML has nowhere to put page size, headers, footers or footnotes, so they're dropped. Fields become their current text.