Conversion options
Everything optional about a conversion lives on ConvertOptions. Pass null, or leave it out, for the defaults. Each conversion reads its options once, at the start, so use a fresh object per call rather than changing a shared one.
Pages, metadata and progress
This converts pages 1 and 3 of a report, stamps PDF metadata and prints each stage as it happens:
using DocWright;
using DocWright.Core.Primitives;
var options = new ConvertOptions
{
Pages = PageRange.Parse("1,3"), // print-dialog syntax: "1-3,7,12-"
Progress = new StageLogger(),
};
// Metadata is get-only: set its properties rather than replacing it.
options.Metadata.Title = "Quarterly line report";
options.Metadata.Author = "Finance";
options.Metadata.Subject = "Q3 2026";
options.Metadata.CreationDate = new DateTimeOffset(2026, 10, 1, 9, 0, 0, TimeSpan.Zero);
using (FileStream input = File.OpenRead("quarterly-report.docx"))
using (FileStream output = File.Create("pages-1-and-3.pdf"))
{
ConversionResult result = converter.Convert(input, output, options);
Console.WriteLine($"Wrote {result.PageCount} page(s).");
}
The progress reporter used above:
/// <summary>Prints each stage once. Reports arrive on the converting thread, in order.</summary>
internal sealed class StageLogger : IProgress<ConversionProgress>
{
private ConversionStage? last;
public void Report(ConversionProgress value)
{
if (value.Stage != this.last)
{
this.last = value.Stage;
string pages = value.HasPageProgress ? $" ({value.PagesCompleted}/{value.PagesTotal} pages)" : "";
Console.WriteLine($"{value.Stage}{pages}");
}
}
}
Output
Preparing
ReadingDocument
ResolvingDocument
LayingOutDocument
RenderingPages (0/2 pages)
Completed (2/2 pages)
Wrote 2 page(s).
Tip
System.Progress<T> posts each report to the thread pool, so in a console app its lines can print after the conversion returns, or out of order. Implement IProgress<ConversionProgress> yourself, as above, when order matters. In a UI app, Progress<T> is what you want: it reports on the UI thread.
Every option
| Option | Default | Meaning |
|---|---|---|
Pages |
PageRange.All |
Which pages to render. PageRange.Parse accepts print-dialog syntax: "1-3,7,12-". |
SourceFormat |
Auto |
What the input is. Required for plain text, which is never detected, and advisable for Markdown. |
Metadata |
empty | PDF Title, Author, Subject, Keywords, Creator, Producer, CreationDate and Conformance (PDF/A). Get-only: set its properties. |
Limits |
safe defaults | Caps on size, time, pages, memory and nesting. See Hardening untrusted input. |
Diagnostics |
null |
Where warnings about degraded content go. See Diagnostics and strict mode. |
Progress |
null |
Stage and page-count callbacks. |
StrictMode |
false |
Throw UnsupportedFeatureException instead of rendering a degraded result. |
Password |
null |
Opens an encrypted document or PDF. See Encryption. |
TaggedPdf |
false |
Write a structure tree for assistive technology. See PDF/A and tagged PDF. |
DefaultLanguage |
null |
The PDF language when the document declares none, for example "en-GB". |
FontDirectories, FontFallbackChain, ScriptFallbackFonts |
empty | Font sources and substitutes. See Fonts and complex scripts. |
WarnOnFontSubstitution, FailOnFontSubstitution |
false |
Report, or refuse, font substitutions. |
TextShaper |
null |
A text shaper for complex scripts, such as HarfBuzzTextShaper. |
RenderRevisions |
false |
Reserved: drawing revision marks is not implemented yet. Revisions are always applied. |
Deterministic by default
DocWright writes no timestamp unless you set Metadata.CreationDate. The same input and options therefore give byte-identical output on every machine, which makes PDFs easy to cache, hash and test. Set the date when you want it recorded.
Telling DocWright what the input is
Convert, ConvertAsync and ConvertToImages detect DOCX, DOC, RTF and HTML from their content. Markdown has only a weak signature and plain text has none, so name them:
using DocWright;
using DocWright.Core.Primitives;
// Markdown's signature is weak and plain text has none: say what the input is.
using (FileStream input = File.OpenRead("article.md"))
using (FileStream output = File.Create("article.pdf"))
{
converter.Convert(input, output, new ConvertOptions { SourceFormat = FormatDetection.Markdown });
}

Load takes the format as its second argument instead: converter.Load(stream, FormatDetection.Text).
Things that follow the document, not an option
- Hidden text is never rendered. Text marked hidden in Word takes no space and is left out of the PDF entirely, including the PDF's extractable text, so hidden notes and prices can't leak.
GetText()and the text exports still include it, because it is still in the document. - East Asian line breaking follows the document's compatibility mode, as it does in Word. To get Word 2013's rules for an older document, set
document.Settings.CompatibilityMode = 15before converting.