puggan icon

lessSorter.php

puggan | PRO | 03/15/21 02:49:07 PM UTC | 0 ⭐ | 1421 👁️ | Never ⏰ | []
PHP |

3.83 KB

|

None

|

0 👍

/

0 👎

<?php
 
lessSorter($argv[1] ?? 'php://stdin');
 
function lessSorter($filename)
{
    $f = fopen($filename, 'rb');
    $stack = [];
    $current = (object) ['type' => 'root', 'content' => []];
    $buffer = '';
    $dqOpen = false;
    $sqOpen = false;
    $counter = 1000000;
    while (!feof($f)) {
        $input = fread($f, 20480);
        while ($input) {
            $pos = [
                'open' => strpos($input, '{'),
                'close' => strpos($input, '}'),
                'end' => strpos($input, ';'),
                'sq' => strpos($input, "'"),
                'dq' => strpos($input, '"'),
            ];
            $pos = array_filter($pos, 'is_numeric');
            if (!$pos) {
                $buffer .= $input;
                $input = false;
                continue;
            }
            asort($pos);
            $firstPos = reset($pos);
            switch (key($pos)) {
                case 'open':
                    $row = $buffer . substr($input, 0, $firstPos);
                    $buffer = '';
                    $input = substr($input, $firstPos + 1);
                    if ($current) {
                        $stack[] = $current;
                    }
                    $current = (object) [
                        'type' => 'block',
                        'key' => trim($row),
                        'content' => [],
                    ];
                    break;
 
                case 'close':
                    $row = trim($buffer . substr($input, 0, $firstPos));
                    $buffer = '';
                    $input = substr($input, $firstPos + 1);
                    if (!$current || !$stack) {
                        throw new \RuntimeException('css closed non-open block');
                    }
                    if ($row) {
                        $sortValue = trim(strstr($row, ':', true)) . '-' . $counter++;
                        $current->content[$sortValue] = $row . ';';
                    }
                    asort($current->content);
                    $old = $current;
                    $current = array_pop($stack);
                    $prefix = in_array($old->key[0], ['#', '.']) ? '' : '*';
                    $current->content[$prefix . $old->key . '-' . $counter++] = $old->key . ' {' . PHP_EOL .
                        "\t" . trim (str_replace("\n", "\n\t", implode(PHP_EOL, $old->content))) . PHP_EOL .
                        '}' . PHP_EOL;
                    break;
 
                case 'end':
                    $row = $buffer . substr($input, 0, $firstPos + 1);
                    $buffer = '';
                    $input = substr($input, $firstPos + 1);
                    if (!$current || $current->type === 'root') {
                        throw new \RuntimeException('css outside block: ' . $row);
                    }
                    $sortValue = '~' . trim(strstr($row, ':', true)) . '-' . $counter++;
                    $current->content[$sortValue] = trim($row);
                    break;
 
                case 'sq':
                    $buffer .= substr($input, 0, $firstPos + 1);
                    $input = substr($input, $firstPos + 1);
                    $sqOpen = !$sqOpen;
                    break;
 
                case 'dq':
                    $buffer .= substr($input, 0, $firstPos + 1);
                    $input = substr($input, $firstPos + 1);
                    $dqOpen = !$dqOpen;
                    break;
 
                default:
                    die('unknown key');
            }
        }
    }
    fclose($f);
    if (trim($buffer)) {
        throw new \RuntimeException('Unexpected end of file: ' . $buffer);
    }
    if (!$current || $stack || $current->type !== 'root') {
        throw new \RuntimeException('Wrong number of blocks closed. stack size: ' . count($stack));
    }
    asort($current->content);
    echo implode(PHP_EOL, $current->content);
}
 

Comments