Skip to content

feat(core): SEO022/SEO023 — title & description length - #58

Merged
oekazuma merged 12 commits into
mainfrom
feat/seo-title-description-length
Jun 26, 2026
Merged

oekazuma merged 12 commits into
mainfrom
feat/seo-title-description-length

Conversation

@oekazuma

@oekazuma oekazuma commented Jun 26, 2026 •

Copy link
Copy Markdown
Owner

SEO Phase B (after Phase C JSON-LD, #55/#57): validate the length of the document <title> and <meta name="description">. Both are info, route-scoped, and run only on static text — presence/emptiness stays owned by SEO001/SEO002.

New rules

ID Check Severity Range
SEO022 Title length info 30–60 chars
SEO023 Description length info 70–160 chars

Both flag too short and too long. A dynamic title/description emits nothing (no false positives).

How it works

  • Capture: a new HeadTag.text field holds the literal visible title/description text, set only when static (mirrors HeadTag.jsonld).
    • CLI (static Svelte): reads the AST literal text; {expr} and quoted "{expr}" both leave text undefined.
    • vite (rendered): uses node-html-parser's decoded title.text / getAttribute('content') — <title> is RCDATA and content is an attribute, so entities are decoded (the SERP-visible text). This is deliberately the opposite of JSON-LD's rawText (raw-text <script>).
  • Measure: pure visibleLength() — trim, collapse internal whitespace, count Unicode code points (astral emoji = 1). No deps.
  • Rules: a small lengthRule factory; len < min / len > max, so exactly 30/60/70/160 are in-range. Follows the seo016-021 pattern.

Surfaces & docs

  • @svelte-vitals/core + svelte-vitals + @svelte-vitals/vite + @svelte-vitals/mcp minor (MCP analyze/explain_rule surface them automatically via allRules).
  • 4 rule reference pages (SEO022/SEO023, en + ja).

Validation

pnpm -r test (385: core 175 / vite 60 / cli 141 / mcp 9), pnpm -r typecheck, pnpm lint, pnpm --filter docs build (71 pages incl. the 4 new) — all green.

Two pre-existing "clean page" test fixtures gained in-range title/description (they were genuinely out-of-range under the new rules); deep-equality assertions on title tags gained the now-captured text — additive, no assertions loosened.

Process

Built spec → plan → subagent-driven (6 tasks, each spec + quality reviewed) + a whole-branch review on Opus (verdict: ready to merge). One review-loop fix landed: quoted dynamic content="{desc}" had captured text:'' (would false-positive SEO023) — now correctly left undefined.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added two new SEO checks for static page metadata: SEO022 (title length) and SEO023 (meta description length).
    • Static <title> and description values are now captured as visible text for more accurate length validation.
  • Bug Fixes

    • Dynamic or absent titles/descriptions are no longer flagged by these length checks.
    • Length is measured as users see it: whitespace is normalized and counts use grapheme clusters (so emoji sequences count correctly), including decoded entities.
  • Documentation

    • Added English and Japanese documentation for SEO022/SEO023, including thresholds and examples.

@coderabbitai

coderabbitai Bot commented Jun 26, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds static title/description text capture, visible-length measurement, SEO022/SEO023 rule evaluation, and matching docs, tests, and release notes.

Changes

Static SEO title and description length checks

Layer / File(s) Summary
Design, plan, and text contract
docs/superpowers/specs/..., docs/superpowers/plans/...
The spec and plan define static-only head text capture, visibleLength, the two length rules, and the planned test and docs coverage.
Head text contract and metrics
packages/core/src/head.ts, packages/core/src/rules/seo/text-metrics.ts, packages/core/test/text-metrics.test.ts
HeadTag gains text, and visibleLength trims, collapses whitespace, and counts visible characters with grapheme-aware behavior.
CLI head text capture
packages/cli/src/providers/source/parse.ts, packages/cli/src/providers/source/adapters/*.ts, packages/cli/test/*.test.ts
The source parser and source adapters now attach static title and description text, and the CLI tests assert static, dynamic, and resolved-title cases.
Rendered head text capture
packages/vite/src/providers/rendered/parse-html.ts, packages/vite/test/*.test.ts
The rendered HTML parser now captures decoded title and description text, and the Vite tests assert the new text field.
Length rules, registry, and docs
packages/core/src/rules/seo/*.ts, packages/core/src/rules/index.ts, packages/core/src/index.ts, packages/core/test/seo-length-rules.test.ts, docs/src/content/docs/*/rules/seo02{2,3}.md, .changeset/seo-title-description-length.md
The new SEO022 and SEO023 rules use visibleLength, are added to the core exports, and are documented in English and Japanese with release notes.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

I nibbled titles, crisp and bright,
and sniffed descriptions just so right.
One text to count, one length to test,
static stars now pass the quest.
🐇✨ SEO carrots, nicely dressed!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding SEO022/SEO023 length checks for title and description.
Docstring Coverage ✅ Passed Docstring coverage is 85.71% which is sufficient. The required threshold is 80.00%.
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.
✨ 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 feat/seo-title-description-length

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.

@oekazuma oekazuma self-assigned this Jun 26, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🧹 Nitpick comments (3)
packages/vite/test/parse-html.test.ts (1)

103-106: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a decoded-description case here too.

This block proves entity decoding for <title>, but the design makes the same guarantee for meta[name="description"] content. A case like content="Caf&eacute; &amp; Bar" would lock that contract down and catch regressions on the description path as well.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/vite/test/parse-html.test.ts` around lines 103 - 106, The
`parseHtmlHead` test for `meta[name="description"]` only covers plain text
today; add a decoded-description assertion alongside `captures description
content text` to verify entity decoding works for description content too.
Update the test in `parse-html.test.ts` using the existing `html(...)` and
`tags.find(...)` pattern, with a case such as `Caf&eacute; &amp; Bar`, and
assert the resulting `desc.text` is the decoded string so the `parseHtmlHead`
contract matches the `<title>` decoding behavior.
packages/cli/test/resolve-transitive.test.ts (1)

52-52: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Cover resolved description text too.

These assertions lock title.text through transitive resolution, but SEO023 depends on the same path for meta[name="description"]. Adding one resolved description case here would catch regressions where parsing keeps text but resolution drops it.

Also applies to: 77-77

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/cli/test/resolve-transitive.test.ts` at line 52, The transitive
resolution test in resolve-transitive.test.ts only covers resolved title text,
but SEO023 uses the same path for meta description resolution as well. Update
the relevant test cases around the existing assertions in the resolve-transitive
suite to include one resolved description expectation (via the same resolution
flow used for title) so regressions in description handling are caught; use the
existing resolve/transitive assertion pattern and the r.tags expectations to
locate where to add it.
packages/core/test/seo-length-rules.test.ts (1)

21-53: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add one visibleLength-specific case here.

These tests only use ASCII literals, so they would still pass if the rules stopped using trimmed/collapsed Unicode code-point counts and fell back to raw .length.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/core/test/seo-length-rules.test.ts` around lines 21 - 53, Add a
visibleLength-specific test case to the SEO022/SEO023 test suite so it fails if
the rules regress to raw .length behavior. Update the relevant checks in
seo-length-rules.test.ts by adding a non-ASCII/whitespace-collapsed input for
seo022TitleLength or seo023DescriptionLength and assert the expected pass/fail
outcome from visibleLength, using the existing helpers like
seo022TitleLength.check, seo023DescriptionLength.check, fails, ctx, title, and
desc to locate the right spot.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/src/content/docs/ja/rules/seo022.md`:
- Around line 18-21: The example title in the SEO022 docs does not meet the
stated 30–60 character range, so update the sample inside the svelte:head block
to a title that actually falls within that range while still being concise and
descriptive. Use the existing SEO022 example section to replace the current
title text with a compliant one, keeping the surrounding structure unchanged.

In `@docs/src/content/docs/ja/rules/seo023.md`:
- Around line 18-21: The example meta description in the SEO023 doc is too short
to satisfy the rule being documented. Update the `<svelte:head>` example so the
`meta[name="description"]` `content` text is actually within the 70〜160
character range, using a compliant Japanese sentence that still reads like a
realistic page description.

In `@docs/superpowers/plans/2026-06-26-seo-title-description-length.md`:
- Around line 639-725: The docs snippet contains stray empty fenced blocks after
the example sections, which triggers markdownlint MD040 and renders empty code
blocks. Remove the extra bare fences in the SEO022/SEO023 English and Japanese
sections, and keep only the intended code fences inside the rule docs content so
the markdown stays properly balanced.
- Around line 205-223: The plan snippet for the meta tag parser currently treats
every meta[name="description"] as static by assigning descText directly from
attrText, which regresses quoted dynamic descriptions. Update the snippet around
the meta handling in the parser example so descText is only added when content
is actually static, matching the parse.ts contract that checks content
resolution before setting text; keep the conditional logic aligned with the
meta/link tag flow and the descText field.

In `@packages/core/src/rules/seo/seo022-023.ts`:
- Around line 6-8: The SEO022/023 result mapping is overwriting the matched tag
metadata with fixed values, which breaks inherited-layout cases. Update the rule
logic in the SEO rule module so the returned `presence`, `value`, and `location`
are taken from the matched `HeadTag` (for both pass and fail paths) instead of
always using the hardcoded `PENALIZED`/`PASS` objects and `head.file`. Use the
existing `HeadTag` fields and the result-building code in the SEO022/023 rule to
preserve the real source tag metadata.

In `@packages/core/test/seo-length-rules.test.ts`:
- Around line 7-19: Update the seo-length-rules tests so they exercise dynamic
tag handling, not just missing text: adjust the shared helpers like headWith,
title, and desc in seo-length-rules.test.ts to allow overriding the tag value
and create cases where value is dynamic. Then add/modify assertions in the
seo022TitleLength.check and related checks to verify that dynamic
title/description tags emit no detection, while static tags with missing text
still fail as before.

---

Nitpick comments:
In `@packages/cli/test/resolve-transitive.test.ts`:
- Line 52: The transitive resolution test in resolve-transitive.test.ts only
covers resolved title text, but SEO023 uses the same path for meta description
resolution as well. Update the relevant test cases around the existing
assertions in the resolve-transitive suite to include one resolved description
expectation (via the same resolution flow used for title) so regressions in
description handling are caught; use the existing resolve/transitive assertion
pattern and the r.tags expectations to locate where to add it.

In `@packages/core/test/seo-length-rules.test.ts`:
- Around line 21-53: Add a visibleLength-specific test case to the SEO022/SEO023
test suite so it fails if the rules regress to raw .length behavior. Update the
relevant checks in seo-length-rules.test.ts by adding a
non-ASCII/whitespace-collapsed input for seo022TitleLength or
seo023DescriptionLength and assert the expected pass/fail outcome from
visibleLength, using the existing helpers like seo022TitleLength.check,
seo023DescriptionLength.check, fails, ctx, title, and desc to locate the right
spot.

In `@packages/vite/test/parse-html.test.ts`:
- Around line 103-106: The `parseHtmlHead` test for `meta[name="description"]`
only covers plain text today; add a decoded-description assertion alongside
`captures description content text` to verify entity decoding works for
description content too. Update the test in `parse-html.test.ts` using the
existing `html(...)` and `tags.find(...)` pattern, with a case such as
`Caf&eacute; &amp; Bar`, and assert the resulting `desc.text` is the decoded
string so the `parseHtmlHead` contract matches the `<title>` decoding behavior.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4b5e4bd6-1024-42b4-a32a-02148ed71d3b

📥 Commits

Reviewing files that changed from the base of the PR and between 93687b5 and 3927424.

📒 Files selected for processing (23)
  • .changeset/seo-title-description-length.md
  • docs/src/content/docs/ja/rules/seo022.md
  • docs/src/content/docs/ja/rules/seo023.md
  • docs/src/content/docs/rules/seo022.md
  • docs/src/content/docs/rules/seo023.md
  • docs/superpowers/plans/2026-06-26-seo-title-description-length.md
  • docs/superpowers/specs/2026-06-26-seo-title-description-length-design.md
  • packages/cli/src/providers/source/parse.ts
  • packages/cli/test/parse-file.test.ts
  • packages/cli/test/parse-length.test.ts
  • packages/cli/test/resolve-transitive.test.ts
  • packages/cli/test/resolve.test.ts
  • packages/core/src/head.ts
  • packages/core/src/index.ts
  • packages/core/src/rules/index.ts
  • packages/core/src/rules/seo/seo022-023.ts
  • packages/core/src/rules/seo/text-metrics.ts
  • packages/core/test/seo-length-rules.test.ts
  • packages/core/test/text-metrics.test.ts
  • packages/vite/src/providers/rendered/parse-html.ts
  • packages/vite/test/collect.test.ts
  • packages/vite/test/dev-handle.test.ts
  • packages/vite/test/parse-html.test.ts

Comment thread docs/src/content/docs/ja/rules/seo022.md
Comment thread docs/src/content/docs/ja/rules/seo023.md
Comment thread docs/superpowers/plans/2026-06-26-seo-title-description-length.md
Comment thread docs/superpowers/plans/2026-06-26-seo-title-description-length.md Outdated
Comment thread packages/core/src/rules/seo/seo022-023.ts Outdated
Comment thread packages/core/test/seo-length-rules.test.ts Outdated
…mples; plan doc

Address CodeRabbit review on PR #58:
- SEO022/023 now report 'location' as tag.file ?? head.file, so a title/description
  inherited from a +layout points at the layout file rather than the route (matches
  the link-rule precedent). detection stays the penalize signal ({none,absent} on
  fail, {own,static} on pass) — using the tag's own presence/value would make a
  too-long static title non-penalized, defeating the rule (codebase-wide convention).
- ja SEO022/SEO023 'how to fix' examples now actually fall within their documented
  ranges (33 chars / 78 chars) instead of violating the rule they illustrate.
- length-rule tests gain a 'value' knob and assert dynamic title/description emit
  nothing, exercising the dynamic→silent contract directly.
- plan doc: align the CLI capture snippet with the shipped static-content guard and
  drop the stray empty fenced blocks (markdownlint MD040).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds SEO Phase B length validation for <title> and <meta name="description"> by capturing static, SERP-visible text into the head model and introducing two new core rules (SEO022/SEO023) that evaluate trimmed/whitespace-collapsed Unicode code-point length.

Changes:

  • Add HeadTag.text capture for title/description in both static (CLI AST) and rendered (vite HTML) collection paths.
  • Introduce visibleLength() plus new core rules SEO022 (title 30–60) and SEO023 (description 70–160), and register/re-export them.
  • Add tests, docs pages (en/ja), and a changeset for the new rules.

Reviewed changes

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

Show a summary per file
File Description
packages/vite/test/parse-html.test.ts Updates expectations to include captured text and adds entity-decoding coverage for rendered title/description capture.
packages/vite/test/dev-handle.test.ts Adjusts rendered fixture HTML title/description to be in-range under the new rules.
packages/vite/test/collect.test.ts Updates rendered collection expectation to include captured title text.
packages/vite/src/providers/rendered/parse-html.ts Captures decoded rendered title/description text into HeadTag.text.
packages/core/test/text-metrics.test.ts Adds unit tests for visibleLength() behavior (trim/collapse/code points).
packages/core/test/seo-length-rules.test.ts Adds rule-level tests for SEO022/SEO023 (short/long/pass/dynamic/absent).
packages/core/src/rules/seo/text-metrics.ts Adds visibleLength() helper (dependency-free).
packages/core/src/rules/seo/seo022-023.ts Implements the SEO022/SEO023 length rules via a small factory.
packages/core/src/rules/index.ts Registers new rules in allRules and re-exports them.
packages/core/src/index.ts Re-exports SEO022/SEO023 from the package entry.
packages/core/src/head.ts Extends HeadTag with optional text?: string for captured static visible text.
packages/cli/test/resolve.test.ts Updates expectations to include captured title text from static resolution.
packages/cli/test/resolve-transitive.test.ts Updates transitive resolution expectations to include captured title text.
packages/cli/test/parse-length.test.ts Adds tests for static capture of title/description text and “dynamic stays undefined” behavior.
packages/cli/test/parse-file.test.ts Updates parsed head tag expectations to include captured title text.
packages/cli/src/providers/source/parse.ts Captures static title/description literal text into HeadTag.text during AST parsing.
docs/superpowers/specs/2026-06-26-seo-title-description-length-design.md Adds approved design spec describing capture, measurement, and rule behavior.
docs/superpowers/plans/2026-06-26-seo-title-description-length.md Adds implementation plan detailing steps/tests/docs/changeset.
docs/src/content/docs/rules/seo023.md Adds English rule reference page for SEO023.
docs/src/content/docs/rules/seo022.md Adds English rule reference page for SEO022.
docs/src/content/docs/ja/rules/seo023.md Adds Japanese rule reference page for SEO023.
docs/src/content/docs/ja/rules/seo022.md Adds Japanese rule reference page for SEO022.
.changeset/seo-title-description-length.md Declares minor bumps and summarizes new SEO022/SEO023 behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/cli/src/providers/source/parse.ts
Comment thread packages/cli/src/providers/source/parse.ts
oekazuma and others added 2 commits June 26, 2026 15:34
… providers

Address Copilot review on PR #58: confirm static (CLI) and rendered (vite) modes
both store the SERP-visible, entity-decoded text, so visibleLength agrees across
modes. Svelte's Text `.data` and attribute Text `.data` are already decoded
(`&amp;`->`&`, `&eacute;`->`é`), as are node-html-parser's `.text` and
getAttribute — no code change needed; these regression tests pin the invariant so
a future switch to raw text can't silently break length counts.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…e counting

Address PR review findings:
- Capture static title/description text from svelte-meta-tags & svelte-seo
  component props (new attrTextOf helper) so SEO022/SEO023 fire in CLI/static
  mode too, not only in rendered mode. A titleTemplate suppresses title
  measurement (the rendered title is longer).
- Measure length by grapheme cluster via Intl.Segmenter so ZWJ/flag/skin-tone
  emoji count as one character; code-point fallback retained.
- Extract shared PENALIZED/PASS detection constants into detection.ts, used by
  both seo016-021 and seo022-023.
- Document static-vs-rendered measurement and grapheme counting (en+ja); update
  changeset.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
packages/cli/src/providers/source/parse.ts (1)

172-181: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Delegate attrTextOf to textFromNodes to avoid divergent copies.

attrTextOf(attr) is functionally identical to textFromNodes(attr?.value) (same ExpressionTag guard, same Text-node join, same trim-emptiness check). Since both paths now feed the same visibleLength/SEO022-023 measurement, keeping two literal copies invites drift if one is later tweaked (e.g., normalization changes).

♻️ Proposed consolidation
 /** Literal static text of a single attribute node (e.g. a component prop), or undefined if dynamic/absent. */
 export function attrTextOf(attr: Node): string | undefined {
-  const v = attr?.value;
-  if (!Array.isArray(v) || v.some((n: Node) => n?.type === 'ExpressionTag')) return undefined;
-  const text = v
-    .filter((n: Node) => n?.type === 'Text')
-    .map((n: Node) => String(n.data ?? ''))
-    .join('');
-  return text.trim().length > 0 ? text : undefined;
+  return textFromNodes(attr?.value);
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/cli/src/providers/source/parse.ts` around lines 172 - 181,
`attrTextOf` duplicates the same literal-text extraction logic already
implemented in `textFromNodes`, so consolidate it to avoid drift. Update
`attrTextOf(attr)` to delegate directly to `textFromNodes(attr?.value)` and keep
the existing `ExpressionTag`/Text-node/trim behavior centralized in
`textFromNodes`. This keeps the `visibleLength` and SEO022-023 measurement paths
aligned and ensures future normalization changes only need to be made in one
place.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@packages/cli/src/providers/source/parse.ts`:
- Around line 172-181: `attrTextOf` duplicates the same literal-text extraction
logic already implemented in `textFromNodes`, so consolidate it to avoid drift.
Update `attrTextOf(attr)` to delegate directly to `textFromNodes(attr?.value)`
and keep the existing `ExpressionTag`/Text-node/trim behavior centralized in
`textFromNodes`. This keeps the `visibleLength` and SEO022-023 measurement paths
aligned and ensures future normalization changes only need to be made in one
place.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f7eafa70-53a2-4f15-af77-0b7e99932143

📥 Commits

Reviewing files that changed from the base of the PR and between 3927424 and 6b306d8.

📒 Files selected for processing (19)
  • .changeset/seo-title-description-length.md
  • docs/src/content/docs/ja/rules/seo022.md
  • docs/src/content/docs/ja/rules/seo023.md
  • docs/src/content/docs/rules/seo022.md
  • docs/src/content/docs/rules/seo023.md
  • docs/superpowers/plans/2026-06-26-seo-title-description-length.md
  • packages/cli/src/providers/source/adapters/svelte-meta-tags.ts
  • packages/cli/src/providers/source/adapters/svelte-seo.ts
  • packages/cli/src/providers/source/parse.ts
  • packages/cli/test/adapters-registry.test.ts
  • packages/cli/test/adapters-smt.test.ts
  • packages/cli/test/parse-length.test.ts
  • packages/core/src/rules/seo/detection.ts
  • packages/core/src/rules/seo/seo016-021.ts
  • packages/core/src/rules/seo/seo022-023.ts
  • packages/core/src/rules/seo/text-metrics.ts
  • packages/core/test/seo-length-rules.test.ts
  • packages/core/test/text-metrics.test.ts
  • packages/vite/test/parse-html.test.ts
✅ Files skipped from review due to trivial changes (6)
  • .changeset/seo-title-description-length.md
  • docs/src/content/docs/rules/seo023.md
  • docs/src/content/docs/ja/rules/seo023.md
  • docs/src/content/docs/ja/rules/seo022.md
  • docs/src/content/docs/rules/seo022.md
  • docs/superpowers/plans/2026-06-26-seo-title-description-length.md
🚧 Files skipped from review as they are similar to previous changes (4)
  • packages/vite/test/parse-html.test.ts
  • packages/core/test/text-metrics.test.ts
  • packages/core/test/seo-length-rules.test.ts
  • packages/core/src/rules/seo/seo022-023.ts

@oekazuma
oekazuma merged commit 94839a2 into main Jun 26, 2026
5 checks passed
@oekazuma
oekazuma deleted the feat/seo-title-description-length branch June 26, 2026 07:08
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.

2 participants