@@ -316,7 +316,9 @@ public function execute($path = null, $parents = array())
316
316
$ css = $ this ->replace ($ css );
317
317
318
318
$ css = $ this ->stripWhitespace ($ css );
319
- $ css = $ this ->shortenColors ($ css );
319
+ $ css = $ this ->convertLegacyColors ($ css );
320
+ $ css = $ this ->cleanupModernColors ($ css );
321
+ $ css = $ this ->shortenHEXColors ($ css );
320
322
$ css = $ this ->shortenZeroes ($ css );
321
323
$ css = $ this ->shortenFontWeights ($ css );
322
324
$ css = $ this ->stripEmptyTags ($ css );
@@ -480,64 +482,152 @@ protected function move(ConverterInterface $converter, $content)
480
482
}
481
483
482
484
/**
483
- * Shorthand hex color codes.
484
- * #FF0000 -> #F00.
485
+ * Shorthand HEX color codes.
486
+ * #FF0000FF -> #f00 -> red
487
+ * #FF00FF00 -> transparent
485
488
*
486
- * @param string $content The CSS content to shorten the hex color codes for
489
+ * @param string $content The CSS content to shorten the HEX color codes for
487
490
*
488
491
* @return string
489
492
*/
490
- protected function shortenColors ($ content )
493
+ protected function shortenHexColors ($ content )
491
494
{
492
- $ content = preg_replace ('/(?<=[: ])#([0-9a-z]) \\1([0-9a-z]) \\2([0-9a-z]) \\3(?:([0-9a-z]) \\4)?(?=[; }])/i ' , '#$1$2$3$4 ' , $ content );
495
+ // shorten repeating patterns within HEX ..
496
+ $ content = preg_replace ('/(?<=[: ])#([0-9a-f]) \\1([0-9a-f]) \\2([0-9a-f]) \\3(?:([0-9a-f]) \\4)?(?=[; }])/i ' , '#$1$2$3$4 ' , $ content );
493
497
494
- // remove alpha channel if it's pointless...
495
- $ content = preg_replace ('/(?<=[: ])#([0-9a-z]{6})ff?(?=[; }])/i ' , '#$1 ' , $ content );
496
- $ content = preg_replace ('/(?<=[: ])#([0-9a-z]{3})f?(?=[; }])/i ' , '#$1 ' , $ content );
498
+ // remove alpha channel if it's pointless ..
499
+ $ content = preg_replace ('/(?<=[: ])#([0-9a-f]{6})ff(?=[; }])/i ' , '#$1 ' , $ content );
500
+ $ content = preg_replace ('/(?<=[: ])#([0-9a-f]{3})f(?=[; }])/i ' , '#$1 ' , $ content );
501
+
502
+ // replace `transparent` with shortcut ..
503
+ $ content = preg_replace ('/(?<=[: ])#[0-9a-f]{6}00(?=[; }])/i ' , '#fff0 ' , $ content );
497
504
498
505
$ colors = array (
506
+ // make these more readable
507
+ '#00f ' => 'blue ' ,
508
+ '#dc143c ' => 'crimson ' ,
509
+ '#0ff ' => 'cyan ' ,
510
+ '#8b0000 ' => 'darkred ' ,
511
+ '#696969 ' => 'dimgray ' ,
512
+ '#ff69b4 ' => 'hotpink ' ,
513
+ '#0f0 ' => 'lime ' ,
514
+ '#fdf5e6 ' => 'oldlace ' ,
515
+ '#87ceeb ' => 'skyblue ' ,
516
+ '#d8bfd8 ' => 'thistle ' ,
499
517
// we can shorten some even more by replacing them with their color name
500
- '#F0FFFF ' => 'azure ' ,
501
- '#F5F5DC ' => 'beige ' ,
502
- '#A52A2A ' => 'brown ' ,
503
- '#FF7F50 ' => 'coral ' ,
504
- '#FFD700 ' => 'gold ' ,
518
+ '#f0ffff ' => 'azure ' ,
519
+ '#f5f5dc ' => 'beige ' ,
520
+ '#ffe4c4 ' => 'bisque ' ,
521
+ '#a52a2a ' => 'brown ' ,
522
+ '#ff7f50 ' => 'coral ' ,
523
+ '#ffd700 ' => 'gold ' ,
505
524
'#808080 ' => 'gray ' ,
506
525
'#008000 ' => 'green ' ,
507
- '#4B0082 ' => 'indigo ' ,
508
- '#FFFFF0 ' => 'ivory ' ,
509
- '#F0E68C ' => 'khaki ' ,
510
- '#FAF0E6 ' => 'linen ' ,
526
+ '#4b0082 ' => 'indigo ' ,
527
+ '#fffff0 ' => 'ivory ' ,
528
+ '#f0e68c ' => 'khaki ' ,
529
+ '#faf0e6 ' => 'linen ' ,
511
530
'#800000 ' => 'maroon ' ,
512
531
'#000080 ' => 'navy ' ,
513
532
'#808000 ' => 'olive ' ,
514
- '#CD853F ' => 'peru ' ,
515
- '#FFC0CB ' => 'pink ' ,
516
- '#DDA0DD ' => 'plum ' ,
533
+ '#ffa500 ' => 'orange ' ,
534
+ '#da70d6 ' => 'orchid ' ,
535
+ '#cd853f ' => 'peru ' ,
536
+ '#ffc0cb ' => 'pink ' ,
537
+ '#dda0dd ' => 'plum ' ,
517
538
'#800080 ' => 'purple ' ,
518
- '#F00 ' => 'red ' ,
519
- '#FA8072 ' => 'salmon ' ,
520
- '#A0522D ' => 'sienna ' ,
521
- '#C0C0C0 ' => 'silver ' ,
522
- '#FFFAFA ' => 'snow ' ,
523
- '#D2B48C ' => 'tan ' ,
524
- '#FF6347 ' => 'tomato ' ,
525
- '#EE82EE ' => 'violet ' ,
526
- '#F5DEB3 ' => 'wheat ' ,
539
+ '#f00 ' => 'red ' ,
540
+ '#fa8072 ' => 'salmon ' ,
541
+ '#a0522d ' => 'sienna ' ,
542
+ '#c0c0c0 ' => 'silver ' ,
543
+ '#fffafa ' => 'snow ' ,
544
+ '#d2b48c ' => 'tan ' ,
545
+ '#008080 ' => 'teal ' ,
546
+ '#ff6347 ' => 'tomato ' ,
547
+ '#ee82ee ' => 'violet ' ,
548
+ '#f5deb3 ' => 'wheat ' ,
527
549
// or the other way around
528
- 'WHITE ' => '#fff ' ,
529
- 'BLACK ' => '#000 ' ,
550
+ 'black ' => '#000 ' ,
551
+ 'fuchsia ' => '#f0f ' ,
552
+ 'magenta ' => '#f0f ' ,
553
+ 'white ' => '#fff ' ,
554
+ 'yellow ' => '#ff0 ' ,
555
+ // and also `transparent`
556
+ 'transparent ' => '#fff0 '
530
557
);
531
558
532
559
return preg_replace_callback (
533
560
'/(?<=[: ])( ' . implode ('| ' , array_keys ($ colors )) . ')(?=[; }])/i ' ,
534
561
function ($ match ) use ($ colors ) {
535
- return $ colors [strtoupper ($ match [0 ])];
562
+ return $ colors [strtolower ($ match [0 ])];
536
563
},
537
564
$ content
538
565
);
539
566
}
540
567
568
+ /**
569
+ * Convert RGB|HSL color codes.
570
+ * rgb(255,0,0,.5) -> rgb(255 0 0 / .5).
571
+ * rgb(255,0,0) -> #f00.
572
+ *
573
+ * @param string $content The CSS content to shorten the RGB color codes for
574
+ *
575
+ * @return string
576
+ */
577
+ protected function convertLegacyColors ($ content )
578
+ {
579
+ /*
580
+ https://drafts.csswg.org/css-color/#color-syntax-legacy
581
+ https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/rgb
582
+ https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/hsl
583
+ */
584
+
585
+ // convert legacy color syntax
586
+ $ content = preg_replace ('/(rgb|hsl)a?\(([^,\s]+)\s*,\s*([^,\s]+)\s*,\s*([^,\s]+)\s*,\s*([^\s\)]+)\)/i ' , '$1($2 $3 $4 / $5) ' , $ content );
587
+ $ content = preg_replace ('/(rgb|hsl)a?\(([^,\s]+)\s*,\s*([^,\s]+)\s*,\s*([^,\s]+)\)/i ' , '$1($2 $3 $4) ' , $ content );
588
+
589
+ // convert `rgb` to `hex`
590
+ $ dec = '([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5]) ' ;// [000-255] THX @ https://www.regular-expressions.info/numericranges.html
591
+ return preg_replace_callback (
592
+ "/rgb\( $ dec $ dec $ dec\)/i " ,
593
+ function ($ match )
594
+ {
595
+ return sprintf ('#%02x%02x%02x ' , $ match [1 ],$ match [2 ],$ match [3 ]);
596
+ },
597
+ $ content
598
+ );
599
+ }
600
+
601
+ /**
602
+ * Cleanup RGB|HSL|HWB|LCH|LAB
603
+ * rgb(255 0 0 / 1) -> rgb(255 0 0).
604
+ * rgb(255 0 0 / 0) -> transparent.
605
+ *
606
+ * @param string $content The CSS content to cleanup HSL|HWB|LCH|LAB
607
+ *
608
+ * @return string
609
+ */
610
+ protected function cleanupModernColors ($ content )
611
+ {
612
+ /*
613
+ https://drafts.csswg.org/css-color/#color-syntax-modern
614
+ https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/hwb
615
+ https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/lch
616
+ https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/lab
617
+ https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/oklch
618
+ https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/oklab
619
+ */
620
+ $ tag = '(rgb|hsl|hwb|(?:(?:ok)?(?:lch|lab))) ' ;
621
+
622
+ // remove alpha channel if it's pointless ..
623
+ $ content = preg_replace ('/ ' .$ tag .'\(([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+\/\s+1(?:[\.\d]*|00%)?\)/i ' , '$1($2 $3 $4) ' , $ content );
624
+
625
+ // replace `transparent` with shortcut ..
626
+ $ content = preg_replace ('/ ' .$ tag .'\([^\s]+\s+[^\s]+\s+[^\s]+\s+\/\s+0(?:[\.0%]*)?\)/i ' , '#fff0 ' , $ content );
627
+
628
+ return $ content ;
629
+ }
630
+
541
631
/**
542
632
* Shorten CSS font weights.
543
633
*
0 commit comments