code: def gen_tutorials(repo_dir: str) -> None:
      """Generate HTML tutorials for botorch Docusaurus site from Jupyter notebooks.
  
      Also create ipynb and py versions of tutorial in Docusaurus site for
      download.
      """
      with open(
          os.path.join(repo_dir, "website", "tutorials.json"), "r"
      ) as infile:
          tutorial_config = json.load(infile)
  
      # create output directories if necessary
      html_out_dir = os.path.join(repo_dir, "website", "_tutorials")
      files_out_dir = os.path.join(
          repo_dir, "website", "static", "files"
      )
      for d in (html_out_dir, files_out_dir):
          if not os.path.exists(d):
              os.makedirs(d)
  
      tutorial_ids = {
          x["id"] for v in tutorial_config.values() for x in v
      }
  
      for tid in tutorial_ids:
          print(f"Generating {tid} tutorial")
  
          # convert notebook to HTML
          ipynb_in_path = os.path.join(
              repo_dir, "tutorials", f"{tid}.ipynb"
          )
          with open(ipynb_in_path, "r") as infile:
              nb_str = infile.read()
              nb = nbformat.reads(nb_str, nbformat.NO_CONVERT)
  
          # displayname is absent from notebook metadata
          nb["metadata"]["kernelspec"]["display_name"] = "python3"
  
          exporter = HTMLExporter(template_name="classic")
          html, meta = exporter.from_notebook_node(nb)
  
          # pull out html div for notebook
          soup = BeautifulSoup(html, "html.parser")
          nb_meat = soup.find("div", {"id": "notebook-container"})
          del nb_meat.attrs["id"]
          nb_meat.attrs["class"] = ["notebook"]
          html_out = JS_SCRIPTS + str(nb_meat)
  
          # generate html file
          html_out_path = os.path.join(
              html_out_dir,
              f"{tid}.html",
          )
          with open(html_out_path, "w") as html_outfile:
              html_outfile.write(html_out)
  
          # generate JS file
          script = TEMPLATE.format(tid)
          js_out_path = os.path.join(
              repo_dir, "website", "pages", "tutorials", f"{tid}.js"
          )
          with open(js_out_path, "w") as js_outfile:
              js_outfile.write(script)
  
          # output tutorial in both ipynb & py form
          ipynb_out_path = os.path.join(files_out_dir, f"{tid}.ipynb")
          with open(ipynb_out_path, "w") as ipynb_outfile:
              ipynb_outfile.write(nb_str)
          exporter = PythonExporter()
          script, meta = exporter.from_notebook_node(nb)
          # make sure to use python3 shebang
          script = script.replace(
              "#!/usr/bin/env python", "#!/usr/bin/env python3"
          )
          py_out_path = os.path.join(
              repo_dir, "website", "static", "files", f"{tid}.py"
          )
          with open(py_out_path, "w") as py_outfile:
              py_outfile.write(script)
  
file_path: botorch/scripts/parse_tutorials.py
imports: from __future__ import annotations
  import argparse
  import json
  import os
  import nbformat
  from bs4 import BeautifulSoup
  from nbconvert import HTMLExporter, PythonExporter
label_desc: Use image node_id 2 for calling a global function with example usage: gen_tutorials(repo_dir) without return types