Home / Function/ next() — tailwindcss Function Reference

next() — tailwindcss Function Reference

Architecture documentation for the next() function in candidate_machine.rs from the tailwindcss codebase.

Entity Profile

Dependency Diagram

graph TD
  e98f75c7_be5d_2b5f_4edb_c53b52a5b951["next()"]
  a7ef7f76_8e61_0bbd_dd62_df9fa5af59c2["reset()"]
  e98f75c7_be5d_2b5f_4edb_c53b52a5b951 -->|calls| a7ef7f76_8e61_0bbd_dd62_df9fa5af59c2
  25880039_5fa6_1766_4f96_aee283033329["done_span()"]
  e98f75c7_be5d_2b5f_4edb_c53b52a5b951 -->|calls| 25880039_5fa6_1766_4f96_aee283033329
  35b2adf8_a27b_5aee_3865_21fb048c97fb["advance()"]
  e98f75c7_be5d_2b5f_4edb_c53b52a5b951 -->|calls| 35b2adf8_a27b_5aee_3865_21fb048c97fb
  1d9f0587_3ee2_e78a_02be_cdc4a682af31["advance_by()"]
  e98f75c7_be5d_2b5f_4edb_c53b52a5b951 -->|calls| 1d9f0587_3ee2_e78a_02be_cdc4a682af31
  95863211_f6f6_7fff_0253_53a5f33740d9["move_to()"]
  e98f75c7_be5d_2b5f_4edb_c53b52a5b951 -->|calls| 95863211_f6f6_7fff_0253_53a5f33740d9
  style e98f75c7_be5d_2b5f_4edb_c53b52a5b951 fill:#6366f1,stroke:#818cf8,color:#fff

Relationship Graph

Source Code

crates/oxide/src/extractor/candidate_machine.rs lines 29–169

    fn next(&mut self, cursor: &mut cursor::Cursor<'_>) -> MachineState {
        let len = cursor.input.len();

        while cursor.pos < len {
            // Skip ahead for known characters that will never be part of a candidate. No need to
            // run any sub-machines.
            if cursor.curr.is_ascii_whitespace() {
                self.reset();
                cursor.advance();
                continue;
            }

            // Candidates don't start with these characters, so we can skip ahead.
            if matches!(cursor.curr, b':' | b'"' | b'\'' | b'`') {
                self.reset();
                cursor.advance();
                continue;
            }

            // Jump ahead if the character is known to be an invalid boundary and we should start
            // at the next boundary even though "valid" candidates can exist.
            //
            // E.g.: `<div class="">`
            //         ^^^            Valid candidate
            //        ^               But this character makes it invalid
            //             ^          Therefore we jump here
            //
            // E.g.: `Some Class`
            //        ^    ^       Invalid, we can jump ahead to the next boundary
            //
            if matches!(cursor.curr, b'<' | b'A'..=b'Z') {
                if let Some(offset) = cursor.input[cursor.pos..]
                    .iter()
                    .position(|&c| is_valid_before_boundary(&c))
                {
                    self.reset();
                    cursor.advance_by(offset + 1);
                } else {
                    return self.restart();
                }

                continue;
            }

            let mut variant_cursor = cursor.clone();
            let variant_machine_state = self.variant_machine.next(&mut variant_cursor);

            let mut utility_cursor = cursor.clone();
            let utility_machine_state = self.utility_machine.next(&mut utility_cursor);

            match (variant_machine_state, utility_machine_state) {
                // No variant, but the utility machine completed
                (MachineState::Idle, MachineState::Done(utility_span)) => {
                    cursor.move_to(utility_cursor.pos + 1);

                    let span = match self.last_variant_end_pos {
                        Some(end_pos) => {
                            // Verify that the utility is touching the last variant
                            if end_pos + 1 != utility_span.start {
                                return self.restart();
                            }

                            Span::new(self.start_pos, utility_span.end)
                        }
                        None => utility_span,
                    };

                    // Ensure the span has valid boundary characters before and after
                    if !has_valid_boundaries(&span, cursor.input) {
                        return self.restart();
                    }

                    return self.done_span(span);
                }

                // Both variant and utility machines are done
                // E.g.: `hover:flex`
                //        ^^^^^^      Variant
                //        ^^^^^       Utility
                //
                (MachineState::Done(variant_span), MachineState::Done(utility_span)) => {
                    cursor.move_to(variant_cursor.pos + 1);

                    if let Some(end_pos) = self.last_variant_end_pos {
                        // Verify variant is touching the last variant
                        if end_pos + 1 != variant_span.start {
                            return self.restart();
                        }
                    } else {
                        // We know that there is no variant before this one.
                        //
                        // Edge case: JavaScript keys should be considered utilities if they are
                        // not preceded by another variant, and followed by any kind of whitespace
                        // or the end of the line.
                        //
                        // E.g.: `{ underline: true }`
                        //          ^^^^^^^^^^        Variant
                        //          ^^^^^^^^^         Utility (followed by `: `)
                        let after = cursor.input.get(utility_span.end + 2).unwrap_or(&b'\0');
                        if after.is_ascii_whitespace() || *after == b'\0' {
                            cursor.move_to(utility_cursor.pos + 2);
                            return self.done_span(utility_span);
                        }

                        self.start_pos = variant_span.start;
                    }

                    self.last_variant_end_pos = Some(variant_cursor.pos);
                }

                // Variant is done, utility is invalid
                (MachineState::Done(variant_span), MachineState::Idle) => {
                    cursor.move_to(variant_cursor.pos + 1);

                    if let Some(end_pos) = self.last_variant_end_pos {
                        if end_pos + 1 > variant_span.start {
                            self.reset();
                            return MachineState::Idle;
                        }
                    } else {
                        self.start_pos = variant_span.start;
                    }

                    self.last_variant_end_pos = Some(variant_cursor.pos);
                }

                (MachineState::Idle, MachineState::Idle) => {
                    // Skip main cursor to the next character after both machines. We already know
                    // there is no candidate here.
                    if variant_cursor.pos > cursor.pos || utility_cursor.pos > cursor.pos {
                        cursor.move_to(variant_cursor.pos.max(utility_cursor.pos));
                    }

                    self.reset();
                    cursor.advance();
                }
            }
        }

        MachineState::Idle
    }

Domain

Subdomains

Frequently Asked Questions

What does next() do?
next() is a function in the tailwindcss codebase.
What does next() call?
next() calls 5 function(s): advance, advance_by, done_span, move_to, reset.

Analyze Your Own Codebase

Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.

Try Supermodel Free