# Test with various patternstest_cases ='''# Simple stringdiv1 = Div(cls="flex items-center justify-between")# Multiple classes in one stringdiv2 = Div(cls="bg-blue-500 text-white px-4 py-2 rounded-lg")# String concatenationdiv3 = Div(cls="flex " + "items-center")# Empty clsdiv4 = Div(cls="")# combine_classes with mixed contentdiv5 = Div(cls=combine_classes( "absolute", "top-0", p(4), # This is already using the library "bg-white"))'''patterns = scan_python_code(test_cases)print(f"Found {len(patterns)} patterns in test cases:\n")for i, pattern inenumerate(patterns, 1):print(f"Pattern {i}: Line {pattern.line_number}")print(f" CSS Classes: {pattern.css_classes}")print(f" Expression: {pattern.full_expression}")print()
Found 5 patterns in test cases:
Pattern 1: Line 3
CSS Classes: ['flex', 'items-center', 'justify-between']
Expression: 'flex items-center justify-between'
Pattern 2: Line 6
CSS Classes: ['bg-blue-500', 'text-white', 'px-4', 'py-2', 'rounded-lg']
Expression: 'bg-blue-500 text-white px-4 py-2 rounded-lg'
Pattern 3: Line 9
CSS Classes: ['flex', 'items-center']
Expression: 'flex ' + 'items-center'
Pattern 4: Line 12
CSS Classes: []
Expression: ''
Pattern 5: Line 15
CSS Classes: ['absolute', 'top-0', 'bg-white']
Expression: combine_classes('absolute', 'top-0', p(4), 'bg-white')
Display Utilities
Functions to display scan results:
display_patterns
def display_patterns( patterns:List, # List of ClsPattern objects to display show_context:bool=True, # Whether to show the code context):
Display found patterns in a formatted way.
get_unique_css_classes
def get_unique_css_classes( patterns:List, # List of ClsPattern objects)->Set: # Set of unique CSS class strings
Extract all unique CSS classes from a list of patterns.
# Test the display function with the original examplepatterns = scan_python_code(test_code)display_patterns(patterns)
Represents a pattern extracted from a test assertion.
get_available_css_classes
def get_available_css_classes( assertion_patterns:List, # List of assertion patterns from test examples)->Set: # Set of unique CSS class strings available in the library
Extract all unique CSS classes from assertion patterns. This handles multi-class assertion strings by splitting them.
extract_assertion_patterns
def extract_assertion_patterns( source_code:str, # Source code of the test function module_name:str, # Name of the module containing the test example_name:str, # Name of the test function)->List: # List of AssertionPattern objects
Extract assertion patterns from test example source code.
collect_all_assertion_patterns
def collect_all_assertion_patterns()->List: # List of AssertionPattern objects from all modules
Collect assertion patterns from all test examples in the library.
def tokenize_css_class( css_class:str, # CSS class string (e.g., "bg-blue-500" or "hover:text-white"))->List: # List of tokens (e.g., ["bg", "blue", "500"] or ["hover:text", "white"])
Tokenize a CSS class by splitting on hyphens. Handles modifiers (hover:, focus:, etc.) separately.
find_pattern_matches
def find_pattern_matches( css_class:str, # CSS class to match (e.g., "px-8" or "hover:text-white") available_classes:Set, # Set of available CSS classes from the library)->Tuple: # Tuple of (matched_pattern, similar_classes) - matched_pattern: Pattern prefix that matches (e.g., "px" for "px-8") - similar_classes: List of similar classes with the same pattern
Find pattern matches for a CSS class by progressively reducing tokens.
match_css_class
def match_css_class( css_class:str, # CSS class to match available_classes:Set, # Set of available CSS classes from the library)->CSSClassMatch: # CSSClassMatch object with match details
Match a CSS class against available library classes.
match_css_classes
def match_css_classes( css_classes:List, # List of CSS classes to match available_classes:Set, # Set of available CSS classes from the library)->Dict: # Dictionary mapping CSS classes to their match results
Match multiple CSS classes against available library classes.
display_match_results
def display_match_results( matches:Dict, # Dictionary of CSS classes to their match results):
Display match results in a formatted way.
analyze_code_patterns
def analyze_code_patterns( code:str, # Python source code to analyze)->Dict: # Dictionary with analysis results including patterns found and suggestions
Analyze Python code for replaceable CSS patterns.
display_code_analysis
def display_code_analysis( code:str, # Python source code to analyze):
Analyze and display replaceable patterns in Python code.
Migration Suggestions
Functions to provide migration suggestions based on test examples:
find_assertion_for_class
def find_assertion_for_class( css_class:str, # The CSS class to find (e.g., "px-6") assertion_patterns:List, # List of all assertion patterns from tests)->Optional: # AssertionPattern if found, None otherwise
Find the assertion pattern that demonstrates how to use a specific CSS class. Prioritizes exact single-class matches over multi-class assertions.
find_pattern_examples
def find_pattern_examples( pattern_prefix:str, # Pattern prefix to match (e.g., "px" for px-* pattern) assertion_patterns:List, # List of all assertion patterns from tests)->List: # List of AssertionPattern objects that match the pattern
Find assertion examples that match a pattern prefix.
get_migration_suggestions
def get_migration_suggestions( matches:Dict, # Dictionary of CSS class matches assertion_patterns:List, # List of all assertion patterns from tests config:Optional=None, # Optional configuration)->Dict: # Dictionary mapping CSS classes to their migration suggestions
Generate migration suggestions for matched CSS classes.
display_migration_suggestions
def display_migration_suggestions( code:str, # Python source code to analyze):
Analyze code and display migration suggestions.
analyze_and_suggest
def analyze_and_suggest( code:str, # Python source code to analyze):
Perform complete analysis of code with migration suggestions.
# Get available classes from assertionsassertion_patterns = collect_all_assertion_patterns()available_classes = get_available_css_classes(assertion_patterns)# Test with the example from the original test codetest_css_classes = ["flex", "font-bold", "items-center", "px-6", "py-4"]print("\nTesting CSS class matching:")print("="*60)for css_class in test_css_classes: match_result = match_css_class(css_class, available_classes)print(f"\nClass: '{css_class}'")print(f" Match Type: {match_result.match_type.value}")if match_result.match_type == MatchType.EXACT:print(f" ✓ Exact match found")elif match_result.match_type == MatchType.PATTERN:print(f" ~ Pattern match: '{match_result.matched_pattern}-*'")print(f" Similar classes: {match_result.similar_classes[:3]}...")else:print(f" ✗ No match found")
Testing CSS class matching:
============================================================
Class: 'flex'
Match Type: exact
✓ Exact match found
Class: 'font-bold'
Match Type: exact
✓ Exact match found
Class: 'items-center'
Match Type: exact
✓ Exact match found
Class: 'px-6'
Match Type: exact
✓ Exact match found
Class: 'py-4'
Match Type: exact
✓ Exact match found
# Test with more diverse CSS classesprint("\nTesting with additional CSS classes:")print("="*60)additional_test_classes = [# Should be exact matches"block", "absolute", "flex",# Should be pattern matches"px-8", "py-12", "mt-16", "gap-10", # Should be no match"font-bold", "text-blue-600", "hover:bg-gray-100",# Edge cases"-mx-4", "w-1/3", "lg:grid-cols-4"]for css_class in additional_test_classes: match_result = match_css_class(css_class, available_classes) status ="✓"if match_result.match_type == MatchType.EXACT else\"~"if match_result.match_type == MatchType.PATTERN else"✗"print(f"{status}{css_class:<20} → {match_result.match_type.value:<10}", end="")if match_result.matched_pattern:print(f" (pattern: {match_result.matched_pattern})")else:print()
# Test batch matching with the original exampleprint("\nBatch matching for original example:")print("="*60)# Extract unique CSS classes from the test codepatterns = scan_python_code(test_code)unique_classes_in_code = get_unique_css_classes(patterns)# Match all classesmatches = match_css_classes(list(unique_classes_in_code), available_classes)# Display resultsdisplay_match_results(matches)
Batch matching for original example:
============================================================
CSS Class Analysis Results:
============================================================
✓ Exact Matches (5):
- flex
- font-bold
- items-center
- px-6
- py-4
Summary: 5/5 classes are potentially replaceable
# Test complete code analysisprint("Complete Code Analysis:")print()display_code_analysis(test_code)
# Test migration suggestions with original exampleprint("Migration Suggestions for Original Example:")print()display_migration_suggestions(test_code)
Migration Suggestions for Original Example:
Migration Suggestions
============================================================
✓ flex:
→ View example: cjm-tailwind-explore example flexbox_and_grid display
✓ font-bold:
→ View example: cjm-tailwind-explore example typography font_weight
✓ items-center:
→ View example: cjm-tailwind-explore example flexbox_and_grid align
✓ px-6:
→ View example: cjm-tailwind-explore example spacing helper
→ View helper: cjm-tailwind-explore helper spacing pad
✓ py-4:
→ View example: cjm-tailwind-explore example spacing helper
→ View helper: cjm-tailwind-explore helper spacing pad
# Test with complex exampleprint("\n\nMigration Suggestions for Complex Example:")print()display_migration_suggestions(complex_example)
Migration Suggestions for Complex Example:
Migration Suggestions
============================================================
~ bg-blue-600:
→ Pattern example 1: cjm-tailwind-explore example backgrounds color
→ Pattern example 2: cjm-tailwind-explore example backgrounds opacity
✓ flex:
→ View example: cjm-tailwind-explore example flexbox_and_grid display
✓ flex-col:
→ View example: cjm-tailwind-explore example flexbox_and_grid direction
✓ font-bold:
→ View example: cjm-tailwind-explore example typography font_weight
✓ items-center:
→ View example: cjm-tailwind-explore example flexbox_and_grid align
✓ justify-center:
→ View example: cjm-tailwind-explore example flexbox_and_grid justify
✓ mb-4:
→ View example: cjm-tailwind-explore example spacing margin_directional
~ mb-8:
→ Pattern example 1: cjm-tailwind-explore example spacing margin_directional
✓ min-h-screen:
→ View example: cjm-tailwind-explore example sizing min_height
~ px-4:
→ Pattern example 1: cjm-tailwind-explore example spacing directional
→ Pattern example 2: cjm-tailwind-explore example spacing helper
✓ px-8:
→ View example: cjm-tailwind-explore example spacing directional
~ py-3:
→ Pattern example 1: cjm-tailwind-explore example spacing directional
→ Pattern example 2: cjm-tailwind-explore example spacing helper
✓ rounded-lg:
→ View example: cjm-tailwind-explore example borders radius
✓ text-6xl:
→ View example: cjm-tailwind-explore example typography font_size
~ text-gray-600:
→ Pattern example 1: cjm-tailwind-explore example typography text_color
~ text-gray-900:
→ Pattern example 1: cjm-tailwind-explore example typography text_color
✓ text-white:
→ View example: cjm-tailwind-explore example typography text_color
✓ text-xl:
→ View example: cjm-tailwind-explore example typography font_size
# Test analysis and migration suggestions with original exampleprint("Analysis & Migration Suggestions for Original Example:")print()analyze_and_suggest(test_code)
Analysis & Migration Suggestions for Original Example:
Code Analysis Report
============================================================
Total cls= patterns found: 3
Unique CSS classes: 5
Replaceable Classes: 5/5
- Exact matches: 5
- Pattern matches: 0
- No matches: 0
CSS Class Analysis Results:
============================================================
✓ Exact Matches (5):
- flex
- font-bold
- items-center
- px-6
- py-4
Summary: 5/5 classes are potentially replaceable
Patterns by Line:
------------------------------------------------------------
Line 12: ✓ combine_classes('flex', justify.between, items.center, 'px-6', 'py-4', 'items-center')
↳ Already uses combine_classes
Line 6: ✓ 'font-bold'
Line 9: ✓ combine_classes('flex', gap(4))
↳ Already uses combine_classes
Migration Suggestions
============================================================
✓ flex:
→ View example: cjm-tailwind-explore example flexbox_and_grid display
✓ font-bold:
→ View example: cjm-tailwind-explore example typography font_weight
✓ items-center:
→ View example: cjm-tailwind-explore example flexbox_and_grid align
✓ px-6:
→ View example: cjm-tailwind-explore example spacing helper
→ View helper: cjm-tailwind-explore helper spacing pad
✓ py-4:
→ View example: cjm-tailwind-explore example spacing helper
→ View helper: cjm-tailwind-explore helper spacing pad
File Input Support
Functions to scan Python files and Jupyter notebooks:
scan_python_file
def scan_python_file( file_path:str, # Path to the Python file)->List: # List of ClsPattern objects found in the file
Scan a Python file for cls= patterns.
scan_jupyter_notebook
def scan_jupyter_notebook( notebook_path:str, # Path to the Jupyter notebook (.ipynb))->List: # List of ClsPattern objects found in the notebook
Scan a Jupyter notebook for cls= patterns.
detect_input_type
def detect_input_type( input_source:str, # Code string or file path)->InputType: # InputType enum value
Detect the type of input based on the source string.
def scan_input( input_source:str, # Code string, Python file path, or notebook path input_type:Optional=None, # Optional explicit input type. If None, will auto-detect.)->List: # List of ClsPattern objects found
Scan various input types for cls= patterns.
analyze_input
def analyze_input( input_source:str, # Code string, Python file path, or notebook path input_type:Optional=None, # Optional explicit input type. If None, will auto-detect.)->Dict: # Dictionary with analysis results
Analyze any input type for replaceable CSS patterns.
display_input_analysis
def display_input_analysis( input_source:str, # Code string, Python file path, or notebook path input_type:Optional=None, # Optional explicit input type. If None, will auto-detect.):
Analyze and display replaceable patterns from any input type.
analyze_and_suggest_input
def analyze_and_suggest_input( input_source:str, # Code string, Python file path, or notebook path input_type:Optional=None, # Optional explicit input type. If None, will auto-detect.):
Perform complete analysis with migration suggestions for any input type.
Testing File Input Support
Test the unified interface with different input types:
# Test auto-detection of input typestest_inputs = ['print("hello")', # Code string'example.py', # Python file'notebook.ipynb', # Jupyter notebook'/path/to/file.py', # Full path'Some("code", cls="flex")'# Code with cls]print("Testing input type detection:")for inp in test_inputs: detected = detect_input_type(inp)print(f" '{inp}' → {detected.value}")