Skip to content

Conversation

@thecrypticace
Copy link
Contributor

Fixes #19239

@thecrypticace thecrypticace marked this pull request as ready for review October 31, 2025 18:21
@thecrypticace thecrypticace requested a review from a team as a code owner October 31, 2025 18:21
Comment on lines +81 to +119
b'"' => {
cursor.advance();

while cursor.pos < len {
match cursor.curr {
// Escaped character, skip ahead to the next character
b'\\' => cursor.advance_twice(),

// End of the string
b'"' => break,

// Everything else is valid
_ => cursor.advance(),
};
}

cursor.advance();
continue;
}

b'\'' => {
cursor.advance();

while cursor.pos < len {
match cursor.curr {
// Escaped character, skip ahead to the next character
b'\\' => cursor.advance_twice(),

// End of the string
b'\'' => break,

// Everything else is valid
_ => cursor.advance(),
};
}

cursor.advance();
continue;
}
Copy link
Member

Choose a reason for hiding this comment

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

Can we add some tests where we handle quotes? We have to be careful with these because it could be that you start a sentence with a ' in it and never close it.

%p a quote here can't exist, or can it 
-#
  This won't be displayed (there is a quote here as well)
    Nor will this
                   Nor will this.
%p a quote here can't exist, or can it

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've added tests and updated the implementation a bit

@coderabbitai
Copy link

coderabbitai bot commented Nov 11, 2025

Walkthrough

This pull request modifies the property extraction and preprocessing logic in the Oxide crate. The arbitrary property machine parser adds handling for top-level exclamation marks, introducing a new Exclamation variant to the Class enum and logic to treat "!important" as a termination condition in arbitrary property values. The Ruby pre-processor is reworked to explicitly handle string literals and comments with stateful parsing, replacing the previous simplistic %w/%W check with improved boundary handling. Additionally, a HAML test fixture is updated by removing variable declarations and annotation lines.

Pre-merge checks

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Out of Scope Changes check ❓ Inconclusive The addition of Exclamation handling in arbitrary_property_machine.rs appears to be addressing related edge cases with exclamation marks and !important CSS values, extending the fix scope. Clarify whether the arbitrary_property_machine.rs changes are necessary for fixing issue #19239 or represent separate scope creep unrelated to Ruby comment handling.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: handling Ruby comments in the pre-processor to prevent parsing warnings from comment content.
Description check ✅ Passed The description references the linked issue #19239, which is directly related to the changeset addressing RDoc patterns and parsing warnings in Ruby files.
Linked Issues check ✅ Passed The changes improve Ruby pre-processor to skip comments and handle strings, addressing the root cause of parsing warnings from RDoc documentation patterns in Rails gem source files.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

Copy link

@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: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3cece1d and c19d255.

📒 Files selected for processing (3)
  • crates/oxide/src/extractor/arbitrary_property_machine.rs (3 hunks)
  • crates/oxide/src/extractor/pre_processors/ruby.rs (5 hunks)
  • crates/oxide/src/extractor/pre_processors/test-fixtures/haml/dst-17051.haml (0 hunks)
💤 Files with no reviewable changes (1)
  • crates/oxide/src/extractor/pre_processors/test-fixtures/haml/dst-17051.haml
🧰 Additional context used
🧬 Code graph analysis (1)
crates/oxide/src/extractor/pre_processors/ruby.rs (2)
crates/oxide/src/extractor/candidate_machine.rs (1)
  • next (29-169)
crates/oxide/src/extractor/string_machine.rs (1)
  • next (32-68)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Linux
  • GitHub Check: Linux / postcss
  • GitHub Check: Linux / vite
  • GitHub Check: Linux / upgrade

Comment on lines +237 to +244
if cursor.input[cursor.pos..].starts_with(b"!important]") {
cursor.advance_by(10);

return self.done(self.start_pos, cursor);
}

return self.restart();
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Handle !important case-insensitively.

starts_with(b"!important]") now rejects valid ASCII-insensitive variants like [color:red!IMPORTANT], which CSS accepts and the prior implementation extracted. Please keep the comparison case-insensitive so we don’t regress these inputs.

Apply this diff to make the comparison ASCII-insensitive:

-                    if cursor.input[cursor.pos..].starts_with(b"!important]") {
-                        cursor.advance_by(10);
+                    const IMPORTANT: &[u8; 10] = b"!important";
+                    let remaining = &cursor.input[cursor.pos..];
+
+                    if remaining.len() >= IMPORTANT.len() + 1
+                        && remaining[IMPORTANT.len()] == b']'
+                        && remaining[..IMPORTANT.len()]
+                            .iter()
+                            .zip(IMPORTANT)
+                            .all(|(byte, expected)| byte.to_ascii_lowercase() == *expected)
+                    {
+                        cursor.advance_by(IMPORTANT.len());

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In crates/oxide/src/extractor/arbitrary_property_machine.rs around lines
237-244, the code currently uses starts_with(b"!important]") which is
case-sensitive; replace it with an ASCII-insensitive check by first ensuring the
remaining slice has at least 10 bytes (use get(..10) or a bounds check), then
compare each byte lowercased (byte.to_ascii_lowercase()) against the literal
b"!important]" (or lowercased literal) — if they all match, advance by 10 and
call done(...), otherwise restart; this preserves ASCII case-insensitivity and
avoids panics on short slices.

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.

Tailwind v4 parsing warnings when scanning Rails gem source files on Heroku

3 participants