Skip to content

Conversation

@magic-akari
Copy link
Contributor

Implement the ability to format specific ranges of CSS code instead of entire files, enabling editor integrations where users can select and format only portions of code.

Implement the ability to format specific ranges of CSS code instead of entire files,
enabling editor integrations where users can select and format only portions of code.
@magic-akari magic-akari marked this pull request as ready for review January 2, 2026 15:44
Copilot AI review requested due to automatic review settings January 2, 2026 15:44
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR implements range formatting functionality for Malva, enabling users to format specific portions of CSS/SCSS/Sass/Less code rather than entire files. This is particularly valuable for editor integrations where users select and format only a portion of their code.

Key changes:

  • Implements format_range function that intelligently expands selections to complete syntactic units (statements or declarations)
  • Calculates and preserves base indentation levels for formatted ranges
  • Adds comprehensive test suite with snapshot testing across multiple CSS dialects

Reviewed changes

Copilot reviewed 19 out of 19 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
malva/src/range.rs Core implementation of range formatting logic with node detection and indent calculation
malva/src/lib.rs Exports public API for format_range function and FormatRangeResult type
malva/src/error.rs Adds RangeOutOfBounds error variant for range validation
malva/tests/fmt_range.rs Comprehensive test suite including unit tests and snapshot tests
malva/tests/fmt_range/**/*.{css,scss,less} Test fixtures for range formatting
malva/tests/fmt_range/**/*.range Range specification files for test cases
malva/tests/fmt_range/**/*.snap Expected output snapshots for test cases

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

// Wrap with base indent
let doc = doc.nest(base_indent);

// Print => doc
Copy link

Copilot AI Jan 2, 2026

Choose a reason for hiding this comment

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

The comment "Print => doc" appears to be backwards or confusing. It should likely say "Print doc" or "Print the doc" since this is converting the doc to a string, not converting print to doc.

Suggested change
// Print => doc
// Print doc

Copilot uses AI. Check for mistakes.

let output = format_range(&input, start..end, syntax, &options).unwrap();
let output = {
let mut result = input.clone();
Copy link

Copilot AI Jan 2, 2026

Choose a reason for hiding this comment

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

The variable input is a string slice, so calling .clone() on line 119 is unnecessary and potentially misleading. Since input is an &str, you should use .to_string() or just construct the result directly without the intermediate clone.

Suggested change
let mut result = input.clone();
let mut result = input.to_string();

Copilot uses AI. Check for mistakes.
fn find_range_node<'a, 's>(
stylesheet: &'a Stylesheet<'s>,
range: &Range<usize>,
_source: &str,
Copy link

Copilot AI Jan 2, 2026

Choose a reason for hiding this comment

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

The parameter _source is prefixed with an underscore indicating it's unused, but it's included in the function signature. If this parameter is genuinely not needed, it should be removed to avoid confusion. If it's kept for future use or consistency, a comment explaining why would be helpful.

Suggested change
_source: &str,
_source: &str, // kept for API compatibility / potential future use; intentionally unused

Copilot uses AI. Check for mistakes.

}
@function grid-width($n) {
@return $very-very-very-very-very-very-vey-long-var * $very-very-very-very-very-very-vey-long-var + ($very-very-very-very-very-very-vey-long-var - 1) * $very-very-very-very-very-very-vey-long-var;
Copy link

Copilot AI Jan 2, 2026

Choose a reason for hiding this comment

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

The word "vey" appears to be a typo and should be "very". This typo is repeated multiple times in this line.

Copilot uses AI. Check for mistakes.

}
@function grid-width($n) {
@return $very-very-very-very-very-very-vey-long-var * $very-very-very-very-very-very-vey-long-var + ($very-very-very-very-very-very-vey-long-var - 1) * $very-very-very-very-very-very-vey-long-var;
Copy link

Copilot AI Jan 2, 2026

Choose a reason for hiding this comment

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

The word "vey" appears to be a typo and should be "very". This typo is repeated multiple times in this line.

Copilot uses AI. Check for mistakes.

/// Represents a node or a list of sibling nodes that should be formatted together.
enum RangeNode<'a, 's> {
/// No formatable node found in the range.
Copy link

Copilot AI Jan 2, 2026

Choose a reason for hiding this comment

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

The word "formatable" should be spelled "formattable" with double 't'.

Suggested change
/// No formatable node found in the range.
/// No formattable node found in the range.

Copilot uses AI. Check for mistakes.
/// - A single node that completely contains the range, or
/// - Multiple sibling nodes that together contain the range
///
/// For CSS, the minimum formatable unit is a "line-level" node:
Copy link

Copilot AI Jan 2, 2026

Choose a reason for hiding this comment

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

The word "formatable" should be spelled "formattable" with double 't'.

Suggested change
/// For CSS, the minimum formatable unit is a "line-level" node:
/// For CSS, the minimum formattable unit is a "line-level" node:

Copilot uses AI. Check for mistakes.
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