Skip to content

[@tailwindcss/upgrade] Don’t migrate inline style properties#19918

Merged
RobinMalfait merged 5 commits into
tailwindlabs:mainfrom
dbpolito:fix/ignore-inline-style-candidates
Apr 29, 2026
Merged

[@tailwindcss/upgrade] Don’t migrate inline style properties#19918
RobinMalfait merged 5 commits into
tailwindlabs:mainfrom
dbpolito:fix/ignore-inline-style-candidates

Conversation

@dbpolito

@dbpolito dbpolito commented Apr 8, 2026

Copy link
Copy Markdown
Contributor

Prevent the upgrade tool from rewriting CSS properties inside inline style attributes.

This fixes cases like style="flex-grow: 1" being changed to style="grow: 1" and adds regression tests.

@dbpolito dbpolito requested a review from a team as a code owner April 8, 2026 00:59
@coderabbitai

coderabbitai Bot commented Apr 8, 2026

Copy link
Copy Markdown
Contributor

Walkthrough

The codemod package was updated to avoid migrating CSS declarations inside inline style/:style attribute values. Tests were added covering flex-grow: 1 and flex-shrink: 0 cases inside HTML/Vue style attributes. The isSafeMigration logic now computes surrounding line context earlier, adds a cached helper to locate inline style value ranges, and returns false when a candidate is located within a quoted inline style. A changelog entry documents this change.

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the main change: preventing migration of inline style properties in the Tailwind upgrade tool.
Description check ✅ Passed The description is directly related to the changeset, explaining the fix for inline style attributes and mentioning the addition of regression tests.
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.


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
Review rate limit: 7/8 reviews remaining, refill in 7 minutes and 30 seconds.

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

@afurm

afurm commented Apr 13, 2026

Copy link
Copy Markdown

The INLINE_STYLE_ATTRIBUTE regex only matches against currentLineBeforeCandidate, but what about multi-line style attributes where a CSS property wraps to the next line? E.g. style="flex-grow:\n1" — the candidate grow would appear on a line that doesn't have the style= prefix.

@RobinMalfait

Copy link
Copy Markdown
Member

@afurm is that an actual issue you have in your projects?

- treat inline style attributes as unsafe migration contexts
- avoid misclassifying CSS property names like flex-grow and flex-shrink
- add regression coverage for inline style attribute cases
- skip inline style attribute values before candidate parsing
- prevent CSS property names like flex-grow from being treated as utilities
- keep template migration safety checks focused on actual class-like content
@RobinMalfait RobinMalfait force-pushed the fix/ignore-inline-style-candidates branch from 964fc54 to 6a50128 Compare April 29, 2026 12:33

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

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

Inline comments:
In `@packages/`@tailwindcss-upgrade/src/codemods/template/is-safe-migration.ts:
- Line 23: The INLINE_STYLE_ATTRIBUTE regex and checks around
currentLineBeforeCandidate in is-safe-migration.ts are too strict (they expect
the opening quote to be the end of the tested string) and miss cases where the
style value begins with whitespace or a newline; update the detection so the
pattern that detects a style attribute (INLINE_STYLE_ATTRIBUTE) matches an
opening quote followed optionally by whitespace/newline (or simply match style=
followed by a quote without anchoring to the end) and adjust the logic in the
function referencing currentLineBeforeCandidate to use that relaxed match; add
regression tests for "<div style=\"  flex-grow: 1\"></div>" and "<div style=\"\n
flex-grow: 1\"></div>" to verify the migration no longer rewrites inside inline
style values.
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 621b1e93-d321-4c07-8613-c72bf9b0a701

📥 Commits

Reviewing files that changed from the base of the PR and between 964fc54 and 6a50128.

📒 Files selected for processing (2)
  • packages/@tailwindcss-upgrade/src/codemods/template/is-safe-migration.test.ts
  • packages/@tailwindcss-upgrade/src/codemods/template/is-safe-migration.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/@tailwindcss-upgrade/src/codemods/template/is-safe-migration.test.ts

Comment thread packages/@tailwindcss-upgrade/src/codemods/template/is-safe-migration.ts Outdated

@RobinMalfait RobinMalfait left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks! I also added some additional tests to make sure that multi-line style attributes don't get migrated either.

@RobinMalfait RobinMalfait enabled auto-merge (squash) April 29, 2026 13:13

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🧹 Nitpick comments (1)
packages/@tailwindcss-upgrade/src/codemods/template/is-safe-migration.test.ts (1)

51-54: Add a direct :style regression case

These new tests cover style=... well, but not the :style branch that the matcher also supports. A single :style case would harden this fix against regressions.

Suggested test additions
     [`<div style="flex-grow: 1"></div>\n`, 'flex-grow'],
     [`<div style='flex-shrink: 0'></div>\n`, 'flex-shrink'],
     [`<div style="  flex-shrink: 0"></div>\n`, 'flex-shrink'],
     [`<div style="\nflex-shrink: 0\n"></div>\n`, 'flex-shrink'],
+    [`<div :style="'flex-grow: 1'"></div>\n`, 'flex-grow'],
+    [`<div :style="{ 'flex-shrink': 0 }"></div>\n`, 'flex-shrink'],
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@packages/`@tailwindcss-upgrade/src/codemods/template/is-safe-migration.test.ts
around lines 51 - 54, Add a regression test for the matcher’s :style branch by
inserting a single test case into the existing test array in
is-safe-migration.test.ts that mirrors one of the existing style= cases but uses
the :style attribute form (so the matcher that handles ":style" is exercised);
ensure the new entry asserts the same token (e.g., 'flex-grow' or 'flex-shrink')
and follows the same array structure and newline formatting as the surrounding
tests.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/`@tailwindcss-upgrade/src/codemods/template/is-safe-migration.ts:
- Around line 283-285: The tag-end search using source.indexOf('>') (near
variables tagStart and tagEnd) is quote-unaware and can stop on a '>' inside a
quoted attribute value; replace it with a quote-aware scanner (or small helper
like findTagEnd) that walks from tagStart+1, tracks single- and double-quote
states and escapes, and only returns the '>' when not inside quotes; update both
occurrences (the tagEnd calculation at tagStart and the similar code around
lines 360-362) to use this scanner so inline style attributes aren't mis-parsed
and ranges remain valid.

---

Nitpick comments:
In
`@packages/`@tailwindcss-upgrade/src/codemods/template/is-safe-migration.test.ts:
- Around line 51-54: Add a regression test for the matcher’s :style branch by
inserting a single test case into the existing test array in
is-safe-migration.test.ts that mirrors one of the existing style= cases but uses
the :style attribute form (so the matcher that handles ":style" is exercised);
ensure the new entry asserts the same token (e.g., 'flex-grow' or 'flex-shrink')
and follows the same array structure and newline formatting as the surrounding
tests.
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 1b53abb3-a119-4b91-96cb-c9519b720fca

📥 Commits

Reviewing files that changed from the base of the PR and between 6a50128 and f16391d.

📒 Files selected for processing (3)
  • CHANGELOG.md
  • packages/@tailwindcss-upgrade/src/codemods/template/is-safe-migration.test.ts
  • packages/@tailwindcss-upgrade/src/codemods/template/is-safe-migration.ts
✅ Files skipped from review due to trivial changes (1)
  • CHANGELOG.md

Comment on lines +283 to +285
let tagEnd = source.indexOf('>', tagStart + 1)
if (tagEnd === -1) return ranges

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.

⚠️ Potential issue | 🟠 Major

Quote-unaware tag-end scan can miss inline style ranges

At Line 283, source.indexOf('>') can stop at a > inside a quoted attribute value. Then Line 361 treats the value as invalid and exits early, so candidates inside inline style can still be migrated.

Proposed fix
+function findTagEnd(source: string, from: number): number {
+  let quote: number | null = null
+  for (let i = from; i < source.length; i++) {
+    let char = source.charCodeAt(i)
+
+    if (quote === null) {
+      if (char === SINGLE_QUOTE || char === DOUBLE_QUOTE) {
+        quote = char
+      } else if (char === GREATER_THAN) {
+        return i
+      }
+      continue
+    }
+
+    if (char === quote) {
+      quote = null
+    }
+  }
+
+  return -1
+}
+
 const inlineStyleAttributeValueRanges = new DefaultMap((source: string) => {
   let ranges: number[] = []
   let offset = 0
@@
-    let tagEnd = source.indexOf('>', tagStart + 1)
+    let tagEnd = findTagEnd(source, tagStart + 1)
     if (tagEnd === -1) return ranges

Also applies to: 360-362

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

In `@packages/`@tailwindcss-upgrade/src/codemods/template/is-safe-migration.ts
around lines 283 - 285, The tag-end search using source.indexOf('>') (near
variables tagStart and tagEnd) is quote-unaware and can stop on a '>' inside a
quoted attribute value; replace it with a quote-aware scanner (or small helper
like findTagEnd) that walks from tagStart+1, tracks single- and double-quote
states and escapes, and only returns the '>' when not inside quotes; update both
occurrences (the tagEnd calculation at tagStart and the similar code around
lines 360-362) to use this scanner so inline style attributes aren't mis-parsed
and ranges remain valid.

@RobinMalfait RobinMalfait merged commit ba66740 into tailwindlabs:main Apr 29, 2026
9 checks passed
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.

3 participants