Skip to content

Alphabetize component index ImgTable blocks#6304

Open
jesserockz wants to merge 3 commits intocurrentfrom
jesserockz-2026-039
Open

Alphabetize component index ImgTable blocks#6304
jesserockz wants to merge 3 commits intocurrentfrom
jesserockz-2026-039

Conversation

@jesserockz
Copy link
Member

Description

Alphabetize all ImgTable item arrays in components/index.mdx below the Network Protocols heading. Within each table, the ordering is:

  1. Core item (at most one per table — the first name ending with " Core") pinned first
  2. Template items (names starting with "Template ") pinned second
  3. All remaining items sorted case-insensitively by display name

Also adds:

  • script/check_component_index.mjs — a reusable script with three modes:
    • (no flag) — check only, exits 1 if misordered
    • --fix — rewrites the file in-place
    • --suggestions — outputs JSON for CI review comments
  • .github/workflows/check-component-index.yml — a GitHub Actions workflow that runs on PRs touching components/index.mdx and posts a REQUEST_CHANGES review with inline code suggestions showing the correct order. Automatically dismisses its review once ordering is fixed.

Related issue (if applicable): N/A

Pull request in esphome with YAML changes (if applicable):

  • N/A

Checklist

  • I am merging into next because this is new documentation that has a matching pull-request in esphome as linked above.
    or

  • I am merging into current because this is a fix, change and/or adjustment in the current documentation and is not for a new component or feature.

  • Link added in /src/content/docs/components/index.mdx when creating new documents for new components or cookbook.

Copilot AI review requested due to automatic review settings March 18, 2026 23:56
@esphome esphome bot added the current label Mar 18, 2026
@netlify
Copy link

netlify bot commented Mar 18, 2026

Deploy Preview for esphome ready!

Name Link
🔨 Latest commit 27efc31
🔍 Latest deploy log https://app.netlify.com/projects/esphome/deploys/69bba2d737ed960008b4ebca
😎 Deploy Preview https://deploy-preview-6304--esphome.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR standardizes ordering of ImgTable component lists in the main components index and adds automation to enforce that ordering going forward.

Changes:

  • Alphabetizes ImgTable item arrays in src/content/docs/components/index.mdx (below Network Protocols) with pinned “Core” and “Template” rules.
  • Adds script/check_component_index.mjs to check, fix, or emit CI suggestion JSON for ordering.
  • Adds a GitHub Actions workflow to run the check on PRs that touch the component index and post inline ordering suggestions.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
src/content/docs/components/index.mdx Reorders ImgTable entries to follow the defined pinned + alphabetical ordering rules.
script/check_component_index.mjs Implements a checker/fixer for consistent ImgTable ordering below “Network Protocols”.
.github/workflows/check-component-index.yml Runs the checker on PRs and posts/dismisses review comments with inline suggestions.

You can also share your feedback on Copilot code review. Take the survey.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 19, 2026

Walkthrough

Adds a GitHub Actions workflow that validates component ordering in the docs index and a Node.js script that detects/fixes/suggests ordering changes; the component index MDX file is updated with reordered and new entries.

Changes

Cohort / File(s) Summary
GitHub Actions Workflow
.github/workflows/check-component-index.yml
New workflow triggered on PRs touching the components index; checks out base and PR head (sparse), runs the checker in suggestions mode, and posts or dismisses bot reviews with inline suggestion blocks.
Validation Script
script/check_component_index.mjs
New Node.js ES module that parses ImgTable blocks (scoped after ## Network Protocols), computes expected order (Core pinned, Template*, then alphabetical), supports check, --fix, and --suggestions modes, and emits JSON suggestions or rewrites the file.
Component Index Content
src/content/docs/components/index.mdx
Reordered multiple <ImgTable> sections and moved/added component entries across Network Protocols, Bluetooth/BLE, Management/Monitoring, Busses, Sensors, Displays, Touchscreen, Electromechanical, Time, and Cookbook lists.

Sequence Diagram

sequenceDiagram
    actor PR as Pull Request
    participant GH as GitHub Actions
    participant Checkout as Checkout (trusted/untrusted)
    participant Script as check_component_index.mjs
    participant File as index.mdx
    participant API as GitHub API

    PR->>GH: Trigger on PR touching `index.mdx`
    GH->>Checkout: Checkout base branch (trusted)
    GH->>Checkout: Sparse-checkout PR head `index.mdx` (untrusted) into pr-head/
    GH->>Script: Run with `--suggestions` against pr-head/src/content/docs/components/index.mdx
    Script->>File: Parse headings and ImgTable blocks
    Script->>Script: Compute expected ordering and diffs
    Script-->>GH: Exit code + `/tmp/suggestions.json`
    alt sorted (exit 0)
        GH->>API: Dismiss existing bot REQUEST_CHANGES review if present
    else unsorted (exit 1)
        GH->>API: Read suggestions JSON and fingerprint against existing review
        API->>API: Create or replace REQUEST_CHANGES review with inline suggestion comments
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested reviewers

  • balloob
  • frenck
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Alphabetize component index ImgTable blocks' directly and accurately summarizes the main change in the PR: reordering ImgTable items alphabetically in the component index with specific ordering rules (Core first, Templates second, then alphabetical).
Description check ✅ Passed The PR description is directly related to the changeset, providing detailed context about alphabetizing ImgTable blocks, the ordering rules applied, and the supporting automation (the check script and GitHub Actions workflow) added alongside the changes.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch jesserockz-2026-039
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/check-component-index.yml:
- Around line 44-50: The current branch treats any non-zero EXIT_CODE from
script/check_component_index.mjs as an ordering issue; change the logic to
distinguish EXIT_CODE values: if EXIT_CODE == 0 set "sorted=true", if EXIT_CODE
== 1 set "sorted=false" (unsorted table) and do NOT write OUTPUT to
/tmp/suggestions.json, otherwise treat it as a checker failure (any EXIT_CODE
other than 0 or 1) and write OUTPUT to /tmp/suggestions.json so the next step
can surface the actual error from the checker; adjust the if/elif/else around
EXIT_CODE, OUTPUT and the /tmp/suggestions.json write accordingly.
- Around line 103-108: The review payload omits start_side for multiline
comments causing GitHub 422s; when building the comments array from
data.suggestions (the object with keys path, start_line, line, side, body), add
a start_side property for entries where start_line !== line (e.g., set
start_side to 'LEFT' for the original/base side or derive it from your
suggestion metadata) so multiline review comments include both start_line and
start_side before calling pulls.createReview.

In `@script/check_component_index.mjs`:
- Around line 37-60: The current identifyCoreItem function picks the first name
matching /\sCore$/i which is unstable; instead, determine the section root and
match that exact root + " Core". Modify identifyCoreItem to extract the section
name from the table context (e.g. derive the root/section label used in the
table header or neighboring rows) and then look specifically for getName(line)
=== `${sectionName} Core` (case-insensitive) or a regex anchored to that
sectionName, falling back to no match (-1) only if that exact root-core row is
absent; reference the identifyCoreItem function and the getName helper when
making the change.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 94ab8d0c-b883-464b-82ce-2db7d7f943a2

📥 Commits

Reviewing files that changed from the base of the PR and between 3e77d4f and c7bf9dd.

📒 Files selected for processing (3)
  • .github/workflows/check-component-index.yml
  • script/check_component_index.mjs
  • src/content/docs/components/index.mdx

@jesserockz jesserockz marked this pull request as draft March 19, 2026 00:40
@jesserockz jesserockz marked this pull request as ready for review March 19, 2026 07:15
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (4)
.github/workflows/check-component-index.yml (1)

143-149: Fingerprint comparison is order-sensitive.

The JSON.stringify comparison at lines 143-144 assumes comments are returned in the same order they were posted. If the GitHub API returns comments in a different order, the fingerprints won't match even for identical suggestions, causing unnecessary review recreation.

Consider sorting both arrays by a stable key (e.g., start_line) before comparison, or use a set-based comparison.

Proposed fix
-            const newFingerprint = JSON.stringify(comments.map(c => ({ path: c.path, start_line: c.start_line, line: c.line, body: c.body })));
-            const existingFingerprint = JSON.stringify(reviewComments);
+            const sortByLine = arr => [...arr].sort((a, b) => a.start_line - b.start_line);
+            const newFingerprint = JSON.stringify(sortByLine(comments.map(c => ({ path: c.path, start_line: c.start_line, line: c.line, body: c.body }))));
+            const existingFingerprint = JSON.stringify(sortByLine(reviewComments));
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/check-component-index.yml around lines 143 - 149, The
fingerprint comparison using JSON.stringify on comments is order-sensitive
(newFingerprint vs existingFingerprint); sort both arrays (the comments array
used to build newFingerprint and the reviewComments array used for
existingFingerprint) by a stable key such as path + start_line + line (or
start_line then line) before JSON.stringify so order differences don't cause
mismatches; update the logic that constructs newFingerprint and
existingFingerprint to perform the same deterministic sort on comments and
reviewComments prior to serialization.
script/check_component_index.mjs (3)

51-55: Consider adding " Protocols" suffix stripping for consistency.

The sectionKeyword function strips " Components" and " Hardware Platforms" but not " Protocols". For the "Network Protocols" heading, the keyword becomes "Network Protocols", which won't match "Network Core" exactly. The fallback at line 96-97 handles this, but adding explicit support would be more robust.

Proposed enhancement
 function sectionKeyword(parentHeading) {
   return parentHeading
     .replace(/\s+Components$/i, "")
-    .replace(/\s+Hardware\s+Platforms$/i, "");
+    .replace(/\s+Hardware\s+Platforms$/i, "")
+    .replace(/\s+Protocols$/i, "");
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@script/check_component_index.mjs` around lines 51 - 55, The sectionKeyword
function currently strips " Components" and " Hardware Platforms" from
parentHeading but not " Protocols"; update sectionKeyword to also remove a
trailing " Protocols" suffix (case-insensitive) so "Network Protocols" becomes
"Network" before further matching — modify the function that returns
parentHeading (sectionKeyword) to include an additional replacement for the
Protocols suffix (e.g., another .replace(...) for /\s+Protocols$/i) so the
keyword normalization covers "Protocols" headings.

186-189: Line range calculation assumes no blank lines between items.

The endLine calculation uses filtered (non-empty) line count, which works correctly when items are contiguous. If the MDX file ever contains blank lines within an ImgTable block, the computed line range would be off. This seems fine given the current file format, but worth noting if formatting conventions change.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@script/check_component_index.mjs` around lines 186 - 189, The endLine
calculation currently drops blank lines by using allItemLines.filter(...).length
which breaks line offsets if ImgTable blocks include blank lines; update the
calculation to count all lines (including empty ones) when computing endLine so
ranges reflect actual file lines — reference the variables prefixLines,
linesBeforeInAfter, startLine, endLine, allItemLines, after, offset and
afterStartLine and replace the filtered length with the total line count from
allItemLines (or equivalent total-from-split) so blank lines are accounted for.

191-210: Minor duplication: fixedBlock and fixedResult are computed identically.

Both variables perform the same mapping and joining operation. Consider reusing fixedBlock for the return value to avoid redundant computation.

Proposed fix
       const originalBlock = lines.map(normalizeLine).join("\n");
-      const fixedBlock = [...coreLines, ...templateLines, ...sorted]
-        .map(normalizeLine)
-        .join("\n");
+      const fixedBlock = [...coreLines, ...templateLines, ...sorted]
+        .map(normalizeLine)
+        .join("\n");

       results.push({
         section: sectionName,
         startLine,
         endLine,
         original: originalBlock,
         fixed: fixedBlock,
       });
     }

-    // Build the fixed version (used by --fix)
-    const fixedResult = [...coreLines, ...templateLines, ...sorted]
-      .map(normalizeLine)
-      .join("\n");
-
-    return `${prefix}${fixedResult}\n${suffix}`;
+    // Build the fixed version (used by --fix)
+    const fixedResult = !isFullyOrdered
+      ? fixedBlock
+      : [...coreLines, ...templateLines, ...sorted].map(normalizeLine).join("\n");
+
+    return `${prefix}${fixedResult}\n${suffix}`;

Actually, a cleaner approach would be to compute fixedBlock once outside the conditional:

Cleaner refactor
+      const fixedBlock = [...coreLines, ...templateLines, ...sorted]
+        .map(normalizeLine)
+        .join("\n");
+
       if (!isFullyOrdered) {
         // Compute 1-indexed line numbers...
         const prefixLines = prefix.split("\n").length - 1;
         const linesBeforeInAfter = after.slice(0, offset).split("\n").length - 1;
         const startLine = afterStartLine + linesBeforeInAfter + prefixLines;
         const endLine = startLine + allItemLines.filter((l) => l.trim().length > 0).length - 1;

         const originalBlock = lines.map(normalizeLine).join("\n");
-        const fixedBlock = [...coreLines, ...templateLines, ...sorted]
-          .map(normalizeLine)
-          .join("\n");

         results.push({
           section: sectionName,
           startLine,
           endLine,
           original: originalBlock,
           fixed: fixedBlock,
         });
       }

-      // Build the fixed version (used by --fix)
-      const fixedResult = [...coreLines, ...templateLines, ...sorted]
-        .map(normalizeLine)
-        .join("\n");
-
-      return `${prefix}${fixedResult}\n${suffix}`;
+      return `${prefix}${fixedBlock}\n${suffix}`;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@script/check_component_index.mjs` around lines 191 - 210, The code duplicates
the same join/mapping logic into both fixedBlock and fixedResult; compute the
fixed block once by creating fixedBlock = [...coreLines, ...templateLines,
...sorted].map(normalizeLine).join("\n") before pushing into results and reuse
that fixedBlock for the return (replace fixedResult usage), ensuring you update
the results.push call to reference fixedBlock and return
`${prefix}${fixedBlock}\n${suffix}`; keep references to normalizeLine,
coreLines, templateLines, sorted, fixedBlock, and results to locate and change
the duplicated computation.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In @.github/workflows/check-component-index.yml:
- Around line 143-149: The fingerprint comparison using JSON.stringify on
comments is order-sensitive (newFingerprint vs existingFingerprint); sort both
arrays (the comments array used to build newFingerprint and the reviewComments
array used for existingFingerprint) by a stable key such as path + start_line +
line (or start_line then line) before JSON.stringify so order differences don't
cause mismatches; update the logic that constructs newFingerprint and
existingFingerprint to perform the same deterministic sort on comments and
reviewComments prior to serialization.

In `@script/check_component_index.mjs`:
- Around line 51-55: The sectionKeyword function currently strips " Components"
and " Hardware Platforms" from parentHeading but not " Protocols"; update
sectionKeyword to also remove a trailing " Protocols" suffix (case-insensitive)
so "Network Protocols" becomes "Network" before further matching — modify the
function that returns parentHeading (sectionKeyword) to include an additional
replacement for the Protocols suffix (e.g., another .replace(...) for
/\s+Protocols$/i) so the keyword normalization covers "Protocols" headings.
- Around line 186-189: The endLine calculation currently drops blank lines by
using allItemLines.filter(...).length which breaks line offsets if ImgTable
blocks include blank lines; update the calculation to count all lines (including
empty ones) when computing endLine so ranges reflect actual file lines —
reference the variables prefixLines, linesBeforeInAfter, startLine, endLine,
allItemLines, after, offset and afterStartLine and replace the filtered length
with the total line count from allItemLines (or equivalent total-from-split) so
blank lines are accounted for.
- Around line 191-210: The code duplicates the same join/mapping logic into both
fixedBlock and fixedResult; compute the fixed block once by creating fixedBlock
= [...coreLines, ...templateLines, ...sorted].map(normalizeLine).join("\n")
before pushing into results and reuse that fixedBlock for the return (replace
fixedResult usage), ensuring you update the results.push call to reference
fixedBlock and return `${prefix}${fixedBlock}\n${suffix}`; keep references to
normalizeLine, coreLines, templateLines, sorted, fixedBlock, and results to
locate and change the duplicated computation.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b8b532e6-f45e-4247-b783-ade13287cb7a

📥 Commits

Reviewing files that changed from the base of the PR and between c7bf9dd and 27efc31.

📒 Files selected for processing (3)
  • .github/workflows/check-component-index.yml
  • script/check_component_index.mjs
  • src/content/docs/components/index.mdx
✅ Files skipped from review due to trivial changes (1)
  • src/content/docs/components/index.mdx

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants