Project 1: Markdown Compiler
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
- understand the Markdown language
- understand string manipulation in Python
- 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:
doctestsruns every function’s doctests withpython -m doctest. Most implementation work is inmarkdown_compiler/util/line_functions.pyandmarkdown_compiler/__init__.py, where each function has doctests that show exactly what it should return for a given input.flake8checks that your code is clean and free of style errors (unused variables, inconsistent indentation, and the like).command_lineinstalls your package and runs themarkdown-compilercommand 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_cssEach 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_cssflag 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. listcurrently compiles to
1. this 2. is 3. a 4. listinstead 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:
- Add 3 doctests to the
compile_linesfunction 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. - 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 = trueThe extra-credit test runs only when that feature is claimed.