Skip to content

feat(docs): expand ComponentGrid in llms.txt output#1509

Open
SeieunYoo wants to merge 3 commits intodevfrom
joy-yoo_karrot/llms-docs-fix
Open

feat(docs): expand ComponentGrid in llms.txt output#1509
SeieunYoo wants to merge 3 commits intodevfrom
joy-yoo_karrot/llms-docs-fix

Conversation

@SeieunYoo
Copy link
Copy Markdown
Collaborator

@SeieunYoo SeieunYoo commented Apr 22, 2026

Add a rule that transforms into a categorized markdown list of components so /llms/docs/components.txt exposes the full component index instead of a bare MDX tag.

Summary by CodeRabbit

릴리스 노트

  • 새로운 기능

    • ComponentGrid 요소가 카테고리별 섹션으로 자동 생성되어 컴포넌트 목록을 그룹화·정렬하고 제목·설명·URL을 표시
    • frontmatter 기반 메타데이터로 deprecated 표기된 항목을 자동으로 제외
  • 테스트

    • ComponentGrid 변환 및 출력(그룹화·정렬·필터링)용 단위 테스트 추가
    • deprecated 판정 로직 및 통과 처리(비대상 노드) 검증용 사례 추가

Add a rule that transforms <ComponentGrid /> into a categorized
markdown list of components so /llms/docs/components.txt exposes
the full component index instead of a bare MDX tag.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Apr 22, 2026

⚠️ No Changeset found

Latest commit: cbab001

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 22, 2026

📝 Walkthrough

Walkthrough

로컬 컴포넌트 문서 디렉터리를 스캔해 frontmatter 기반 엔트리를 수집·캐시하고, 카테고리별로 그룹화한 마이그된 Markdown 링크 목록을 생성해 <ComponentGrid /> MDX 노드를 HTML 마크다운으로 대체하는 새 MDX 규칙과 테스트·픽스처를 추가합니다.

Changes

Cohort / File(s) Summary
Rule implementation
docs/app/_llms/rules/component-grid-rule.ts
컴포넌트 디렉터리 탐색, 카테고리 폴더 스캔, --- frontmatter 파싱(키/값), isDeprecatedValue 기반 필터링, 엔트리 캐싱, buildMarkdown 생성 및 ComponentGrid MDX 노드 변환 로직(HTML 노드 삽입) 추가. ComponentEntry 인터페이스 및 유틸 함수들(export) 포함.
Rule registration
docs/app/_llms/rules/index.ts
componentGridRule 임포트·내보내기 및 activeRules 배열에 추가.
Fixtures (input/output)
docs/app/_llms/__fixtures__/component-grid/basic.output.md, docs/app/_llms/__fixtures__/component-grid/passthrough.input.mdx, docs/app/_llms/__fixtures__/component-grid/passthrough.output.mdx
컴포넌트 목록용 출력 MD 마크다운 픽스처과 passthrough 입력/출력 픽스처 추가(예: <SomethingElse />).
Tests
docs/app/_llms/rules/component-grid-rule.test.ts
buildMarkdown 출력 검증, normalizeLLMBodyWithRules 통과/비통과 경로 검사(픽스처 비교), isDeprecatedValue 경계 케이스 단위테스트 추가.

Sequence Diagram(s)

sequenceDiagram
    participant LLM as "LLM Processor"
    participant Rule as "ComponentGrid Rule"
    participant FS as "Filesystem (docs/components)"
    participant Cache as "In-memory Cache"

    LLM->>Rule: encounters <ComponentGrid /> node
    Rule->>Cache: check cached entries
    alt cache miss
        Rule->>FS: scan category folders & read .mdx files
        FS-->>Rule: return file list and frontmatter
        Rule->>Rule: parse frontmatter, filter deprecated, build entries
        Rule->>Cache: store entries
    end
    Rule->>Rule: buildMarkdown(grouped entries)
    Rule-->>LLM: return HTML node with generated markdown
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 새 규칙으로 폴더를 훑네,
frontmatter로 묶어 링크를 엮네.
오래된 건 건너뛰고, 목록을 말끔히,
토끼가 만든 마크다운 한 조각 —
읽는 이에게 산뜻한 길잡이 🌿

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 제목은 변경 사항의 핵심을 명확하게 나타낸다: ComponentGrid를 llms.txt 출력에 전개하는 기능 추가.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ 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 joy-yoo_karrot/llms-docs-fix

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
Copy Markdown
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: 2

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

Inline comments:
In `@docs/app/_llms/rules/component-grid-rule.test.ts`:
- Around line 5-30: The tests in component-grid-rule.test.ts use partial
matching (toContain/not.toContain) against normalizeLLMBodyWithRules output;
replace these with full-fixture comparisons using normalizeForAssert and
readFixture: import { normalizeForAssert, readFixture } from
'docs/app/_llms/test-utils.ts', call const expected =
readFixture('<appropriate-fixture-filename>.md') and assert
expect(normalizeForAssert(actual)).toBe(normalizeForAssert(expected)); update
each test ("expands ComponentGrid...", "excludes deprecated components...") to
use this pattern and corresponding fixtures, and rename the third test from
"leaves the node as-is when no components are available" to "non-target node
passthrough" (or similar) while also asserting full-fixture equality for the
passthrough case using normalizeForAssert. Ensure tests still call
normalizeLLMBodyWithRules(input, [componentGridRule]) as before.

In `@docs/app/_llms/rules/component-grid-rule.ts`:
- Around line 28-42: parseFrontmatter currently returns all frontmatter values
as strings so a frontmatter like deprecated: false becomes the string "false"
and is treated truthily; update parseFrontmatter to detect boolean-like values
(at least for the "deprecated" key) and convert "true"/"false"
(case-insensitive) to actual booleans (true/false) before storing in result, or
more generally parse "true"/"false" and numeric strings to proper types;
reference the parseFrontmatter function and the "deprecated" frontmatter key so
the boolean false is not treated as truthy in the downstream filter that
excludes deprecated components.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 7cfa20d2-5930-43f0-ab0e-243cd406575d

📥 Commits

Reviewing files that changed from the base of the PR and between 20bca67 and 6ed8858.

📒 Files selected for processing (3)
  • docs/app/_llms/rules/component-grid-rule.test.ts
  • docs/app/_llms/rules/component-grid-rule.ts
  • docs/app/_llms/rules/index.ts

Comment thread docs/app/_llms/rules/component-grid-rule.test.ts
Comment thread docs/app/_llms/rules/component-grid-rule.ts
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 22, 2026

Alpha Preview (Docs)

- Treat deprecated: false / "no" / empty as not deprecated so valid
  components are no longer filtered out by the string-coerced parser.
- Switch tests to fixture-based equality via readFixture /
  normalizeForAssert to match the project's _llms test convention,
  and add unit coverage for isDeprecatedValue.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 23, 2026

Alpha Preview (Stackflow SPA)

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 23, 2026

Alpha Preview (Storybook)

Copy link
Copy Markdown
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)
docs/app/_llms/rules/component-grid-rule.ts (4)

86-91: 모듈 수준 캐시는 프로세스 생애 동안 무효화되지 않습니다.

cachedEntries가 첫 호출 이후 영구히 재사용되므로, dev 서버가 장시간 떠 있는 상태에서 컴포넌트 MDX를 추가/수정/삭제해도 /llms/docs/components.txt 결과에 반영되지 않습니다. 빌드 타임에만 실행된다면 문제없지만, HMR/런타임 호출 경로가 있다면 NODE_ENV !== 'production'에서 캐시를 우회하거나 파일 mtime 기반 무효화를 고려해 주세요.

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

In `@docs/app/_llms/rules/component-grid-rule.ts` around lines 86 - 91, The
module-level cache (cachedEntries) never invalidates, so getEntries() will
return stale ComponentEntry[] after files change; update getEntries() to
invalidate or bypass the cache when NODE_ENV !== 'production' (or when file
mtimes change): e.g., check process.env.NODE_ENV and call loadEntries() directly
in dev, or track last-modified timestamps of the source MDX files and refresh
cachedEntries when any mtime is newer; target symbols: cachedEntries,
getEntries, and loadEntries.

50-52: titleCase는 첫 글자만 대문자화합니다.

(form-controls) 같은 다단어/하이픈 카테고리 폴더가 생기면 "Form-controls"처럼 어색하게 출력됩니다. 현재 카테고리 폴더 네이밍 컨벤션이 단일 소문자 단어로 고정되어 있다면 문제 없지만, 향후 확장을 고려해 단어 경계별 대문자화(또는 하이픈/언더스코어 처리)를 권장합니다.

