Fall 2026
  • Discord
  • Gradescope
  • Syllabus

On this page

  • A financial aside
  • Learning objectives
  • Instructions
  • Grading rubric
  • Extra credit
  • Submission

Project 1: Markdown Compiler

Comic titled 'The only valid measurement of code quality: WTFs/minute.' Two doors: one labeled 'good code' with a couple of 'WTF' notes, the other labeled 'bad code' covered in 'WTF' notes.

In this project you’ll write a Python program that reads a Markdown file and compiles it into HTML.

Markdown is a much smaller language than HTML. You have already used GitHub-flavored Markdown in every README.md and GitHub issue, including the ones for your labs. Reddit comments and R Markdown reports use it too. Your program will do the same job on a smaller scale: read Markdown like # Header and **bold** and write out the matching <h1> and <b> tags. The compiler uses string slicing, the find method, and loops over characters from the Python readings.

A financial aside

Suppose an entry-level engineer takes a week to build GitHub’s Markdown compiler. Entry-level engineers at GitHub make around $148k a year, so the feature costs about $3000 in salary. GitHub has well over 100 million users, which puts the one-time development cost at a small fraction of a cent per user. After that week of development, the compiler can handle each new page automatically.

Fork and clone the starter repository: github.com/rtealwitter/markdown-compiler. All of your work happens inside your fork of this repo.

Due: Wednesday, October 7 at 11:59pm, see the schedule.

Learning objectives

  1. understand the Markdown language
  2. understand string manipulation in Python
  3. understand how compilers translate from one programming language into another

Instructions

The starter code splits the compiler into small functions with doctests, just like a lab. Solve it the way you solve a lab: make the doctests pass one function at a time instead of trying to write the whole compiler at once.

Step 1: make the tests pass. Your repository ships with three GitHub Actions, and right now they all fail. Fix the code in markdown_compiler/ until each one passes:

  • doctests runs every function’s doctests with python -m doctest. Most implementation work is in markdown_compiler/util/line_functions.py and markdown_compiler/__init__.py, where each function has doctests that show exactly what it should return for a given input.
  • flake8 checks that your code is clean and free of style errors (unused variables, inconsistent indentation, and the like).
  • command_line installs your package and runs the markdown-compiler command from end to end.

You do not need to edit the Actions themselves; they show exactly how your code is tested. The command_line test also requires the --add_css flag in markdown_compiler/__main__.py; a FIXME comment marks where to add it.

Step 2: generate and inspect a page. Once the tests pass, run your compiler on the example document, both without and with CSS:

$ markdown-compiler --input_file=example/README.md
$ markdown-compiler --input_file=example/README.md --add_css

Each command writes an HTML file next to the input, at example/README.html. The second command overwrites the first, so open the file in your browser after each run and inspect it. You do not submit screenshots: Gradescope runs the command on a new Markdown fixture and checks the generated HTML directly.

The --add_css flag adds two stylesheets to the generated page, so the same Markdown can produce pages with different designs.

Run these commands as you complete each function. A broken function is easier to spot in a half-rendered page than in a wall of doctest failures.

Grading rubric

This project is worth 20 points. GitHub Actions provide quick public feedback while you work, but the score comes from instructor-owned pytest tests inside Gradescope:

The authoritative tests belong to the instructor, so changing a doctest or GitHub workflow cannot change your grade. Gradescope shows which behavior failed and you can fix, push, and resubmit.

Extra credit

The compiler does not support Markdown lists. For example, the Markdown

1. this
2. is
3. a
4. list

currently compiles to

1. this 2. is 3. a 4. list

instead of

<ol><li>this</li><li>is</li><li>a</li><li>list</li></ol>

For 1 point of extra credit, so the maximum score is 21/20, add list support:

  1. Add 3 doctests to the compile_lines function that contain Markdown lists. These should be good doctests that reasonably test that the list functionality works; come talk to us if you’d like feedback on whether yours are good ones.
  2. Modify your code so that these doctests pass.

Submission

Push your work to GitHub, then submit your repository and branch to the Project 1 programming assignment on Gradescope. Gradescope grades the exact commit you select.

If you completed the list extra credit, add this file at the repository root:

# submission.toml
[features]
ordered_lists = true

The extra-credit test runs only when that feature is claimed.