├── src ├── Views │ ├── debugbar │ │ ├── icon.png │ │ ├── debugbar.php │ │ ├── scripts.js │ │ └── styles.css │ ├── exceptions │ │ ├── production.php │ │ └── development.php │ └── assets │ │ ├── prism-aplus.css │ │ └── prism.js ├── Languages │ ├── en │ │ └── debug.php │ ├── es │ │ └── debug.php │ └── pt-br │ │ └── debug.php ├── Collector.php ├── Collection.php ├── Timer.php ├── Debugger.php └── ExceptionHandler.php ├── .phpstorm.meta.php ├── LICENSE ├── README.md └── composer.json /src/Views/debugbar/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/natanfelles/aplus-debug/master/src/Views/debugbar/icon.png -------------------------------------------------------------------------------- /src/Languages/en/debug.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | return [ 11 | 'exception' => 'Exception', 12 | 'message' => 'Message', 13 | 'file' => 'File', 14 | 'line' => 'Line', 15 | 'trace' => 'Trace', 16 | 'exceptionTitle' => 'Error 500 - Internal Server Error', 17 | 'exceptionDescription' => 'Something went wrong. Please, back later.', 18 | ]; 19 | -------------------------------------------------------------------------------- /src/Languages/es/debug.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | return [ 11 | 'exception' => 'Excepción', 12 | 'message' => 'Mensaje', 13 | 'file' => 'Archivo', 14 | 'line' => 'Línea', 15 | 'trace' => 'Trace', 16 | 'exceptionTitle' => 'Error 500 - Error Interno del Servidor', 17 | 'exceptionDescription' => 'Algo salió mal. Por favor vuelve más tarde.', 18 | ]; 19 | -------------------------------------------------------------------------------- /src/Languages/pt-br/debug.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | return [ 11 | 'exception' => 'Exceção', 12 | 'message' => 'Mensagem', 13 | 'file' => 'Arquivo', 14 | 'line' => 'Linha', 15 | 'trace' => 'Trace', 16 | 'exceptionTitle' => 'Erro 500 - Erro Interno no Servidor', 17 | 'exceptionDescription' => 'Algo deu errado. Por favor, volte mais tarde.', 18 | ]; 19 | -------------------------------------------------------------------------------- /.phpstorm.meta.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | namespace PHPSTORM_META; 11 | 12 | registerArgumentsSet( 13 | 'eh_env', 14 | \Framework\Debug\ExceptionHandler::DEVELOPMENT, 15 | \Framework\Debug\ExceptionHandler::PRODUCTION, 16 | ); 17 | expectedArguments( 18 | \Framework\Debug\ExceptionHandler::__construct(), 19 | 0, 20 | argumentsSet('eh_env') 21 | ); 22 | expectedArguments( 23 | \Framework\Debug\ExceptionHandler::setEnvironment(), 24 | 0, 25 | argumentsSet('eh_env') 26 | ); 27 | expectedReturnValues( 28 | \Framework\Debug\ExceptionHandler::getEnvironment(), 29 | argumentsSet('eh_env') 30 | ); 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Natan Felles 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/Views/exceptions/production.php: -------------------------------------------------------------------------------- 1 | 6 | 7 | 9 | 10 | 11 | 12 | <?= $handler->getLanguage()->render('debug', 'exceptionTitle') ?> 13 | 27 | 28 | 29 |

getLanguage()->render('debug', 'exceptionTitle') ?>

30 |

getLanguage()->render('debug', 'exceptionDescription') ?>

