cataract 0.2.1 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -32,10 +32,21 @@ VALUE eSizeError;
32
32
  * This matches the old parse_css API
33
33
  *
34
34
  * @param css_string [String] CSS to parse
35
+ * @param parser_options [Hash] Parser options (optional, defaults to {})
35
36
  * @return [Hash] { rules: [...], media_index: {...}, charset: "..." }
36
37
  */
37
- VALUE parse_css_new(VALUE self, VALUE css_string) {
38
- return parse_css_new_impl(css_string, 0);
38
+ VALUE parse_css_new(int argc, VALUE *argv, VALUE self) {
39
+ VALUE css_string, parser_options;
40
+
41
+ // Parse arguments: required css_string, optional parser_options hash
42
+ rb_scan_args(argc, argv, "11", &css_string, &parser_options);
43
+
44
+ // Default to empty hash if not provided
45
+ if (NIL_P(parser_options)) {
46
+ parser_options = rb_hash_new();
47
+ }
48
+
49
+ return parse_css_new_impl(css_string, parser_options, 0);
39
50
  }
40
51
 
41
52
  /*
@@ -292,6 +303,17 @@ struct build_rule_map_ctx {
292
303
  VALUE rule_to_media;
293
304
  };
294
305
 
306
+ // Formatting options for stylesheet serialization
307
+ // Avoids mode flags and if/else branches - all behavior controlled by struct values
308
+ struct format_opts {
309
+ const char *opening_brace; // " { " (compact) vs " {\n" (formatted)
310
+ const char *closing_brace; // " }\n" (compact) vs "}\n" (formatted)
311
+ const char *media_indent; // "" (compact) vs " " (formatted)
312
+ const char *decl_indent_base; // NULL (compact) vs " " (formatted base rules)
313
+ const char *decl_indent_media; // NULL (compact) vs " " (formatted media rules)
314
+ int add_blank_lines; // 0 (compact) vs 1 (formatted)
315
+ };
316
+
295
317
  // Callback to build reverse map from rule_id to media_sym
296
318
  static int build_rule_map_callback(VALUE media_sym, VALUE rule_ids, VALUE arg) {
297
319
  struct build_rule_map_ctx *ctx = (struct build_rule_map_ctx *)arg;
@@ -318,27 +340,28 @@ static int build_rule_map_callback(VALUE media_sym, VALUE rule_ids, VALUE arg) {
318
340
  return ST_CONTINUE;
319
341
  }
320
342
 
321
- // Original stylesheet serialization (no nesting support)
322
- static VALUE stylesheet_to_s_original(VALUE rules_array, VALUE media_index, VALUE charset) {
323
- Check_Type(rules_array, T_ARRAY);
324
- Check_Type(media_index, T_HASH);
325
-
326
- VALUE result = rb_str_new_cstr("");
327
-
328
- // Add charset if present
329
- if (!NIL_P(charset)) {
330
- rb_str_cat2(result, "@charset \"");
331
- rb_str_append(result, charset);
332
- rb_str_cat2(result, "\";\n");
333
- }
334
-
343
+ // Private shared implementation for stylesheet serialization with optional selector list grouping
344
+ // All formatting behavior controlled by format_opts struct to avoid mode flags and if/else branches
345
+ static VALUE serialize_stylesheet_with_grouping(
346
+ VALUE rules_array,
347
+ VALUE media_index,
348
+ VALUE result,
349
+ VALUE selector_lists,
350
+ const struct format_opts *opts
351
+ ) {
335
352
  long total_rules = RARRAY_LEN(rules_array);
336
353
 
354
+ // Check if selector list grouping is enabled (non-empty hash)
355
+ int grouping_enabled = (!NIL_P(selector_lists) && TYPE(selector_lists) == T_HASH && RHASH_SIZE(selector_lists) > 0);
356
+
337
357
  // Build a map from rule_id to media query symbol using rb_hash_foreach
338
358
  VALUE rule_to_media = rb_hash_new();
339
359
  struct build_rule_map_ctx map_ctx = { rule_to_media };
340
360
  rb_hash_foreach(media_index, build_rule_map_callback, (VALUE)&map_ctx);
341
361
 
362
+ // Track processed rules to avoid duplicates when grouping
363
+ VALUE processed_rule_ids = rb_hash_new();
364
+
342
365
  // Iterate through rules in insertion order, grouping consecutive media queries
343
366
  VALUE current_media = Qnil;
344
367
  int in_media_block = 0;
@@ -346,7 +369,14 @@ static VALUE stylesheet_to_s_original(VALUE rules_array, VALUE media_index, VALU
346
369
  for (long i = 0; i < total_rules; i++) {
347
370
  VALUE rule = rb_ary_entry(rules_array, i);
348
371
  VALUE rule_id = rb_struct_aref(rule, INT2FIX(RULE_ID));
372
+
373
+ // Skip if already processed (when grouped)
374
+ if (RTEST(rb_hash_aref(processed_rule_ids, rule_id))) {
375
+ continue;
376
+ }
377
+
349
378
  VALUE rule_media = rb_hash_aref(rule_to_media, rule_id);
379
+ int is_first_rule = (i == 0);
350
380
 
351
381
  if (NIL_P(rule_media)) {
352
382
  // Not in any media query - close any open media block first
@@ -356,8 +386,100 @@ static VALUE stylesheet_to_s_original(VALUE rules_array, VALUE media_index, VALU
356
386
  current_media = Qnil;
357
387
  }
358
388
 
359
- // Output rule directly
360
- serialize_rule(result, rule);
389
+ // Add blank line prefix for non-first rules (formatted only)
390
+ if (opts->add_blank_lines && !is_first_rule) {
391
+ rb_str_cat2(result, "\n");
392
+ }
393
+
394
+ // Try to group with other rules from same selector list
395
+ // Check if this is a Rule (not AtRule) before accessing selector_list_id
396
+ if (grouping_enabled && rb_obj_is_kind_of(rule, cRule)) {
397
+ VALUE selector_list_id = rb_struct_aref(rule, INT2FIX(RULE_SELECTOR_LIST_ID));
398
+ if (!NIL_P(selector_list_id)) {
399
+ // Get list of rule IDs in this selector list
400
+ VALUE rule_ids_in_list = rb_hash_aref(selector_lists, selector_list_id);
401
+
402
+ if (NIL_P(rule_ids_in_list) || RARRAY_LEN(rule_ids_in_list) <= 1) {
403
+ // Just this rule, serialize normally
404
+ if (opts->decl_indent_base) {
405
+ serialize_rule_formatted(result, rule, "", 1);
406
+ } else {
407
+ serialize_rule(result, rule);
408
+ }
409
+ rb_hash_aset(processed_rule_ids, rule_id, Qtrue);
410
+ } else {
411
+ // Find all rules with matching declarations and same media context
412
+ VALUE matching_selectors = rb_ary_new();
413
+ VALUE rule_declarations = rb_struct_aref(rule, INT2FIX(RULE_DECLARATIONS));
414
+
415
+ long list_len = RARRAY_LEN(rule_ids_in_list);
416
+ for (long j = 0; j < list_len; j++) {
417
+ VALUE other_rule_id = rb_ary_entry(rule_ids_in_list, j);
418
+
419
+ // Skip if already processed
420
+ if (RTEST(rb_hash_aref(processed_rule_ids, other_rule_id))) {
421
+ continue;
422
+ }
423
+
424
+ // Find the rule by ID
425
+ VALUE other_rule = rb_ary_entry(rules_array, FIX2INT(other_rule_id));
426
+ if (NIL_P(other_rule)) continue;
427
+
428
+ // Check same media context (both should be nil for base rules)
429
+ VALUE other_rule_media = rb_hash_aref(rule_to_media, other_rule_id);
430
+ if (!rb_equal(rule_media, other_rule_media)) {
431
+ continue;
432
+ }
433
+
434
+ // Check if declarations match
435
+ VALUE other_declarations = rb_struct_aref(other_rule, INT2FIX(RULE_DECLARATIONS));
436
+ if (rb_equal(rule_declarations, other_declarations)) {
437
+ VALUE other_selector = rb_struct_aref(other_rule, INT2FIX(RULE_SELECTOR));
438
+ rb_ary_push(matching_selectors, other_selector);
439
+ rb_hash_aset(processed_rule_ids, other_rule_id, Qtrue);
440
+ }
441
+ }
442
+
443
+ // Serialize grouped or single rule
444
+ if (RARRAY_LEN(matching_selectors) > 1) {
445
+ // Group selectors with comma-space separator
446
+ VALUE selector_str = rb_ary_join(matching_selectors, rb_str_new_cstr(", "));
447
+ rb_str_append(result, selector_str);
448
+ rb_str_cat2(result, opts->opening_brace);
449
+ if (opts->decl_indent_base) {
450
+ serialize_declarations_formatted(result, rule_declarations, opts->decl_indent_base);
451
+ } else {
452
+ serialize_declarations(result, rule_declarations);
453
+ }
454
+ rb_str_cat2(result, opts->closing_brace);
455
+ RB_GC_GUARD(selector_str);
456
+ } else {
457
+ // Just one rule, serialize normally
458
+ if (opts->decl_indent_base) {
459
+ serialize_rule_formatted(result, rule, "", 1);
460
+ } else {
461
+ serialize_rule(result, rule);
462
+ }
463
+ }
464
+ }
465
+ } else {
466
+ // No selector_list_id, serialize normally
467
+ if (opts->decl_indent_base) {
468
+ serialize_rule_formatted(result, rule, "", 1);
469
+ } else {
470
+ serialize_rule(result, rule);
471
+ }
472
+ rb_hash_aset(processed_rule_ids, rule_id, Qtrue);
473
+ }
474
+ } else {
475
+ // Grouping disabled, serialize normally
476
+ if (opts->decl_indent_base) {
477
+ serialize_rule_formatted(result, rule, "", 1);
478
+ } else {
479
+ serialize_rule(result, rule);
480
+ }
481
+ rb_hash_aset(processed_rule_ids, rule_id, Qtrue);
482
+ }
361
483
  } else {
362
484
  // This rule is in a media query
363
485
  // Check if media query changed from previous rule
@@ -367,6 +489,11 @@ static VALUE stylesheet_to_s_original(VALUE rules_array, VALUE media_index, VALU
367
489
  rb_str_cat2(result, "}\n");
368
490
  }
369
491
 
492
+ // Add blank line prefix for non-first rules (formatted only)
493
+ if (opts->add_blank_lines && !is_first_rule) {
494
+ rb_str_cat2(result, "\n");
495
+ }
496
+
370
497
  // Open new media block
371
498
  current_media = rule_media;
372
499
  rb_str_cat2(result, "@media ");
@@ -375,8 +502,80 @@ static VALUE stylesheet_to_s_original(VALUE rules_array, VALUE media_index, VALU
375
502
  in_media_block = 1;
376
503
  }
377
504
 
378
- // Serialize rule inside media block
379
- serialize_rule(result, rule);
505
+ // Serialize rule inside media block (with grouping if enabled)
506
+ // Check if this is a Rule (not AtRule) before accessing selector_list_id
507
+ if (grouping_enabled && rb_obj_is_kind_of(rule, cRule)) {
508
+ VALUE selector_list_id = rb_struct_aref(rule, INT2FIX(RULE_SELECTOR_LIST_ID));
509
+ if (!NIL_P(selector_list_id)) {
510
+ VALUE rule_ids_in_list = rb_hash_aref(selector_lists, selector_list_id);
511
+
512
+ if (NIL_P(rule_ids_in_list) || RARRAY_LEN(rule_ids_in_list) <= 1) {
513
+ if (opts->decl_indent_media) {
514
+ serialize_rule_formatted(result, rule, opts->media_indent, 1);
515
+ } else {
516
+ serialize_rule(result, rule);
517
+ }
518
+ rb_hash_aset(processed_rule_ids, rule_id, Qtrue);
519
+ } else {
520
+ VALUE matching_selectors = rb_ary_new();
521
+ VALUE rule_declarations = rb_struct_aref(rule, INT2FIX(RULE_DECLARATIONS));
522
+
523
+ long list_len = RARRAY_LEN(rule_ids_in_list);
524
+ for (long j = 0; j < list_len; j++) {
525
+ VALUE other_rule_id = rb_ary_entry(rule_ids_in_list, j);
526
+ if (RTEST(rb_hash_aref(processed_rule_ids, other_rule_id))) continue;
527
+
528
+ VALUE other_rule = rb_ary_entry(rules_array, FIX2INT(other_rule_id));
529
+ if (NIL_P(other_rule)) continue;
530
+
531
+ VALUE other_rule_media = rb_hash_aref(rule_to_media, other_rule_id);
532
+ if (!rb_equal(rule_media, other_rule_media)) continue;
533
+
534
+ VALUE other_declarations = rb_struct_aref(other_rule, INT2FIX(RULE_DECLARATIONS));
535
+ if (rb_equal(rule_declarations, other_declarations)) {
536
+ VALUE other_selector = rb_struct_aref(other_rule, INT2FIX(RULE_SELECTOR));
537
+ rb_ary_push(matching_selectors, other_selector);
538
+ rb_hash_aset(processed_rule_ids, other_rule_id, Qtrue);
539
+ }
540
+ }
541
+
542
+ if (RARRAY_LEN(matching_selectors) > 1) {
543
+ VALUE selector_str = rb_ary_join(matching_selectors, rb_str_new_cstr(", "));
544
+ rb_str_cat2(result, opts->media_indent);
545
+ rb_str_append(result, selector_str);
546
+ rb_str_cat2(result, opts->opening_brace);
547
+ if (opts->decl_indent_media) {
548
+ serialize_declarations_formatted(result, rule_declarations, opts->decl_indent_media);
549
+ } else {
550
+ serialize_declarations(result, rule_declarations);
551
+ }
552
+ rb_str_cat2(result, opts->media_indent);
553
+ rb_str_cat2(result, opts->closing_brace);
554
+ RB_GC_GUARD(selector_str);
555
+ } else {
556
+ if (opts->decl_indent_media) {
557
+ serialize_rule_formatted(result, rule, opts->media_indent, 1);
558
+ } else {
559
+ serialize_rule(result, rule);
560
+ }
561
+ }
562
+ }
563
+ } else {
564
+ if (opts->decl_indent_media) {
565
+ serialize_rule_formatted(result, rule, opts->media_indent, 1);
566
+ } else {
567
+ serialize_rule(result, rule);
568
+ }
569
+ rb_hash_aset(processed_rule_ids, rule_id, Qtrue);
570
+ }
571
+ } else {
572
+ if (opts->decl_indent_media) {
573
+ serialize_rule_formatted(result, rule, opts->media_indent, 1);
574
+ } else {
575
+ serialize_rule(result, rule);
576
+ }
577
+ rb_hash_aset(processed_rule_ids, rule_id, Qtrue);
578
+ }
380
579
  }
381
580
  }
382
581
 
@@ -385,9 +584,38 @@ static VALUE stylesheet_to_s_original(VALUE rules_array, VALUE media_index, VALU
385
584
  rb_str_cat2(result, "}\n");
386
585
  }
387
586
 
587
+ RB_GC_GUARD(rule_to_media);
588
+ RB_GC_GUARD(processed_rule_ids);
388
589
  return result;
389
590
  }
390
591
 
592
+ // Original stylesheet serialization (no nesting support) - compact format
593
+ static VALUE stylesheet_to_s_original(VALUE rules_array, VALUE media_index, VALUE charset, VALUE selector_lists) {
594
+ Check_Type(rules_array, T_ARRAY);
595
+ Check_Type(media_index, T_HASH);
596
+
597
+ VALUE result = rb_str_new_cstr("");
598
+
599
+ // Add charset if present
600
+ if (!NIL_P(charset)) {
601
+ rb_str_cat2(result, "@charset \"");
602
+ rb_str_append(result, charset);
603
+ rb_str_cat2(result, "\";\n");
604
+ }
605
+
606
+ // Compact formatting options
607
+ struct format_opts opts = {
608
+ .opening_brace = " { ",
609
+ .closing_brace = " }\n",
610
+ .media_indent = "",
611
+ .decl_indent_base = NULL,
612
+ .decl_indent_media = NULL,
613
+ .add_blank_lines = 0
614
+ };
615
+
616
+ return serialize_stylesheet_with_grouping(rules_array, media_index, result, selector_lists, &opts);
617
+ }
618
+
391
619
  // Forward declarations
392
620
  static void serialize_children_only(VALUE result, VALUE rules_array, long rule_idx,
393
621
  VALUE rule_to_media, VALUE parent_to_children, VALUE parent_selector,
@@ -598,13 +826,15 @@ static void serialize_rule_with_children(VALUE result, VALUE rules_array, long r
598
826
  }
599
827
 
600
828
  // New stylesheet serialization entry point - checks for nesting and delegates
601
- static VALUE stylesheet_to_s_new(VALUE self, VALUE rules_array, VALUE media_index, VALUE charset, VALUE has_nesting) {
829
+ static VALUE stylesheet_to_s_new(VALUE self, VALUE rules_array, VALUE media_index, VALUE charset, VALUE has_nesting, VALUE selector_lists) {
602
830
  Check_Type(rules_array, T_ARRAY);
603
831
  Check_Type(media_index, T_HASH);
832
+ // TODO: Phase 2 - use selector_lists for grouping
833
+ (void)selector_lists; // Suppress unused parameter warning
604
834
 
605
835
  // Fast path: if no nesting, use original implementation (zero overhead)
606
836
  if (!RTEST(has_nesting)) {
607
- return stylesheet_to_s_original(rules_array, media_index, charset);
837
+ return stylesheet_to_s_original(rules_array, media_index, charset, selector_lists);
608
838
  }
609
839
 
610
840
  // SLOW PATH: Has nesting - use lookahead approach
@@ -713,12 +943,13 @@ static VALUE stylesheet_to_s_new(VALUE self, VALUE rules_array, VALUE media_inde
713
943
  rb_str_cat2(result, "}\n");
714
944
  }
715
945
 
946
+ RB_GC_GUARD(rule_to_media);
947
+ RB_GC_GUARD(parent_to_children);
716
948
  return result;
717
949
  }
718
950
 
719
951
  // Original formatted serialization (no nesting support)
720
- static VALUE stylesheet_to_formatted_s_original(VALUE rules_array, VALUE media_index, VALUE charset) {
721
- long total_rules = RARRAY_LEN(rules_array);
952
+ static VALUE stylesheet_to_formatted_s_original(VALUE rules_array, VALUE media_index, VALUE charset, VALUE selector_lists) {
722
953
  VALUE result = rb_str_new_cstr("");
723
954
 
724
955
  // Add charset if present
@@ -728,79 +959,27 @@ static VALUE stylesheet_to_formatted_s_original(VALUE rules_array, VALUE media_i
728
959
  rb_str_cat2(result, "\";\n");
729
960
  }
730
961
 
731
- // Build a map from rule_id to media query symbol
732
- VALUE rule_to_media = rb_hash_new();
733
- struct build_rule_map_ctx map_ctx = { rule_to_media };
734
- rb_hash_foreach(media_index, build_rule_map_callback, (VALUE)&map_ctx);
735
-
736
- // Iterate through rules, grouping consecutive media queries
737
- VALUE current_media = Qnil;
738
- int in_media_block = 0;
739
-
740
- for (long i = 0; i < total_rules; i++) {
741
- VALUE rule = rb_ary_entry(rules_array, i);
742
- VALUE rule_id = rb_struct_aref(rule, INT2FIX(RULE_ID));
743
- VALUE rule_media = rb_hash_aref(rule_to_media, rule_id);
744
- int is_first_rule = (i == 0);
745
-
746
- if (NIL_P(rule_media)) {
747
- // Not in any media query - close any open media block first
748
- if (in_media_block) {
749
- rb_str_cat2(result, "}\n");
750
- in_media_block = 0;
751
- current_media = Qnil;
752
- }
753
-
754
- // Add blank line prefix for non-first rules
755
- if (!is_first_rule) {
756
- rb_str_cat2(result, "\n");
757
- }
758
-
759
- // Output rule with no indentation (always single newline suffix)
760
- serialize_rule_formatted(result, rule, "", 1);
761
- } else {
762
- // This rule is in a media query
763
- if (NIL_P(current_media) || !rb_equal(current_media, rule_media)) {
764
- // Close previous media block if open
765
- if (in_media_block) {
766
- rb_str_cat2(result, "}\n");
767
- }
768
-
769
- // Add blank line prefix for non-first rules
770
- if (!is_first_rule) {
771
- rb_str_cat2(result, "\n");
772
- }
773
-
774
- // Open new media block
775
- current_media = rule_media;
776
- rb_str_cat2(result, "@media ");
777
- rb_str_append(result, rb_sym2str(rule_media));
778
- rb_str_cat2(result, " {\n");
779
- in_media_block = 1;
780
- }
781
-
782
- // Serialize rule inside media block with 2-space indentation
783
- // Rules inside media blocks always get single newline (is_last=1)
784
- serialize_rule_formatted(result, rule, " ", 1);
785
- }
786
- }
787
-
788
- // Close final media block if still open
789
- if (in_media_block) {
790
- rb_str_cat2(result, "}\n");
791
- }
792
-
793
- return result;
962
+ // Formatted output options
963
+ struct format_opts opts = {
964
+ .opening_brace = " {\n",
965
+ .closing_brace = "}\n",
966
+ .media_indent = " ",
967
+ .decl_indent_base = " ",
968
+ .decl_indent_media = " ",
969
+ .add_blank_lines = 1
970
+ };
971
+
972
+ return serialize_stylesheet_with_grouping(rules_array, media_index, result, selector_lists, &opts);
794
973
  }
795
974
 
796
975
  // Formatted version with indentation and newlines (with nesting support)
797
- static VALUE stylesheet_to_formatted_s_new(VALUE self, VALUE rules_array, VALUE media_index, VALUE charset, VALUE has_nesting) {
976
+ static VALUE stylesheet_to_formatted_s_new(VALUE self, VALUE rules_array, VALUE media_index, VALUE charset, VALUE has_nesting, VALUE selector_lists) {
798
977
  Check_Type(rules_array, T_ARRAY);
799
978
  Check_Type(media_index, T_HASH);
800
979
 
801
980
  // Fast path: if no nesting, use original implementation (zero overhead)
802
981
  if (!RTEST(has_nesting)) {
803
- return stylesheet_to_formatted_s_original(rules_array, media_index, charset);
982
+ return stylesheet_to_formatted_s_original(rules_array, media_index, charset, selector_lists);
804
983
  }
805
984
 
806
985
  // SLOW PATH: Has nesting - use parameterized serialization with formatted=1
@@ -909,6 +1088,8 @@ static VALUE stylesheet_to_formatted_s_new(VALUE self, VALUE rules_array, VALUE
909
1088
  rb_str_cat2(result, "}\n");
910
1089
  }
911
1090
 
1091
+ RB_GC_GUARD(rule_to_media);
1092
+ RB_GC_GUARD(parent_to_children);
912
1093
  return result;
913
1094
  }
914
1095
 
@@ -1165,9 +1346,9 @@ void Init_native_extension(void) {
1165
1346
  cStylesheet = rb_define_class_under(mCataract, "Stylesheet", rb_cObject);
1166
1347
 
1167
1348
  // Define module functions
1168
- rb_define_module_function(mCataract, "_parse_css", parse_css_new, 1);
1169
- rb_define_module_function(mCataract, "_stylesheet_to_s", stylesheet_to_s_new, 4);
1170
- rb_define_module_function(mCataract, "_stylesheet_to_formatted_s", stylesheet_to_formatted_s_new, 4);
1349
+ rb_define_module_function(mCataract, "_parse_css", parse_css_new, -1);
1350
+ rb_define_module_function(mCataract, "_stylesheet_to_s", stylesheet_to_s_new, 5);
1351
+ rb_define_module_function(mCataract, "_stylesheet_to_formatted_s", stylesheet_to_formatted_s_new, 5);
1171
1352
  rb_define_module_function(mCataract, "parse_media_types", parse_media_types, 1);
1172
1353
  rb_define_module_function(mCataract, "parse_declarations", new_parse_declarations, 1);
1173
1354
  rb_define_module_function(mCataract, "flatten", cataract_flatten, 1);
@@ -23,13 +23,14 @@ extern VALUE eSizeError;
23
23
  // Struct field indices
24
24
  // ============================================================================
25
25
 
26
- // Rule struct field indices (id, selector, declarations, specificity, parent_rule_id, nesting_style)
26
+ // Rule struct field indices (id, selector, declarations, specificity, parent_rule_id, nesting_style, selector_list_id)
27
27
  #define RULE_ID 0
28
28
  #define RULE_SELECTOR 1
29
29
  #define RULE_DECLARATIONS 2
30
30
  #define RULE_SPECIFICITY 3
31
31
  #define RULE_PARENT_RULE_ID 4
32
32
  #define RULE_NESTING_STYLE 5
33
+ #define RULE_SELECTOR_LIST_ID 6
33
34
 
34
35
  // Nesting style constants
35
36
  #define NESTING_STYLE_IMPLICIT 0 // .parent { .child { } } - no &
@@ -141,8 +142,8 @@ static inline VALUE strip_string(const char *str, long len) {
141
142
  // ============================================================================
142
143
 
143
144
  // CSS parser (css_parser_new.c)
144
- VALUE parse_css_new(VALUE self, VALUE css_string);
145
- VALUE parse_css_new_impl(VALUE css_string, int rule_id_offset);
145
+ VALUE parse_css_new(int argc, VALUE *argv, VALUE self);
146
+ VALUE parse_css_new_impl(VALUE css_string, VALUE parser_options, int rule_id_offset);
146
147
  VALUE parse_media_types(VALUE self, VALUE media_query_sym);
147
148
 
148
149
  // Flatten (flatten.c)