PartSolPartSolΒΆ
A solution appears after each individual part.
Minimal ExampleΒΆ
A PDF which this filter parses correctly is shown below:
π LaTeX Code
\documentclass[12pt]{article}
\usepackage{comment}
% This is a common method for including/excluding solutions from the PDF.
\includecomment{solution}
%\excludecomment{solution}
\begin{document}
\section*{Minimal Example}
\begin{enumerate}
\item Here is some interesting information. Calculate the following:
\begin{enumerate}
\item $1+1$
\begin{solution}
$1+1 = 2$
\end{solution}
\item $2+2$
\begin{solution}
$2+2=4$
\end{solution}
\end{enumerate}
\item This questions has no parts. What is the solution?
\begin{solution}
This is the solution.
\end{solution}
\end{enumerate}
\end{document}
π Python Filter
#!/usr/bin/env python3
"""A solution appears after each individual part."""
from collections import deque
from typing import Optional
import panflute as pf
from in2lambda.api.module import Module
from in2lambda.filters.markdown import filter
@filter
def pandoc_filter(
elem: pf.Element,
doc: pf.elements.Doc,
module: Module,
parsing_answers: bool,
) -> Optional[pf.Str]:
"""A Pandoc filter that parses and translates various TeX elements.
Args:
elem: The current TeX element being processed. This could be a paragraph,
ordered list, etc.
doc: A Pandoc document container - essentially the Pandoc AST.
module: The Python API that is used to store the result after processing
the TeX file.
parsing_answers: Whether an answers-only document is currently being parsed.
Returns:
Converted TeX elements for the AST where required
e.g. replaces math equations so that they are surrounded by $.
"""
# Question text (ListItem -> List -> Doc)
if isinstance(elem.ancestor(3), pf.Doc):
match type(elem):
case pf.Para:
pandoc_filter.solutions = deque()
if hasattr(pandoc_filter, "question"):
pandoc_filter.question.append(pf.stringify(elem))
else:
pandoc_filter.question = [pf.stringify(elem)]
case pf.OrderedList:
for listItem in elem.content:
part = [
pf.stringify(item)
for item in listItem.content
if not isinstance(item, pf.Div)
]
module.current_question.add_part_text("\n".join(part))
module.current_question.add_solution(
pandoc_filter.solutions.popleft()
)
if isinstance(elem, pf.Div):
pandoc_filter.solutions.append(pf.stringify(elem))
if pandoc_filter.question:
module.add_question(main_text="\n".join(pandoc_filter.question))
module.current_question.add_solution(pf.stringify(elem))
module.current_question._last_part["solution"] -= 1
pandoc_filter.question = []
return None