SpecWorks.MarkMyWord 0.9.0

dotnet add package SpecWorks.MarkMyWord --version 0.9.0
                    
NuGet\Install-Package SpecWorks.MarkMyWord -Version 0.9.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="SpecWorks.MarkMyWord" Version="0.9.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="SpecWorks.MarkMyWord" Version="0.9.0" />
                    
Directory.Packages.props
<PackageReference Include="SpecWorks.MarkMyWord" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add SpecWorks.MarkMyWord --version 0.9.0
                    
#r "nuget: SpecWorks.MarkMyWord, 0.9.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package SpecWorks.MarkMyWord@0.9.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=SpecWorks.MarkMyWord&version=0.9.0
                    
Install as a Cake Addin
#tool nuget:?package=SpecWorks.MarkMyWord&version=0.9.0
                    
Install as a Cake Tool

MarkMyWord

A .NET 9 library for bidirectional conversion between CommonMark/GitHub Flavored Markdown and Microsoft Word (.docx) documents.

Features

MarkMyWord provides bidirectional conversion between Markdown and Word:

  • Markdown → Word: Convert CommonMark markdown to Word (.docx) documents using the Open XML SDK
  • Word → Markdown: Convert Word documents back to CommonMark or GitHub Flavored Markdown, optimized for LLM grounding and roundtripping

Markdown to Word - Currently Supported