31 | getLogger()?->getLastLog(); 33 | if ($log) { 34 | echo '

Log Id: ' . htmlentities($log->id) . '

'; 35 | } 36 | ?> 37 | 38 | 39 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Aplus Framework Debug Library 2 | 3 | # Aplus Framework Debug Library 4 | 5 | - [Home](https://aplus-framework.com/packages/debug) 6 | - [User Guide](https://docs.aplus-framework.com/guides/libraries/debug/index.html) 7 | - [API Documentation](https://docs.aplus-framework.com/packages/debug.html) 8 | 9 | [![tests](https://github.com/aplus-framework/debug/actions/workflows/tests.yml/badge.svg)](https://github.com/aplus-framework/debug/actions/workflows/tests.yml) 10 | [![pipeline](https://gitlab.com/aplus-framework/libraries/debug/badges/master/pipeline.svg)](https://gitlab.com/aplus-framework/libraries/debug/-/pipelines?scope=branches) 11 | [![coverage](https://gitlab.com/aplus-framework/libraries/debug/badges/master/coverage.svg?job=test:php)](https://aplus-framework.gitlab.io/libraries/debug/coverage/) 12 | [![packagist](https://img.shields.io/packagist/v/aplus/debug)](https://packagist.org/packages/aplus/debug) 13 | [![open-source](https://img.shields.io/badge/open--source-sponsor-magenta)](https://aplus-framework.com/sponsor) 14 | -------------------------------------------------------------------------------- /src/Collector.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | namespace Framework\Debug; 11 | 12 | /** 13 | * Class Collector. 14 | * 15 | * @package debug 16 | */ 17 | abstract class Collector 18 | { 19 | protected string $name; 20 | /** 21 | * @var array 22 | */ 23 | protected array $data = []; 24 | /** 25 | * @var array> 26 | */ 27 | protected array $activities = []; 28 | 29 | public function __construct(string $name = 'default') 30 | { 31 | $this->name = $name; 32 | } 33 | 34 | public function getName() : string 35 | { 36 | return $this->name; 37 | } 38 | 39 | public function getSafeName() : string 40 | { 41 | return Debugger::makeSafeName($this->getName()); 42 | } 43 | 44 | /** 45 | * @param array $data 46 | * 47 | * @return static 48 | */ 49 | public function addData(array $data) : static 50 | { 51 | $this->data[] = $data; 52 | return $this; 53 | } 54 | 55 | /** 56 | * @return array 57 | */ 58 | public function getData() : array 59 | { 60 | return $this->data; 61 | } 62 | 63 | public function hasData() : bool 64 | { 65 | return ! empty($this->data); 66 | } 67 | 68 | /** 69 | * @return array> 70 | */ 71 | public function getActivities() : array 72 | { 73 | return $this->activities; 74 | } 75 | 76 | abstract public function getContents() : string; 77 | } 78 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "aplus/debug", 3 | "description": "Aplus Framework Debug Library", 4 | "license": "MIT", 5 | "type": "library", 6 | "keywords": [ 7 | "debug", 8 | "timer", 9 | "error", 10 | "handler", 11 | "error-handling", 12 | "exception-handling", 13 | "exception", 14 | "log", 15 | "error-reporting", 16 | "view" 17 | ], 18 | "authors": [ 19 | { 20 | "name": "Natan Felles", 21 | "email": "natanfelles@gmail.com", 22 | "homepage": "https://natanfelles.github.io" 23 | } 24 | ], 25 | "homepage": "https://aplus-framework.com/packages/debug", 26 | "support": { 27 | "email": "support@aplus-framework.com", 28 | "issues": "https://gitlab.com/aplus-framework/libraries/debug/issues", 29 | "forum": "https://aplus-framework.com/forum", 30 | "source": "https://gitlab.com/aplus-framework/libraries/debug", 31 | "docs": "https://docs.aplus-framework.com/guides/libraries/debug/" 32 | }, 33 | "funding": [ 34 | { 35 | "type": "Aplus Sponsor", 36 | "url": "https://aplus-framework.com/sponsor" 37 | } 38 | ], 39 | "require": { 40 | "php": ">=8.1", 41 | "aplus/cli": "^2.1", 42 | "aplus/helpers": "^3.0", 43 | "aplus/language": "^3.0", 44 | "aplus/log": "^3.0" 45 | }, 46 | "require-dev": { 47 | "ext-xdebug": "*", 48 | "aplus/coding-standard": "^1.14", 49 | "ergebnis/composer-normalize": "^2.25", 50 | "jetbrains/phpstorm-attributes": "^1.0", 51 | "phpmd/phpmd": "^2.13", 52 | "phpstan/phpstan": "^1.5", 53 | "phpunit/phpunit": "^9.5" 54 | }, 55 | "minimum-stability": "dev", 56 | "prefer-stable": true, 57 | "autoload": { 58 | "psr-4": { 59 | "Framework\\Debug\\": "src/" 60 | } 61 | }, 62 | "autoload-dev": { 63 | "psr-4": { 64 | "Tests\\Debug\\": "tests/" 65 | } 66 | }, 67 | "config": { 68 | "allow-plugins": { 69 | "ergebnis/composer-normalize": true 70 | }, 71 | "optimize-autoloader": true, 72 | "preferred-install": "dist", 73 | "sort-packages": true 74 | }, 75 | "extra": { 76 | "branch-alias": { 77 | "dev-master": "3.x-dev" 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/Collection.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | namespace Framework\Debug; 11 | 12 | /** 13 | * Class Collection. 14 | * 15 | * @package debug 16 | */ 17 | class Collection 18 | { 19 | protected string $name; 20 | /** 21 | * @var array 22 | */ 23 | protected array $collectors = []; 24 | /** 25 | * @var array 26 | */ 27 | protected array $actions = []; 28 | 29 | public function __construct(string $name) 30 | { 31 | $this->name = $name; 32 | } 33 | 34 | public function getName() : string 35 | { 36 | return $this->name; 37 | } 38 | 39 | public function getSafeName() : string 40 | { 41 | return Debugger::makeSafeName($this->getName()); 42 | } 43 | 44 | public function addCollector(Collector $collector) : static 45 | { 46 | $this->collectors[] = $collector; 47 | return $this; 48 | } 49 | 50 | /** 51 | * @return array 52 | */ 53 | public function getCollectors() : array 54 | { 55 | return $this->collectors; 56 | } 57 | 58 | public function addAction(string $action) : static 59 | { 60 | $this->actions[] = $action; 61 | return $this; 62 | } 63 | 64 | /** 65 | * @return array 66 | */ 67 | public function getActions() : array 68 | { 69 | return $this->actions; 70 | } 71 | 72 | public function hasCollectors() : bool 73 | { 74 | return ! empty($this->collectors); 75 | } 76 | 77 | /** 78 | * @return array>> 79 | */ 80 | public function getActivities() : array 81 | { 82 | $result = []; 83 | foreach ($this->getCollectors() as $collector) { 84 | $activities = $collector->getActivities(); 85 | if ($activities) { 86 | foreach ($activities as &$activity) { 87 | $activity = \array_merge([ 88 | 'collection' => $this->getName(), 89 | ], $activity); 90 | } 91 | unset($activity); 92 | $result[] = $activities; 93 | } 94 | } 95 | return $result; 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/Views/assets/prism-aplus.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Aplus Theme for Prism 3 | * @author natanfelles 4 | */ 5 | .aplus-debug code[class*=language-], 6 | .aplus-debug pre[class*=language-] { 7 | color: #ddd; 8 | font-family: 'JetBrains Mono', Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; 9 | font-size: 14px; 10 | text-align: left; 11 | white-space: pre; 12 | word-spacing: normal; 13 | word-break: normal; 14 | word-wrap: normal; 15 | -moz-tab-size: 4; 16 | -o-tab-size: 4; 17 | tab-size: 4; 18 | -webkit-hyphens: none; 19 | -moz-hyphens: none; 20 | -ms-hyphens: none; 21 | hyphens: none 22 | } 23 | 24 | .aplus-debug pre[class*=language-] { 25 | margin: 0; 26 | overflow: auto; 27 | border-radius: 4px 28 | } 29 | 30 | .aplus-debug :not(pre) > code[class*=language-] { 31 | padding: .1em; 32 | border-radius: .3em; 33 | white-space: normal 34 | } 35 | 36 | .aplus-debug .token.cdata, 37 | .aplus-debug .token.comment, 38 | .aplus-debug .token.doctype, 39 | .aplus-debug .token.prolog { 40 | color: #5c6370 41 | } 42 | 43 | .aplus-debug .token.operator, 44 | .aplus-debug .token.punctuation { 45 | color: #abb2bf 46 | } 47 | 48 | .aplus-debug .token.namespace { 49 | opacity: .7 50 | } 51 | 52 | .aplus-debug .token.attr-name, 53 | .aplus-debug .token.boolean, 54 | .aplus-debug .token.constant, 55 | .aplus-debug .token.deleted, 56 | .aplus-debug .token.name, 57 | .aplus-debug .token.number, 58 | .aplus-debug .token.selector, 59 | .aplus-debug .token.symbol, 60 | .aplus-debug .token.char-class-punctuation.punctuation { 61 | color: #d19a66 62 | } 63 | 64 | .aplus-debug code.language-regex, 65 | .aplus-debug .language-css .token.string, 66 | .aplus-debug .style .token.string, 67 | .aplus-debug .token.argument-delimiter.operator, 68 | .aplus-debug .token.attr-value, 69 | .aplus-debug .token.builtin, 70 | .aplus-debug .token.char, 71 | .aplus-debug .token.char-class, 72 | .aplus-debug .token.inserted, 73 | .aplus-debug .token.range, 74 | .aplus-debug .token.regex, 75 | .aplus-debug .token.string, 76 | .aplus-debug .token.string.url, 77 | .aplus-debug .token.url { 78 | color: #98c379 79 | } 80 | 81 | .aplus-debug .token.doctype, 82 | .aplus-debug .token.entity, 83 | .aplus-debug .token.parameter, 84 | .aplus-debug .token.property, 85 | .aplus-debug .token.tag, 86 | .aplus-debug .token.variable { 87 | color: #eb6772 88 | } 89 | 90 | .aplus-debug .token.function, 91 | .aplus-debug .token.section-name { 92 | color: #61afef 93 | } 94 | 95 | .aplus-debug .token.class-name, 96 | .aplus-debug .token.package { 97 | color: #e5c07b 98 | } 99 | 100 | .aplus-debug .token.builtin.class-name { 101 | color: #55b6c2 102 | } 103 | 104 | .aplus-debug .token.atrule, 105 | .aplus-debug .token.key.attr-name, 106 | .aplus-debug .token.keyword, 107 | .aplus-debug .token.range-punctuation { 108 | color: #c678dd 109 | } 110 | 111 | .aplus-debug .token.important { 112 | color: #be5046 113 | } 114 | 115 | .aplus-debug .token.bold, 116 | .aplus-debug .token.important { 117 | font-weight: 700 118 | } 119 | 120 | .aplus-debug .token.italic { 121 | font-style: italic 122 | } 123 | 124 | .aplus-debug .token.entity { 125 | cursor: help 126 | } 127 | -------------------------------------------------------------------------------- /src/Timer.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | namespace Framework\Debug; 11 | 12 | use JetBrains\PhpStorm\ArrayShape; 13 | 14 | /** 15 | * Class Timer. 16 | * 17 | * @package debug 18 | */ 19 | class Timer 20 | { 21 | /** 22 | * @var array> 23 | */ 24 | protected array $marks = []; 25 | protected int $testsCount = 1; 26 | 27 | /** 28 | * Timer constructor. 29 | */ 30 | public function __construct() 31 | { 32 | $this->addMark('debug[start]'); 33 | } 34 | 35 | /** 36 | * @param int $times 37 | * @param callable $function 38 | * @param bool $flush 39 | * 40 | * @return array Two keys - "memory" in MB and "time" in seconds 41 | */ 42 | #[ArrayShape(['memory' => 'string', 'time' => 'string'])] 43 | public function test(int $times, callable $function, bool $flush = false) : array 44 | { 45 | if ( ! $flush) { 46 | \ob_start(); 47 | } 48 | $this->testsCount++; 49 | $this->addMark('test[' . $this->testsCount . '][start]'); 50 | for ($i = 0; $i < $times; $i++) { 51 | $function(); 52 | } 53 | $this->addMark('test[' . ($this->testsCount) . '][end]'); 54 | if ( ! $flush) { 55 | \ob_end_clean(); 56 | } 57 | return $this->diff( 58 | 'test[' . $this->testsCount . '][start]', 59 | 'test[' . $this->testsCount . '][end]' 60 | ); 61 | } 62 | 63 | /** 64 | * @param string $name 65 | * 66 | * @return static 67 | */ 68 | public function addMark(string $name) : static 69 | { 70 | $this->marks[$name] = [ 71 | 'memory' => \memory_get_usage(), 72 | 'time' => \microtime(true), 73 | ]; 74 | return $this; 75 | } 76 | 77 | /** 78 | * @param string $name 79 | * @param int $memoryUsage 80 | * @param float $microtime 81 | * 82 | * @return static 83 | */ 84 | public function setMark(string $name, int $memoryUsage, float $microtime) : static 85 | { 86 | $this->marks[$name] = [ 87 | 'memory' => $memoryUsage, 88 | 'time' => $microtime, 89 | ]; 90 | return $this; 91 | } 92 | 93 | /** 94 | * @param string $name 95 | * 96 | * @return array|false 97 | */ 98 | public function getMark(string $name) : array | false 99 | { 100 | return $this->marks[$name] ?? false; 101 | } 102 | 103 | /** 104 | * @param bool $format 105 | * 106 | * @return array> 107 | */ 108 | public function getMarks(bool $format = false) : array 109 | { 110 | $marks = $this->marks; 111 | if ($format) { 112 | foreach ($marks as &$mark) { 113 | $mark['memory'] = \number_format($mark['memory'] / 1024 / 1024, 3) . ' MB'; 114 | $mark['time'] = \number_format($mark['time'], 3) . ' s'; 115 | } 116 | } 117 | return $marks; 118 | } 119 | 120 | /** 121 | * @param string $from 122 | * @param string $to 123 | * 124 | * @return array Two keys: memory in MB and time in seconds 125 | */ 126 | #[ArrayShape(['memory' => 'string', 'time' => 'string'])] 127 | public function diff(string $from, string $to) : array 128 | { 129 | $number = $this->marks[$to]['memory'] - $this->marks[$from]['memory']; 130 | $number = \number_format($number / 1024 / 1024, 3); 131 | $diff = []; 132 | $diff['memory'] = $number . ' MB'; 133 | $number = $this->marks[$to]['time'] - $this->marks[$from]['time']; 134 | $number = \number_format($number, 3); 135 | $diff['time'] = $number . ' s'; 136 | return $diff; 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /src/Debugger.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | namespace Framework\Debug; 11 | 12 | use Framework\Helpers\Isolation; 13 | use InvalidArgumentException; 14 | 15 | /** 16 | * Class Debugger. 17 | * 18 | * @package debug 19 | */ 20 | class Debugger 21 | { 22 | /** 23 | * @var array 24 | */ 25 | protected array $collections = []; 26 | /** 27 | * @var array 28 | */ 29 | protected array $options = []; 30 | protected string $debugbarView = __DIR__ . '/Views/debugbar/debugbar.php'; 31 | 32 | public function addCollection(Collection $collection) : static 33 | { 34 | $this->collections[$collection->getName()] = $collection; 35 | return $this; 36 | } 37 | 38 | /** 39 | * @return array 40 | */ 41 | public function getCollections() : array 42 | { 43 | return $this->collections; 44 | } 45 | 46 | public function getCollection(string $name) : ?Collection 47 | { 48 | return $this->getCollections()[$name] ?? null; 49 | } 50 | 51 | public function addCollector(Collector $collector, string $collectionName) : static 52 | { 53 | $collection = $this->getCollection($collectionName); 54 | if ($collection === null) { 55 | $collection = new Collection($collectionName); 56 | $this->addCollection($collection); 57 | } 58 | $collection->addCollector($collector); 59 | return $this; 60 | } 61 | 62 | /** 63 | * @param array $options 64 | * 65 | * @return static 66 | */ 67 | public function setOptions(array $options) : static 68 | { 69 | $this->options = $options; 70 | return $this; 71 | } 72 | 73 | /** 74 | * @return array 75 | */ 76 | public function getOptions() : array 77 | { 78 | return $this->options; 79 | } 80 | 81 | /** 82 | * @return array 83 | */ 84 | public function getActivities() : array 85 | { 86 | $collected = []; 87 | foreach ($this->getCollections() as $collection) { 88 | foreach ($collection->getActivities() as $activities) { 89 | $collected = [...$collected, ...$activities]; 90 | } 91 | } 92 | $min = .0; 93 | $max = .0; 94 | if ($collected) { 95 | \usort($collected, static function ($c1, $c2) { 96 | return $c1['start'] <=> $c2['start']; 97 | }); 98 | $min = \min(\array_column($collected, 'start')); 99 | $max = \max(\array_column($collected, 'end')); 100 | foreach ($collected as &$activity) { 101 | $this->addActivityValues($activity, $min, $max); 102 | } 103 | } 104 | return [ 105 | 'min' => $min, 106 | 'max' => $max, 107 | 'total' => $max - $min, 108 | 'collected' => $collected, 109 | ]; 110 | } 111 | 112 | /** 113 | * @param array $activity 114 | * @param float $min 115 | * @param float $max 116 | */ 117 | protected function addActivityValues(array &$activity, float $min, float $max) : void 118 | { 119 | $total = $max - $min; 120 | $activity['total'] = $activity['end'] - $activity['start']; 121 | $activity['left'] = \round(($activity['start'] - $min) * 100 / $total, 3); 122 | $activity['width'] = \round($activity['total'] * 100 / $total, 3); 123 | } 124 | 125 | public function setDebugbarView(string $file) : static 126 | { 127 | $realpath = \realpath($file); 128 | if ( ! $realpath || ! \is_file($realpath)) { 129 | throw new InvalidArgumentException( 130 | 'Invalid debugbar view file: ' . $file 131 | ); 132 | } 133 | $this->debugbarView = $realpath; 134 | return $this; 135 | } 136 | 137 | public function getDebugbarView() : string 138 | { 139 | return $this->debugbarView; 140 | } 141 | 142 | public function renderDebugbar() : string 143 | { 144 | \ob_start(); 145 | Isolation::require($this->getDebugbarView(), [ 146 | 'collections' => $this->getCollections(), 147 | 'activities' => $this->getActivities(), 148 | 'options' => $this->getOptions(), 149 | ]); 150 | return \ob_get_clean(); // @phpstan-ignore-line 151 | } 152 | 153 | public static function makeSafeName(string $name) : string 154 | { 155 | return \strtr(\trim(\strip_tags(\strtolower($name))), [ 156 | '·' => '-', 157 | ':' => '-', 158 | '(' => '-', 159 | ')' => '-', 160 | '/' => '-', 161 | '\\' => '-', 162 | ' ' => '-', 163 | ]); 164 | } 165 | 166 | public static function convertSize(float | int $size) : string 167 | { 168 | if (empty($size)) { 169 | return '0 B'; 170 | } 171 | $unit = ['B', 'KB', 'MB', 'GB', 'TB', 'PB']; 172 | $index = \floor(\log($size, 1024)); 173 | return \round($size / (1024 ** $index), 3) . ' ' . $unit[$index]; 174 | } 175 | 176 | public static function makeDebugValue(mixed $value) : string 177 | { 178 | $type = \get_debug_type($value); 179 | return (string) match ($type) { 180 | 'array' => 'array', 181 | 'bool' => $value ? 'true' : 'false', 182 | 'float', 'int' => $value, 183 | 'null' => 'null', 184 | 'string' => "'" . \strtr($value, ["'" => "\\'"]) . "'", 185 | default => 'instanceof ' . $type, 186 | }; 187 | } 188 | 189 | /** 190 | * Remove dots and zeros from the end of the version. 191 | * 192 | * @param string $version 193 | * 194 | * @return string 195 | */ 196 | public static function roundVersion(string $version) : string 197 | { 198 | if (\str_ends_with($version, '.0')) { 199 | $version = \substr($version, 0, -2); 200 | return static::roundVersion($version); 201 | } 202 | return $version; 203 | } 204 | } 205 | -------------------------------------------------------------------------------- /src/Views/debugbar/debugbar.php: -------------------------------------------------------------------------------- 1 | $collections 7 | * @var array $activities 8 | * @var array $options 9 | */ 10 | ?> 11 | 12 | 15 | 24 |
25 |
26 |
27 |
28 |
29 |
Info
30 |
31 |
32 |
33 |

Running on with PHP 37 | 38 |

39 |

★ 40 | aplus-framework.com 41 |

42 | 46 |

activit collected in seconds: 49 |

50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 63 | 64 | 65 | 66 | $collected): ?> 67 | 68 | 69 | 70 | 71 | 72 | 73 | 81 | 82 | 83 | 84 |
#CollectionCollectorDescriptionRuntime 59 | 10%20%30%40% 60 | 50%60%70%80% 61 | 90%100% 62 |
74 | 80 |
85 | 88 |
89 |
90 |
91 | 92 | hasCollectors()): ?> 93 |
94 |
95 |
96 |
getName() ?>
97 |
getActions()) ?>
98 |
99 | getCollectors(); 101 | ?> 102 | 108 |
109 |
110 |
111 | getCollectors() as $collector): ?> 112 |
getContents() ?>
113 | 114 |
115 |
116 | 117 | 118 |
119 |
120 |
121 | A+ 122 |
123 |
124 | 125 | hasCollectors()): ?> 126 | 127 | 128 | 129 |
130 | 131 |
132 |
133 |
134 |
135 | 141 | 145 | 146 | -------------------------------------------------------------------------------- /src/Views/debugbar/scripts.js: -------------------------------------------------------------------------------- 1 | let Debugbar = { 2 | icon: null, 3 | collections: null, 4 | panels: null, 5 | init: function () { 6 | Debugbar.icon = document.querySelector('#debugbar .icon'); 7 | Debugbar.collections = document.querySelectorAll('#debugbar .collection'); 8 | Debugbar.panels = document.querySelectorAll('#debugbar .panel'); 9 | if (Debugbar.isWide()) { 10 | Debugbar.showWide(); 11 | } else { 12 | Debugbar.hideWide(); 13 | } 14 | Debugbar.prepareIcon(); 15 | Debugbar.prepareCollections(); 16 | Debugbar.prepareKeys(); 17 | }, 18 | prepareIcon: function () { 19 | Debugbar.icon.addEventListener('click', function () { 20 | Debugbar.toggleWide(); 21 | }); 22 | }, 23 | prepareCollections: function () { 24 | Debugbar.collections.forEach(function (collector) { 25 | collector.addEventListener('click', function () { 26 | let wasActive = this.classList.contains('active'); 27 | Debugbar.panels.forEach(function (panel) { 28 | panel.style.display = 'none'; 29 | }); 30 | Debugbar.collections.forEach(function (collector) { 31 | collector.classList.remove('active'); 32 | }); 33 | if (wasActive) { 34 | Debugbar.removeActivePanel(); 35 | return; 36 | } 37 | Debugbar.setActivePanel(this.id); 38 | Debugbar.activeCollector(this.id); 39 | let panel = document.querySelector('.' + this.id); 40 | panel.style.display = 'block'; 41 | if (!wasActive) { 42 | this.classList.add('active'); 43 | } 44 | }); 45 | }); 46 | }, 47 | prepareKeys: function () { 48 | document.addEventListener('keydown', function (e) { 49 | if (e.ctrlKey && e.code === 'F12') { 50 | Debugbar.toggleWide(); 51 | } 52 | }); 53 | }, 54 | setWide: function (active) { 55 | localStorage.setItem('debugbar-wide', active); 56 | }, 57 | isWide: function () { 58 | return localStorage.getItem('debugbar-wide') === 'y'; 59 | }, 60 | showWide: function () { 61 | let debugbar = document.querySelector('#debugbar'); 62 | let panelsDiv = document.querySelector('#debugbar .panels'); 63 | let collectionsDiv = document.querySelector('#debugbar .collections'); 64 | let toolbar = document.querySelector('#debugbar .toolbar'); 65 | debugbar.style.width = '100%'; 66 | panelsDiv.style.display = 'block'; 67 | collectionsDiv.style.display = 'flex'; 68 | toolbar.style.borderRightWidth = '0'; 69 | Debugbar.activePanel(); 70 | }, 71 | hideWide: function () { 72 | let debugbar = document.querySelector('#debugbar'); 73 | let panelsDiv = document.querySelector('#debugbar .panels'); 74 | let collectionsDiv = document.querySelector('#debugbar .collections'); 75 | let toolbar = document.querySelector('#debugbar .toolbar'); 76 | debugbar.style.width = 'auto'; 77 | panelsDiv.style.display = 'none'; 78 | collectionsDiv.style.display = 'none'; 79 | toolbar.style.borderRightWidth = '1px'; 80 | }, 81 | toggleWide: function () { 82 | if (Debugbar.isWide()) { 83 | Debugbar.hideWide(); 84 | Debugbar.setWide('n'); 85 | return; 86 | } 87 | Debugbar.showWide(); 88 | Debugbar.setWide('y'); 89 | }, 90 | activePanel: function () { 91 | let id = localStorage.getItem('debugbar-panel'); 92 | if (id) { 93 | let collection = document.querySelector('#' + id); 94 | let panel = document.querySelector('.' + id); 95 | if (!collection || !panel) { 96 | return; 97 | } 98 | collection.classList.add('active'); 99 | Debugbar.activeCollector(id); 100 | panel.style.display = 'block'; 101 | } 102 | }, 103 | setActivePanel: function (id) { 104 | localStorage.setItem('debugbar-panel', id); 105 | }, 106 | isActivePanel: function (id) { 107 | return localStorage.getItem('debugbar-panel') === id; 108 | }, 109 | removeActivePanel: function () { 110 | localStorage.removeItem('debugbar-panel'); 111 | }, 112 | activeCollector: function (collection) { 113 | let contents = document.querySelector('.' + collection + ' .contents'); 114 | for (let i = 0; i < contents.children.length; i++) { 115 | contents.children[i].style.display = 'none'; 116 | } 117 | Debugbar.makeResizable(contents); 118 | let collector = 'default'; 119 | let select = document.querySelector('.' + collection + ' .collectors select'); 120 | if (select) { 121 | select.onchange = function () { 122 | Debugbar.activeCollector(collection); 123 | }; 124 | collector = select.value; 125 | } 126 | document.querySelector('.' + collection + ' .collector-' + collector).style.display = 'block'; 127 | }, 128 | makeResizable: function (contents) { 129 | if (!contents.style.height) { 130 | contents.style.height = '250px'; 131 | } 132 | const storageKey = 'debugbar-panel-contents-height'; 133 | let storedHeight = localStorage.getItem(storageKey); 134 | if (storedHeight) { 135 | contents.style.height = storedHeight; 136 | } 137 | let resizer = contents.parentElement.querySelector('.resize'); 138 | resizer.addEventListener('mousedown', function (e) { 139 | e.preventDefault(); 140 | window.addEventListener('mousemove', resize); 141 | window.addEventListener('mouseup', stopResize); 142 | window.addEventListener('dblclick', autoHeight); 143 | }); 144 | let header = contents.parentElement.querySelector('header'); 145 | let toolbar = document.querySelector('#debugbar .toolbar'); 146 | 147 | function resize(e) { 148 | let move = resizer.getBoundingClientRect().top - e.clientY; 149 | let height = contents.offsetHeight - 20 + move; 150 | let toRemove = header.clientHeight + toolbar.clientHeight + 25; 151 | let maxHeight = window.innerHeight - toRemove; 152 | if (height < 0) { 153 | height = 0; 154 | } else if (height > maxHeight) { 155 | height = maxHeight; 156 | } 157 | contents.style.height = height + 'px'; 158 | localStorage.setItem(storageKey, height + 'px'); 159 | } 160 | 161 | function stopResize() { 162 | window.removeEventListener('mousemove', resize); 163 | } 164 | 165 | function autoHeight() { 166 | let toRemove = header.clientHeight + toolbar.clientHeight + 25; 167 | let height = window.innerHeight - toRemove + 'px'; 168 | let current = localStorage.getItem(storageKey); 169 | if (current === height) { 170 | height = '250px'; 171 | } 172 | contents.style.height = height; 173 | localStorage.setItem(storageKey, height); 174 | } 175 | }, 176 | }; 177 | -------------------------------------------------------------------------------- /src/Views/debugbar/styles.css: -------------------------------------------------------------------------------- 1 | .aplus-debug { 2 | position: fixed; 3 | bottom: 0; 4 | left: 0; 5 | width: 100%; 6 | font-size: 16px; 7 | color: #eee; 8 | font-family: Arial, Helvetica, sans-serif !important; 9 | font-weight: normal; 10 | line-height: normal; 11 | z-index: 9999; 12 | } 13 | 14 | .aplus-debug *, 15 | .aplus-debug ::after, 16 | .aplus-debug ::before { 17 | box-sizing: unset; 18 | } 19 | 20 | .aplus-debug h1, 21 | .aplus-debug h2, 22 | .aplus-debug h3, 23 | .aplus-debug h4, 24 | .aplus-debug h5, 25 | .aplus-debug h6 { 26 | color: #fff; 27 | font-family: inherit; 28 | font-weight: 700; 29 | margin: 0 0 10px 0; 30 | } 31 | 32 | .aplus-debug h1 { 33 | font-size: 32px; 34 | } 35 | 36 | .aplus-debug h2 { 37 | font-size: 24px; 38 | } 39 | 40 | .aplus-debug h3 { 41 | font-size: 19px; 42 | } 43 | 44 | .aplus-debug h4 { 45 | font-size: 16px; 46 | } 47 | 48 | .aplus-debug h5 { 49 | font-size: 13px; 50 | } 51 | 52 | .aplus-debug h6 { 53 | font-size: 11px; 54 | } 55 | 56 | .aplus-debug a { 57 | color: magenta; 58 | text-decoration: none; 59 | } 60 | 61 | .aplus-debug p { 62 | margin-top: 0; 63 | margin-bottom: 10px; 64 | } 65 | 66 | .aplus-debug hr { 67 | background: #222; 68 | border: 0; 69 | height: 1px; 70 | margin-block-start: 10px; 71 | margin-block-end: 10px; 72 | } 73 | 74 | .aplus-debug pre { 75 | background: #000; 76 | color: #eee; 77 | padding: 16px; 78 | margin: 0; 79 | overflow: auto; 80 | border: 1px solid #222; 81 | border-radius: 4px; 82 | } 83 | 84 | .aplus-debug code { 85 | background: #000; 86 | font-family: 'JetBrains Mono', Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; 87 | margin: 0; 88 | padding: 0; 89 | } 90 | 91 | .aplus-debug :not(td) > pre { 92 | margin-bottom: 10px !important; 93 | } 94 | 95 | .aplus-debug :not(pre) > code { 96 | background: #222; 97 | color: inherit; 98 | padding: 3px; 99 | border-radius: 4px; 100 | } 101 | 102 | .aplus-debug button { 103 | background-color: transparent; 104 | color: #fff; 105 | border: 1px solid transparent; 106 | cursor: pointer; 107 | font-family: inherit; 108 | font-size: 14px; 109 | font-weight: normal; 110 | border-radius: 4px; 111 | padding: 3px 5px; 112 | height: 11px; 113 | line-height: 11px; 114 | margin: 0; 115 | text-transform: none; 116 | } 117 | 118 | .aplus-debug button:hover { 119 | background-color: #eee; 120 | color: #000; 121 | border: 1px solid #eee; 122 | cursor: pointer; 123 | } 124 | 125 | .aplus-debug button.active { 126 | background-color: #fff; 127 | color: #000; 128 | border: 1px solid #fff; 129 | } 130 | 131 | .aplus-debug img { 132 | background: inherit; 133 | border: 0; 134 | } 135 | 136 | .aplus-debug select { 137 | background: none; 138 | color: #fff; 139 | border: 1px solid #222; 140 | font-size: 14px; 141 | padding: 3px 5px; 142 | height: 16px; 143 | line-height: 16px; 144 | } 145 | 146 | .aplus-debug select:hover { 147 | cursor: pointer; 148 | } 149 | 150 | .aplus-debug select:disabled { 151 | border-color: #000; 152 | color: #666; 153 | cursor: default; 154 | } 155 | 156 | .aplus-debug strong { 157 | color: inherit; 158 | } 159 | 160 | .aplus-debug ul { 161 | padding-left: 15px; 162 | } 163 | 164 | .aplus-debug .panels { 165 | background: #000; 166 | position: fixed; 167 | bottom: 43px; 168 | left: 0; 169 | width: 100%; 170 | z-index: 999; 171 | } 172 | 173 | .aplus-debug .panels .panel { 174 | display: none; 175 | margin: 0; 176 | } 177 | 178 | .aplus-debug .panels .panel .contents > * { 179 | display: none; 180 | } 181 | 182 | .aplus-debug .panels .panel .resize { 183 | cursor: ns-resize; 184 | width: 100%; 185 | height: 2px; 186 | background: #222; 187 | border-bottom: 2px solid #000; 188 | } 189 | 190 | .aplus-debug table { 191 | margin-top: 0; 192 | margin-bottom: 10px; 193 | border-collapse: collapse; 194 | border-spacing: 0; 195 | color: #eee; 196 | width: 100%; 197 | text-align: left; 198 | table-layout: auto; 199 | } 200 | 201 | .aplus-debug td table { 202 | margin: 0; 203 | } 204 | 205 | .aplus-debug table, 206 | .aplus-debug th, 207 | .aplus-debug td { 208 | border: 1px solid #222; 209 | } 210 | 211 | .aplus-debug td, 212 | .aplus-debug th { 213 | padding: 8px; 214 | } 215 | 216 | .aplus-debug th { 217 | color: #fff; 218 | background: #000; 219 | } 220 | 221 | .aplus-debug thead th { 222 | border-bottom: 2px solid #222; 223 | } 224 | 225 | .aplus-debug tbody th { 226 | border-right: 2px solid #222; 227 | } 228 | 229 | .aplus-debug tbody td table thead th { 230 | border-right-width: 1px; 231 | } 232 | 233 | .aplus-debug tr:hover { 234 | background: #111; 235 | } 236 | 237 | .aplus-debug tr.active { 238 | background: #333; 239 | } 240 | 241 | .aplus-debug .panels header { 242 | background-color: #000; 243 | border-bottom: 1px solid #222; 244 | height: 38px; 245 | line-height: 38px; 246 | padding: 0 10px 2px 10px; 247 | display: flex; 248 | align-items: center; 249 | } 250 | 251 | .aplus-debug .panels header .title { 252 | float: left; 253 | color: #fff; 254 | font-weight: bold; 255 | font-size: inherit; 256 | margin: 0; 257 | } 258 | 259 | .aplus-debug .panels header .actions { 260 | margin-left: auto; 261 | } 262 | 263 | .aplus-debug .panels header .collectors { 264 | margin-left: 5px; 265 | } 266 | 267 | .aplus-debug .panels .contents { 268 | height: 250px; 269 | padding: 10px; 270 | overflow: auto; 271 | } 272 | 273 | .aplus-debug .panels .contents a:hover { 274 | text-decoration: underline; 275 | } 276 | 277 | .aplus-debug .panels .contents button { 278 | border-color: #222; 279 | font-size: 16px; 280 | padding: 5px; 281 | } 282 | 283 | .aplus-debug .panels .contents button:hover { 284 | border-color: #fff; 285 | } 286 | 287 | .aplus-debug .toolbar { 288 | background-color: #000; 289 | border-top: 1px solid #222; 290 | border-right: 1px solid #222; 291 | box-shadow: rgba(255, 255, 255, .25) 0 2px 5px 0; 292 | height: 42px; 293 | line-height: 0; 294 | padding: 0 5px 0 5px; 295 | z-index: 1000; 296 | display: flex; 297 | align-items: center; 298 | position: sticky; 299 | } 300 | 301 | .aplus-debug .toolbar .icon { 302 | display: inline; 303 | cursor: pointer; 304 | } 305 | 306 | .aplus-debug .toolbar .collections { 307 | display: flex; 308 | align-items: center; 309 | width: 100%; 310 | } 311 | 312 | .aplus-debug .toolbar .collections .collection { 313 | margin-left: 5px; 314 | } 315 | 316 | .aplus-debug .toolbar .collections .info { 317 | margin-left: auto; 318 | } 319 | 320 | .aplus-debug .info-collection table th:last-of-type, 321 | .aplus-debug .info-collection table td:last-of-type { 322 | font-size: 14px; 323 | font-weight: normal; 324 | padding: 8px 0; 325 | width: 50% 326 | } 327 | 328 | .aplus-debug .info-collection table th span { 329 | float: left; 330 | text-align: right; 331 | width: 10%; 332 | } 333 | 334 | .aplus-debug .info-collection table td span { 335 | background: magenta; 336 | display: block; 337 | font-size: 12px; 338 | height: 16px; 339 | line-height: 16px; 340 | text-align: center; 341 | } 342 | 343 | .aplus-debug .info-collection table td:last-of-type { 344 | background: repeating-linear-gradient( 345 | to right, 346 | #111, 347 | #111 10%, 348 | #000 10%, 349 | #000 20% 350 | ); 351 | } 352 | 353 | .aplus-debug .info-collection table tr:hover td:last-of-type { 354 | background: repeating-linear-gradient( 355 | to right, 356 | #222, 357 | #222 10%, 358 | #111 10%, 359 | #111 20% 360 | ); 361 | } 362 | 363 | .aplus-debug.inverted { 364 | filter: invert(1); 365 | } 366 | -------------------------------------------------------------------------------- /src/ExceptionHandler.php: -------------------------------------------------------------------------------- 1 | 6 | * 7 | * For the full copyright and license information, please view the LICENSE 8 | * file that was distributed with this source code. 9 | */ 10 | namespace Framework\Debug; 11 | 12 | use ErrorException; 13 | use Framework\CLI\CLI; 14 | use Framework\Helpers\Isolation; 15 | use Framework\Language\Language; 16 | use Framework\Log\Logger; 17 | use InvalidArgumentException; 18 | use RuntimeException; 19 | use Throwable; 20 | 21 | /** 22 | * Class ExceptionHandler. 23 | * 24 | * @package debug 25 | */ 26 | class ExceptionHandler 27 | { 28 | /** 29 | * Development environment. 30 | * 31 | * @var string 32 | */ 33 | public const DEVELOPMENT = 'development'; 34 | /** 35 | * Production environment. 36 | * 37 | * @var string 38 | */ 39 | public const PRODUCTION = 'production'; 40 | protected string $developmentView = __DIR__ . '/Views/exceptions/development.php'; 41 | protected string $productionView = __DIR__ . '/Views/exceptions/production.php'; 42 | protected ?Logger $logger = null; 43 | protected string $environment = ExceptionHandler::PRODUCTION; 44 | protected Language $language; 45 | protected bool $testing = false; 46 | 47 | /** 48 | * ExceptionHandler constructor. 49 | * 50 | * @param string $environment 51 | * @param Logger|null $logger 52 | * @param Language|null $language 53 | * 54 | * @throws InvalidArgumentException if environment is invalid 55 | */ 56 | public function __construct( 57 | string $environment = ExceptionHandler::PRODUCTION, 58 | Logger $logger = null, 59 | Language $language = null 60 | ) { 61 | $this->setEnvironment($environment); 62 | if ($logger) { 63 | $this->logger = $logger; 64 | } 65 | if ($language) { 66 | $this->setLanguage($language); 67 | } 68 | } 69 | 70 | public function setEnvironment(string $environment) : static 71 | { 72 | if ( ! \in_array($environment, [ 73 | static::DEVELOPMENT, 74 | static::PRODUCTION, 75 | ], true)) { 76 | throw new InvalidArgumentException('Invalid environment: ' . $environment); 77 | } 78 | $this->environment = $environment; 79 | return $this; 80 | } 81 | 82 | public function getEnvironment() : string 83 | { 84 | return $this->environment; 85 | } 86 | 87 | /** 88 | * @return Logger|null 89 | */ 90 | public function getLogger() : ?Logger 91 | { 92 | return $this->logger; 93 | } 94 | 95 | public function setLanguage(Language $language = null) : static 96 | { 97 | $this->language = $language ?? new Language(); 98 | $this->language->addDirectory(__DIR__ . '/Languages'); 99 | return $this; 100 | } 101 | 102 | /** 103 | * @return Language 104 | */ 105 | public function getLanguage() : Language 106 | { 107 | if ( ! isset($this->language)) { 108 | $this->setLanguage(); 109 | } 110 | return $this->language; 111 | } 112 | 113 | protected function validateView(string $file) : string 114 | { 115 | $realpath = \realpath($file); 116 | if ( ! $realpath || ! \is_file($realpath)) { 117 | throw new InvalidArgumentException( 118 | 'Invalid exceptions view file: ' . $file 119 | ); 120 | } 121 | return $realpath; 122 | } 123 | 124 | public function setDevelopmentView(string $file) : static 125 | { 126 | $this->developmentView = $this->validateView($file); 127 | return $this; 128 | } 129 | 130 | public function getDevelopmentView() : string 131 | { 132 | return $this->developmentView; 133 | } 134 | 135 | public function setProductionView(string $file) : static 136 | { 137 | $this->productionView = $this->validateView($file); 138 | return $this; 139 | } 140 | 141 | public function getProductionView() : string 142 | { 143 | return $this->productionView; 144 | } 145 | 146 | public function initialize(bool $handleErrors = true) : void 147 | { 148 | \set_exception_handler([$this, 'exceptionHandler']); 149 | if ($handleErrors) { 150 | \set_error_handler([$this, 'errorHandler']); 151 | } 152 | } 153 | 154 | /** 155 | * Exception handler. 156 | * 157 | * @param Throwable $exception The Throwable, exception, instance 158 | * 159 | * @throws RuntimeException if view file is not found 160 | */ 161 | public function exceptionHandler(Throwable $exception) : void 162 | { 163 | if (\ob_get_length()) { 164 | \ob_end_clean(); 165 | } 166 | $this->log((string) $exception); 167 | if ($this->isCli()) { 168 | $this->cliError($exception); 169 | return; 170 | } 171 | \http_response_code(500); 172 | if ( ! \headers_sent()) { 173 | $this->sendHeaders(); 174 | } 175 | if ($this->isJson()) { 176 | $this->sendJson($exception); 177 | return; 178 | } 179 | $file = $this->getEnvironment() === static::DEVELOPMENT 180 | ? $this->getDevelopmentView() 181 | : $this->getProductionView(); 182 | Isolation::require($file, [ 183 | 'handler' => $this, 184 | 'exception' => $exception, 185 | ]); 186 | } 187 | 188 | protected function isCli() : bool 189 | { 190 | return \PHP_SAPI === 'cli' || \defined('STDIN'); 191 | } 192 | 193 | protected function isJson() : bool 194 | { 195 | return isset($_SERVER['HTTP_CONTENT_TYPE']) 196 | && \str_starts_with($_SERVER['HTTP_CONTENT_TYPE'], 'application/json'); 197 | } 198 | 199 | protected function sendJson(Throwable $exception) : void 200 | { 201 | $data = $this->getEnvironment() === static::DEVELOPMENT 202 | ? [ 203 | 'exception' => $exception::class, 204 | 'message' => $exception->getMessage(), 205 | 'file' => $exception->getFile(), 206 | 'line' => $exception->getLine(), 207 | 'trace' => $exception->getTrace(), 208 | ] 209 | : [ 210 | 'message' => $this->getLanguage()->render('debug', 'exceptionDescription'), 211 | ]; 212 | echo \json_encode([ 213 | 'status' => [ 214 | 'code' => 500, 215 | 'reason' => 'Internal Server Error', 216 | ], 217 | 'data' => $data, 218 | ], \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE); 219 | } 220 | 221 | protected function sendHeaders() : void 222 | { 223 | $contentType = 'text/html'; 224 | if ($this->isJson()) { 225 | $contentType = 'application/json'; 226 | } 227 | \header('Content-Type: ' . $contentType . '; charset=UTF-8'); 228 | } 229 | 230 | protected function cliError(Throwable $exception) : void 231 | { 232 | $language = $this->getLanguage(); 233 | $message = $language->render('debug', 'exception') 234 | . ': ' . $exception::class . \PHP_EOL; 235 | $message .= $language->render('debug', 'message') 236 | . ': ' . $exception->getMessage() . \PHP_EOL; 237 | $message .= $language->render('debug', 'file') 238 | . ': ' . $exception->getFile() . \PHP_EOL; 239 | $message .= $language->render('debug', 'line') 240 | . ': ' . $exception->getLine() . \PHP_EOL; 241 | $message .= $language->render('debug', 'trace') 242 | . ': ' . $exception->getTraceAsString(); 243 | CLI::error($message, $this->testing ? null : 1); 244 | } 245 | 246 | protected function log(string $message) : void 247 | { 248 | $this->getLogger()?->logCritical($message); 249 | } 250 | 251 | /** 252 | * Error handler. 253 | * 254 | * @param int $errno The level of the error raised 255 | * @param string $errstr The error message 256 | * @param string|null $errfile The filename that the error was raised in 257 | * @param int|null $errline The line number where the error was raised 258 | * 259 | * @see http://php.net/manual/en/function.set-error-handler.php 260 | * 261 | * @throws ErrorException if the error is included in the error_reporting 262 | * 263 | * @return bool 264 | */ 265 | public function errorHandler( 266 | int $errno, 267 | string $errstr, 268 | string $errfile = null, 269 | int $errline = null 270 | ) : bool { 271 | if ( ! (\error_reporting() & $errno)) { 272 | return true; 273 | } 274 | $type = match ($errno) { 275 | \E_ERROR => 'Error', 276 | \E_WARNING => 'Warning', 277 | \E_PARSE => 'Parse', 278 | \E_NOTICE => 'Notice', 279 | \E_CORE_ERROR => 'Core Error', 280 | \E_CORE_WARNING => 'Core Warning', 281 | \E_COMPILE_ERROR => 'Compile Error', 282 | \E_COMPILE_WARNING => 'Compile Warning', 283 | \E_USER_ERROR => 'User Error', 284 | \E_USER_WARNING => 'User Warning', 285 | \E_USER_NOTICE => 'User Notice', 286 | \E_STRICT => 'Strict', 287 | \E_RECOVERABLE_ERROR => 'Recoverable Error', 288 | \E_DEPRECATED => 'Deprecated', 289 | \E_USER_DEPRECATED => 'User Deprecated', 290 | \E_ALL => 'All', 291 | default => '', 292 | }; 293 | throw new ErrorException( 294 | ($type ? $type . ': ' : '') . $errstr, 295 | 0, 296 | $errno, 297 | $errfile, 298 | $errline 299 | ); 300 | } 301 | } 302 | -------------------------------------------------------------------------------- /src/Views/exceptions/development.php: -------------------------------------------------------------------------------- 1 | 10 | 11 | 13 | 14 | 15 | 16 | <?= $handler->getLanguage()->render('debug', 'exception') ?>: <?= 17 | htmlentities($exception->getMessage()) ?> 18 | 21 | 169 | 170 | 171 |
172 | getLanguage()->render('debug', 'exception') ?>: 173 |

174 | getLanguage()->render('debug', 'message') ?>: 175 |

getMessage()) ?>

176 |
177 |
178 |
179 | getLanguage()->render('debug', 'file') ?>: 180 |

getFile()) ?>

181 |
182 |
183 | getLanguage()->render('debug', 'line') ?>: 184 |

getLine() ?>

185 |
186 |
187 |
188 |
getLanguage()->render('debug', 'trace') ?>:
189 | getTrace(); 191 | if ($traces 192 | && isset($traces[0]['file']) 193 | && ($traces[0]['file'] !== $exception->getFile() 194 | || (isset($traces[0]['line']) && $traces[0]['line'] !== $exception->getLine())) 195 | ) { 196 | $traces = array_reverse($traces); 197 | $traces[] = [ 198 | 'file' => $exception->getFile(), 199 | 'line' => $exception->getLine(), 200 | ]; 201 | $traces = array_reverse($traces); 202 | } 203 | ?> 204 | $trace) : ?> 205 | 206 | 207 |
208 |
209 | 210 | 213 |
214 |
215 | = ($trace['line'] - 10) 224 | && $line <= ($trace['line'] + 10) 225 | ) { 226 | $pre .= rtrim((string) $code) . \PHP_EOL; 227 | $lines[] = $line; 228 | } 229 | $line++; 230 | } 231 | if ($handle) { 232 | fclose($handle); 233 | } 234 | ?> 235 |
'; 239 | echo $line . \PHP_EOL; 240 | echo ''; 241 | } else { 242 | echo $line . \PHP_EOL; 243 | } 244 | } 245 | ?>
246 |
247 |
248 |
249 | 250 |
251 |
252 | File 253 | is not readable. 254 |
255 |
256 | 257 | 258 | 259 |
260 |
261 |
Input:
262 | filter_input_array(\INPUT_ENV) ?: [], 265 | 'SERVER' => filter_input_array(\INPUT_SERVER) ?: [], 266 | 'GET' => ArraySimple::convert(filter_input_array(\INPUT_GET) ?: []), 267 | 'POST' => ArraySimple::convert(filter_input_array(\INPUT_POST) ?: []), 268 | 'COOKIE' => filter_input_array(\INPUT_COOKIE) ?: [], 269 | ]; 270 | foreach ($input as &$item) { 271 | ksort($item); 272 | } 273 | unset($item); 274 | ?> 275 | 276 | $values) : ?> 277 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | $value) : ?> 290 | 291 | 292 | 293 | 294 | 295 | 296 |
297 | 298 |
299 | getLogger()?->getLastLog(); 301 | if ($log): ?> 302 |
303 |
Log:
304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 326 | 327 |
Datetime) ?>
Timetime) ?>
Levellevel->name) ?>
IDid) ?>
Message 324 |
message) ?>
325 |
328 |
329 | 331 | 334 | 335 | 336 | -------------------------------------------------------------------------------- /src/Views/assets/prism.js: -------------------------------------------------------------------------------- 1 | /* PrismJS 1.29.0 2 | https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript+bash+css-extras+csv+docker+git+http+icu-message-format+ignore+ini+javadoclike+js-extras+json+log+markdown+markup-templating+nginx+php+phpdoc+php-extras+regex+sql&plugins=line-highlight */ 3 | var _self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},Prism=function(e){var n=/(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i,t=0,r={},a={manual:e.Prism&&e.Prism.manual,disableWorkerMessageHandler:e.Prism&&e.Prism.disableWorkerMessageHandler,util:{encode:function e(n){return n instanceof i?new i(n.type,e(n.content),n.alias):Array.isArray(n)?n.map(e):n.replace(/&/g,"&").replace(/=g.reach);A+=w.value.length,w=w.next){var E=w.value;if(n.length>e.length)return;if(!(E instanceof i)){var P,L=1;if(y){if(!(P=l(b,A,e,m))||P.index>=e.length)break;var S=P.index,O=P.index+P[0].length,j=A;for(j+=w.value.length;S>=j;)j+=(w=w.next).value.length;if(A=j-=w.value.length,w.value instanceof i)continue;for(var C=w;C!==n.tail&&(jg.reach&&(g.reach=W);var z=w.prev;if(_&&(z=u(n,z,_),A+=_.length),c(n,z,L),w=u(n,z,new i(f,p?a.tokenize(N,p):N,k,N)),M&&u(n,w,M),L>1){var I={cause:f+","+d,reach:W};o(e,n,t,w.prev,A,I),g&&I.reach>g.reach&&(g.reach=I.reach)}}}}}}function s(){var e={value:null,prev:null,next:null},n={value:null,prev:e,next:null};e.next=n,this.head=e,this.tail=n,this.length=0}function u(e,n,t){var r=n.next,a={value:t,prev:n,next:r};return n.next=a,r.prev=a,e.length++,a}function c(e,n,t){for(var r=n.next,a=0;a"+i.content+""},!e.document)return e.addEventListener?(a.disableWorkerMessageHandler||e.addEventListener("message",(function(n){var t=JSON.parse(n.data),r=t.language,i=t.code,l=t.immediateClose;e.postMessage(a.highlight(i,a.languages[r],r)),l&&e.close()}),!1),a):a;var g=a.util.currentScript();function f(){a.manual||a.highlightAll()}if(g&&(a.filename=g.src,g.hasAttribute("data-manual")&&(a.manual=!0)),!a.manual){var h=document.readyState;"loading"===h||"interactive"===h&&g&&g.defer?document.addEventListener("DOMContentLoaded",f):window.requestAnimationFrame?window.requestAnimationFrame(f):window.setTimeout(f,16)}return a}(_self);"undefined"!=typeof module&&module.exports&&(module.exports=Prism),"undefined"!=typeof global&&(global.Prism=Prism); 4 | Prism.languages.markup={comment:{pattern://,greedy:!0},prolog:{pattern:/<\?[\s\S]+?\?>/,greedy:!0},doctype:{pattern:/"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|)*\]\s*)?>/i,greedy:!0,inside:{"internal-subset":{pattern:/(^[^\[]*\[)[\s\S]+(?=\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},punctuation:/^$|[[\]]/,"doctype-tag":/^DOCTYPE/i,name:/[^\s<>'"]+/}},cdata:{pattern://i,greedy:!0},tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"special-attr":[],"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:"attr-equals"},{pattern:/^(\s*)["']|["']$/,lookbehind:!0}]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/&#x?[\da-f]{1,8};/i]},Prism.languages.markup.tag.inside["attr-value"].inside.entity=Prism.languages.markup.entity,Prism.languages.markup.doctype.inside["internal-subset"].inside=Prism.languages.markup,Prism.hooks.add("wrap",(function(a){"entity"===a.type&&(a.attributes.title=a.content.replace(/&/,"&"))})),Object.defineProperty(Prism.languages.markup.tag,"addInlined",{value:function(a,e){var s={};s["language-"+e]={pattern:/(^$)/i,lookbehind:!0,inside:Prism.languages[e]},s.cdata=/^$/i;var t={"included-cdata":{pattern://i,inside:s}};t["language-"+e]={pattern:/[\s\S]+/,inside:Prism.languages[e]};var n={};n[a]={pattern:RegExp("(<__[^>]*>)(?:))*\\]\\]>|(?!)".replace(/__/g,(function(){return a})),"i"),lookbehind:!0,greedy:!0,inside:t},Prism.languages.insertBefore("markup","cdata",n)}}),Object.defineProperty(Prism.languages.markup.tag,"addAttribute",{value:function(a,e){Prism.languages.markup.tag.inside["special-attr"].push({pattern:RegExp("(^|[\"'\\s])(?:"+a+")\\s*=\\s*(?:\"[^\"]*\"|'[^']*'|[^\\s'\">=]+(?=[\\s>]))","i"),lookbehind:!0,inside:{"attr-name":/^[^\s=]+/,"attr-value":{pattern:/=[\s\S]+/,inside:{value:{pattern:/(^=\s*(["']|(?!["'])))\S[\s\S]*(?=\2$)/,lookbehind:!0,alias:[e,"language-"+e],inside:Prism.languages[e]},punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}}}})}}),Prism.languages.html=Prism.languages.markup,Prism.languages.mathml=Prism.languages.markup,Prism.languages.svg=Prism.languages.markup,Prism.languages.xml=Prism.languages.extend("markup",{}),Prism.languages.ssml=Prism.languages.xml,Prism.languages.atom=Prism.languages.xml,Prism.languages.rss=Prism.languages.xml; 5 | !function(s){var e=/(?:"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n])*')/;s.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:RegExp("@[\\w-](?:[^;{\\s\"']|\\s+(?!\\s)|"+e.source+")*?(?:;|(?=\\s*\\{))"),inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/,lookbehind:!0,alias:"selector"},keyword:{pattern:/(^|[^\w-])(?:and|not|only|or)(?![\w-])/,lookbehind:!0}}},url:{pattern:RegExp("\\burl\\((?:"+e.source+"|(?:[^\\\\\r\n()\"']|\\\\[^])*)\\)","i"),greedy:!0,inside:{function:/^url/i,punctuation:/^\(|\)$/,string:{pattern:RegExp("^"+e.source+"$"),alias:"url"}}},selector:{pattern:RegExp("(^|[{}\\s])[^{}\\s](?:[^{};\"'\\s]|\\s+(?![\\s{])|"+e.source+")*(?=\\s*\\{)"),lookbehind:!0},string:{pattern:e,greedy:!0},property:{pattern:/(^|[^-\w\xA0-\uFFFF])(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i,lookbehind:!0},important:/!important\b/i,function:{pattern:/(^|[^-a-z0-9])[-a-z0-9]+(?=\()/i,lookbehind:!0},punctuation:/[(){};:,]/},s.languages.css.atrule.inside.rest=s.languages.css;var t=s.languages.markup;t&&(t.tag.addInlined("style","css"),t.tag.addAttribute("style","css"))}(Prism); 6 | Prism.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|trait)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:break|catch|continue|do|else|finally|for|function|if|in|instanceof|new|null|return|throw|try|while)\b/,boolean:/\b(?:false|true)\b/,function:/\b\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/}; 7 | Prism.languages.javascript=Prism.languages.extend("clike",{"class-name":[Prism.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:constructor|prototype))/,lookbehind:!0}],keyword:[{pattern:/((?:^|\})\s*)catch\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|function|(?:get|set)(?=\s*(?:[#\[$\w\xA0-\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],function:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,number:{pattern:RegExp("(^|[^\\w$])(?:NaN|Infinity|0[bB][01]+(?:_[01]+)*n?|0[oO][0-7]+(?:_[0-7]+)*n?|0[xX][\\dA-Fa-f]+(?:_[\\dA-Fa-f]+)*n?|\\d+(?:_\\d+)*n|(?:\\d+(?:_\\d+)*(?:\\.(?:\\d+(?:_\\d+)*)?)?|\\.\\d+(?:_\\d+)*)(?:[Ee][+-]?\\d+(?:_\\d+)*)?)(?![\\w$])"),lookbehind:!0},operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/}),Prism.languages.javascript["class-name"][0].pattern=/(\b(?:class|extends|implements|instanceof|interface|new)\s+)[\w.\\]+/,Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:RegExp("((?:^|[^$\\w\\xA0-\\uFFFF.\"'\\])\\s]|\\b(?:return|yield))\\s*)/(?:(?:\\[(?:[^\\]\\\\\r\n]|\\\\.)*\\]|\\\\.|[^/\\\\\\[\r\n])+/[dgimyus]{0,7}|(?:\\[(?:[^[\\]\\\\\r\n]|\\\\.|\\[(?:[^[\\]\\\\\r\n]|\\\\.|\\[(?:[^[\\]\\\\\r\n]|\\\\.)*\\])*\\])*\\]|\\\\.|[^/\\\\\\[\r\n])+/[dgimyus]{0,7}v[dgimyus]{0,7})(?=(?:\\s|/\\*(?:[^*]|\\*(?!/))*\\*/)*(?:$|[\r\n,.;:})\\]]|//))"),lookbehind:!0,greedy:!0,inside:{"regex-source":{pattern:/^(\/)[\s\S]+(?=\/[a-z]*$)/,lookbehind:!0,alias:"language-regex",inside:Prism.languages.regex},"regex-delimiter":/^\/|\/$/,"regex-flags":/^[a-z]+$/}},"function-variable":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,lookbehind:!0,inside:Prism.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),Prism.languages.insertBefore("javascript","string",{hashbang:{pattern:/^#!.*/,greedy:!0,alias:"comment"},"template-string":{pattern:/`(?:\\[\s\S]|\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}|(?!\$\{)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:Prism.languages.javascript}},string:/[\s\S]+/}},"string-property":{pattern:/((?:^|[,{])[ \t]*)(["'])(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2(?=\s*:)/m,lookbehind:!0,greedy:!0,alias:"property"}}),Prism.languages.insertBefore("javascript","operator",{"literal-property":{pattern:/((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m,lookbehind:!0,alias:"property"}}),Prism.languages.markup&&(Prism.languages.markup.tag.addInlined("script","javascript"),Prism.languages.markup.tag.addAttribute("on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)","javascript")),Prism.languages.js=Prism.languages.javascript; 8 | !function(e){var t="\\b(?:BASH|BASHOPTS|BASH_ALIASES|BASH_ARGC|BASH_ARGV|BASH_CMDS|BASH_COMPLETION_COMPAT_DIR|BASH_LINENO|BASH_REMATCH|BASH_SOURCE|BASH_VERSINFO|BASH_VERSION|COLORTERM|COLUMNS|COMP_WORDBREAKS|DBUS_SESSION_BUS_ADDRESS|DEFAULTS_PATH|DESKTOP_SESSION|DIRSTACK|DISPLAY|EUID|GDMSESSION|GDM_LANG|GNOME_KEYRING_CONTROL|GNOME_KEYRING_PID|GPG_AGENT_INFO|GROUPS|HISTCONTROL|HISTFILE|HISTFILESIZE|HISTSIZE|HOME|HOSTNAME|HOSTTYPE|IFS|INSTANCE|JOB|LANG|LANGUAGE|LC_ADDRESS|LC_ALL|LC_IDENTIFICATION|LC_MEASUREMENT|LC_MONETARY|LC_NAME|LC_NUMERIC|LC_PAPER|LC_TELEPHONE|LC_TIME|LESSCLOSE|LESSOPEN|LINES|LOGNAME|LS_COLORS|MACHTYPE|MAILCHECK|MANDATORY_PATH|NO_AT_BRIDGE|OLDPWD|OPTERR|OPTIND|ORBIT_SOCKETDIR|OSTYPE|PAPERSIZE|PATH|PIPESTATUS|PPID|PS1|PS2|PS3|PS4|PWD|RANDOM|REPLY|SECONDS|SELINUX_INIT|SESSION|SESSIONTYPE|SESSION_MANAGER|SHELL|SHELLOPTS|SHLVL|SSH_AUTH_SOCK|TERM|UID|UPSTART_EVENTS|UPSTART_INSTANCE|UPSTART_JOB|UPSTART_SESSION|USER|WINDOWID|XAUTHORITY|XDG_CONFIG_DIRS|XDG_CURRENT_DESKTOP|XDG_DATA_DIRS|XDG_GREETER_DATA_DIR|XDG_MENU_PREFIX|XDG_RUNTIME_DIR|XDG_SEAT|XDG_SEAT_PATH|XDG_SESSION_DESKTOP|XDG_SESSION_ID|XDG_SESSION_PATH|XDG_SESSION_TYPE|XDG_VTNR|XMODIFIERS)\\b",a={pattern:/(^(["']?)\w+\2)[ \t]+\S.*/,lookbehind:!0,alias:"punctuation",inside:null},n={bash:a,environment:{pattern:RegExp("\\$"+t),alias:"constant"},variable:[{pattern:/\$?\(\([\s\S]+?\)\)/,greedy:!0,inside:{variable:[{pattern:/(^\$\(\([\s\S]+)\)\)/,lookbehind:!0},/^\$\(\(/],number:/\b0x[\dA-Fa-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[Ee]-?\d+)?/,operator:/--|\+\+|\*\*=?|<<=?|>>=?|&&|\|\||[=!+\-*/%<>^&|]=?|[?~:]/,punctuation:/\(\(?|\)\)?|,|;/}},{pattern:/\$\((?:\([^)]+\)|[^()])+\)|`[^`]+`/,greedy:!0,inside:{variable:/^\$\(|^`|\)$|`$/}},{pattern:/\$\{[^}]+\}/,greedy:!0,inside:{operator:/:[-=?+]?|[!\/]|##?|%%?|\^\^?|,,?/,punctuation:/[\[\]]/,environment:{pattern:RegExp("(\\{)"+t),lookbehind:!0,alias:"constant"}}},/\$(?:\w+|[#?*!@$])/],entity:/\\(?:[abceEfnrtv\\"]|O?[0-7]{1,3}|U[0-9a-fA-F]{8}|u[0-9a-fA-F]{4}|x[0-9a-fA-F]{1,2})/};e.languages.bash={shebang:{pattern:/^#!\s*\/.*/,alias:"important"},comment:{pattern:/(^|[^"{\\$])#.*/,lookbehind:!0},"function-name":[{pattern:/(\bfunction\s+)[\w-]+(?=(?:\s*\(?:\s*\))?\s*\{)/,lookbehind:!0,alias:"function"},{pattern:/\b[\w-]+(?=\s*\(\s*\)\s*\{)/,alias:"function"}],"for-or-select":{pattern:/(\b(?:for|select)\s+)\w+(?=\s+in\s)/,alias:"variable",lookbehind:!0},"assign-left":{pattern:/(^|[\s;|&]|[<>]\()\w+(?:\.\w+)*(?=\+?=)/,inside:{environment:{pattern:RegExp("(^|[\\s;|&]|[<>]\\()"+t),lookbehind:!0,alias:"constant"}},alias:"variable",lookbehind:!0},parameter:{pattern:/(^|\s)-{1,2}(?:\w+:[+-]?)?\w+(?:\.\w+)*(?=[=\s]|$)/,alias:"variable",lookbehind:!0},string:[{pattern:/((?:^|[^<])<<-?\s*)(\w+)\s[\s\S]*?(?:\r?\n|\r)\2/,lookbehind:!0,greedy:!0,inside:n},{pattern:/((?:^|[^<])<<-?\s*)(["'])(\w+)\2\s[\s\S]*?(?:\r?\n|\r)\3/,lookbehind:!0,greedy:!0,inside:{bash:a}},{pattern:/(^|[^\\](?:\\\\)*)"(?:\\[\s\S]|\$\([^)]+\)|\$(?!\()|`[^`]+`|[^"\\`$])*"/,lookbehind:!0,greedy:!0,inside:n},{pattern:/(^|[^$\\])'[^']*'/,lookbehind:!0,greedy:!0},{pattern:/\$'(?:[^'\\]|\\[\s\S])*'/,greedy:!0,inside:{entity:n.entity}}],environment:{pattern:RegExp("\\$?"+t),alias:"constant"},variable:n.variable,function:{pattern:/(^|[\s;|&]|[<>]\()(?:add|apropos|apt|apt-cache|apt-get|aptitude|aspell|automysqlbackup|awk|basename|bash|bc|bconsole|bg|bzip2|cal|cargo|cat|cfdisk|chgrp|chkconfig|chmod|chown|chroot|cksum|clear|cmp|column|comm|composer|cp|cron|crontab|csplit|curl|cut|date|dc|dd|ddrescue|debootstrap|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|docker|docker-compose|du|egrep|eject|env|ethtool|expand|expect|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|git|gparted|grep|groupadd|groupdel|groupmod|groups|grub-mkconfig|gzip|halt|head|hg|history|host|hostname|htop|iconv|id|ifconfig|ifdown|ifup|import|install|ip|java|jobs|join|kill|killall|less|link|ln|locate|logname|logrotate|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|lynx|make|man|mc|mdadm|mkconfig|mkdir|mke2fs|mkfifo|mkfs|mkisofs|mknod|mkswap|mmv|more|most|mount|mtools|mtr|mutt|mv|nano|nc|netstat|nice|nl|node|nohup|notify-send|npm|nslookup|op|open|parted|passwd|paste|pathchk|ping|pkill|pnpm|podman|podman-compose|popd|pr|printcap|printenv|ps|pushd|pv|quota|quotacheck|quotactl|ram|rar|rcp|reboot|remsync|rename|renice|rev|rm|rmdir|rpm|rsync|scp|screen|sdiff|sed|sendmail|seq|service|sftp|sh|shellcheck|shuf|shutdown|sleep|slocate|sort|split|ssh|stat|strace|su|sudo|sum|suspend|swapon|sync|sysctl|tac|tail|tar|tee|time|timeout|top|touch|tr|traceroute|tsort|tty|umount|uname|unexpand|uniq|units|unrar|unshar|unzip|update-grub|uptime|useradd|userdel|usermod|users|uudecode|uuencode|v|vcpkg|vdir|vi|vim|virsh|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yarn|yes|zenity|zip|zsh|zypper)(?=$|[)\s;|&])/,lookbehind:!0},keyword:{pattern:/(^|[\s;|&]|[<>]\()(?:case|do|done|elif|else|esac|fi|for|function|if|in|select|then|until|while)(?=$|[)\s;|&])/,lookbehind:!0},builtin:{pattern:/(^|[\s;|&]|[<>]\()(?:\.|:|alias|bind|break|builtin|caller|cd|command|continue|declare|echo|enable|eval|exec|exit|export|getopts|hash|help|let|local|logout|mapfile|printf|pwd|read|readarray|readonly|return|set|shift|shopt|source|test|times|trap|type|typeset|ulimit|umask|unalias|unset)(?=$|[)\s;|&])/,lookbehind:!0,alias:"class-name"},boolean:{pattern:/(^|[\s;|&]|[<>]\()(?:false|true)(?=$|[)\s;|&])/,lookbehind:!0},"file-descriptor":{pattern:/\B&\d\b/,alias:"important"},operator:{pattern:/\d?<>|>\||\+=|=[=~]?|!=?|<<[<-]?|[&\d]?>>|\d[<>]&?|[<>][&=]?|&[>&]?|\|[&|]?/,inside:{"file-descriptor":{pattern:/^\d/,alias:"important"}}},punctuation:/\$?\(\(?|\)\)?|\.\.|[{}[\];\\]/,number:{pattern:/(^|\s)(?:[1-9]\d*|0)(?:[.,]\d+)?\b/,lookbehind:!0}},a.inside=e.languages.bash;for(var s=["comment","function-name","for-or-select","assign-left","parameter","string","environment","function","keyword","builtin","boolean","file-descriptor","operator","punctuation","number"],o=n.variable[1].inside,i=0;i|\+|~|\|\|/,punctuation:/[(),]/}},e.languages.css.atrule.inside["selector-function-argument"].inside=a,e.languages.insertBefore("css","property",{variable:{pattern:/(^|[^-\w\xA0-\uFFFF])--(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*/i,lookbehind:!0}});var r={pattern:/(\b\d+)(?:%|[a-z]+(?![\w-]))/,lookbehind:!0},i={pattern:/(^|[^\w.-])-?(?:\d+(?:\.\d+)?|\.\d+)/,lookbehind:!0};e.languages.insertBefore("css","function",{operator:{pattern:/(\s)[+\-*\/](?=\s)/,lookbehind:!0},hexcode:{pattern:/\B#[\da-f]{3,8}\b/i,alias:"color"},color:[{pattern:/(^|[^\w-])(?:AliceBlue|AntiqueWhite|Aqua|Aquamarine|Azure|Beige|Bisque|Black|BlanchedAlmond|Blue|BlueViolet|Brown|BurlyWood|CadetBlue|Chartreuse|Chocolate|Coral|CornflowerBlue|Cornsilk|Crimson|Cyan|DarkBlue|DarkCyan|DarkGoldenRod|DarkGr[ae]y|DarkGreen|DarkKhaki|DarkMagenta|DarkOliveGreen|DarkOrange|DarkOrchid|DarkRed|DarkSalmon|DarkSeaGreen|DarkSlateBlue|DarkSlateGr[ae]y|DarkTurquoise|DarkViolet|DeepPink|DeepSkyBlue|DimGr[ae]y|DodgerBlue|FireBrick|FloralWhite|ForestGreen|Fuchsia|Gainsboro|GhostWhite|Gold|GoldenRod|Gr[ae]y|Green|GreenYellow|HoneyDew|HotPink|IndianRed|Indigo|Ivory|Khaki|Lavender|LavenderBlush|LawnGreen|LemonChiffon|LightBlue|LightCoral|LightCyan|LightGoldenRodYellow|LightGr[ae]y|LightGreen|LightPink|LightSalmon|LightSeaGreen|LightSkyBlue|LightSlateGr[ae]y|LightSteelBlue|LightYellow|Lime|LimeGreen|Linen|Magenta|Maroon|MediumAquaMarine|MediumBlue|MediumOrchid|MediumPurple|MediumSeaGreen|MediumSlateBlue|MediumSpringGreen|MediumTurquoise|MediumVioletRed|MidnightBlue|MintCream|MistyRose|Moccasin|NavajoWhite|Navy|OldLace|Olive|OliveDrab|Orange|OrangeRed|Orchid|PaleGoldenRod|PaleGreen|PaleTurquoise|PaleVioletRed|PapayaWhip|PeachPuff|Peru|Pink|Plum|PowderBlue|Purple|RebeccaPurple|Red|RosyBrown|RoyalBlue|SaddleBrown|Salmon|SandyBrown|SeaGreen|SeaShell|Sienna|Silver|SkyBlue|SlateBlue|SlateGr[ae]y|Snow|SpringGreen|SteelBlue|Tan|Teal|Thistle|Tomato|Transparent|Turquoise|Violet|Wheat|White|WhiteSmoke|Yellow|YellowGreen)(?![\w-])/i,lookbehind:!0},{pattern:/\b(?:hsl|rgb)\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*\)\B|\b(?:hsl|rgb)a\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*,\s*(?:0|0?\.\d+|1)\s*\)\B/i,inside:{unit:r,number:i,function:/[\w-]+(?=\()/,punctuation:/[(),]/}}],entity:/\\[\da-f]{1,8}/i,unit:r,number:i})}(Prism); 10 | Prism.languages.csv={value:/[^\r\n,"]+|"(?:[^"]|"")*"(?!")/,punctuation:/,/}; 11 | !function(e){var n="(?:[ \t]+(?![ \t])(?:)?|)".replace(//g,(function(){return"\\\\[\r\n](?:\\s|\\\\[\r\n]|#.*(?!.))*(?![\\s#]|\\\\[\r\n])"})),r="\"(?:[^\"\\\\\r\n]|\\\\(?:\r\n|[^]))*\"|'(?:[^'\\\\\r\n]|\\\\(?:\r\n|[^]))*'",t="--[\\w-]+=(?:|(?![\"'])(?:[^\\s\\\\]|\\\\.)+)".replace(//g,(function(){return r})),o={pattern:RegExp(r),greedy:!0},i={pattern:/(^[ \t]*)#.*/m,lookbehind:!0,greedy:!0};function a(e,r){return e=e.replace(//g,(function(){return t})).replace(//g,(function(){return n})),RegExp(e,r)}e.languages.docker={instruction:{pattern:/(^[ \t]*)(?:ADD|ARG|CMD|COPY|ENTRYPOINT|ENV|EXPOSE|FROM|HEALTHCHECK|LABEL|MAINTAINER|ONBUILD|RUN|SHELL|STOPSIGNAL|USER|VOLUME|WORKDIR)(?=\s)(?:\\.|[^\r\n\\])*(?:\\$(?:\s|#.*$)*(?![\s#])(?:\\.|[^\r\n\\])*)*/im,lookbehind:!0,greedy:!0,inside:{options:{pattern:a("(^(?:ONBUILD)?\\w+)(?:)*","i"),lookbehind:!0,greedy:!0,inside:{property:{pattern:/(^|\s)--[\w-]+/,lookbehind:!0},string:[o,{pattern:/(=)(?!["'])(?:[^\s\\]|\\.)+/,lookbehind:!0}],operator:/\\$/m,punctuation:/=/}},keyword:[{pattern:a("(^(?:ONBUILD)?HEALTHCHECK(?:)*)(?:CMD|NONE)\\b","i"),lookbehind:!0,greedy:!0},{pattern:a("(^(?:ONBUILD)?FROM(?:)*(?!--)[^ \t\\\\]+)AS","i"),lookbehind:!0,greedy:!0},{pattern:a("(^ONBUILD)\\w+","i"),lookbehind:!0,greedy:!0},{pattern:/^\w+/,greedy:!0}],comment:i,string:o,variable:/\$(?:\w+|\{[^{}"'\\]*\})/,operator:/\\$/m}},comment:i},e.languages.dockerfile=e.languages.docker}(Prism); 12 | Prism.languages.git={comment:/^#.*/m,deleted:/^[-–].*/m,inserted:/^\+.*/m,string:/("|')(?:\\.|(?!\1)[^\\\r\n])*\1/,command:{pattern:/^.*\$ git .*$/m,inside:{parameter:/\s--?\w+/}},coord:/^@@.*@@$/m,"commit-sha1":/^commit \w{40}$/m}; 13 | !function(t){function a(t){return RegExp("(^(?:"+t+"):[ \t]*(?![ \t]))[^]+","i")}t.languages.http={"request-line":{pattern:/^(?:CONNECT|DELETE|GET|HEAD|OPTIONS|PATCH|POST|PRI|PUT|SEARCH|TRACE)\s(?:https?:\/\/|\/)\S*\sHTTP\/[\d.]+/m,inside:{method:{pattern:/^[A-Z]+\b/,alias:"property"},"request-target":{pattern:/^(\s)(?:https?:\/\/|\/)\S*(?=\s)/,lookbehind:!0,alias:"url",inside:t.languages.uri},"http-version":{pattern:/^(\s)HTTP\/[\d.]+/,lookbehind:!0,alias:"property"}}},"response-status":{pattern:/^HTTP\/[\d.]+ \d+ .+/m,inside:{"http-version":{pattern:/^HTTP\/[\d.]+/,alias:"property"},"status-code":{pattern:/^(\s)\d+(?=\s)/,lookbehind:!0,alias:"number"},"reason-phrase":{pattern:/^(\s).+/,lookbehind:!0,alias:"string"}}},header:{pattern:/^[\w-]+:.+(?:(?:\r\n?|\n)[ \t].+)*/m,inside:{"header-value":[{pattern:a("Content-Security-Policy"),lookbehind:!0,alias:["csp","languages-csp"],inside:t.languages.csp},{pattern:a("Public-Key-Pins(?:-Report-Only)?"),lookbehind:!0,alias:["hpkp","languages-hpkp"],inside:t.languages.hpkp},{pattern:a("Strict-Transport-Security"),lookbehind:!0,alias:["hsts","languages-hsts"],inside:t.languages.hsts},{pattern:a("[^:]+"),lookbehind:!0}],"header-name":{pattern:/^[^:]+/,alias:"keyword"},punctuation:/^:/}}};var e,n=t.languages,s={"application/javascript":n.javascript,"application/json":n.json||n.javascript,"application/xml":n.xml,"text/xml":n.xml,"text/html":n.html,"text/css":n.css,"text/plain":n.plain},i={"application/json":!0,"application/xml":!0};function r(t){var a=t.replace(/^[a-z]+\//,"");return"(?:"+t+"|\\w+/(?:[\\w.-]+\\+)+"+a+"(?![+\\w.-]))"}for(var p in s)if(s[p]){e=e||{};var l=i[p]?r(p):p;e[p.replace(/\//g,"-")]={pattern:RegExp("(content-type:\\s*"+l+"(?:(?:\r\n?|\n)[\\w-].*)*(?:\r(?:\n|(?!\n))|\n))[^ \t\\w-][^]*","i"),lookbehind:!0,inside:s[p]}}e&&t.languages.insertBefore("http","header",e)}(Prism); 14 | !function(e){function t(e,s){return s<=0?"[]":e.replace(//g,(function(){return t(e,s-1)}))}var s=/'[{}:=,](?:[^']|'')*'(?!')/,n={pattern:/''/,greedy:!0,alias:"operator"},r={pattern:s,greedy:!0,inside:{escape:n}},a=t("\\{(?:[^{}']|'(?![{},'])|''||)*\\}".replace(//g,(function(){return s.source})),8),i={pattern:RegExp(a),inside:{message:{pattern:/^(\{)[\s\S]+(?=\}$)/,lookbehind:!0,inside:null},"message-delimiter":{pattern:/./,alias:"punctuation"}}};e.languages["icu-message-format"]={argument:{pattern:RegExp(a),greedy:!0,inside:{content:{pattern:/^(\{)[\s\S]+(?=\}$)/,lookbehind:!0,inside:{"argument-name":{pattern:/^(\s*)[^{}:=,\s]+/,lookbehind:!0},"choice-style":{pattern:/^(\s*,\s*choice\s*,\s*)\S(?:[\s\S]*\S)?/,lookbehind:!0,inside:{punctuation:/\|/,range:{pattern:/^(\s*)[+-]?(?:\d+(?:\.\d*)?|\u221e)\s*[<#\u2264]/,lookbehind:!0,inside:{operator:/[<#\u2264]/,number:/\S+/}},rest:null}},"plural-style":{pattern:/^(\s*,\s*(?:plural|selectordinal)\s*,\s*)\S(?:[\s\S]*\S)?/,lookbehind:!0,inside:{offset:/^offset:\s*\d+/,"nested-message":i,selector:{pattern:/=\d+|[^{}:=,\s]+/,inside:{keyword:/^(?:few|many|one|other|two|zero)$/}}}},"select-style":{pattern:/^(\s*,\s*select\s*,\s*)\S(?:[\s\S]*\S)?/,lookbehind:!0,inside:{"nested-message":i,selector:{pattern:/[^{}:=,\s]+/,inside:{keyword:/^other$/}}}},keyword:/\b(?:choice|plural|select|selectordinal)\b/,"arg-type":{pattern:/\b(?:date|duration|number|ordinal|spellout|time)\b/,alias:"keyword"},"arg-skeleton":{pattern:/(,\s*)::[^{}:=,\s]+/,lookbehind:!0},"arg-style":{pattern:/(,\s*)(?:currency|full|integer|long|medium|percent|short)(?=\s*$)/,lookbehind:!0},"arg-style-text":{pattern:RegExp("(^\\s*,\\s*(?=\\S))"+t("(?:[^{}']|'[^']*'|\\{(?:)?\\})+",8)+"$"),lookbehind:!0,alias:"string"},punctuation:/,/}},"argument-delimiter":{pattern:/./,alias:"operator"}}},escape:n,string:r},i.inside.message.inside=e.languages["icu-message-format"],e.languages["icu-message-format"].argument.inside.content.inside["choice-style"].inside.rest=e.languages["icu-message-format"]}(Prism); 15 | !function(n){n.languages.ignore={comment:/^#.*/m,entry:{pattern:/\S(?:.*(?:(?:\\ )|\S))?/,alias:"string",inside:{operator:/^!|\*\*?|\?/,regex:{pattern:/(^|[^\\])\[[^\[\]]*\]/,lookbehind:!0},punctuation:/\//}}},n.languages.gitignore=n.languages.ignore,n.languages.hgignore=n.languages.ignore,n.languages.npmignore=n.languages.ignore}(Prism); 16 | Prism.languages.ini={comment:{pattern:/(^[ \f\t\v]*)[#;][^\n\r]*/m,lookbehind:!0},section:{pattern:/(^[ \f\t\v]*)\[[^\n\r\]]*\]?/m,lookbehind:!0,inside:{"section-name":{pattern:/(^\[[ \f\t\v]*)[^ \f\t\v\]]+(?:[ \f\t\v]+[^ \f\t\v\]]+)*/,lookbehind:!0,alias:"selector"},punctuation:/\[|\]/}},key:{pattern:/(^[ \f\t\v]*)[^ \f\n\r\t\v=]+(?:[ \f\t\v]+[^ \f\n\r\t\v=]+)*(?=[ \f\t\v]*=)/m,lookbehind:!0,alias:"attr-name"},value:{pattern:/(=[ \f\t\v]*)[^ \f\n\r\t\v]+(?:[ \f\t\v]+[^ \f\n\r\t\v]+)*/,lookbehind:!0,alias:"attr-value",inside:{"inner-value":{pattern:/^("|').+(?=\1$)/,lookbehind:!0}}},punctuation:/=/}; 17 | !function(e){function n(e,n){return"___"+e.toUpperCase()+n+"___"}Object.defineProperties(e.languages["markup-templating"]={},{buildPlaceholders:{value:function(t,a,r,o){if(t.language===a){var c=t.tokenStack=[];t.code=t.code.replace(r,(function(e){if("function"==typeof o&&!o(e))return e;for(var r,i=c.length;-1!==t.code.indexOf(r=n(a,i));)++i;return c[i]=e,r})),t.grammar=e.languages.markup}}},tokenizePlaceholders:{value:function(t,a){if(t.language===a&&t.tokenStack){t.grammar=e.languages[a];var r=0,o=Object.keys(t.tokenStack);!function c(i){for(var u=0;u=o.length);u++){var g=i[u];if("string"==typeof g||g.content&&"string"==typeof g.content){var l=o[r],s=t.tokenStack[l],f="string"==typeof g?g:g.content,p=n(a,l),k=f.indexOf(p);if(k>-1){++r;var m=f.substring(0,k),d=new e.Token(a,e.tokenize(s,t.grammar),"language-"+a,s),h=f.substring(k+p.length),v=[];m&&v.push.apply(v,c([m])),v.push(d),h&&v.push.apply(v,c([h])),"string"==typeof g?i.splice.apply(i,[u,1].concat(v)):g.content=v}}else g.content&&c(g.content)}return i}(t.tokens)}}}})}(Prism); 18 | !function(e){var a=/\/\*[\s\S]*?\*\/|\/\/.*|#(?!\[).*/,t=[{pattern:/\b(?:false|true)\b/i,alias:"boolean"},{pattern:/(::\s*)\b[a-z_]\w*\b(?!\s*\()/i,greedy:!0,lookbehind:!0},{pattern:/(\b(?:case|const)\s+)\b[a-z_]\w*(?=\s*[;=])/i,greedy:!0,lookbehind:!0},/\b(?:null)\b/i,/\b[A-Z_][A-Z0-9_]*\b(?!\s*\()/],i=/\b0b[01]+(?:_[01]+)*\b|\b0o[0-7]+(?:_[0-7]+)*\b|\b0x[\da-f]+(?:_[\da-f]+)*\b|(?:\b\d+(?:_\d+)*\.?(?:\d+(?:_\d+)*)?|\B\.\d+)(?:e[+-]?\d+)?/i,n=/|\?\?=?|\.{3}|\??->|[!=]=?=?|::|\*\*=?|--|\+\+|&&|\|\||<<|>>|[?~]|[/^|%*&<>.+-]=?/,s=/[{}\[\](),:;]/;e.languages.php={delimiter:{pattern:/\?>$|^<\?(?:php(?=\s)|=)?/i,alias:"important"},comment:a,variable:/\$+(?:\w+\b|(?=\{))/,package:{pattern:/(namespace\s+|use\s+(?:function\s+)?)(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,lookbehind:!0,inside:{punctuation:/\\/}},"class-name-definition":{pattern:/(\b(?:class|enum|interface|trait)\s+)\b[a-z_]\w*(?!\\)\b/i,lookbehind:!0,alias:"class-name"},"function-definition":{pattern:/(\bfunction\s+)[a-z_]\w*(?=\s*\()/i,lookbehind:!0,alias:"function"},keyword:[{pattern:/(\(\s*)\b(?:array|bool|boolean|float|int|integer|object|string)\b(?=\s*\))/i,alias:"type-casting",greedy:!0,lookbehind:!0},{pattern:/([(,?]\s*)\b(?:array(?!\s*\()|bool|callable|(?:false|null)(?=\s*\|)|float|int|iterable|mixed|object|self|static|string)\b(?=\s*\$)/i,alias:"type-hint",greedy:!0,lookbehind:!0},{pattern:/(\)\s*:\s*(?:\?\s*)?)\b(?:array(?!\s*\()|bool|callable|(?:false|null)(?=\s*\|)|float|int|iterable|mixed|never|object|self|static|string|void)\b/i,alias:"return-type",greedy:!0,lookbehind:!0},{pattern:/\b(?:array(?!\s*\()|bool|float|int|iterable|mixed|object|string|void)\b/i,alias:"type-declaration",greedy:!0},{pattern:/(\|\s*)(?:false|null)\b|\b(?:false|null)(?=\s*\|)/i,alias:"type-declaration",greedy:!0,lookbehind:!0},{pattern:/\b(?:parent|self|static)(?=\s*::)/i,alias:"static-context",greedy:!0},{pattern:/(\byield\s+)from\b/i,lookbehind:!0},/\bclass\b/i,{pattern:/((?:^|[^\s>:]|(?:^|[^-])>|(?:^|[^:]):)\s*)\b(?:abstract|and|array|as|break|callable|case|catch|clone|const|continue|declare|default|die|do|echo|else|elseif|empty|enddeclare|endfor|endforeach|endif|endswitch|endwhile|enum|eval|exit|extends|final|finally|fn|for|foreach|function|global|goto|if|implements|include|include_once|instanceof|insteadof|interface|isset|list|match|namespace|never|new|or|parent|print|private|protected|public|readonly|require|require_once|return|self|static|switch|throw|trait|try|unset|use|var|while|xor|yield|__halt_compiler)\b/i,lookbehind:!0}],"argument-name":{pattern:/([(,]\s*)\b[a-z_]\w*(?=\s*:(?!:))/i,lookbehind:!0},"class-name":[{pattern:/(\b(?:extends|implements|instanceof|new(?!\s+self|\s+static))\s+|\bcatch\s*\()\b[a-z_]\w*(?!\\)\b/i,greedy:!0,lookbehind:!0},{pattern:/(\|\s*)\b[a-z_]\w*(?!\\)\b/i,greedy:!0,lookbehind:!0},{pattern:/\b[a-z_]\w*(?!\\)\b(?=\s*\|)/i,greedy:!0},{pattern:/(\|\s*)(?:\\?\b[a-z_]\w*)+\b/i,alias:"class-name-fully-qualified",greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}},{pattern:/(?:\\?\b[a-z_]\w*)+\b(?=\s*\|)/i,alias:"class-name-fully-qualified",greedy:!0,inside:{punctuation:/\\/}},{pattern:/(\b(?:extends|implements|instanceof|new(?!\s+self\b|\s+static\b))\s+|\bcatch\s*\()(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,alias:"class-name-fully-qualified",greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}},{pattern:/\b[a-z_]\w*(?=\s*\$)/i,alias:"type-declaration",greedy:!0},{pattern:/(?:\\?\b[a-z_]\w*)+(?=\s*\$)/i,alias:["class-name-fully-qualified","type-declaration"],greedy:!0,inside:{punctuation:/\\/}},{pattern:/\b[a-z_]\w*(?=\s*::)/i,alias:"static-context",greedy:!0},{pattern:/(?:\\?\b[a-z_]\w*)+(?=\s*::)/i,alias:["class-name-fully-qualified","static-context"],greedy:!0,inside:{punctuation:/\\/}},{pattern:/([(,?]\s*)[a-z_]\w*(?=\s*\$)/i,alias:"type-hint",greedy:!0,lookbehind:!0},{pattern:/([(,?]\s*)(?:\\?\b[a-z_]\w*)+(?=\s*\$)/i,alias:["class-name-fully-qualified","type-hint"],greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}},{pattern:/(\)\s*:\s*(?:\?\s*)?)\b[a-z_]\w*(?!\\)\b/i,alias:"return-type",greedy:!0,lookbehind:!0},{pattern:/(\)\s*:\s*(?:\?\s*)?)(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,alias:["class-name-fully-qualified","return-type"],greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}}],constant:t,function:{pattern:/(^|[^\\\w])\\?[a-z_](?:[\w\\]*\w)?(?=\s*\()/i,lookbehind:!0,inside:{punctuation:/\\/}},property:{pattern:/(->\s*)\w+/,lookbehind:!0},number:i,operator:n,punctuation:s};var l={pattern:/\{\$(?:\{(?:\{[^{}]+\}|[^{}]+)\}|[^{}])+\}|(^|[^\\{])\$+(?:\w+(?:\[[^\r\n\[\]]+\]|->\w+)?)/,lookbehind:!0,inside:e.languages.php},r=[{pattern:/<<<'([^']+)'[\r\n](?:.*[\r\n])*?\1;/,alias:"nowdoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<<'[^']+'|[a-z_]\w*;$/i,alias:"symbol",inside:{punctuation:/^<<<'?|[';]$/}}}},{pattern:/<<<(?:"([^"]+)"[\r\n](?:.*[\r\n])*?\1;|([a-z_]\w*)[\r\n](?:.*[\r\n])*?\2;)/i,alias:"heredoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<<(?:"[^"]+"|[a-z_]\w*)|[a-z_]\w*;$/i,alias:"symbol",inside:{punctuation:/^<<<"?|[";]$/}},interpolation:l}},{pattern:/`(?:\\[\s\S]|[^\\`])*`/,alias:"backtick-quoted-string",greedy:!0},{pattern:/'(?:\\[\s\S]|[^\\'])*'/,alias:"single-quoted-string",greedy:!0},{pattern:/"(?:\\[\s\S]|[^\\"])*"/,alias:"double-quoted-string",greedy:!0,inside:{interpolation:l}}];e.languages.insertBefore("php","variable",{string:r,attribute:{pattern:/#\[(?:[^"'\/#]|\/(?![*/])|\/\/.*$|#(?!\[).*$|\/\*(?:[^*]|\*(?!\/))*\*\/|"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*')+\](?=\s*[a-z$#])/im,greedy:!0,inside:{"attribute-content":{pattern:/^(#\[)[\s\S]+(?=\]$)/,lookbehind:!0,inside:{comment:a,string:r,"attribute-class-name":[{pattern:/([^:]|^)\b[a-z_]\w*(?!\\)\b/i,alias:"class-name",greedy:!0,lookbehind:!0},{pattern:/([^:]|^)(?:\\?\b[a-z_]\w*)+/i,alias:["class-name","class-name-fully-qualified"],greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}}],constant:t,number:i,operator:n,punctuation:s}},delimiter:{pattern:/^#\[|\]$/,alias:"punctuation"}}}}),e.hooks.add("before-tokenize",(function(a){/<\?/.test(a.code)&&e.languages["markup-templating"].buildPlaceholders(a,"php",/<\?(?:[^"'/#]|\/(?![*/])|("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|(?:\/\/|#(?!\[))(?:[^?\n\r]|\?(?!>))*(?=$|\?>|[\r\n])|#\[|\/\*(?:[^*]|\*(?!\/))*(?:\*\/|$))*?(?:\?>|$)/g)})),e.hooks.add("after-tokenize",(function(a){e.languages["markup-templating"].tokenizePlaceholders(a,"php")}))}(Prism); 19 | !function(a){var e=a.languages.javadoclike={parameter:{pattern:/(^[\t ]*(?:\/{3}|\*|\/\*\*)\s*@(?:arg|arguments|param)\s+)\w+/m,lookbehind:!0},keyword:{pattern:/(^[\t ]*(?:\/{3}|\*|\/\*\*)\s*|\{)@[a-z][a-zA-Z-]+\b/m,lookbehind:!0},punctuation:/[{}]/};Object.defineProperty(e,"addSupport",{value:function(e,n){"string"==typeof e&&(e=[e]),e.forEach((function(e){!function(e,n){var t="doc-comment",r=a.languages[e];if(r){var o=r[t];if(o||(o=(r=a.languages.insertBefore(e,"comment",{"doc-comment":{pattern:/(^|[^\\])\/\*\*[^/][\s\S]*?(?:\*\/|$)/,lookbehind:!0,alias:"comment"}}))[t]),o instanceof RegExp&&(o=r[t]={pattern:o}),Array.isArray(o))for(var i=0,s=o.length;i/g,(function(){return"(?!\\s)[_$a-zA-Z\\xA0-\\uFFFF](?:(?!\\s)[$\\w\\xA0-\\uFFFF])*"})),e)}a.languages.insertBefore("javascript","function-variable",{"method-variable":{pattern:RegExp("(\\.\\s*)"+a.languages.javascript["function-variable"].pattern.source),lookbehind:!0,alias:["function-variable","method","function","property-access"]}}),a.languages.insertBefore("javascript","function",{method:{pattern:RegExp("(\\.\\s*)"+a.languages.javascript.function.source),lookbehind:!0,alias:["function","property-access"]}}),a.languages.insertBefore("javascript","constant",{"known-class-name":[{pattern:/\b(?:(?:Float(?:32|64)|(?:Int|Uint)(?:8|16|32)|Uint8Clamped)?Array|ArrayBuffer|BigInt|Boolean|DataView|Date|Error|Function|Intl|JSON|(?:Weak)?(?:Map|Set)|Math|Number|Object|Promise|Proxy|Reflect|RegExp|String|Symbol|WebAssembly)\b/,alias:"class-name"},{pattern:/\b(?:[A-Z]\w*)Error\b/,alias:"class-name"}]}),a.languages.insertBefore("javascript","keyword",{imports:{pattern:e("(\\bimport\\b\\s*)(?:(?:\\s*,\\s*(?:\\*\\s*as\\s+|\\{[^{}]*\\}))?|\\*\\s*as\\s+|\\{[^{}]*\\})(?=\\s*\\bfrom\\b)"),lookbehind:!0,inside:a.languages.javascript},exports:{pattern:e("(\\bexport\\b\\s*)(?:\\*(?:\\s*as\\s+)?(?=\\s*\\bfrom\\b)|\\{[^{}]*\\})"),lookbehind:!0,inside:a.languages.javascript}}),a.languages.javascript.keyword.unshift({pattern:/\b(?:as|default|export|from|import)\b/,alias:"module"},{pattern:/\b(?:await|break|catch|continue|do|else|finally|for|if|return|switch|throw|try|while|yield)\b/,alias:"control-flow"},{pattern:/\bnull\b/,alias:["null","nil"]},{pattern:/\bundefined\b/,alias:"nil"}),a.languages.insertBefore("javascript","operator",{spread:{pattern:/\.{3}/,alias:"operator"},arrow:{pattern:/=>/,alias:"operator"}}),a.languages.insertBefore("javascript","punctuation",{"property-access":{pattern:e("(\\.\\s*)#?"),lookbehind:!0},"maybe-class-name":{pattern:/(^|[^$\w\xA0-\uFFFF])[A-Z][$\w\xA0-\uFFFF]+/,lookbehind:!0},dom:{pattern:/\b(?:document|(?:local|session)Storage|location|navigator|performance|window)\b/,alias:"variable"},console:{pattern:/\bconsole(?=\s*\.)/,alias:"class-name"}});for(var t=["function","function-variable","method","method-variable","property-access"],r=0;r.]/,email:{pattern:/(^|\s)[-\w+.]+@[a-z][a-z0-9-]*(?:\.[a-z][a-z0-9-]*)+(?=\s)/,lookbehind:!0,alias:"url"},"ip-address":{pattern:/\b(?:\d{1,3}(?:\.\d{1,3}){3})\b/,alias:"constant"},"mac-address":{pattern:/\b[a-f0-9]{2}(?::[a-f0-9]{2}){5}\b/i,alias:"constant"},domain:{pattern:/(^|\s)[a-z][a-z0-9-]*(?:\.[a-z][a-z0-9-]*)*\.[a-z][a-z0-9-]+(?=\s)/,lookbehind:!0,alias:"constant"},uuid:{pattern:/\b[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\b/i,alias:"constant"},hash:{pattern:/\b(?:[a-f0-9]{32}){1,2}\b/i,alias:"constant"},"file-path":{pattern:/\b[a-z]:[\\/][^\s|,;:(){}\[\]"']+|(^|[\s:\[\](>|])\.{0,2}\/\w[^\s|,;:(){}\[\]"']*/i,lookbehind:!0,greedy:!0,alias:"string"},date:{pattern:RegExp("\\b\\d{4}[-/]\\d{2}[-/]\\d{2}(?:T(?=\\d{1,2}:)|(?=\\s\\d{1,2}:))|\\b\\d{1,4}[-/ ](?:\\d{1,2}|Apr|Aug|Dec|Feb|Jan|Jul|Jun|Mar|May|Nov|Oct|Sep)[-/ ]\\d{2,4}T?\\b|\\b(?:(?:Fri|Mon|Sat|Sun|Thu|Tue|Wed)(?:\\s{1,2}(?:Apr|Aug|Dec|Feb|Jan|Jul|Jun|Mar|May|Nov|Oct|Sep))?|Apr|Aug|Dec|Feb|Jan|Jul|Jun|Mar|May|Nov|Oct|Sep)\\s{1,2}\\d{1,2}\\b","i"),alias:"number"},time:{pattern:/\b\d{1,2}:\d{1,2}:\d{1,2}(?:[.,:]\d+)?(?:\s?[+-]\d{2}:?\d{2}|Z)?\b/,alias:"number"},boolean:/\b(?:false|null|true)\b/i,number:{pattern:/(^|[^.\w])(?:0x[a-f0-9]+|0o[0-7]+|0b[01]+|v?\d[\da-f]*(?:\.\d+)*(?:e[+-]?\d+)?[a-z]{0,3}\b)\b(?!\.\w)/i,lookbehind:!0},operator:/[;:?<=>~/@!$%&+\-|^(){}*#]/,punctuation:/[\[\].,]/}; 23 | !function(n){function e(n){return n=n.replace(//g,(function(){return"(?:\\\\.|[^\\\\\n\r]|(?:\n|\r\n?)(?![\r\n]))"})),RegExp("((?:^|[^\\\\])(?:\\\\{2})*)(?:"+n+")")}var t="(?:\\\\.|``(?:[^`\r\n]|`(?!`))+``|`[^`\r\n]+`|[^\\\\|\r\n`])+",a="\\|?__(?:\\|__)+\\|?(?:(?:\n|\r\n?)|(?![^]))".replace(/__/g,(function(){return t})),i="\\|?[ \t]*:?-{3,}:?[ \t]*(?:\\|[ \t]*:?-{3,}:?[ \t]*)+\\|?(?:\n|\r\n?)";n.languages.markdown=n.languages.extend("markup",{}),n.languages.insertBefore("markdown","prolog",{"front-matter-block":{pattern:/(^(?:\s*[\r\n])?)---(?!.)[\s\S]*?[\r\n]---(?!.)/,lookbehind:!0,greedy:!0,inside:{punctuation:/^---|---$/,"front-matter":{pattern:/\S+(?:\s+\S+)*/,alias:["yaml","language-yaml"],inside:n.languages.yaml}}},blockquote:{pattern:/^>(?:[\t ]*>)*/m,alias:"punctuation"},table:{pattern:RegExp("^"+a+i+"(?:"+a+")*","m"),inside:{"table-data-rows":{pattern:RegExp("^("+a+i+")(?:"+a+")*$"),lookbehind:!0,inside:{"table-data":{pattern:RegExp(t),inside:n.languages.markdown},punctuation:/\|/}},"table-line":{pattern:RegExp("^("+a+")"+i+"$"),lookbehind:!0,inside:{punctuation:/\||:?-{3,}:?/}},"table-header-row":{pattern:RegExp("^"+a+"$"),inside:{"table-header":{pattern:RegExp(t),alias:"important",inside:n.languages.markdown},punctuation:/\|/}}}},code:[{pattern:/((?:^|\n)[ \t]*\n|(?:^|\r\n?)[ \t]*\r\n?)(?: {4}|\t).+(?:(?:\n|\r\n?)(?: {4}|\t).+)*/,lookbehind:!0,alias:"keyword"},{pattern:/^```[\s\S]*?^```$/m,greedy:!0,inside:{"code-block":{pattern:/^(```.*(?:\n|\r\n?))[\s\S]+?(?=(?:\n|\r\n?)^```$)/m,lookbehind:!0},"code-language":{pattern:/^(```).+/,lookbehind:!0},punctuation:/```/}}],title:[{pattern:/\S.*(?:\n|\r\n?)(?:==+|--+)(?=[ \t]*$)/m,alias:"important",inside:{punctuation:/==+$|--+$/}},{pattern:/(^\s*)#.+/m,lookbehind:!0,alias:"important",inside:{punctuation:/^#+|#+$/}}],hr:{pattern:/(^\s*)([*-])(?:[\t ]*\2){2,}(?=\s*$)/m,lookbehind:!0,alias:"punctuation"},list:{pattern:/(^\s*)(?:[*+-]|\d+\.)(?=[\t ].)/m,lookbehind:!0,alias:"punctuation"},"url-reference":{pattern:/!?\[[^\]]+\]:[\t ]+(?:\S+|<(?:\\.|[^>\\])+>)(?:[\t ]+(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\)))?/,inside:{variable:{pattern:/^(!?\[)[^\]]+/,lookbehind:!0},string:/(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\))$/,punctuation:/^[\[\]!:]|[<>]/},alias:"url"},bold:{pattern:e("\\b__(?:(?!_)|_(?:(?!_))+_)+__\\b|\\*\\*(?:(?!\\*)|\\*(?:(?!\\*))+\\*)+\\*\\*"),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^..)[\s\S]+(?=..$)/,lookbehind:!0,inside:{}},punctuation:/\*\*|__/}},italic:{pattern:e("\\b_(?:(?!_)|__(?:(?!_))+__)+_\\b|\\*(?:(?!\\*)|\\*\\*(?:(?!\\*))+\\*\\*)+\\*"),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^.)[\s\S]+(?=.$)/,lookbehind:!0,inside:{}},punctuation:/[*_]/}},strike:{pattern:e("(~~?)(?:(?!~))+\\2"),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^~~?)[\s\S]+(?=\1$)/,lookbehind:!0,inside:{}},punctuation:/~~?/}},"code-snippet":{pattern:/(^|[^\\`])(?:``[^`\r\n]+(?:`[^`\r\n]+)*``(?!`)|`[^`\r\n]+`(?!`))/,lookbehind:!0,greedy:!0,alias:["code","keyword"]},url:{pattern:e('!?\\[(?:(?!\\]))+\\](?:\\([^\\s)]+(?:[\t ]+"(?:\\\\.|[^"\\\\])*")?\\)|[ \t]?\\[(?:(?!\\]))+\\])'),lookbehind:!0,greedy:!0,inside:{operator:/^!/,content:{pattern:/(^\[)[^\]]+(?=\])/,lookbehind:!0,inside:{}},variable:{pattern:/(^\][ \t]?\[)[^\]]+(?=\]$)/,lookbehind:!0},url:{pattern:/(^\]\()[^\s)]+/,lookbehind:!0},string:{pattern:/(^[ \t]+)"(?:\\.|[^"\\])*"(?=\)$)/,lookbehind:!0}}}}),["url","bold","italic","strike"].forEach((function(e){["url","bold","italic","strike","code-snippet"].forEach((function(t){e!==t&&(n.languages.markdown[e].inside.content.inside[t]=n.languages.markdown[t])}))})),n.hooks.add("after-tokenize",(function(n){"markdown"!==n.language&&"md"!==n.language||function n(e){if(e&&"string"!=typeof e)for(var t=0,a=e.length;t",quot:'"'},l=String.fromCodePoint||String.fromCharCode;n.languages.md=n.languages.markdown}(Prism); 24 | !function(e){var n=/\$(?:\w[a-z\d]*(?:_[^\x00-\x1F\s"'\\()$]*)?|\{[^}\s"'\\]+\})/i;e.languages.nginx={comment:{pattern:/(^|[\s{};])#.*/,lookbehind:!0,greedy:!0},directive:{pattern:/(^|\s)\w(?:[^;{}"'\\\s]|\\.|"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|\s+(?:#.*(?!.)|(?![#\s])))*?(?=\s*[;{])/,lookbehind:!0,greedy:!0,inside:{string:{pattern:/((?:^|[^\\])(?:\\\\)*)(?:"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')/,lookbehind:!0,greedy:!0,inside:{escape:{pattern:/\\["'\\nrt]/,alias:"entity"},variable:n}},comment:{pattern:/(\s)#.*/,lookbehind:!0,greedy:!0},keyword:{pattern:/^\S+/,greedy:!0},boolean:{pattern:/(\s)(?:off|on)(?!\S)/,lookbehind:!0},number:{pattern:/(\s)\d+[a-z]*(?!\S)/i,lookbehind:!0},variable:n}},punctuation:/[{};]/}}(Prism); 25 | !function(a){var e="(?:\\b[a-zA-Z]\\w*|[|\\\\[\\]])+";a.languages.phpdoc=a.languages.extend("javadoclike",{parameter:{pattern:RegExp("(@(?:global|param|property(?:-read|-write)?|var)\\s+(?:"+e+"\\s+)?)\\$\\w+"),lookbehind:!0}}),a.languages.insertBefore("phpdoc","keyword",{"class-name":[{pattern:RegExp("(@(?:global|package|param|property(?:-read|-write)?|return|subpackage|throws|var)\\s+)"+e),lookbehind:!0,inside:{keyword:/\b(?:array|bool|boolean|callback|double|false|float|int|integer|mixed|null|object|resource|self|string|true|void)\b/,punctuation:/[|\\[\]()]/}}]}),a.languages.javadoclike.addSupport("php",a.languages.phpdoc)}(Prism); 26 | Prism.languages.insertBefore("php","variable",{this:{pattern:/\$this\b/,alias:"keyword"},global:/\$(?:GLOBALS|HTTP_RAW_POST_DATA|_(?:COOKIE|ENV|FILES|GET|POST|REQUEST|SERVER|SESSION)|argc|argv|http_response_header|php_errormsg)\b/,scope:{pattern:/\b[\w\\]+::/,inside:{keyword:/\b(?:parent|self|static)\b/,punctuation:/::|\\/}}}); 27 | !function(a){var e={pattern:/\\[\\(){}[\]^$+*?|.]/,alias:"escape"},n=/\\(?:x[\da-fA-F]{2}|u[\da-fA-F]{4}|u\{[\da-fA-F]+\}|0[0-7]{0,2}|[123][0-7]{2}|c[a-zA-Z]|.)/,t="(?:[^\\\\-]|"+n.source+")",s=RegExp(t+"-"+t),i={pattern:/(<|')[^<>']+(?=[>']$)/,lookbehind:!0,alias:"variable"};a.languages.regex={"char-class":{pattern:/((?:^|[^\\])(?:\\\\)*)\[(?:[^\\\]]|\\[\s\S])*\]/,lookbehind:!0,inside:{"char-class-negation":{pattern:/(^\[)\^/,lookbehind:!0,alias:"operator"},"char-class-punctuation":{pattern:/^\[|\]$/,alias:"punctuation"},range:{pattern:s,inside:{escape:n,"range-punctuation":{pattern:/-/,alias:"operator"}}},"special-escape":e,"char-set":{pattern:/\\[wsd]|\\p\{[^{}]+\}/i,alias:"class-name"},escape:n}},"special-escape":e,"char-set":{pattern:/\.|\\[wsd]|\\p\{[^{}]+\}/i,alias:"class-name"},backreference:[{pattern:/\\(?![123][0-7]{2})[1-9]/,alias:"keyword"},{pattern:/\\k<[^<>']+>/,alias:"keyword",inside:{"group-name":i}}],anchor:{pattern:/[$^]|\\[ABbGZz]/,alias:"function"},escape:n,group:[{pattern:/\((?:\?(?:<[^<>']+>|'[^<>']+'|[>:]|?|<|>)?|>[>=]?|\b(?:AND|BETWEEN|DIV|ILIKE|IN|IS|LIKE|NOT|OR|REGEXP|RLIKE|SOUNDS LIKE|XOR)\b/i,punctuation:/[;[\]()`,.]/}; 29 | !function(){if("undefined"!=typeof Prism&&"undefined"!=typeof document&&document.querySelector){var e,t="line-numbers",i="linkable-line-numbers",n=/\n(?!$)/g,r=!0;Prism.plugins.lineHighlight={highlightLines:function(o,u,c){var h=(u="string"==typeof u?u:o.getAttribute("data-line")||"").replace(/\s+/g,"").split(",").filter(Boolean),d=+o.getAttribute("data-line-offset")||0,f=(function(){if(void 0===e){var t=document.createElement("div");t.style.fontSize="13px",t.style.lineHeight="1.5",t.style.padding="0",t.style.border="0",t.innerHTML=" 
 ",document.body.appendChild(t),e=38===t.offsetHeight,document.body.removeChild(t)}return e}()?parseInt:parseFloat)(getComputedStyle(o).lineHeight),p=Prism.util.isActive(o,t),g=o.querySelector("code"),m=p?o:g||o,v=[],y=g.textContent.match(n),b=y?y.length+1:1,A=g&&m!=g?function(e,t){var i=getComputedStyle(e),n=getComputedStyle(t);function r(e){return+e.substr(0,e.length-2)}return t.offsetTop+r(n.borderTopWidth)+r(n.paddingTop)-r(i.paddingTop)}(o,g):0;h.forEach((function(e){var t=e.split("-"),i=+t[0],n=+t[1]||i;if(!((n=Math.min(b+d,n))i&&r.setAttribute("data-end",String(n)),r.style.top=(i-d-1)*f+A+"px",r.textContent=new Array(n-i+2).join(" \n")}));v.push((function(){r.style.width=o.scrollWidth+"px"})),v.push((function(){m.appendChild(r)}))}}));var P=o.id;if(p&&Prism.util.isActive(o,i)&&P){l(o,i)||v.push((function(){o.classList.add(i)}));var E=parseInt(o.getAttribute("data-start")||"1");s(".line-numbers-rows > span",o).forEach((function(e,t){var i=t+E;e.onclick=function(){var e=P+"."+i;r=!1,location.hash=e,setTimeout((function(){r=!0}),1)}}))}return function(){v.forEach(a)}}};var o=0;Prism.hooks.add("before-sanity-check",(function(e){var t=e.element.parentElement;if(u(t)){var i=0;s(".line-highlight",t).forEach((function(e){i+=e.textContent.length,e.parentNode.removeChild(e)})),i&&/^(?: \n)+$/.test(e.code.slice(-i))&&(e.code=e.code.slice(0,-i))}})),Prism.hooks.add("complete",(function e(i){var n=i.element.parentElement;if(u(n)){clearTimeout(o);var r=Prism.plugins.lineNumbers,s=i.plugins&&i.plugins.lineNumbers;l(n,t)&&r&&!s?Prism.hooks.add("line-numbers",e):(Prism.plugins.lineHighlight.highlightLines(n)(),o=setTimeout(c,1))}})),window.addEventListener("hashchange",c),window.addEventListener("resize",(function(){s("pre").filter(u).map((function(e){return Prism.plugins.lineHighlight.highlightLines(e)})).forEach(a)}))}function s(e,t){return Array.prototype.slice.call((t||document).querySelectorAll(e))}function l(e,t){return e.classList.contains(t)}function a(e){e()}function u(e){return!!(e&&/pre/i.test(e.nodeName)&&(e.hasAttribute("data-line")||e.id&&Prism.util.isActive(e,i)))}function c(){var e=location.hash.slice(1);s(".temporary.line-highlight").forEach((function(e){e.parentNode.removeChild(e)}));var t=(e.match(/\.([\d,-]+)$/)||[,""])[1];if(t&&!document.getElementById(e)){var i=e.slice(0,e.lastIndexOf(".")),n=document.getElementById(i);n&&(n.hasAttribute("data-line")||n.setAttribute("data-line",""),Prism.plugins.lineHighlight.highlightLines(n,t,"temporary ")(),r&&document.querySelector(".temporary.line-highlight").scrollIntoView())}}}(); 30 | --------------------------------------------------------------------------------