{
  "__type": "IngestedDoc",
  "__tag": 4010,
  "_content": {},
  "_ordered_sections": [],
  "item_file": null,
  "item_line": null,
  "item_type": null,
  "aliases": [],
  "example_section_data": {
    "__type": "Section",
    "__tag": 4015,
    "children": [],
    "title": [],
    "level": 0,
    "target": null
  },
  "see_also": [],
  "signature": null,
  "references": null,
  "qa": "injecting",
  "arbitrary": [
    {
      "__type": "Section",
      "__tag": 4015,
      "children": [
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "Some documentation is "
            },
            {
              "__type": "Emphasis",
              "__tag": 4047,
              "children": [
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": "built"
                }
              ]
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": ", not written: a CLI's option reference, a plugin or magic listing, a key-binding table.  Sphinx projects typically generate such pages with custom scripts before "
            },
            {
              "__type": "InlineCode",
              "__tag": 4051,
              "value": "sphinx-build"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " (IPython runs three "
            },
            {
              "__type": "InlineCode",
              "__tag": 4051,
              "value": "autogen_*.py"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " scripts from its "
            },
            {
              "__type": "InlineCode",
              "__tag": 4051,
              "value": "docs/Makefile"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": ")."
            }
          ]
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "Papyri's equivalent is a custom step "
            },
            {
              "__type": "Strong",
              "__tag": 4048,
              "children": [
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": "between"
                }
              ]
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " "
            },
            {
              "__type": "InlineCode",
              "__tag": 4051,
              "value": "gen"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " and "
            },
            {
              "__type": "InlineCode",
              "__tag": 4051,
              "value": "pack"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": ". The bundle directory "
            },
            {
              "__type": "InlineCode",
              "__tag": 4051,
              "value": "papyri gen"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " writes is deliberately lenient, human-readable JSON so that tools other than gen can operate on it; the "
            },
            {
              "__type": "CrossRef",
              "__tag": 4002,
              "value": "papyri.bundle_edit",
              "reference": {
                "__type": "RefInfo",
                "__tag": 4000,
                "module": "papyri",
                "version": "?",
                "kind": "module",
                "path": "papyri.bundle_edit"
              },
              "kind": "module"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " module is the supported way to do that from Python.  Content is built directly as IR nodes — no intermediate RST files, no re-parsing — and the whole flow is three CI lines     "
            }
          ]
        },
        {
          "__type": "Code",
          "__tag": 4050,
          "value": "papyri gen examples/IPython.toml\npython examples/ipython_inject.py ~/.papyri/data/IPython_<version>\npapyri pack ~/.papyri/data/IPython_<version>",
          "execution_status": null,
          "out": ""
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "InlineCode",
              "__tag": 4051,
              "value": "papyri pack"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " validates whatever the injector wrote exactly like gen-produced content: pages must decode as "
            },
            {
              "__type": "InlineCode",
              "__tag": 4051,
              "value": "GeneratedDoc"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": ", toc entries must point at existing docs, and (under "
            },
            {
              "__type": "InlineCode",
              "__tag": 4051,
              "value": "--strict"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": ") injected pages must be reachable from the toc."
            }
          ]
        }
      ],
      "title": [
        {
          "__type": "Text",
          "__tag": 4046,
          "value": "Injecting generated pages into a bundle"
        }
      ],
      "level": 0,
      "target": "injecting"
    },
    {
      "__type": "Section",
      "__tag": 4015,
      "children": [
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "The common case: a hand-written page should carry a generated block (IPython's "
            },
            {
              "__type": "InlineCode",
              "__tag": 4051,
              "value": "config/options/index.rst"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " introduces the options; the options themselves come from traitlets introspection).  Read the page, replace the block, write it back:"
            }
          ]
        },
        {
          "__type": "Code",
          "__tag": 4050,
          "value": "from papyri.bundle_edit import read_doc, replace_block, write_doc\nfrom papyri.nodes import Paragraph, Section, Text\n\ngenerated = Section(\n    (Paragraph((Text(\"… introspected content …\"),)),),\n    (Text(\"Options reference\"),),\n    level=2,\n)\n\ndoc = read_doc(bundle_dir, \"config:options:index\")\nreplace_block(doc, \"Options reference\", [generated])\nwrite_doc(bundle_dir, \"config:options:index\", doc)",
          "execution_status": null,
          "out": ""
        },
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "Narrative pages are a "
            },
            {
              "__type": "Emphasis",
              "__tag": 4047,
              "children": [
                {
                  "__type": "Text",
                  "__tag": 4046,
                  "value": "flat"
                }
              ]
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " sequence of "
            },
            {
              "__type": "InlineCode",
              "__tag": 4051,
              "value": "Section"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " nodes with heading depth in "
            },
            {
              "__type": "InlineCode",
              "__tag": 4051,
              "value": "Section.level"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " — sections do not nest.  "
            },
            {
              "__type": "InlineCode",
              "__tag": 4051,
              "value": "replace_block"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " treats \"the section titled X plus every following section of deeper level\" as one block and replaces it, or appends when no section matches. Because the injected block's leading title matches on the next run, injectors are idempotent: re-running updates content in place."
            }
          ]
        }
      ],
      "title": [
        {
          "__type": "Text",
          "__tag": 4046,
          "value": "Patching an existing page"
        }
      ],
      "level": 1,
      "target": null
    },
    {
      "__type": "Section",
      "__tag": 4015,
      "children": [
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "InlineCode",
              "__tag": 4051,
              "value": "narrative_doc"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " builds a page in the same shape gen produces; "
            },
            {
              "__type": "InlineCode",
              "__tag": 4051,
              "value": "add_toc_entry"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " wires it into "
            },
            {
              "__type": "InlineCode",
              "__tag": 4051,
              "value": "toc.json"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " so it is reachable (an unreferenced page is an orphan — a warning at pack time, an error under "
            },
            {
              "__type": "InlineCode",
              "__tag": 4051,
              "value": "pack --strict"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "):"
            }
          ]
        },
        {
          "__type": "Code",
          "__tag": 4050,
          "value": "from papyri.bundle_edit import add_toc_entry, narrative_doc, write_doc\n\nwrite_doc(bundle_dir, \"reference:options\", narrative_doc(sections))\nadd_toc_entry(bundle_dir, \"reference:options\", \"Options\", parent=\"index\")",
          "execution_status": null,
          "out": ""
        }
      ],
      "title": [
        {
          "__type": "Text",
          "__tag": 4046,
          "value": "Adding a new page"
        }
      ],
      "level": 1,
      "target": null
    },
    {
      "__type": "Section",
      "__tag": 4015,
      "children": [
        {
          "__type": "Paragraph",
          "__tag": 4045,
          "children": [
            {
              "__type": "InlineCode",
              "__tag": 4051,
              "value": "examples/ipython_inject.py"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": " ports IPython's three doc-generation scripts to this model: traitlets config options become titled admonitions, magics a definition list, and the prompt_toolkit key bindings a table — all produced by importing IPython and introspecting at inject time, in the same environment that ran "
            },
            {
              "__type": "InlineCode",
              "__tag": 4051,
              "value": "papyri gen"
            },
            {
              "__type": "Text",
              "__tag": 4046,
              "value": "."
            }
          ]
        }
      ],
      "title": [
        {
          "__type": "Text",
          "__tag": 4046,
          "value": "A complete injector"
        }
      ],
      "level": 1,
      "target": null
    }
  ],
  "local_refs": []
}