diff --git a/doc/_extensions/zephyr/domain/__init__.py b/doc/_extensions/zephyr/domain/__init__.py index 3081460254a2..38cacd20d119 100644 --- a/doc/_extensions/zephyr/domain/__init__.py +++ b/doc/_extensions/zephyr/domain/__init__.py @@ -36,7 +36,7 @@ from anytree import ChildResolverError, Node, PreOrderIter, Resolver, search from docutils import nodes -from docutils.parsers.rst import directives +from docutils.parsers.rst import directives, roles from docutils.statemachine import StringList from sphinx import addnodes from sphinx.application import Sphinx @@ -797,55 +797,33 @@ def run(self): result_nodes.append(note) return result_nodes - # Add the note before any tables - note = nodes.admonition(classes=["legend"]) - note += nodes.title(text="Table Legend", classes=["note"]) - - legend = nodes.definition_list(classes=["supported-hardware field-list"]) - - def add_legend_item(legend_list, term_text, term_classes, definition_text): - dl_item = nodes.definition_list_item() - dt = nodes.term() - dt += nodes.inline("", term_text, classes=term_classes) - dd = nodes.definition() - dd += nodes.Text(definition_text) - dl_item += dt - dl_item += dd - legend_list += dl_item - - add_legend_item( - legend, "on-chip", ["location-chip", "onchip"], "Feature integrated in the SoC." - ) - add_legend_item( - legend, "on-board", ["location-chip", "onboard"], "Feature present on the board." - ) - add_legend_item( - legend, - "2", - ["count", "okay-count"], - "Number of instances of the feature that are present and enabled.", - ) - add_legend_item( - legend, - "2", - ["count", "disabled-count"], - "Number of instances of the feature that are present but initially disabled.", - ) - - dl_item = nodes.definition_list_item() - dt = nodes.term() - dt += nodes.literal(text="vnd,foo") - dd = nodes.definition() - dd += nodes.Text( - "Compatible string for the Devicetree binding matching the feature. " - "Click on the link to checkout the binding documentation." - ) - dl_item += dt - dl_item += dd - legend += dl_item - - note += legend - result_nodes.append(note) + html_contents = """
+
+
+ on-chip / + on-board +
+
+ Feature integrated in the SoC / present on the board. +
+
+ 2 / + 2 +
+
+ Number of instances that are enabled / disabled.
+ Click on the label to see the first instance of this feature in DTS source files. +
+
+ vnd,foo +
+
+ Compatible string for the Devicetree binding matching the feature.
+ Click on the link to view the binding documentation. +
+
+
""" + result_nodes.append(nodes.raw("", html_contents, format="html")) for target, features in sorted(supported_features.items()): if not features: @@ -893,7 +871,7 @@ def feature_sort_key(feature): for i, (key, value) in enumerate(items): row = nodes.row() - if value.get("disabled_count", 0) > 0 and value.get("okay_count", 0) == 0: + if value.get("disabled_nodes", []) and not value.get("okay_nodes", []): row["classes"].append("disabled") # TYPE column @@ -934,22 +912,39 @@ def feature_sort_key(feature): desc_para += nodes.Text(value["description"]) # Add count indicators for okay and not-okay instances - okay_count = value.get("okay_count", 0) - disabled_count = value.get("disabled_count", 0) + okay_nodes = value.get("okay_nodes", []) + disabled_nodes = value.get("disabled_nodes", []) - if okay_count > 0: - okay_count_indicator = nodes.inline( - classes=["count", "okay-count"], - text=str(okay_count), - ) - desc_para += okay_count_indicator + role_fn, _ = roles.role( + "zephyr_file", self.state_machine.language, self.lineno, self.state.reporter + ) + + def create_count_indicator(nodes_list, class_type, role_function=role_fn): + if not nodes_list: + return None + + count = len(nodes_list) + + if role_function is None: + return nodes.inline( + classes=["count", f"{class_type}-count"], text=str(count) + ) - if disabled_count > 0: - disabled_count_indicator = nodes.inline( - classes=["count", "disabled-count"], - text=str(disabled_count), + # Create a reference to the first node in the list + first_node = nodes_list[0] + file_ref = f"{count} <{first_node['filename']}#L{first_node['lineno']}>" + + role_nodes, _ = role_function( + "zephyr_file", file_ref, file_ref, self.lineno, self.state.inliner ) - desc_para += disabled_count_indicator + + count_node = role_nodes[0] + count_node["classes"] = ["count", f"{class_type}-count"] + + return count_node + + desc_para += create_count_indicator(okay_nodes, "okay") + desc_para += create_count_indicator(disabled_nodes, "disabled") desc_entry += desc_para row += desc_entry diff --git a/doc/_extensions/zephyr/domain/static/css/board.css b/doc/_extensions/zephyr/domain/static/css/board.css index 1224067bfff2..5a50c419fb03 100644 --- a/doc/_extensions/zephyr/domain/static/css/board.css +++ b/doc/_extensions/zephyr/domain/static/css/board.css @@ -83,7 +83,6 @@ .legend { font-size: 0.9em; - max-width: 600px; border-radius: 6px; margin: auto; @@ -179,6 +178,7 @@ font-size: 0.7em; font-weight: 600; margin-left: 4px; + padding-right: 6px !important; &::before { content: "×"; diff --git a/doc/_scripts/gen_boards_catalog.py b/doc/_scripts/gen_boards_catalog.py index 681b7a735b6c..482fbf208f57 100755 --- a/doc/_scripts/gen_boards_catalog.py +++ b/doc/_scripts/gen_boards_catalog.py @@ -254,7 +254,7 @@ def get_catalog(generate_hw_features=False): # Use pre-gathered build info and DTS files if board.name in board_devicetrees: for board_target, edt in board_devicetrees[board.name].items(): - target_features = {} + features = {} for node in edt.nodes: if node.binding_path is None: continue @@ -271,6 +271,7 @@ def get_catalog(generate_hw_features=False): description = DeviceTreeUtils.get_cached_description(node) filename = node.filename + lineno = node.lineno locations = set() if Path(filename).is_relative_to(ZEPHYR_BASE): filename = Path(filename).relative_to(ZEPHYR_BASE) @@ -279,23 +280,30 @@ def get_catalog(generate_hw_features=False): else: locations.add("soc") - existing_feature = target_features.get(binding_type, {}).get( + existing_feature = features.get(binding_type, {}).get( node.matching_compat ) + + node_info = {"filename": str(filename), "lineno": lineno} + node_list_key = "okay_nodes" if node.status == "okay" else "disabled_nodes" + if existing_feature: locations.update(existing_feature["locations"]) - key = "okay_count" if node.status == "okay" else "disabled_count" - existing_feature[key] = existing_feature.get(key, 0) + 1 - else: - key = "okay_count" if node.status == "okay" else "disabled_count" - target_features.setdefault(binding_type, {})[node.matching_compat] = { - "description": description, - "locations": locations, - key: 1 - } + existing_feature.setdefault(node_list_key, []).append(node_info) + continue + + feature_data = { + "description": description, + "locations": locations, + "okay_nodes": [], + "disabled_nodes": [], + } + feature_data[node_list_key].append(node_info) + + features.setdefault(binding_type, {})[node.matching_compat] = feature_data # Store features for this specific target - supported_features[board_target] = target_features + supported_features[board_target] = features # Grab all the twister files for this board and use them to figure out all the archs it # supports.