♻️ 예시
-function titleCase(value: string): string {
-  return value.charAt(0).toUpperCase() + value.slice(1);
-}
+function titleCase(value: string): string {
+  return value
+    .split(/[-_\s]+/)
+    .filter(Boolean)
+    .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
+    .join(" ");
+}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/app/_llms/rules/component-grid-rule.ts` around lines 50 - 52, titleCase
currently only uppercases the first character and yields awkward results for
multi-word or hyphenated names; update the titleCase function to split the input
on hyphens, underscores or spaces (e.g. using a regex like /[-_\s]+/),
capitalize the first letter of each segment and lowercase the rest, then join
the segments with a space so inputs like "form-controls" or "multi_word name"
become "Form Controls" (handle empty segments safely).

108-111: description 내 특수문자로 마크다운이 깨질 수 있습니다.

프론트매터 description], ), 개행, 백틱 등이 포함되면 - [title](url) — description 라인이 깨집니다. 프론트매터 파싱 단계에서 따옴표는 이미 벗겨지므로, 렌더 시점에 최소한 ]/)/개행 정도는 이스케이프하거나 치환하는 것을 권장합니다.

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

In `@docs/app/_llms/rules/component-grid-rule.ts` around lines 108 - 111,
description에 포함된 특수문자 때문에 마크다운이 깨집니다; for (const entry of list) 루프에서 suffix를 만들기
전에 entry.description을 안전하게 치환/이스케이프하세요 (예: ']' → '\]', ')' → '\)', 줄바꿈은 공백 또는
'\\n'으로 대체, 백틱은 '\`'로 이스케이프 등). 그런 다음 lines.push(`-
[${entry.title}](${entry.url})${suffix}`)에서 치환된 safeDescription을 사용하도록 변경하세요.

33-48: parseFrontmatter 유틸리티는 프론트매터 파싱 개선으로 이점을 볼 수 있습니다.

현재 정규식 /^["']|["']$/g는 비대칭 입력(예: title: 'Hello")을 예기치 않게 처리하며, 프로젝트에 이미 있는 yaml@^2.8.2 라이브러리를 사용하면 더 견고하게 만들 수 있습니다. 실제 문서의 프론트매터는 따옴표 없는 단순 key-value 형식(title: Docs MCP, description: ...)이므로 현재 동작에 즉각적인 문제는 없지만, 더 견고한 파싱을 위해 yaml 패키지 활용을 검토할 수 있습니다.

참고로, componentGridRule의 Rule 인터페이스 구현(이름, match, transform)은 적절하게 분리되어 있고, 에러 처리도 안전하게 원본 노드를 반환하고 있습니다.

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

In `@docs/app/_llms/rules/component-grid-rule.ts` around lines 33 - 48, Replace
the fragile manual frontmatter parsing in parseFrontmatter with the project's
yaml library: keep the existing frontmatter extraction (the regex that finds the
--- block) but pass match[1] to YAML.parse (imported from the yaml@^2.8.2
package) to obtain a parsed object, then convert/normalize its values to strings
(e.g., String(value)) before returning a Record<string,string>; catch and return
{} on parse errors so behavior remains safe. Ensure you update the
parseFrontmatter function to import YAML and to handle non-string YAML values
and exceptions.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@docs/app/_llms/rules/component-grid-rule.ts`:
- Around line 86-91: The module-level cache (cachedEntries) never invalidates,
so getEntries() will return stale ComponentEntry[] after files change; update
getEntries() to invalidate or bypass the cache when NODE_ENV !== 'production'
(or when file mtimes change): e.g., check process.env.NODE_ENV and call
loadEntries() directly in dev, or track last-modified timestamps of the source
MDX files and refresh cachedEntries when any mtime is newer; target symbols:
cachedEntries, getEntries, and loadEntries.
- Around line 50-52: titleCase currently only uppercases the first character and
yields awkward results for multi-word or hyphenated names; update the titleCase
function to split the input on hyphens, underscores or spaces (e.g. using a
regex like /[-_\s]+/), capitalize the first letter of each segment and lowercase
the rest, then join the segments with a space so inputs like "form-controls" or
"multi_word name" become "Form Controls" (handle empty segments safely).
- Around line 108-111: description에 포함된 특수문자 때문에 마크다운이 깨집니다; for (const entry of
list) 루프에서 suffix를 만들기 전에 entry.description을 안전하게 치환/이스케이프하세요 (예: ']' → '\]',
')' → '\)', 줄바꿈은 공백 또는 '\\n'으로 대체, 백틱은 '\`'로 이스케이프 등). 그런 다음 lines.push(`-
[${entry.title}](${entry.url})${suffix}`)에서 치환된 safeDescription을 사용하도록 변경하세요.
- Around line 33-48: Replace the fragile manual frontmatter parsing in
parseFrontmatter with the project's yaml library: keep the existing frontmatter
extraction (the regex that finds the --- block) but pass match[1] to YAML.parse
(imported from the yaml@^2.8.2 package) to obtain a parsed object, then
convert/normalize its values to strings (e.g., String(value)) before returning a
Record<string,string>; catch and return {} on parse errors so behavior remains
safe. Ensure you update the parseFrontmatter function to import YAML and to
handle non-string YAML values and exceptions.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 63621421-39bf-49d6-b860-49914712fd80