Block Elements

  • Headings (ATX: # H1 through ###### H6, Setext: underlined)
  • Paragraphs
  • Code blocks (fenced with ``` and indented)
  • Block quotes (>)
  • Thematic breaks (---, ***, ___)
  • Lists (ordered, unordered, nested with proper indentation)
  • Tables (with headers, borders, and shading)

Inline Elements

  • Bold (**text** or __text__)
  • Italic (*text* or _text_)
  • Bold + Italic (***text***)
  • Inline code (`code`)
  • Links ([text](url))
  • Images (![alt](url) - supports local files and URLs with fallback)
  • Hard line breaks (two spaces or \ at end of line)

Styling

  • Customizable fonts and colors
  • Configurable heading styles
  • Code syntax highlighting for JSON, TypeSpec, and Bash
  • Automatic spell/grammar check suppression for code blocks

Coming Soon

  • Task lists
  • Footnotes
  • Definition lists

Word to Markdown Conversion

Supported Elements

  • Headings (H1-H6) → Markdown headings (# through ######)
  • Paragraphs → Plain text with proper spacing
  • Bold and Italic text → Markdown emphasis (**bold**, *italic*)
  • Inline code → Backtick syntax (`code`)
  • Lists (ordered and unordered, nested) → Markdown lists
  • Tables → GitHub Flavored Markdown table syntax
  • Links → [text](url) syntax
  • Images → ![alt](path) with optional extraction
  • Code blocks → Fenced code blocks with ```
  • Block quotes → > prefix

Conversion Options

  • CommonMark or GitHub Flavored Markdown output
  • LLM-optimized output - Clean, semantic content for AI grounding
  • Metadata extraction - Document properties as YAML frontmatter
  • Image extraction - Save embedded images to files
  • Roundtripping support - Preserve formatting for Word ↔ Markdown conversion

Installation

dotnet add package MarkMyWord

Quick Start

Markdown to Word

using MarkMyWord;

// Convert markdown string to .docx file
string markdown = "# Hello World\n\nThis is **bold** text.";
MarkdownConverter.ConvertToDocx(markdown, "output.docx");

Word to Markdown

using MarkMyWord;
using MarkMyWord.Configuration;

// Convert Word document to markdown file
WordConverter.ConvertToMarkdown("input.docx", "output.md");

// With options for LLM grounding
var options = new WordToMarkdownOptions
{
    Flavor = MarkdownFlavor.GitHubFlavoredMarkdown,
    OptimizeForLLM = true,
    ExtractImages = true,
    IncludeMetadata = false
};
WordConverter.ConvertToMarkdown("document.docx", "output.md", options);

// Convert to string
string markdown = WordConverter.ConvertToMarkdownString("document.docx");

Convert to Byte Array

// Get the document as a byte array (useful for web scenarios)
byte[] docxBytes = MarkdownConverter.ConvertToDocxBytes(markdown);

Stream-based Conversion

// Convert from stream to stream
using var inputStream = File.OpenRead("input.md");
using var outputStream = File.Create("output.docx");
MarkdownConverter.ConvertToDocx(inputStream, outputStream);

Async Conversion

// Async conversion
await MarkdownConverter.ConvertToDocxAsync(markdown, "output.docx");

Lists

// Unordered list
string unorderedList = @"
# Shopping List
- Apples
- Bananas
- Oranges
  - Naval oranges
  - Blood oranges
";

MarkdownConverter.ConvertToDocx(unorderedList, "shopping.docx");

// Ordered list
string orderedList = @"
# Instructions
1. Preheat oven to 350°F
2. Mix ingredients
3. Bake for 30 minutes
   1. Check at 25 minutes
   2. Test with toothpick
4. Let cool
";

MarkdownConverter.ConvertToDocx(orderedList, "instructions.docx");

Command-Line Interface

MarkMyWord includes a powerful CLI for converting markdown files from the command line.

Installation

dotnet tool install --global SpecWorks.MarkMyWord.CLI

Or run directly from the project:

dotnet run --project src/MarkMyWord.CLI/MarkMyWord.CLI.csproj -- [command] [options]

Usage

The CLI automatically detects the conversion direction based on file extension:

  • .md or .markdown input → converts to Word (.docx)
  • .docx input → converts to Markdown (.md)

Markdown to Word:

markmyword convert -i README.md
markmyword convert -i input.md -o output.docx

Word to Markdown:

markmyword convert -i document.docx
markmyword convert -i input.docx -o output.md

Specify output file:

markmyword convert -i input.md -o output.docx

Custom font and size:

markmyword convert -i document.md --font "Times New Roman" --font-size 12

Use dark theme:

markmyword convert -i document.md --theme dark

Use custom style configuration:

markmyword convert -i document.md --style custom-style.json

Verbose output:

markmyword convert -i document.md -v

Force overwrite:

markmyword convert -i document.md --force

Word to Markdown with options:

# Convert Word to GitHub Flavored Markdown (default)
markmyword convert -i document.docx -o output.md

# Convert to strict CommonMark
markmyword convert -i document.docx --commonmark

# Optimize for LLM grounding (clean, semantic output)
markmyword convert -i document.docx --optimize-llm

# Include document metadata as YAML frontmatter
markmyword convert -i document.docx --include-metadata

# Don't extract images
markmyword convert -i document.docx --extract-images false

View version:

markmyword version

Get help:

markmyword --help
markmyword convert --help

CLI Options

Common Options
Option Alias Description
--input -i Input file path (.md or .docx) (required)
--output -o Output file path (auto-detects extension)
--verbose -v Enable verbose output
--force - Overwrite output file if it exists
Markdown to Word Options
Option Alias Description
--font -f Default font name (e.g., 'Calibri')
--font-size -s Default font size (6-72 points)
--theme - Color theme: light (default) or dark
--style - Path to JSON style configuration file
Word to Markdown Options
Option Description Default
--to-markdown Explicitly convert to Markdown (auto-detected) false
--extract-images Extract and save embedded images true
--optimize-llm Optimize output for LLM grounding true
--commonmark Use strict CommonMark instead of GFM false
--include-metadata Include document metadata as YAML frontmatter false

Advanced Usage

Word to Markdown Options

using MarkMyWord;
using MarkMyWord.Configuration;

// Configure Word to Markdown conversion
var options = new WordToMarkdownOptions
{
    // Use GitHub Flavored Markdown (supports tables, strikethrough, etc.)
    Flavor = MarkdownFlavor.GitHubFlavoredMarkdown,

    // Optimize for LLM grounding (clean, semantic content)
    OptimizeForLLM = true,

    // Extract embedded images to files
    ExtractImages = true,

    // Directory for extracted images (default: same as output file)
    ImageOutputDirectory = "./images",

    // URL prefix for image links in markdown
    ImageUrlPrefix = "https://example.com/images/",

    // Include document metadata as YAML frontmatter
    IncludeMetadata = true,

    // Preserve formatting metadata for roundtripping
    PreserveFormattingMetadata = false,

    // Use HTML for complex formatting when no markdown equivalent exists
    UseHtmlForComplexFormatting = false,

    // Line ending style
    LineEndings = LineEndingStyle.LF
};

WordConverter.ConvertToMarkdown("document.docx", "output.md", options);

Markdown to Word Custom Styling

using MarkMyWord.Configuration;

var options = new ConversionOptions
{
    Styles = new StyleConfiguration
    {
        DefaultFontName = "Georgia",
        DefaultFontSize = 12,
        CodeFontName = "Fira Code",
        CodeFontSize = 10,
        CodeBackgroundColor = "F5F5F5",
        QuoteLeftBorderColor = "4A90E2",
        QuoteBackgroundColor = "EEF7FF"
    }
};

MarkdownConverter.ConvertToDocx(markdown, "output.docx", options);

Custom Heading Styles

var options = new ConversionOptions
{
    Styles = new StyleConfiguration
    {
        HeadingStyles = new[]
        {
            new HeadingStyle
            {
                Level = 1,
                FontSize = 24,
                Bold = true,
                Color = "2E74B5",
                SpacingBeforeTwips = 480,  // 1/3 inch
                SpacingAfterTwips = 240    // 1/6 inch
            },
            // ... configure levels 2-6
        }
    }
};

JSON Style Configuration

You can define styles in a JSON file and load them using the CLI or programmatically:

custom-style.json:

{
  "styles": {
    "defaultFontName": "Georgia",
    "defaultFontSize": 12,
    "headingStyles": [
      {
        "level": 1,
        "fontSize": 28,
        "bold": true,
        "color": "2E74B5",
        "spacingBeforeTwips": 480,
        "spacingAfterTwips": 240
      },
      {
        "level": 2,
        "fontSize": 20,
        "bold": true,
        "color": "2E74B5",
        "spacingBeforeTwips": 400,
        "spacingAfterTwips": 200
      },
      {
        "level": 3,
        "fontSize": 16,
        "bold": true,
        "color": "1F4D78",
        "spacingBeforeTwips": 320,
        "spacingAfterTwips": 160
      }
    ],
    "codeFontName": "Fira Code",
    "codeFontSize": 10,
    "codeBackgroundColor": "282C34",
    "quoteLeftBorderColor": "4A90E2",
    "quoteLeftBorderWidth": 4,
    "quoteBackgroundColor": "EEF7FF",
    "listIndentationTwips": 720
  }
}

Use with CLI:

markmyword convert -i document.md --style custom-style.json

Load programmatically:

using System.Text.Json;

var json = File.ReadAllText("custom-style.json");
var config = JsonSerializer.Deserialize<ConversionOptions>(json);
MarkdownConverter.ConvertToDocx(markdown, "output.docx", config);

Notes:

  • Colors are hex values without the # prefix
  • Spacing values are in twips (1440 twips = 1 inch)
  • Font sizes are in points

Document Metadata

var options = new ConversionOptions
{
    DocumentTitle = "My Document",
    Author = "John Doe",
    Subject = "Technical Documentation"
};

MarkdownConverter.ConvertToDocx(markdown, "output.docx", options);

Architecture

MarkMyWord uses a three-stage conversion pipeline:

  1. Parse: Markdown is parsed into an Abstract Syntax Tree (AST) using Markdig
  2. Render: The AST is traversed and converted to OpenXML elements using specialized renderers
  3. Style: Styles are applied and the document is saved using DocumentFormat.OpenXml
Markdown Text
     ↓
  Markdig Parser
     ↓
   AST (Syntax Tree)
     ↓
OpenXmlRenderer
     ↓
  OpenXML Elements
     ↓
 Word Document (.docx)

Project Structure

MarkMyWord/
├── src/
│   ├── MarkMyWord/                    # Core library
│   │   ├── MarkdownConverter.cs       # Public API
│   │   ├── Converters/
│   │   │   ├── OpenXmlRenderer.cs     # Main renderer
│   │   │   ├── BlockRenderers/        # Block element renderers
│   │   │   │   ├── CodeBlockRenderer.cs  # Code block rendering
│   │   │   │   ├── ListRenderer.cs    # List rendering
│   │   │   │   └── TableRenderer.cs   # Table rendering
│   │   │   └── InlineRenderers/       # Inline element renderers
│   │   │       └── LinkInlineRenderer.cs  # Links & images
│   │   ├── SyntaxHighlighting/        # Syntax highlighting
│   │   │   ├── ISyntaxHighlighter.cs  # Highlighter interface
│   │   │   ├── ColorCodeHighlighter.cs   # JSON highlighting
│   │   │   ├── TypeSpecHighlighter.cs    # TypeSpec highlighting
│   │   │   ├── BashHighlighter.cs     # Bash/Shell highlighting
│   │   │   └── SyntaxHighlighterFactory.cs
│   │   ├── OpenXml/
│   │   │   ├── DocumentBuilder.cs     # OpenXML document builder
│   │   │   ├── StyleManager.cs        # Style management
│   │   │   └── ListManager.cs         # List numbering management
│   │   └── Configuration/             # Configuration classes
│   └── MarkMyWord.CLI/                # Command-line tool
└── tests/
    └── MarkMyWord.Tests/              # Unit tests (29 tests)

Requirements

  • .NET 9.0 or later
  • Dependencies:
    • Markdig 0.37.0
    • DocumentFormat.OpenXml 3.1.0
    • ColorCode.Core 2.0.15

Building from Source

git clone https://github.com/yourusername/MarkMyWord.git
cd MarkMyWord
dotnet build
dotnet test

Examples

Convert a README file

var markdown = File.ReadAllText("README.md");
MarkdownConverter.ConvertToDocx(markdown, "README.docx");

Lists Example

string markdown = @"
# Shopping List

## Groceries
- Milk
- Eggs
- Bread

## Tasks
1. Buy groceries
2. Clean house
3. Do laundry
   - Whites
   - Colors
";

MarkdownConverter.ConvertToDocx(markdown, "shopping-list.docx");

Images Example

string markdown = @"
# Product Documentation

![Product Logo](logo.png)

Our product features:
![Feature 1](https://example.com/feature1.png)
![Feature 2](./images/feature2.jpg)
";

MarkdownConverter.ConvertToDocx(markdown, "product-doc.docx");

Tables Example

string markdown = @"
# Sales Report

| Product | Q1 Sales | Q2 Sales | Total |
|---------|----------|----------|-------|
| Widget A | $1,000 | $1,200 | $2,200 |
| Widget B | $850 | $900 | $1,750 |
| Widget C | $1,500 | $1,600 | $3,100 |
";

MarkdownConverter.ConvertToDocx(markdown, "sales-report.docx");

Syntax Highlighting

MarkMyWord supports syntax highlighting for code blocks, making code more readable in Word documents:

Supported Languages:

  • JSON - Property names, strings, numbers, keywords (true/false/null)
  • TypeSpec - Keywords, types, decorators, comments
  • Bash/Shell - Commands, keywords, variables, strings, comments

Example:

string markdown = @"
# API Response

```json
{
  ""name"": ""MarkMyWord"",
  ""version"": ""0.2.0"",
  ""enabled"": true
}
#!/bin/bash
echo ""Converting files...""
for file in *.md; do
    markmyword convert -i ""$file""
done

";

MarkdownConverter.ConvertToDocx(markdown, "highlighted.docx");


**Features:**
- Colors optimized for grey code block backgrounds
- Automatic spell/grammar check suppression (no red squiggles!)
- Trailing empty lines automatically removed
- Property names vs values distinguished in JSON

**Disable syntax highlighting:**
```csharp
var options = new ConversionOptions
{
    EnableSyntaxHighlighting = false
};

MarkdownConverter.ConvertToDocx(markdown, "plain-code.docx", options);

Custom syntax colors:

var options = new ConversionOptions
{
    Styles = new StyleConfiguration
    {
        SyntaxColorScheme = new SyntaxColorScheme
        {
            KeywordColor = "0000FF",     // Blue
            StringColor = "A31515",      // Red
            NumberColor = "098658",      // Green
            CommentColor = "6A9955",     // Green
            TypeColor = "4EC9B0",        // Cyan
            FunctionColor = "C4A000"     // Gold
        }
    }
};

Convert with custom code block styling

var options = new ConversionOptions
{
    Styles = new StyleConfiguration
    {
        CodeFontName = "Consolas",
        CodeFontSize = 9,
        CodeBackgroundColor = "F5F5F5"  // Light grey
    }
};

string code = @"
# Code Example

```json
{
  ""message"": ""Hello, World!""
}

";

MarkdownConverter.ConvertToDocx(code, "code.docx", options);


## Testing

The library includes comprehensive unit tests covering all supported markdown syntax:

```bash
dotnet test

Current test coverage (29 tests):

  • ✅ Basic paragraph conversion
  • ✅ Headings (levels 1-6)
  • ✅ Bold and italic text
  • ✅ Inline code
  • ✅ Code blocks with language labels
  • ✅ Hyperlinks
  • Lists (ordered, unordered, nested, mixed, with formatting)
  • Images (with fallback for missing images)
  • Tables (headers, multiple rows, shading, borders)

Specifications

MarkMyWord implements:

Contributing

Contributions are welcome! Areas for contribution:

  • Task lists and checkboxes
  • Footnotes and references
  • Definition lists
  • Extended markdown features
  • Performance optimizations
  • Additional tests

License

MIT License - See LICENSE file for details

Acknowledgments

Status

🚀 Beta - Core functionality and CLI are fully working with comprehensive CommonMark support.

Fully supported:

  • Headings, paragraphs, emphasis (bold/italic)
  • Code blocks (fenced and indented) with syntax highlighting (JSON, TypeSpec, Bash)
  • Inline code
  • Links and hyperlinks
  • Block quotes
  • Horizontal rules / thematic breaks
  • Lists (ordered, unordered, nested with proper numbering)
  • Images (local files and URLs with fallback support)
  • Tables (with headers, borders, and shading)
  • Command-line interface with full options
  • Spell/grammar check suppression for code

Coming soon: Task lists, footnotes, definition lists


Generated with ❤️ using Claude Code

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.9.0 0 4/9/2026
0.8.0 84 3/20/2026
0.8.0-preview3 81 3/18/2026
0.8.0-preview2 77 3/18/2026
0.8.0-preview 79 3/18/2026
0.7.0 94 3/14/2026
0.6.0 83 3/7/2026
0.5.0 117 1/24/2026
0.4.0 97 1/19/2026
0.3.0 102 1/15/2026
0.1.0 108 1/2/2026