-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256 NEFARIOUSPLAN-CANONICAL-V1 {"body_md":"## The pipeline is markdown, then bleach, then Jinja2\n\n`cookbook/helper/template_helper.py`, at version 1.5.23, defines `render_instructions(step)`. It is called from `StepSerializer.get_instructions_markdown`, which the recipe API invokes every time a recipe step is fetched. The function mutates a single `instructions` variable through three stages:\n\n```python\ndef render_instructions(step): # TODO deduplicate markdown cleanup code\n instructions = step.instruction\n\n tags = {\n \"h1\", \"h2\", \"h3\", \"h4\", \"h5\", \"h6\",\n \"b\", \"i\", \"strong\", \"em\", \"tt\",\n \"p\", \"br\",\n \"span\", \"div\", \"blockquote\", \"code\", \"pre\", \"hr\",\n \"ul\", \"ol\", \"li\", \"dd\", \"dt\",\n \"img\",\n \"a\",\n \"sub\", \"sup\",\n 'pre', 'table', 'td', 'tr', 'th', 'tbody', 'style', 'thead'\n }\n parsed_md = md.markdown(\n instructions,\n extensions=[\n 'markdown.extensions.fenced_code', TableExtension(),\n UrlizeExtension(), MarkdownFormatExtension()\n ]\n )\n markdown_attrs = {\n \"*\": [\"id\", \"class\", 'width', 'height'],\n \"img\": [\"src\", \"alt\", \"title\"],\n \"a\": [\"href\", \"alt\", \"title\"],\n }\n\n instructions = bleach.clean(parsed_md, tags, markdown_attrs)\n\n ingredients = []\n for i in step.ingredients.all():\n ingredients.append(IngredientObject(i))\n\n def scale(number):\n return f\"\"\n\n try:\n template = Template(instructions)\n instructions = template.render(ingredients=ingredients, scale=scale)\n except TemplateSyntaxError:\n return _('Could not parse template code.') + ' Error: Template Syntax broken'\n except UndefinedError:\n return _('Could not parse template code.') + ' Error: Undefined Error'\n\n return instructions\n```\n\nThe three stages, in order:\n\n1. `md.markdown()` converts `step.instruction` from markdown source to HTML.\n2. `bleach.clean()` strips HTML tags and attributes not in the allowlist.\n3. `jinja2.Template(instructions).render()` compiles the bleached HTML as a Jinja2 template and executes it. The render context supplies `ingredients` and `scale`.\n\nbleach's job is to ensure HTML that reaches the browser is free of `