📥 Commits

Reviewing files that changed from the base of the PR and between 6ed8858 and 8035644.

📒 Files selected for processing (5)
  • docs/app/_llms/__fixtures__/component-grid/basic.output.md
  • docs/app/_llms/__fixtures__/component-grid/passthrough.input.mdx
  • docs/app/_llms/__fixtures__/component-grid/passthrough.output.mdx
  • docs/app/_llms/rules/component-grid-rule.test.ts
  • docs/app/_llms/rules/component-grid-rule.ts
✅ Files skipped from review due to trivial changes (3)
  • docs/app/_llms/fixtures/component-grid/passthrough.output.mdx
  • docs/app/_llms/fixtures/component-grid/passthrough.input.mdx
  • docs/app/_llms/fixtures/component-grid/basic.output.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • docs/app/_llms/rules/component-grid-rule.test.ts

Replace hardcoded /llms/docs/components/{slug}.txt template with the
existing getLLMMarkdownUrl helper so URL construction stays centralized.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Copy link
Copy Markdown
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.

♻️ Duplicate comments (1)
docs/app/_llms/rules/component-grid-rule.ts (1)

16-21: ⚠️ Potential issue | 🟡 Minor

deprecated 판정은 true 계열 allowlist로 좁히는 편이 안전합니다.

현재는 빈 값/false/no만 제외해서 deprecated: offdeprecated: 0 같은 false 계열 값도 deprecated로 처리되어 컴포넌트 인덱스에서 빠질 수 있습니다. 명시적인 true 계열만 제외하도록 좁혀 주세요.

🐛 제안 수정
 export function isDeprecatedValue(value: string | undefined): boolean {
   if (value === undefined) return false;
   const normalized = value.trim().toLowerCase();
   if (normalized === "") return false;
-  return normalized !== "false" && normalized !== "no";
+  return normalized === "true" || normalized === "yes" || normalized === "on" || normalized === "1";
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/app/_llms/rules/component-grid-rule.ts` around lines 16 - 21, The
isDeprecatedValue function currently treats any value other than
empty/"false"/"no" as deprecated, which mislabels values like "off" or "0";
update isDeprecatedValue to return true only for an explicit true allowlist
(e.g., "true","yes","1","on") and false for all other values (still returning
false for undefined/empty). Modify the logic inside isDeprecatedValue to
normalize the input and check membership in that explicit true-set instead of
using the current negative checks.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@docs/app/_llms/rules/component-grid-rule.ts`:
- Around line 16-21: The isDeprecatedValue function currently treats any value
other than empty/"false"/"no" as deprecated, which mislabels values like "off"
or "0"; update isDeprecatedValue to return true only for an explicit true
allowlist (e.g., "true","yes","1","on") and false for all other values (still
returning false for undefined/empty). Modify the logic inside isDeprecatedValue
to normalize the input and check membership in that explicit true-set instead of
using the current negative checks.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ff14e8c9-dadf-42fa-924b-5b15a4344355

📥 Commits

Reviewing files that changed from the base of the PR and between 8035644 and cbab001.

📒 Files selected for processing (1)
  • docs/app/_llms/rules/component-grid-rule.ts

@SeieunYoo SeieunYoo requested review from junghyeonsu and te6-in April 23, 2026 09:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant