summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYuriy Andamasov <yuriy@vyos.io>2026-05-12 15:34:04 +0300
committerMergify <37929162+mergify[bot]@users.noreply.github.com>2026-05-12 13:40:46 +0000
commitbd89afa9eb35e69dcd65a6fda768e462d03d9c6d (patch)
treecd4708a6ca1e20c4374434f408cfa1a0c4a9cb3d
parent16543fc5808bd76c5737ce8a983a75ab72806ad6 (diff)
downloadvyos-documentation-bd89afa9eb35e69dcd65a6fda768e462d03d9c6d.tar.gz
vyos-documentation-bd89afa9eb35e69dcd65a6fda768e462d03d9c6d.zip
fix(ext): parse cmdincludemd content as RST so legacy `_include/*.txt` directives render
The `_include/*.txt` library is written in reStructuredText (`.. cfgcmd::`, `.. code-block::`, `.. note::`, `.. cmdinclude::`). After the RST→MyST migration, the `{cmdincludemd}` fence on .md pages routed include content through `MockState.nested_parse`, which in MyST 2.0 simply replays the content through the MyST renderer (see myst_parser/mocking.py:153). RST directives in the .txt file then rendered as literal paragraph text: <p>.. cmdinclude:: /_include/interface-description.txt</p> <p>.. cfgcmd:: set interfaces ethernet ...</p> <p>.. code-block:: none</p> User-visible symptom (reported on rolling docs): the Ethernet, dummy, tunnel, bonding, bridge, macsec, vxlan, l2tpv3, pseudo-ethernet, virtual-ethernet, and wireless pages all showed unprocessed `.. cfgcmd::` and `.. cmdinclude::` directives instead of styled command boxes. Fix: mirror MyST's own `{eval-rst}` plumbing (`MockRSTParser().parse(text, doc)` per `mdit_to_docutils/base.py:1655`). Build a fresh document that inherits the outer document's settings + reporter, run `MockRSTParser` over the substituted include content, and graft the resulting children back into the calling document with explicit-target registration. Keeps the Sphinx env available to `cfgcmd`/`opcmd`/`cmdinclude` directives. Verified locally on rolling (Sphinx 7.x, myst-parser 2.0): zero literal `cfgcmd::` / `cmdinclude::` / `code-block::` / `opcmd::` / `note::` / `include::` strings remain in any built HTML page under `configuration/`, `automation/`, `installation/`, `operation/`, `vpp/`; all 11 affected interface pages now render proper `cfgcmd-heading` / `cfgcmd-body` blocks (e.g. ethernet.html: 160, wireless.html: 172, dummy.html: 4). 🤖 Generated by [robots](https://vyos.io) (cherry picked from commit 9c815d689a2a4a5d433ba15154cb606bd986fc8d)
-rw-r--r--docs/_ext/vyos.py33
1 files changed, 22 insertions, 11 deletions
diff --git a/docs/_ext/vyos.py b/docs/_ext/vyos.py
index 527178d1..0c90f4bd 100644
--- a/docs/_ext/vyos.py
+++ b/docs/_ext/vyos.py
@@ -364,18 +364,29 @@ class CmdInclude(SphinxDirective):
line = re.sub('{{\s?var' + str(i) + '\s?}}',value,line)
new_include_lines.append(line)
- if hasattr(self.state, '_renderer'):
- self.state._renderer.nested_render_text(''.join(new_include_lines), self.lineno)
- return []
- from docutils.statemachine import ViewList
- from docutils import nodes
+ # The _include/*.txt library is written in reStructuredText
+ # (`.. cfgcmd::`, `.. code-block::`, `.. note::`, `.. cmdinclude::`).
+ # When called from a MyST `.md` page, `self.state` is MyST's
+ # MockState whose `nested_parse` just routes back through MyST —
+ # so the RST directives render as literal paragraph text.
+ #
+ # Parse the file as RST directly, mirroring what MyST itself does
+ # for `{eval-rst}` blocks (myst_parser.mocking.MockRSTParser via
+ # render_restructuredtext): build a fresh document that inherits
+ # the parent's settings (so Sphinx env / reporter survive) and
+ # graft its children back into the calling document.
+ from docutils.utils import new_document
+ from myst_parser.mocking import MockRSTParser
+
content = ''.join(new_include_lines)
- vl = ViewList()
- for i, line in enumerate(content.splitlines(keepends=False)):
- vl.append(line, include_file[1], i)
- node = nodes.Element()
- self.state.nested_parse(vl, self.content_offset, node, match_titles=True)
- return node.children
+ outer_doc = self.state.document
+ newdoc = new_document(include_file[1], outer_doc.settings)
+ newdoc.reporter = outer_doc.reporter
+ MockRSTParser().parse(content, newdoc)
+ for node in newdoc.children:
+ if getattr(node, 'attributes', None) and node.get('names'):
+ outer_doc.note_explicit_target(node, node)
+ return list(newdoc.children)
class CfgcmdlistDirective(Directive):