From 11fea40a40de77a7068ab1172587af3c4b66c9fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Cab=C3=A9?= Date: Thu, 15 May 2025 17:51:39 +0200 Subject: [PATCH] doc: boards: catalog: add shields to board catalog MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Populate board catalog with shields as well and have them show up in the boards/index page. Signed-off-by: Benjamin Cabé --- boards/index.rst | 39 ++++++---------- boards/shields/index.rst | 8 ++++ doc/_extensions/zephyr/domain/__init__.py | 2 + .../domain/static/css/board-catalog.css | 46 +++++++++++++++++++ .../zephyr/domain/static/js/board-catalog.js | 24 +++++----- .../domain/templates/board-catalog.html | 14 ++++-- .../zephyr/domain/templates/shield-card.html | 25 ++++++++++ doc/_scripts/gen_boards_catalog.py | 19 ++++++++ doc/hardware/porting/shields.rst | 2 + 9 files changed, 140 insertions(+), 39 deletions(-) create mode 100644 boards/shields/index.rst create mode 100644 doc/_extensions/zephyr/domain/templates/shield-card.html diff --git a/boards/index.rst b/boards/index.rst index 9b83276abbf..3cc92770cfe 100644 --- a/boards/index.rst +++ b/boards/index.rst @@ -3,26 +3,28 @@ Supported Boards and Shields ############################ +This page lists all the boards and shields that are currently supported in Zephyr. + If you are looking to add Zephyr support for a new board, please start with the -:ref:`board_porting_guide`. +:ref:`board_porting_guide`. When adding support documentation for a board, remember to use the +template available under :zephyr_file:`doc/templates/board.tmpl`. -When adding support documentation for a board, remember to use the template -available under :zephyr_file:`doc/templates/board.tmpl`. - -Shields are hardware add-ons that can be stacked on top of a board to add extra -functionality. They are listed separately from boards, towards :ref:`the end of -this page `. +Shields are hardware add-ons that can be stacked on top of a board to add extra functionality. +Refer to the :ref:`shield_porting_guide` for more information on how to port a shield. .. admonition:: Search Tips :class: dropdown - * Use the form below to filter the list of supported boards. If a field is left empty, it will - not be used in the filtering process. + * Use the form below to filter the list of supported boards and shields. If a field is left + empty, it will not be used in the filtering process. - * A board must meet **all** criteria selected across different fields. For example, if you select - both a vendor and an architecture, only boards that match both will be displayed. Within a - single field, selecting multiple options (such as two architectures) will show boards matching - **either** option. + * Filtering by name and vendor is available for both boards and shields. The rest of the fields + apply only to boards. + + * A board/shield must meet **all** criteria selected across different fields. For example, if you + select both a vendor and an architecture, only boards that match both will be displayed. Within + a single field, selecting multiple options (such as two architectures) will show boards + matching **either** option. * The list of supported hardware features for each board is automatically generated using information from the Devicetree. It may not be reflecting the full list of supported features @@ -40,14 +42,3 @@ this page `. */index .. zephyr:board-catalog:: - -.. _boards-shields: - -Shields -####### - -.. toctree:: - :maxdepth: 1 - :glob: - - shields/**/* diff --git a/boards/shields/index.rst b/boards/shields/index.rst new file mode 100644 index 00000000000..a2bfea271ce --- /dev/null +++ b/boards/shields/index.rst @@ -0,0 +1,8 @@ +Shields +####### + +.. toctree:: + :maxdepth: 1 + :glob: + + **/* diff --git a/doc/_extensions/zephyr/domain/__init__.py b/doc/_extensions/zephyr/domain/__init__.py index 3df05b29573..044ceda57a0 100644 --- a/doc/_extensions/zephyr/domain/__init__.py +++ b/doc/_extensions/zephyr/domain/__init__.py @@ -757,6 +757,7 @@ class BoardCatalogDirective(SphinxDirective): "board-catalog.html", { "boards": domain_data["boards"], + "shields": domain_data["shields"], "vendors": domain_data["vendors"], "socs": domain_data["socs"], "hw_features_present": self.env.app.config.zephyr_generate_hw_features, @@ -1381,6 +1382,7 @@ def load_board_catalog_into_domain(app: Sphinx) -> None: hw_features_vendor_filter=app.config.zephyr_hw_features_vendor_filter, ) app.env.domaindata["zephyr"]["boards"] = board_catalog["boards"] + app.env.domaindata["zephyr"]["shields"] = board_catalog["shields"] app.env.domaindata["zephyr"]["vendors"] = board_catalog["vendors"] app.env.domaindata["zephyr"]["socs"] = board_catalog["socs"] app.env.domaindata["zephyr"]["runners"] = board_catalog["runners"] diff --git a/doc/_extensions/zephyr/domain/static/css/board-catalog.css b/doc/_extensions/zephyr/domain/static/css/board-catalog.css index 8062ac8fe18..fbfc6021945 100644 --- a/doc/_extensions/zephyr/domain/static/css/board-catalog.css +++ b/doc/_extensions/zephyr/domain/static/css/board-catalog.css @@ -146,6 +146,7 @@ flex-direction: column; align-items: center; transition: transform 0.3s ease; + position: relative; } .board-card:hover, @@ -155,6 +156,34 @@ text-decoration: none; } +.board-card.shield::before { + content: ""; + position: absolute; + top: 0; + right: 0; + border-style: solid; + border-width: 0 48px 48px 0; + border-color: transparent var(--admonition-note-title-background-color) transparent transparent; + border-radius: 0 8px 0 0; +} + +.board-card.shield::after { + rotate: 45deg; + content: "SHIELD"; + position: absolute; + top: 7px; + right: 6px; + color: var(--admonition-note-title-color); + font-size: 11px; + font-weight: 600; + z-index: 1; + width: 24px; + height: 24px; + display: flex; + align-items: center; + justify-content: center; +} + .board-card .picture { width: auto; height: auto; @@ -247,6 +276,23 @@ max-width: none; } +#catalog.compact .board-card.shield::before { + display: none; /* Remove the S prefix */ +} + +#catalog.compact .board-card.shield::after { + content: "Shield"; + color: var(--admonition-note-color); + background-color: var(--admonition-note-background-color); + padding: 2px 10px 2px 10px; + border-radius: 30px; + font-size: 0.8em; +} + +#catalog.compact .board-card.shield { + padding: 4px 0; +} + #catalog.compact .board-card .vendor, #catalog.compact .board-card .picture { display: none; diff --git a/doc/_extensions/zephyr/domain/static/js/board-catalog.js b/doc/_extensions/zephyr/domain/static/js/board-catalog.js index 0e8c2767c7f..67e872548a1 100644 --- a/doc/_extensions/zephyr/domain/static/js/board-catalog.js +++ b/doc/_extensions/zephyr/domain/static/js/board-catalog.js @@ -119,7 +119,7 @@ function setupHWCapabilitiesField() { const datalist = document.getElementById('tag-list'); const tagCounts = Array.from(document.querySelectorAll('.board-card')).reduce((acc, board) => { - board.getAttribute('data-supported-features').split(' ').forEach(tag => { + (board.getAttribute('data-supported-features') || '').split(' ').forEach(tag => { acc[tag] = (acc[tag] || 0) + 1; }); return acc; @@ -254,12 +254,14 @@ function resetForm() { } function updateBoardCount() { - const boards = document.getElementsByClassName("board-card"); - const visibleBoards = Array.from(boards).filter( - (board) => !board.classList.contains("hidden") - ).length; - const totalBoards = boards.length; - document.getElementById("nb-matches").textContent = `Showing ${visibleBoards} of ${totalBoards}`; + const boards = Array.from(document.getElementsByClassName("board-card")); + const visible = boards.filter(board => !board.classList.contains("hidden")); + const shields = boards.filter(board => board.classList.contains("shield")); + const visibleShields = visible.filter(board => board.classList.contains("shield")); + + document.getElementById("nb-matches").textContent = + `Showing ${visible.length - visibleShields.length} of ${boards.length - shields.length} boards,` + + ` ${visibleShields.length} of ${shields.length} shields`; } function filterBoards() { @@ -281,10 +283,10 @@ function filterBoards() { Array.from(boards).forEach(function (board) { const boardName = board.getAttribute("data-name").toLowerCase(); - const boardArchs = board.getAttribute("data-arch").split(" "); - const boardVendor = board.getAttribute("data-vendor"); - const boardSocs = board.getAttribute("data-socs").split(" "); - const boardSupportedFeatures = board.getAttribute("data-supported-features").split(" "); + const boardArchs = (board.getAttribute("data-arch") || "").split(" ").filter(Boolean); + const boardVendor = board.getAttribute("data-vendor") || ""; + const boardSocs = (board.getAttribute("data-socs") || "").split(" ").filter(Boolean); + const boardSupportedFeatures = (board.getAttribute("data-supported-features") || "").split(" ").filter(Boolean); let matches = true; diff --git a/doc/_extensions/zephyr/domain/templates/board-catalog.html b/doc/_extensions/zephyr/domain/templates/board-catalog.html index 959d28950ad..5eb8e87cc13 100644 --- a/doc/_extensions/zephyr/domain/templates/board-catalog.html +++ b/doc/_extensions/zephyr/domain/templates/board-catalog.html @@ -3,12 +3,12 @@ SPDX-License-Identifier: Apache-2.0 #} -
+
@@ -35,9 +35,11 @@
@@ -98,6 +100,10 @@ {% for board_name, board in boards | items | sort(attribute='1.full_name') -%} {% include "board-card.html" %} {% endfor %} + + {% for shield_name, shield in shields | items | sort(attribute='1.full_name') -%} + {% include "shield-card.html" %} + {% endfor %}