Alphabetize component index ImgTable blocks#6304
Conversation
✅ Deploy Preview for esphome ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
There was a problem hiding this comment.
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
ImgTableitem arrays insrc/content/docs/components/index.mdx(below Network Protocols) with pinned “Core” and “Template” rules. - Adds
script/check_component_index.mjsto 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.
WalkthroughAdds 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
Sequence DiagramsequenceDiagram
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
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Suggested reviewers
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
📝 Coding Plan
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. Comment |
There was a problem hiding this comment.
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
📒 Files selected for processing (3)
.github/workflows/check-component-index.ymlscript/check_component_index.mjssrc/content/docs/components/index.mdx
There was a problem hiding this comment.
🧹 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
sectionKeywordfunction 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
endLinecalculation uses filtered (non-empty) line count, which works correctly when items are contiguous. If the MDX file ever contains blank lines within anImgTableblock, 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:fixedBlockandfixedResultare computed identically.Both variables perform the same mapping and joining operation. Consider reusing
fixedBlockfor 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
fixedBlockonce 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
📒 Files selected for processing (3)
.github/workflows/check-component-index.ymlscript/check_component_index.mjssrc/content/docs/components/index.mdx
✅ Files skipped from review due to trivial changes (1)
- src/content/docs/components/index.mdx
Description
Alphabetize all
ImgTableitem arrays incomponents/index.mdxbelow the Network Protocols heading. Within each table, the ordering is:Also adds:
script/check_component_index.mjs— a reusable script with three modes:--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 touchingcomponents/index.mdxand posts aREQUEST_CHANGESreview 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):
Checklist
I am merging into
nextbecause this is new documentation that has a matching pull-request in esphome as linked above.or
I am merging into
currentbecause 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.mdxwhen creating new documents for new components or cookbook.