├── README.md ├── app.js ├── index.php ├── rew.phps └── style.css /README.md: -------------------------------------------------------------------------------- 1 | apache2nginx 2 | ============ 3 | 4 | Converts apache rewrite rules to nginx rewrite rules 5 | 6 | for more information please visit http://www.anilcetin.com/convert-apache-htaccess-to-nginx/ 7 | 8 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | var textarea; 2 | var results; 3 | var loader; 4 | 5 | function convertRules() { 6 | 7 | if ($(this).data('oldVal') == $(this).val()) { 8 | return; 9 | } 10 | 11 | var rules = $(this).val(); 12 | 13 | if (rules != '') { 14 | loader.addClass('visible'); 15 | $.ajax({ 16 | type: 'POST', 17 | data: {rules: rules} 18 | }).done(function (result) { 19 | loader.removeClass('visible'); 20 | results.val(result); 21 | }) 22 | } else { 23 | results.val(''); 24 | } 25 | 26 | $(this).data('oldVal', $(this).val()); 27 | } 28 | 29 | $(function () { 30 | textarea = $('#apache').find('textarea'); 31 | results = $('#nginx').find('textarea'); 32 | loader = $('#loader'); 33 | textarea.on('propertychange change click keyup input paste', convertRules).data('oldVal', textarea.val()); 34 | }); -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | parseContent(); 9 | $RC->writeConfig(); 10 | exit($RC->confOk); 11 | } 12 | ?> 13 | 14 | 15 | 16 | Rule convertor, convert apache htaccess rewrite rules to nginx rewrite rules automatically 17 | 18 | 19 | 20 | 21 |
22 |

Apache2Nginx rules converter

23 | attention: not so much beta, but check twice before using! 24 |
25 |
26 |
27 |

Apache Rewrite Rules

28 | 29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |

Nginx converted Rules

