Auto-generated software tools tables
docs/intro.mdx has five "Software tools" tables, one per category —
SDK, ROS2, ROS1, Physics Engine, Other — each listing
every product that has a tool in that category, with each cell showing
that tool's support badge linked to its page. Every category is built the
same way: one column per distinct tool title found under that category's
leaf pages. For ROS1/ROS2 those columns are distro names (e.g. "Humble"),
because a ROS leaf page's title is its distro name (see
step 3 of adding a new tool)
— there's no separate distro-vs-tool distinction in the script.
SDK / Physics Engine / Other get the same tables again, single-row
versions scoped to just that product, on that product's own
docs/drivers/<Product>/index.mdx. ROS2 / ROS1 get theirs on that
product's docs/drivers/<Product>/ROS/index.mdx instead — since a
product's ROS distros usually outnumber its other tools, splitting them
onto their own landing page keeps the top-level product page short. You
never edit any of these by hand — all of them are regenerated by
scripts/generate-tools-table.js,
which runs automatically on npm start / npm run build (same as
sync-external-docs.js).
The script walks each docs/drivers/<Product>/ folder tree looking for
tool leaf pages — an index.mdx carrying a Category badge — regardless
of how deeply it's nested (SDK/, ROS/, Physics Engine/, Other/, or
no container folder at all). For each leaf page found:
- Row — the product's own
titlefrontmatter (fromdocs/drivers/<Product>/index.mdx). - Column — the tool's own
titlefrontmatter (e.g.Python,Humble). - Cell — the tool's
Supported_by-<Label>-<color>badge, shown compactly (no "Supported by" prefix — only the source page keeps the full badge), linking to that tool's own page.
This means adding a new product or tool page, with a title and the right badges, is enough to make it appear in the matching tables on the next build — no manual edit needed. A category with no products yet renders a short placeholder line instead of an empty table.
A few things are still hand-maintained in the script itself, by design — they're presentation choices, not derivable from the file tree:
COLUMN_ORDER— preferred left-to-right order for each category's columns (e.g. ROS distros in chronological release order). Anything not listed still gets its own column, just sorted alphabetically after the known ones.COLUMN_DESCRIPTIONS— the one-line legend shown under each table. A column missing here still appears, just with no legend line, until one is added.
To test a change locally:
node scripts/generate-tools-table.js
It rewrites the content between each AUTO-GENERATED-<CATEGORY>-TABLE
marker pair (AUTO-GENERATED-SDK-TABLE, AUTO-GENERATED-ROS2-TABLE,
AUTO-GENERATED-ROS1-TABLE, AUTO-GENERATED-PHYSICS_ENGINE-TABLE,
AUTO-GENERATED-OTHER-TABLE) in docs/intro.mdx, the matching
AUTO-GENERATED-PRODUCT-<CATEGORY>-TABLE marker pairs for SDK / Physics
Engine / Other in each product's own index.mdx, and the
AUTO-GENERATED-PRODUCT-ROS2-TABLE / AUTO-GENERATED-PRODUCT-ROS1-TABLE
pairs in each product's ROS/index.mdx — leaving the rest of each page
untouched. If a product has ROS tool pages but no ROS/index.mdx with
those markers, the script throws a build error naming the missing file
rather than silently skipping it.
The three destinations use different link styles on purpose:
docs/intro.mdx needs root-relative links (drivers/<Product>/<Tool>); a
product's own page needs page-relative links (<Tool>); a product's
ROS/index.mdx needs links relative to that page (<Distro>, one level
deeper than the product root). Reusing the wrong style would silently
double or misalign the path — the script keeps these as three separate
href fields (href, localHref, rosLocalHref) to avoid that.