markup conversion
markdown formatting
diff tools
text editing
strikeout text

Convert diff to markdown with strikeout?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Converting a unified diff into Markdown with strikethrough for removed lines and bold (or highlighted) text for added lines makes code changes readable in documents, pull request summaries, and changelogs. The approach is to parse the diff output, identify lines starting with - (removals) and + (additions), and wrap them in Markdown formatting. Strikethrough in Markdown uses ~~text~~ syntax. This can be done with a simple Python script, a shell pipeline, or JavaScript for web-based rendering.

Unified Diff Format

 
1--- a/config.py
2+++ b/config.py
3@@ -10,4 +10,4 @@
4 HOST = "localhost"
5-PORT = 8080
6+PORT = 9090
7 DEBUG = True
8-LOG_LEVEL = "INFO"
9+LOG_LEVEL = "DEBUG"

Lines starting with - were removed, lines starting with + were added, and lines with a space prefix are unchanged context. The @@ line shows the line number range.

Python Converter

python
1def diff_to_markdown(diff_text):
2    lines = diff_text.strip().split('\n')
3    md_lines = []
4
5    for line in lines:
6        if line.startswith('---') or line.startswith('+++'):
7            # File header
8            md_lines.append(f"**{line}**")
9        elif line.startswith('@@'):
10            md_lines.append(f"*{line}*")
11        elif line.startswith('-'):
12            # Removed line — strikethrough
13            content = line[1:].strip()
14            md_lines.append(f"~~{content}~~")
15        elif line.startswith('+'):
16            # Added line — bold
17            content = line[1:].strip()
18            md_lines.append(f"**{content}**")
19        else:
20            # Context line
21            md_lines.append(line.lstrip(' '))
22
23    return '\n\n'.join(md_lines)
24
25diff = """--- a/config.py
26+++ b/config.py
27@@ -10,4 +10,4 @@
28 HOST = "localhost"
29-PORT = 8080
30+PORT = 9090
31 DEBUG = True"""
32
33print(diff_to_markdown(diff))

Output:

markdown
1**--- a/config.py**
2
3**+++ b/config.py**
4
5*@@ -10,4 +10,4 @@*
6
7HOST = "localhost"
8
9~~PORT = 8080~~
10
11**PORT = 9090**
12
13DEBUG = True

Side-by-Side Format

python
1def diff_to_table(diff_text):
2    lines = diff_text.strip().split('\n')
3    rows = []
4    rows.append("| Removed | Added |")
5    rows.append("|---|---|")
6
7    removed = []
8    added = []
9
10    for line in lines:
11        if line.startswith('---') or line.startswith('+++') or line.startswith('@@'):
12            continue
13        elif line.startswith('-'):
14            removed.append(line[1:].strip())
15        elif line.startswith('+'):
16            added.append(line[1:].strip())
17        else:
18            # Flush paired changes
19            max_len = max(len(removed), len(added))
20            for i in range(max_len):
21                r = f"~~{removed[i]}~~" if i < len(removed) else ""
22                a = f"**{added[i]}**" if i < len(added) else ""
23                rows.append(f"| {r} | {a} |")
24            removed.clear()
25            added.clear()
26            rows.append(f"| {line.strip()} | {line.strip()} |")
27
28    # Flush remaining
29    max_len = max(len(removed), len(added), 0)
30    for i in range(max_len):
31        r = f"~~{removed[i]}~~" if i < len(removed) else ""
32        a = f"**{added[i]}**" if i < len(added) else ""
33        rows.append(f"| {r} | {a} |")
34
35    return '\n'.join(rows)
36
37print(diff_to_table(diff))

This produces a Markdown table with removed lines (strikethrough) on the left and added lines (bold) on the right, similar to a side-by-side diff viewer.

Shell One-Liner

bash
1# Convert git diff to markdown with strikethrough
2git diff HEAD~1 -- config.py | \
3  sed -e 's/^-\(.*\)/~~\1~~/' \
4      -e 's/^+\(.*\)/**\1**/' \
5      -e '/^@@/s/.*/*&*/' \
6      -e '/^---/s/.*/**&**/' \
7      -e '/^+++/s/.*/**&**/'

This uses sed to wrap removed lines in ~~ and added lines in **. It is a quick approach for simple diffs but does not handle edge cases like lines containing Markdown syntax.

JavaScript for Web Rendering

javascript
1function diffToMarkdown(diffText) {
2  return diffText
3    .split('\n')
4    .map(line => {
5      if (line.startsWith('---') || line.startsWith('+++')) {
6        return `**${line}**`;
7      }
8      if (line.startsWith('@@')) {
9        return `*${line}*`;
10      }
11      if (line.startsWith('-')) {
12        return `~~${line.slice(1)}~~`;
13      }
14      if (line.startsWith('+')) {
15        return `**${line.slice(1)}**`;
16      }
17      return line.slice(1); // Remove leading space from context
18    })
19    .join('\n\n');
20}

This JavaScript function is suitable for rendering diffs as Markdown in web applications, documentation generators, or GitHub Actions workflow summaries.

Using Colors Instead of Strikethrough

html
1<!-- For HTML output with colored backgrounds -->
2<style>
3  .diff-removed { background-color: #fdd; text-decoration: line-through; }
4  .diff-added { background-color: #dfd; font-weight: bold; }
5</style>
6
7<pre>
8<span class="diff-removed">PORT = 8080</span>
9<span class="diff-added">PORT = 9090</span>
10</pre>
python
1def diff_to_html(diff_text):
2    lines = diff_text.strip().split('\n')
3    html = ['<pre>']
4    for line in lines:
5        if line.startswith('-') and not line.startswith('---'):
6            html.append(f'<span class="diff-removed">{line}</span>')
7        elif line.startswith('+') and not line.startswith('+++'):
8            html.append(f'<span class="diff-added">{line}</span>')
9        else:
10            html.append(line)
11    html.append('</pre>')
12    return '\n'.join(html)

When Markdown strikethrough is not expressive enough, generate HTML with CSS classes for colored backgrounds. This works in tools that support HTML in Markdown (GitHub, Notion).

Common Pitfalls

  • Markdown inside diff lines: If a removed line contains ~~ or **, wrapping it in strikethrough Markdown creates broken formatting. Escape existing Markdown syntax before wrapping, or use code blocks instead.
  • Confusing file headers with content: Lines starting with --- and +++ are file headers, not content removals/additions. Always skip or handle these separately to avoid false strikethrough formatting.
  • Strikethrough not supported everywhere: ~~text~~ is a GitHub Flavored Markdown extension, not part of standard CommonMark. Verify that your rendering target supports strikethrough before using this approach.
  • Multiline changes spanning paragraphs: Markdown strikethrough does not work across paragraph boundaries (blank lines). Each line must be individually wrapped. Use <del> HTML tags if you need cross-paragraph strikethrough.
  • Binary diffs: Binary file diffs show "Binary files differ" without line-by-line content. The line-parsing approach does not work for binary diffs — check for this and skip or note it in the output.

Summary

  • Parse unified diff lines by prefix: - for removals, + for additions, space for context
  • Wrap removed lines in ~~text~~ for Markdown strikethrough
  • Wrap added lines in **text** for bold emphasis
  • Use a Markdown table for side-by-side comparison of changes
  • For richer formatting, generate HTML with <del> and <ins> tags or colored CSS classes
  • Escape existing Markdown syntax inside diff lines to prevent formatting conflicts

Course illustration
Course illustration

All Rights Reserved.