41 | 42 |
43 |
44 | 60 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /rew.phps: -------------------------------------------------------------------------------- 1 | htContent = $htContent; 6 | } 7 | */ 8 | function parseLine($line){ 9 | list($cmd,$regex,$rew,$flags) = explode(" ",$line); 10 | if(!empty($flags)){ 11 | $flagsArray = explode(",",trim(substr(substr(trim($flags),strpos($flags,'[')+1),0,strpos($flags,']')-1))); 12 | $flagsArray = array_map("trim",$flagsArray); 13 | } 14 | return array(trim($regex),trim($rew),$flagsArray); 15 | } 16 | 17 | function readRules(){ 18 | $lines = explode("\n",$this->htContent); 19 | $i = 0; 20 | foreach($lines as $line){ 21 | $line = trim($line); 22 | if($line[0] != '#' && !empty($line[0])){ 23 | if(strpos($line,"RewriteCond") !== false){ 24 | if(!isset($k))$k = 0; 25 | if(!isset($p))$p = 0; 26 | $parsedLine = $this->parseLine($line); 27 | $conds[$p] = array( 28 | 'match' => $parsedLine[0], 29 | 'rule' => $parsedLine[1], 30 | 'flags' => $parsedLine[2] 31 | ); 32 | $p++; 33 | } 34 | if(strpos($line,"RewriteRule") !== false){ 35 | if(!isset($k))$k = 0; 36 | $parsedLine = $this->parseLine($line); 37 | $condBit = 'AND'; 38 | if(is_array($conds[0]["flags"]) && in_array('OR',$conds[0]["flags"]))$condBit = 'OR'; 39 | $rules[$k] = array( 40 | 'rule' => array( 41 | 'regex' => $parsedLine[0], 42 | 'rew' => $parsedLine[1], 43 | 'flags' => $parsedLine[2] 44 | ), 45 | 'condBit' => $condBit, 46 | 'conditions' => $conds 47 | ); 48 | unset($p,$conds,$parsedLine,$condBit); 49 | $k++; 50 | } 51 | } 52 | } 53 | return $rules; 54 | } 55 | 56 | 57 | function parseFlags($flagArray,$type,$r,$c){ 58 | //type: 0 -> rule 1-> condition 59 | //this function returns an array; 60 | /* 61 | array( 62 | return => 0|return code 63 | break => 0|1 64 | appendEnd => last|permanent|redirect|break 65 | env => var=value 66 | matchOperator => ~*|~ 67 | unknown => 0|1 68 | set => key:var 69 | ) 70 | */ 71 | $returnArray = array('return' => '0','break' => '0','appendEnd' => '', 'env' => '', 'matchOperator' => '~'); 72 | foreach($flagArray as $flag){ 73 | switch($flag[0]){ 74 | case 'N': 75 | case 'n': 76 | $returnArray["matchOperator"] = '~*'; 77 | if(!isset($returnArray["unknown"]))$returnArray["unknown"] = '0'; 78 | break; 79 | case 'F': 80 | case 'f': 81 | $returnArray["return"] = '403'; 82 | $returnArray["break"] = '1'; 83 | if(!isset($returnArray["unknown"]))$returnArray["unknown"] = '0'; 84 | break; 85 | case 'G': 86 | case 'g': 87 | $returnArray["return"] = '410'; 88 | $returnArray["break"] = '1'; 89 | if(!isset($returnArray["unknown"]))$returnArray["unknown"] = '0'; 90 | break; 91 | case 'R': 92 | case 'r': 93 | list($flaga,$rcode) = explode("=",$flag); 94 | if($rcode == '301' || $rcode == 'permanent'){ 95 | $returnArray["appendEnd"] = 'permanent'; 96 | } else { 97 | $returnArray["appendEnd"] = 'redirect'; 98 | } 99 | $returnArray["break"] = '1'; 100 | if(!isset($returnArray["unknown"]))$returnArray["unknown"] = '0'; 101 | break; 102 | case 'L': 103 | case 'l': 104 | if(empty($returnArray["appendEnd"])){ 105 | $returnArray["appendEnd"] = 'last'; 106 | } 107 | if(!isset($returnArray["unknown"]))$returnArray["unknown"] = '0'; 108 | break; 109 | case 'E': 110 | case 'e': 111 | list($cmd,$envvar) = explode("=",$flag); 112 | //list($ekey,$evar) = explode(":",$envvar); 113 | $returnArray["env"][] = $envvar; 114 | break; 115 | case 'O': 116 | case 'o': 117 | $returnArray["set"][] = '$rule_'.$r.' 1'; 118 | break; 119 | case 'A': 120 | $returnArray["set"][] = '$rule_'.$r.' '.($c+1).'$rule_'.$r; 121 | break; 122 | } 123 | } 124 | if(count($flagArray) > 1){ 125 | if(!isset($returnArray["unknown"]))$returnArray["unknown"] = '1'; 126 | } else { 127 | $returnArray["unknown"] = '0'; 128 | } 129 | return $returnArray; 130 | 131 | } 132 | 133 | function parseCondMatch($condition,$r,$c,$condBit){ 134 | $matchOperator = '~'; 135 | 136 | if($condition["rule"][0] == '!'){ 137 | $nomatch = '!'; 138 | $condition["rule"] = substr($condition["rule"],1); 139 | } 140 | 141 | $condition["flags"][] = $condBit; 142 | $condition["flags"] = array_unique($condition["flags"]); 143 | 144 | 145 | $fromFlags = $this->parseFlags($condition["flags"],1,$r,$c); 146 | 147 | 148 | if($fromFlags["matchOperator"]){ 149 | $matchOperator = $fromFlags["matchOperator"]; 150 | } 151 | 152 | switch($condition["rule"]){ 153 | case "-f": 154 | case "-F": 155 | $left = $nomatch.'-f'; 156 | $right = $condition["match"]; 157 | $operand = ''; 158 | break; 159 | case "-d": 160 | $left = $nomatch.'-d'; 161 | $right = $condition["match"]; 162 | $operand = ''; 163 | break; 164 | case "-s": 165 | $left = $nomatch.'-e'; 166 | $right = $condition["match"]; 167 | $operand = ''; 168 | break; 169 | default: 170 | $left = $condition["match"]; 171 | $right = $condition["rule"]; 172 | $operand = $nomatch.$matchOperator; 173 | 174 | break; 175 | } 176 | 177 | $returnArray = array( 178 | 'left' => $left, 179 | 'right' => $right, 180 | 'operand' => $operand, 181 | 'flags' => $fromFlags 182 | ); 183 | return $returnArray; 184 | } 185 | 186 | function parseRewirteCond($rule,$r){ 187 | $c = 0; 188 | if(is_array($rule["conditions"])){ 189 | foreach($rule["conditions"] as $condition){ 190 | 191 | $condResult[$c] = $this->parseCondMatch($condition,$r,$c,$rule["condBit"]); 192 | $c++; 193 | } 194 | } 195 | return $condResult; 196 | } 197 | 198 | function mustSkipForCond($conditions){ 199 | if(count($conditions)==0){ 200 | return 0; 201 | } elseif(count($conditions) == 1) { 202 | if($conditions[0]["flags"]["unknown"] == 1){ 203 | return "skipped because all flags in condition are unknown"; 204 | } 205 | return 0; 206 | } else { 207 | $unknown = 0; 208 | foreach($conditions as $cond){ 209 | if($cond["flags"]["unknown"] == 1){ 210 | $unknown++; 211 | } 212 | } 213 | if(count($conditions) == $unknown){ 214 | return "skipped because all flags for all conditions are unknown"; 215 | } 216 | return 0; 217 | } 218 | } 219 | 220 | function setBackRef(&$rule,&$condsParsed){ 221 | if(preg_match_all('/\%([0-9])/',$rule["rule"]["regex"],$matchesRule)!=0){ 222 | $rule["rule"]["regex"] = preg_replace('/\%([0-9])/','$bref_$1',$rule["rule"]["regex"]); 223 | } 224 | 225 | if(preg_match_all('/\%([0-9])/',$rule["rule"]["rew"],$matchesRew)!=0){ 226 | $rule["rule"]["rew"] = preg_replace('/\%([0-9])/','$bref_$1',$rule["rule"]["rew"]); 227 | } 228 | 229 | $totalMatches = array_merge($matchesRule[1],$matchesRew[1]); 230 | 231 | 232 | if(is_array($rule["rule"]["flags"])){ 233 | $i=0; 234 | foreach($rule["rule"]["flags"] as $flags){ 235 | if(preg_match_all('/\%([0-9])/',$rule["rule"]["flags"][$i],$matchesFlag)!=0){ 236 | $rule["rule"]["flags"][$i] = preg_replace('/\%([0-9])/','$bref_$1',$rule["rule"]["flags"][$i]); 237 | $totalMatches = array_merge($totalMatches,$matchesFlag[1]); 238 | } 239 | $i++; 240 | } 241 | } 242 | 243 | $totalMatches = array_unique($totalMatches); 244 | if(is_array($totalMatches)){ 245 | foreach($totalMatches as $match){ 246 | $i=0; 247 | if($rule["condBit"] == 'OR'){ 248 | foreach($condsParsed as $cond){ 249 | array_push($condsParsed[$i]["flags"]["set"], '$bref_'.$match.' $'.$match); 250 | $i++; 251 | } 252 | } else { 253 | array_push($condsParsed[count($condsParsed)-1]["flags"]["set"], '$bref_'.$match.' $'.$match); 254 | } 255 | } 256 | } 257 | 258 | 259 | } 260 | 261 | function parseRule(&$rule,$c){ 262 | 263 | if($rule["rule"]["regex"][0] == '^'){ 264 | if($rule["rule"]["regex"][1]!='/'){ 265 | $rule["rule"]["regex"] = '^/'.substr($rule["rule"]["regex"],1); 266 | } 267 | } else { 268 | if($rule["rule"]["regex"][0]!='/'){ 269 | $rule["rule"]["regex"] = '/'.$rule["rule"]["regex"]; 270 | } 271 | } 272 | 273 | if($rule["rule"]["rew"][0] == '^' && substr($rule["rule"]["rew"],0,4) != 'http'){ 274 | if($rule["rule"]["rew"][1]!='/'){ 275 | $rule["rule"]["rew"] = '^/'.substr($rule["rule"]["rew"],1); 276 | } 277 | } else { 278 | if($rule["rule"]["rew"][0]!='/' && substr($rule["rule"]["rew"],0,4) != 'http'){ 279 | $rule["rule"]["rew"] = '/'.$rule["rule"]["rew"]; 280 | } 281 | } 282 | 283 | if($rule["rule"]["rew"] == '/-'){ 284 | unset($rule["rule"]["rew"],$rule["rule"]["regex"]); 285 | } 286 | 287 | 288 | if($c != 0){ 289 | 290 | if($rule["condBit"] == 'OR'){ 291 | $rule["rule"]["trueExp"] = '1'; 292 | } else { 293 | $i=0; 294 | while($i < $c){ 295 | $backme = ($i+1).$backme; 296 | $i++; 297 | } 298 | $rule["rule"]["trueExp"] = $backme; 299 | } 300 | } 301 | } 302 | 303 | function replaceVariables(&$val,&$key){ 304 | 305 | if(preg_match_all('/\%\{HTTP\:(.*)\}/',$val,$matches)){ 306 | foreach($matches[1] as $match){ 307 | $val = str_replace('%{HTTP:'.$match.'}','$http_'.str_replace('-','_',strtolower($match)),$val); 308 | } 309 | } 310 | 311 | 312 | $pat = array( 313 | '%{HTTP_USER_AGENT}', 314 | '%{HTTP_REFERER}', 315 | '%{HTTP_COOKIE}', 316 | '%{HTTP_FORWARDED}', 317 | '%{HTTP_HOST}', 318 | '%{HTTP_PROXY_CONNECTION}', 319 | '%{HTTP_ACCEPT}', 320 | '%{REMOTE_ADDR}', 321 | '%{REMOTE_PORT}', 322 | '%{REMOTE_USER}', 323 | '%{REQUEST_METHOD}', 324 | '%{SCRIPT_FILENAME}', 325 | '%{PATH_INFO}', 326 | '%{QUERY_STRING}', 327 | '%{DOCUMENT_ROOT}', 328 | '%{SERVER_NAME}', 329 | '%{SERVER_ADDR}', 330 | '%{SERVER_PORT}', 331 | '%{SERVER_PROTOCOL}', 332 | '%{REQUEST_URI}', 333 | '%{REQUEST_FILENAME}' 334 | ); 335 | 336 | $rep = array( 337 | '$http_user_agent', 338 | '$http_referer', 339 | '$http_cookie', 340 | '$http_forwarded', 341 | '$http_host', 342 | '$http_proxy_connection', 343 | '$http_accept', 344 | '$remote_addr', 345 | '$remote_port', 346 | '$remote_user', 347 | '$request_method', 348 | '$uri', 349 | '$uri', 350 | '$args', 351 | '$document_root', 352 | '$server_name', 353 | '$server_addr', 354 | '$server_port', 355 | '$server_protocol', 356 | '$uri', 357 | '$request_filename' 358 | ); 359 | $oldVal = $val; 360 | $val = str_replace($pat,$rep,$val); 361 | 362 | if($oldVal == $val && preg_match('/\%\{(.*)\}/i',$val)!=0){ 363 | $val = "IGNORE"; 364 | } 365 | } 366 | 367 | 368 | function walkRecursive(&$input, $funcname, $userdata = ""){ 369 | 370 | if (!is_array($input)){ 371 | return false; 372 | } 373 | 374 | foreach ($input AS $key => $value){ 375 | if(is_array($input[$key])){ 376 | $this->walkRecursive($input[$key], $funcname, $userdata); 377 | } else { 378 | $saved_value = $value; 379 | if(!empty($userdata)){ 380 | $this->$funcname($value, $key, $userdata); 381 | } else { 382 | $this->$funcname($value, $key); 383 | } 384 | 385 | if($value != $saved_value){ 386 | if($value == 'IGNORE'){ 387 | unset($input[$key]); 388 | } else { 389 | $input[$key] = $value; 390 | } 391 | } 392 | } 393 | } 394 | return true; 395 | } 396 | 397 | function writeConfig(){ 398 | $r = 0; 399 | foreach($this->conf as $conf){ 400 | if(is_array($conf)){ 401 | //array_walk_recursive($conf,'rewriteConf::replaceVariables'); 402 | $this->walkRecursive($conf,'replaceVariables'); 403 | //print_r($conf); 404 | //exit; 405 | $c = 0; 406 | if(is_array($conf["conds"])){ 407 | foreach($conf["conds"] as $cond){ 408 | if($cond["flags"]["unknown"]!=1 && isset($cond["left"]) && isset($cond["right"])){ 409 | if($cond["operand"] == ''){ 410 | $ret.= 'if ('.$cond["left"].' '.$cond["right"].'){ 411 | '; 412 | } else { 413 | $ret.= 'if ('.$cond["left"].' '.$cond["operand"].' "'.$cond["right"].'"){ 414 | '; 415 | } 416 | if(is_array($cond["flags"]["set"])){ 417 | foreach($cond["flags"]["set"] as $set){ 418 | $ret.= ' set '.$set.'; 419 | '; 420 | } 421 | } 422 | 423 | if(is_array($cond["flags"]["env"])){ 424 | foreach($cond["flags"]["env"] as $env){ 425 | $ret.= ' setenv '.$env.'; 426 | '; 427 | } 428 | } 429 | if($conf["condBit"] == 'OR'){ 430 | if($conf["rule"]["flags"]["return"] > 0){ 431 | $ret.= ' return '.$conf["rule"]["flags"]["return"].'; 432 | '; 433 | $isReturned = 1; 434 | } 435 | if($conf["rule"]["flags"]["break"] == 1){ 436 | $ret.= ' break; 437 | '; 438 | } 439 | } 440 | $ret.='} 441 | '; 442 | 443 | } else { 444 | $conf["rule"]["trueExp"] = str_replace($c,'',$conf["rule"]["trueExp"]); 445 | $ret.= '#ignored: condition '.$c.' 446 | '; 447 | } 448 | $c++; 449 | } 450 | } 451 | if(!isset($isReturned)){ 452 | if($conf["rule"]["flags"]["unknown"] != 1){ 453 | 454 | if(!empty($conf["rule"]["trueExp"])) 455 | { 456 | $ret.= 'if ($rule_'.$r.' = "'.$conf["rule"]["trueExp"].'"){ 457 | '; 458 | } 459 | 460 | if($conf["rule"]["flags"]["return"] < 1){ 461 | 462 | if(is_array($conf["rule"]["flags"]["set"])){ 463 | foreach($conf["rule"]["flags"]["set"] as $set){ 464 | $ret.= ' set '.$set.'; 465 | '; 466 | } 467 | } 468 | 469 | if(is_array($conf["rule"]["flags"]["env"])){ 470 | foreach($conf["rule"]["flags"]["env"] as $env){ 471 | $ret.= ' setenv '.$env.'; 472 | '; 473 | } 474 | } 475 | if(isset($conf["rule"]["regex"]) && isset($conf["rule"]["rew"])){ 476 | if(!empty($conf["rule"]["flags"]["appendEnd"])){ 477 | $conf["rule"]["flags"]["appendEnd"] = ' '.$conf["rule"]["flags"]["appendEnd"]; 478 | } 479 | 480 | // Check if we need to escape the regex 481 | $to_escape = array('{', '}', ';'); 482 | $quotes = ''; 483 | 484 | foreach($to_escape as $escape) 485 | { 486 | if (strpos($conf["rule"]["regex"], $escape) !== false) { 487 | $quotes = '"'; 488 | break; 489 | } 490 | } 491 | 492 | $ret.= ' rewrite '.$quotes.$conf["rule"]["regex"].$quotes.' '.$conf["rule"]["rew"].''.$conf["rule"]["flags"]["appendEnd"].'; 493 | '; 494 | } else { 495 | $ret.= '#ignored: "-" thing used or unknown variable in regex/rew 496 | '; 497 | } 498 | } else { 499 | $ret.= ' return '.$conf["rule"]["flags"]["return"].'; 500 | '; 501 | if($conf["rule"]["flags"]["break"] == 1){ 502 | $ret.= ' break; 503 | '; 504 | } 505 | } 506 | if(!empty($conf["rule"]["trueExp"])) 507 | { 508 | $ret.='} 509 | '; 510 | } 511 | } else { 512 | $ret.= '#ignored: unknown variable in rule flag 513 | '; 514 | } 515 | } 516 | unset($isReturned,$cond,$env,$set); 517 | } else { 518 | $ret.= $conf.' 519 | '; 520 | } 521 | $r++; 522 | } 523 | $this->confOk = $ret; 524 | } 525 | 526 | function parseContent(){ 527 | $this->rules = $this->readRules(); 528 | $r = 0; 529 | foreach($this->rules as $rule){ 530 | $condsParsed = $this->parseRewirteCond($rule,$r); 531 | $beforeMscr = $mscr; 532 | if(($mscr = $this->mustSkipForCond($condsParsed))!=0){ 533 | $conf[$r]["conds"] = $mscr; 534 | $conf[$r]["rule"] = $mscr; 535 | } else { 536 | if($beforeMscr != 0){ 537 | //set last|break to before rule if any 538 | } 539 | $this->setBackRef($rule,$condsParsed); 540 | if(is_array($rule["rule"]["flags"])){ 541 | $rule["rule"]["flags"] = $this->parseFlags($rule["rule"]["flags"],0,$r,0); 542 | } else { 543 | unset($rule["rule"]["flags"]); 544 | } 545 | $this->parseRule($rule,count($condsParsed)); 546 | $conf[$r]["conds"] = $condsParsed; 547 | $conf[$r]["rule"] = $rule["rule"]; 548 | } 549 | $conf[$r]["condBit"] = $rule["condBit"]; 550 | $r++; 551 | } 552 | $this->conf = $conf; 553 | } 554 | 555 | } 556 | ?> 557 | -------------------------------------------------------------------------------- /style.css: -------------------------------------------------------------------------------- 1 | article, aside, dialog, figure, footer, header, hgroup, nav, section { 2 | display: block; 3 | zoom: 1; 4 | } 5 | 6 | html { 7 | box-sizing: border-box; 8 | } 9 | 10 | *, *:before, *:after { 11 | box-sizing: inherit; 12 | } 13 | 14 | html, body { 15 | width: 100%; 16 | height: 100%; 17 | 18 | margin: 0; 19 | padding: 0; 20 | } 21 | 22 | body { 23 | background: #2c3e50; 24 | font-family: 'Roboto', sans-serif; 25 | display: -webkit-box; 26 | display: -webkit-flex; 27 | display: -ms-flexbox; 28 | display: flex; 29 | margin: 0; 30 | padding: 0; 31 | height: 100vh; 32 | -webkit-box-orient: vertical; 33 | -webkit-box-direction: normal; 34 | -webkit-flex-direction: column; 35 | -ms-flex-direction: column; 36 | flex-direction: column; 37 | 38 | -webkit-box-pack: start; 39 | 40 | -webkit-justify-content: flex-start; 41 | 42 | -ms-flex-pack: start; 43 | 44 | justify-content: flex-start; /* align items in Main Axis */ 45 | -webkit-box-align: stretch; 46 | -webkit-align-items: stretch; 47 | -ms-flex-align: stretch; 48 | align-items: stretch; /* align items in Cross Axis */ 49 | -webkit-align-content: stretch; 50 | -ms-flex-line-pack: stretch; 51 | align-content: stretch; /* Extra space in Cross Axis */ 52 | } 53 | 54 | header, footer { 55 | background: white; 56 | margin: 0; 57 | padding: 20px; 58 | text-align: center; 59 | box-shadow: 0 0 30px rgba(0, 0, 0, .3); 60 | max-height: 60px; 61 | } 62 | 63 | header { 64 | max-height: 180px; 65 | } 66 | 67 | h1, footer, section { 68 | -webkit-box-flex: 1; 69 | -webkit-flex: 1; 70 | -ms-flex: 1; 71 | flex: 1; 72 | } 73 | 74 | h1, h2 { 75 | font-weight: 300; 76 | } 77 | 78 | h1 { 79 | margin-bottom: 8px; 80 | } 81 | 82 | h2 { 83 | color: white; 84 | } 85 | 86 | p a { 87 | color: white; 88 | } 89 | 90 | i { 91 | color: #ccc; 92 | } 93 | 94 | footer a { 95 | color: black; 96 | } 97 | 98 | article { 99 | -webkit-box-flex: 1; 100 | -webkit-flex: 1 auto; 101 | -ms-flex: 1 auto; 102 | flex: 1 auto; 103 | padding: 30px; 104 | -webkit-box-orient: vertical; 105 | -webkit-box-direction: normal; 106 | -webkit-flex-direction: column; 107 | -ms-flex-direction: column; 108 | flex-direction: column; 109 | display: -webkit-box; 110 | display: -webkit-flex; 111 | display: -ms-flexbox; 112 | display: flex; 113 | 114 | -webkit-box-pack: start; 115 | 116 | -webkit-justify-content: flex-start; 117 | 118 | -ms-flex-pack: start; 119 | 120 | justify-content: flex-start; /* align items in Main Axis */ 121 | -webkit-box-align: stretch; 122 | -webkit-align-items: stretch; 123 | -ms-flex-align: stretch; 124 | align-items: stretch; /* align items in Cross Axis */ 125 | -webkit-align-content: stretch; 126 | -ms-flex-line-pack: stretch; 127 | align-content: stretch; /* Extra space in Cross Axis */ 128 | } 129 | 130 | section { 131 | display: -webkit-box; 132 | display: -webkit-flex; 133 | display: -ms-flexbox; 134 | display: flex; 135 | -webkit-box-orient: horizontal; 136 | -webkit-box-direction: normal; 137 | -webkit-flex-direction: row; 138 | -ms-flex-direction: row; 139 | flex-direction: row; 140 | position: relative; 141 | } 142 | 143 | textarea, h2 { 144 | -webkit-box-flex: 1; 145 | -webkit-flex: 1 auto; 146 | -ms-flex: 1 auto; 147 | flex: 1 auto; 148 | } 149 | 150 | h2 { 151 | max-height: 50px; 152 | } 153 | 154 | textarea { 155 | width: 100%; 156 | display: block; 157 | padding: 20px; 158 | color: white; 159 | 160 | background: none; 161 | border: 1px solid #ccc; 162 | } 163 | 164 | section:first-of-type { 165 | border-right: 1px solid white; 166 | } 167 | 168 | aside { 169 | padding: 40px; 170 | background: rgba(0, 0, 0, .3); 171 | display: -webkit-box; 172 | display: -webkit-flex; 173 | display: -ms-flexbox; 174 | display: flex; 175 | } 176 | 177 | aside p { 178 | -webkit-box-flex: 1; 179 | -webkit-flex-grow: 1; 180 | -ms-flex-positive: 1; 181 | flex-grow: 1; 182 | color: #ccc; 183 | padding: 0 20px; 184 | line-height: 1.6; 185 | } 186 | 187 | aside p:last-child { 188 | -webkit-box-flex: 2; 189 | -webkit-flex-grow: 2; 190 | -ms-flex-positive: 2; 191 | flex-grow: 2; 192 | } 193 | 194 | aside p strong { 195 | text-transform: uppercase; 196 | display: block; 197 | margin-bottom: 20px; 198 | } 199 | 200 | @-webkit-keyframes rotate_pacman_half_up { 201 | 0% { 202 | -webkit-transform: rotate(270deg); 203 | transform: rotate(270deg); 204 | } 205 | 50% { 206 | -webkit-transform: rotate(360deg); 207 | transform: rotate(360deg); 208 | } 209 | 100% { 210 | -webkit-transform: rotate(270deg); 211 | transform: rotate(270deg); 212 | } 213 | } 214 | 215 | @keyframes rotate_pacman_half_up { 216 | 0% { 217 | -webkit-transform: rotate(270deg); 218 | transform: rotate(270deg); 219 | } 220 | 50% { 221 | -webkit-transform: rotate(360deg); 222 | transform: rotate(360deg); 223 | } 224 | 100% { 225 | -webkit-transform: rotate(270deg); 226 | transform: rotate(270deg); 227 | } 228 | } 229 | 230 | @-webkit-keyframes rotate_pacman_half_down { 231 | 0% { 232 | -webkit-transform: rotate(90deg); 233 | transform: rotate(90deg); 234 | } 235 | 50% { 236 | -webkit-transform: rotate(0deg); 237 | transform: rotate(0deg); 238 | } 239 | 100% { 240 | -webkit-transform: rotate(90deg); 241 | transform: rotate(90deg); 242 | } 243 | } 244 | 245 | @keyframes rotate_pacman_half_down { 246 | 0% { 247 | -webkit-transform: rotate(90deg); 248 | transform: rotate(90deg); 249 | } 250 | 50% { 251 | -webkit-transform: rotate(0deg); 252 | transform: rotate(0deg); 253 | } 254 | 100% { 255 | -webkit-transform: rotate(90deg); 256 | transform: rotate(90deg); 257 | } 258 | } 259 | 260 | @-webkit-keyframes pacman-balls { 261 | 75% { 262 | opacity: 0.7; 263 | } 264 | 100% { 265 | -webkit-transform: translate(-100px, -6.25px); 266 | transform: translate(-100px, -6.25px); 267 | } 268 | } 269 | 270 | @keyframes pacman-balls { 271 | 75% { 272 | opacity: 0.7; 273 | } 274 | 100% { 275 | -webkit-transform: translate(-100px, -6.25px); 276 | transform: translate(-100px, -6.25px); 277 | } 278 | } 279 | 280 | #loader { 281 | position: absolute; 282 | top: 50%; 283 | left: 50%; 284 | background: white; 285 | height: 160px; 286 | width: 160px; 287 | margin-left: -80px; 288 | margin-top: -80px; 289 | display: -webkit-box; 290 | display: -webkit-flex; 291 | display: -ms-flexbox; 292 | display: flex; 293 | -webkit-align-content: center; 294 | -ms-flex-line-pack: center; 295 | align-content: center; 296 | -webkit-box-pack: center; 297 | -webkit-justify-content: center; 298 | -ms-flex-pack: center; 299 | justify-content: center; 300 | -webkit-box-align: center; 301 | -webkit-align-items: center; 302 | -ms-flex-align: center; 303 | align-items: center; 304 | border-radius: 100%; 305 | opacity: 0; 306 | pointer-events: none; 307 | -webkit-transition: .3s; 308 | transition: .3s; 309 | } 310 | 311 | #loader.visible { 312 | opacity: 1; 313 | } 314 | 315 | .pacman { 316 | position: relative; 317 | -webkit-transform: scale(-1, 1); 318 | transform: scale(-1, 1); 319 | } 320 | 321 | .pacman > div:nth-child(2) { 322 | -webkit-animation: pacman-balls 1s -0.99s infinite linear; 323 | animation: pacman-balls 1s -0.99s infinite linear; 324 | } 325 | 326 | .pacman > div:nth-child(3) { 327 | -webkit-animation: pacman-balls 1s -0.66s infinite linear; 328 | animation: pacman-balls 1s -0.66s infinite linear; 329 | } 330 | 331 | .pacman > div:nth-child(4) { 332 | -webkit-animation: pacman-balls 1s -0.33s infinite linear; 333 | animation: pacman-balls 1s -0.33s infinite linear; 334 | } 335 | 336 | .pacman > div:nth-child(5) { 337 | -webkit-animation: pacman-balls 1s 0s infinite linear; 338 | animation: pacman-balls 1s 0s infinite linear; 339 | } 340 | 341 | .pacman > div:first-of-type { 342 | width: 0px; 343 | height: 0px; 344 | border-right: 25px solid transparent; 345 | border-top: 25px solid #2c3e50; 346 | border-left: 25px solid #2c3e50; 347 | border-bottom: 25px solid #2c3e50; 348 | border-radius: 25px; 349 | -webkit-animation: rotate_pacman_half_up 0.5s 0s infinite; 350 | animation: rotate_pacman_half_up 0.5s 0s infinite; 351 | position: relative; 352 | left: -30px; 353 | } 354 | 355 | .pacman > div:nth-child(2) { 356 | width: 0px; 357 | height: 0px; 358 | border-right: 25px solid transparent; 359 | border-top: 25px solid #2c3e50; 360 | border-left: 25px solid #2c3e50; 361 | border-bottom: 25px solid #2c3e50; 362 | border-radius: 25px; 363 | -webkit-animation: rotate_pacman_half_down 0.5s 0s infinite; 364 | animation: rotate_pacman_half_down 0.5s 0s infinite; 365 | margin-top: -50px; 366 | position: relative; 367 | left: -30px; 368 | } 369 | 370 | .pacman > div:nth-child(3), 371 | .pacman > div:nth-child(4), 372 | .pacman > div:nth-child(5), 373 | .pacman > div:nth-child(6) { 374 | background-color: #2c3e50; 375 | width: 15px; 376 | height: 15px; 377 | border-radius: 100%; 378 | margin: 2px; 379 | width: 10px; 380 | height: 10px; 381 | position: absolute; 382 | -webkit-transform: translate(0, -6.25px); 383 | transform: translate(0, -6.25px); 384 | top: 25px; 385 | left: 70px; 386 | } --------------------------------------------------------------------------------