diff --git a/sphinx_better_subsection.py b/sphinx_better_subsection.py index fb95267..f95d06f 100644 --- a/sphinx_better_subsection.py +++ b/sphinx_better_subsection.py @@ -34,10 +34,10 @@ class PreferSectionTarget(Transform): .. code-block:: xml ... - - - -
+ + + +
... Transforming it gives: @@ -45,19 +45,19 @@ class PreferSectionTarget(Transform): .. code-block:: xml ... - - + + -
+
... Note that the other IDs are all preserved; only the order is modified. Nested subsections are also checked. """ - # Post processing priority from - # https://www.sphinx-doc.org/en/master/extdev/appapi.html?highlight=transform#sphinx.application.Sphinx.add_transform - default_priority = 700 + # Run before `docutils.transforms.references.PropagateTransform` which has + # priority 260. + default_priority = 255 def apply(self): """Docutils transform entry point""" @@ -79,14 +79,55 @@ def apply(self): # Filter away nodes that aren't targets if not isinstance(last, nodes.target): continue - # Internal hyperlink targets have refid (external ones have refuri) - if "refid" not in last: + # Filter away targets with content + if ( + isinstance(last.parent, nodes.TextElement) + or last.hasattr("refid") + or last.hasattr("refuri") + or last.hasattr("refname") + ): continue - refid = last["refid"] - assert refid in node["ids"] + + # Store ID and name + print(last.parent, node) + refname = last["names"][0] + refid = last["ids"][0] + + # Propagate the previous target + # Source from `PropagateTargets.apply` + node["ids"].extend(last["ids"]) + node["names"].extend(last["names"]) + # Set defaults for node.expect_referenced_by_name/id. + if not hasattr(node, "expect_referenced_by_name"): + node.expect_referenced_by_name = {} + if not hasattr(node, "expect_referenced_by_id"): + node.expect_referenced_by_id = {} + for id_ in last["ids"]: + node.expect_referenced_by_id[id_] = last + # Update IDs to node mapping. + self.document.ids[id_] = node + last["ids"] = [] + for name in last["names"]: + node.expect_referenced_by_name[name] = last + last["names"] = [] + # If there are any expect_referenced_by_name/id attributes in + # target set, copy them to node. + node.expect_referenced_by_name.update( + getattr(last, "expect_referenced_by_name", {})) + node.expect_referenced_by_id.update( + getattr(last, "expect_referenced_by_id", {})) + # Set refid to point to the first former ID of target which is now + # an ID of next_node. + last["refid"] = refid + self.document.note_refid(last) + # End source + # Prefer the target's ID node["ids"].remove(refid) node["ids"].insert(0, refid) + # Also prefer the target's name + node["names"].remove(refname) + node["names"].insert(0, refname) def setup(app): """Sphinx extension entry point"""