Advertisement
puggan

lessSorter.php

Mar 15th, 2021
723
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 3.83 KB | None | 0 0
  1. <?php
  2.  
  3. lessSorter($argv[1] ?? 'php://stdin');
  4.  
  5. function lessSorter($filename)
  6. {
  7.     $f = fopen($filename, 'rb');
  8.     $stack = [];
  9.     $current = (object) ['type' => 'root', 'content' => []];
  10.     $buffer = '';
  11.     $dqOpen = false;
  12.     $sqOpen = false;
  13.     $counter = 1000000;
  14.     while (!feof($f)) {
  15.         $input = fread($f, 20480);
  16.         while ($input) {
  17.             $pos = [
  18.                 'open' => strpos($input, '{'),
  19.                 'close' => strpos($input, '}'),
  20.                 'end' => strpos($input, ';'),
  21.                 'sq' => strpos($input, "'"),
  22.                 'dq' => strpos($input, '"'),
  23.             ];
  24.             $pos = array_filter($pos, 'is_numeric');
  25.             if (!$pos) {
  26.                 $buffer .= $input;
  27.                 $input = false;
  28.                 continue;
  29.             }
  30.             asort($pos);
  31.             $firstPos = reset($pos);
  32.             switch (key($pos)) {
  33.                 case 'open':
  34.                     $row = $buffer . substr($input, 0, $firstPos);
  35.                     $buffer = '';
  36.                     $input = substr($input, $firstPos + 1);
  37.                     if ($current) {
  38.                         $stack[] = $current;
  39.                     }
  40.                     $current = (object) [
  41.                         'type' => 'block',
  42.                         'key' => trim($row),
  43.                         'content' => [],
  44.                     ];
  45.                     break;
  46.  
  47.                 case 'close':
  48.                     $row = trim($buffer . substr($input, 0, $firstPos));
  49.                     $buffer = '';
  50.                     $input = substr($input, $firstPos + 1);
  51.                     if (!$current || !$stack) {
  52.                         throw new \RuntimeException('css closed non-open block');
  53.                     }
  54.                     if ($row) {
  55.                         $sortValue = trim(strstr($row, ':', true)) . '-' . $counter++;
  56.                         $current->content[$sortValue] = $row . ';';
  57.                     }
  58.                     asort($current->content);
  59.                     $old = $current;
  60.                     $current = array_pop($stack);
  61.                     $prefix = in_array($old->key[0], ['#', '.']) ? '' : '*';
  62.                     $current->content[$prefix . $old->key . '-' . $counter++] = $old->key . ' {' . PHP_EOL .
  63.                         "\t" . trim (str_replace("\n", "\n\t", implode(PHP_EOL, $old->content))) . PHP_EOL .
  64.                         '}' . PHP_EOL;
  65.                     break;
  66.  
  67.                 case 'end':
  68.                     $row = $buffer . substr($input, 0, $firstPos + 1);
  69.                     $buffer = '';
  70.                     $input = substr($input, $firstPos + 1);
  71.                     if (!$current || $current->type === 'root') {
  72.                         throw new \RuntimeException('css outside block: ' . $row);
  73.                     }
  74.                     $sortValue = '~' . trim(strstr($row, ':', true)) . '-' . $counter++;
  75.                     $current->content[$sortValue] = trim($row);
  76.                     break;
  77.  
  78.                 case 'sq':
  79.                     $buffer .= substr($input, 0, $firstPos + 1);
  80.                     $input = substr($input, $firstPos + 1);
  81.                     $sqOpen = !$sqOpen;
  82.                     break;
  83.  
  84.                 case 'dq':
  85.                     $buffer .= substr($input, 0, $firstPos + 1);
  86.                     $input = substr($input, $firstPos + 1);
  87.                     $dqOpen = !$dqOpen;
  88.                     break;
  89.  
  90.                 default:
  91.                     die('unknown key');
  92.             }
  93.         }
  94.     }
  95.     fclose($f);
  96.     if (trim($buffer)) {
  97.         throw new \RuntimeException('Unexpected end of file: ' . $buffer);
  98.     }
  99.     if (!$current || $stack || $current->type !== 'root') {
  100.         throw new \RuntimeException('Wrong number of blocks closed. stack size: ' . count($stack));
  101.     }
  102.     asort($current->content);
  103.     echo implode(PHP_EOL, $current->content);
  104. }
  105.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement