Project 1: Markdown Compiler
Due: Wednesday, October 7 at 11:59pm · Worth: 20 points (+1 extra credit; maximum 21/20)
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 readings on Python and strings.
Start
Open the markdown-compiler starter repository, select Use this template, and create a repository named markdown-compiler under your account. Clone your copy and do all of your work inside it.
Open a terminal in the repository root, the folder containing pyproject.toml. From that folder, set up its Python environment. Then install the project and its style checker:
$ python -m pip install -e .
$ python -m pip install -r requirements.txtThe starter’s requirements.txt contains flake8; if an earlier copy has an empty file, add that line before running its install command. The first command creates the markdown-compiler command. The -e makes the installation use your source files as you edit them.
Learning Objectives
Build the Compiler
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. Fix the code in markdown_compiler/ using these three local checks:
The command-line checks also require the --add_css flag in markdown_compiler/__main__.py; a FIXME comment marks where to add it.
From the repository root, run the doctests and style checker:
$ python -m doctest -v markdown_compiler/util/line_functions.py
$ python -m doctest -v markdown_compiler/__init__.py
$ python -m flake8 --isolated markdown_compiler --ignore=E501A successful verbose doctest run ends with Test passed.; flake8 prints nothing when there are no style errors. Fix the failures and rerun the commands. Keep the starter’s function names, parameters, and doctests. Match its expected output, including spaces and tags, even where it differs from other Markdown tools. For example, the starter uses <ins> for ~~text~~; preserve that convention for this assignment. Style fixes include replacing the starter’s import * statements with imports of the names you actually use. Once two delimiter transformations work, consider a helper that takes the delimiter and HTML tag as parameters. The named starter functions can call that helper, keeping their interfaces while avoiding copies of the same search loop.
The minify function practices collapsing whitespace with string operations. Keep its doctests, but do not run that simple transformation on a complete HTML page: spaces and newlines inside <pre> are part of the displayed code. The starter’s convert_file saves the compiled HTML directly, preserving the code-block layout as the poem exporter did in the strings reading. If you created your repository before this repair, remove html = minify(html) from convert_file, and specify encoding='utf-8' in both its text-file open calls.
Step 2: generate and inspect a page. Once the tests pass, use the command installed earlier to compile 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. The editable installation continues to use your saved source changes; rerun the command after each repair. Check a fenced code block in the output: its newlines and indentation should survive into the saved HTML. 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.
You can also inspect the page while implementing the functions; some formatting will remain incomplete until their tests pass.
Grading Rubric
This project is worth 20 points. The local checks help you debug; instructor-owned pytest tests inside Gradescope determine the score:
The authoritative tests belong to the instructor, so changing a starter doctest cannot change the grading requirements. Gradescope shows which behavior failed and you can fix, push, and resubmit. Its cases follow the starter’s doctests, including unchanged text with unmatched delimiters and preserved indentation inside fenced code blocks. The command-line check installs your submitted package and runs its markdown-compiler command without downloading dependencies. The style check runs flake8 --isolated markdown_compiler --ignore=E501. It ignores submitted flake8 configuration so every submission receives the same style checks.
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 ordered (numbered) list support:
- Add 3 doctests to
compile_linesthat cover a one-item list, a multi-item list, and a list next to an ordinary paragraph. Show the expected HTML, including item order and list boundaries. - Modify your code so that these doctests pass.
Submit
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. It checks the generated list items and runs the three list doctests you added to compile_lines.
Commit and sync your updated markdown_compiler/ files, keep the starter’s pyproject.toml and requirements.txt, and include submission.toml if claiming extra credit. On Gradescope, choose GitHub and submit your markdown-compiler repository and the branch containing your commit.