ai-sf /
lepton
| 1 | <?php |
||
| 2 | |||
| 3 | // Set the directory to monitor |
||
| 4 | |||
| 5 | namespace Lepton; |
||
| 6 | |||
| 7 | use ScssPhp\ScssPhp\{Compiler, OutputStyle}; |
||
| 8 | |||
| 9 | class LeptonServer |
||
| 10 | { |
||
| 11 | private array $fileHashes = array(); |
||
| 12 | private array $dependancyTree = array(); |
||
| 13 | private bool $compile_sass = false; |
||
| 14 | private $webServerProcess; |
||
| 15 | |||
| 16 | public function __construct(public readonly string $sass_directory, public readonly string $css_directory, private readonly string $application) |
||
| 17 | { |
||
| 18 | |||
| 19 | echo "Running...".PHP_EOL; |
||
| 20 | |||
| 21 | if(is_dir($this->sass_directory)) { |
||
| 22 | // Clean output folder |
||
| 23 | array_map('unlink', array_filter((array) glob($this->css_directory."*"))); |
||
| 24 | |||
| 25 | $this->compile_sass = true; |
||
| 26 | echo "\e[32mCompiling assets...\e[39m".PHP_EOL; |
||
| 27 | |||
| 28 | $this->updateMainFiles(); |
||
| 29 | |||
| 30 | // Compile the files |
||
| 31 | foreach($this->fileHashes as $file => $hash) { |
||
| 32 | |||
| 33 | $file = realpath($file); |
||
| 34 | $fileDependancies = $this->compileFile($file); |
||
| 35 | $this->fileHashes[$file] = filemtime($file); |
||
| 36 | $this->dependancyTree[$file] = $fileDependancies; |
||
| 37 | foreach($fileDependancies as $dep) { |
||
| 38 | $this->fileHashes[realpath($dep)] = filemtime($dep); |
||
| 39 | } |
||
| 40 | } |
||
| 41 | |||
| 42 | |||
| 43 | echo "Dependancies tree built.".PHP_EOL.PHP_EOL; |
||
| 44 | |||
| 45 | // Compute md5 hash for files |
||
| 46 | foreach($this->dependancyTree as $file => $where) { |
||
| 47 | $fileHashes[$file] = filemtime($file); |
||
| 48 | } |
||
| 49 | |||
| 50 | } else { |
||
| 51 | echo "\e[32mNo _sass directory found\e[39m".PHP_EOL; |
||
| 52 | } |
||
| 53 | } |
||
| 54 | |||
| 55 | |||
| 56 | public function run() |
||
| 57 | { |
||
| 58 | |||
| 59 | |||
| 60 | declare(ticks=1); // Enable tick processing for signal handling |
||
| 61 | |||
| 62 | pcntl_signal(SIGINT, array($this, "terminate")); |
||
| 63 | |||
| 64 | echo "\e[32mWatching in ".$this->sass_directory."\e[39m".PHP_EOL.PHP_EOL; |
||
| 65 | |||
| 66 | echo "\e[33mStarting PHP WebServer (ONLY FOR DEVELOPMENT) at http://127.0.0.1:5555\e[39m".PHP_EOL.PHP_EOL; |
||
| 67 | |||
| 68 | //Start the PHP built-in web server |
||
| 69 | $command = sprintf('php -S localhost:5555 -t %s %s/webserver.php', $this->application, $this->application); |
||
| 70 | $this->webServerProcess = proc_open($command, [STDIN, STDOUT, STDERR], $pipes); |
||
| 71 | while(true) { |
||
| 72 | if($this->compile_sass) { |
||
| 73 | $this->cleanDeletedFiles(); |
||
| 74 | $this->updateMainFiles(); |
||
| 75 | foreach($this->fileHashes as $file => $hash) { |
||
| 76 | $file = realpath($file); |
||
| 77 | if(file_exists($file)) { |
||
| 78 | $newHash = filemtime($file); |
||
| 79 | if($newHash != $hash) { |
||
| 80 | echo "\e[93mFile $file modified!\e[39m".PHP_EOL; |
||
| 81 | $this->fileHashes[$file] = $newHash; |
||
| 82 | |||
| 83 | // if it's a main file |
||
| 84 | if(key_exists($file, $this->dependancyTree)) { |
||
| 85 | $this->dependancyTree[$file] = $this->compileFile($file); |
||
| 86 | } else { // if it's an included file |
||
| 87 | foreach($this->dependancyTree as $main => $dependancies) { |
||
| 88 | if(in_array($file, $dependancies)) { |
||
| 89 | $this->dependancyTree[$main] = $this->compileFile($main); |
||
| 90 | } |
||
| 91 | } |
||
| 92 | } |
||
| 93 | |||
| 94 | } |
||
| 95 | } else { |
||
| 96 | unset($this->fileHashes[$file]); |
||
| 97 | } |
||
| 98 | } |
||
| 99 | } |
||
| 100 | sleep(1); |
||
| 101 | } |
||
| 102 | |||
| 103 | } |
||
| 104 | |||
| 105 | public function terminate() |
||
| 106 | { |
||
| 107 | echo "\n\n\e[31mTERMINATING...\e[39m\n"; |
||
| 108 | proc_terminate($this->webServerProcess); |
||
| 109 | exit(130); |
||
| 110 | } |
||
| 111 | |||
| 112 | |||
| 113 | public function cleanDeletedFiles() |
||
| 114 | { |
||
| 115 | |||
| 116 | foreach($this->fileHashes as $file => $hash) { |
||
| 117 | if(!file_exists($file)) { |
||
| 118 | unset($fileHashes[$file]); |
||
|
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
Loading history...
|
|||
| 119 | foreach($this->dependancyTree as $main => $dependancies) { |
||
| 120 | if($main == $file) { |
||
| 121 | unset($this->dependancyTree[$main]); |
||
| 122 | } |
||
| 123 | if(in_array($file, $dependancies)) { |
||
| 124 | $key = array_search($file, $dependancies); |
||
| 125 | unset($this->dependancyTree[$main][$key]); |
||
| 126 | } |
||
| 127 | } |
||
| 128 | } |
||
| 129 | } |
||
| 130 | } |
||
| 131 | |||
| 132 | |||
| 133 | public function compileScss($inputFile) |
||
| 134 | { |
||
| 135 | |||
| 136 | $compiler = new Compiler(); |
||
| 137 | $compiler->setImportPaths($this->sass_directory); |
||
| 138 | $compiler->setOutputStyle(OutputStyle::COMPRESSED); |
||
| 139 | |||
| 140 | if (is_file($inputFile)) { |
||
| 141 | // Set the path to the output CSS file |
||
| 142 | $outputFile = preg_replace('/(.*)\.(sass|scss)$/', '$1.css', basename($inputFile)); |
||
| 143 | $outputFile = $this->css_directory.$outputFile; |
||
| 144 | // Compile the SCSS code into CSS |
||
| 145 | try { |
||
| 146 | $result = $compiler->compileString(file_get_contents($inputFile)); |
||
| 147 | |||
| 148 | $outputdir = dirname($outputFile); |
||
| 149 | |||
| 150 | // Create the directories recursively |
||
| 151 | if (!is_dir($outputdir)) { |
||
| 152 | mkdir($outputdir, 0755, true); |
||
| 153 | } |
||
| 154 | file_put_contents($outputFile, $result->getCss()); |
||
| 155 | return $result->getIncludedFiles(); |
||
| 156 | } catch (\Exception $e) { |
||
| 157 | print_r($e); |
||
| 158 | syslog(LOG_ERR, 'scssphp: Unable to compile content'); |
||
| 159 | } |
||
| 160 | |||
| 161 | } else { |
||
| 162 | echo "Invalid file".PHP_EOL; |
||
| 163 | } |
||
| 164 | } |
||
| 165 | |||
| 166 | public function compileFile($file) |
||
| 167 | { |
||
| 168 | $fileNameArray = explode("/", $file); |
||
| 169 | $fileName = end($fileNameArray); |
||
| 170 | echo "\e[39m\t==> Compiling $fileName... \e[39m"; |
||
| 171 | $included = $this->compileScss($file); |
||
| 172 | echo "\e[32mDone!\e[39m".PHP_EOL; |
||
| 173 | return $included; |
||
| 174 | } |
||
| 175 | |||
| 176 | public function updateMainFiles() |
||
| 177 | { |
||
| 178 | $files = glob($this->sass_directory . '/*'); // Get all files in the directory |
||
| 179 | |||
| 180 | |||
| 181 | foreach ($files as $file) { |
||
| 182 | $file = realpath($file); |
||
| 183 | $pattern = '/^\/.+\/[^_]*[.](scss|sass)/'; // Specify the regex pattern for file names |
||
| 184 | if(preg_match($pattern, $file)) { |
||
| 185 | if(! array_key_exists($file, $this->fileHashes)) { |
||
| 186 | $this->fileHashes[$file] = 0; |
||
| 187 | } |
||
| 188 | } |
||
| 189 | } |
||
| 190 | |||
| 191 | } |
||
| 192 | |||
| 193 | } |
||
| 194 |