├── 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 | = $handler->getLanguage()->render('debug', 'exceptionTitle') ?>
30 | = $handler->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 |
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 | [](https://github.com/aplus-framework/debug/actions/workflows/tests.yml)
10 | [](https://gitlab.com/aplus-framework/libraries/debug/-/pipelines?scope=branches)
11 | [](https://aplus-framework.gitlab.io/libraries/debug/coverage/)
12 | [](https://packagist.org/packages/aplus/debug)
13 | [](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 |
31 |
32 |
33 |
Running=
34 | class_exists('Aplus')
35 | ? ' Aplus ' . Debugger::roundVersion(Aplus::VERSION)
36 | : '' ?> on = \PHP_OS_FAMILY ?> with PHP
37 | = Debugger::roundVersion(\PHP_VERSION) ?>
38 |
39 |
★
40 | aplus-framework.com
41 |
42 |
46 |
= $count ?> activit= $count === 1
47 | ? 'y was'
48 | : 'ies were' ?> collected in = round($activities['total'], 6) ?> seconds:
49 |
50 |
51 |
52 |
53 | | # |
54 | Collection |
55 | Collector |
56 | Description |
57 | Runtime |
58 |
59 | 10%20%30%40%
60 | 50%60%70%80%
61 | 90%100%
62 | |
63 |
64 |
65 |
66 | $collected): ?>
67 |
68 | | = $index + 1 ?> |
69 | = htmlentities($collected['collection']) ?> |
70 | = htmlentities($collected['collector']) ?> |
71 | = htmlentities($collected['description']) ?> |
72 | = round($collected['total'], 6) ?> |
73 |
74 |
80 | |
81 |
82 |
83 |
84 |
85 |
88 |
89 |
90 |
91 |
92 | hasCollectors()): ?>
93 |
94 |
95 |
96 | = $collection->getName() ?>
97 | = implode(' ', $collection->getActions()) ?>
98 |
99 | getCollectors();
101 | ?>
102 |
108 |
109 |
110 |
111 | getCollectors() as $collector): ?>
112 |
= $collector->getContents() ?>
113 |
114 |
115 |
116 |
117 |
118 |
119 |
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 | = $handler->getLanguage()->render('debug', 'exception') ?>:
173 | = $exception::class ?>
174 | = $handler->getLanguage()->render('debug', 'message') ?>:
175 | = htmlentities($exception->getMessage()) ?>
176 |
177 |
178 |
179 | = $handler->getLanguage()->render('debug', 'file') ?>:
180 |
= htmlentities($exception->getFile()) ?>
181 |
182 |
183 | = $handler->getLanguage()->render('debug', 'line') ?>:
184 |
= $exception->getLine() ?>
185 |
186 |
187 |
188 |
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 | = count($traces) - $key ?>
210 | = $trace['file'] ?>=
211 | isset($trace['line']) ? ':' . $trace['line'] : ''
212 | ?>
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 | = htmlentities($pre) ?>
247 |
248 |
249 |
250 |
251 | -
252 | = $key ?> File
253 | = $trace['file'] ?> is not readable.
254 |
255 |
256 |
257 |
258 |
259 |
260 |
299 | getLogger()?->getLastLog();
301 | if ($log): ?>
302 |
303 |
304 |
305 |
306 | | Date |
307 | = date('Y-m-d', $log->time) ?> |
308 |
309 |
310 | | Time |
311 | = date('H:i:s', $log->time) ?> |
312 |
313 |
314 | | Level |
315 | = htmlentities($log->level->name) ?> |
316 |
317 |
318 | | ID |
319 | = htmlentities($log->id) ?> |
320 |
321 |
322 | | Message |
323 |
324 | = htmlentities($log->message) ?>
325 | |
326 |
327 |
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+""+i.tag+">"},!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"},/?[\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:/\((?:\?(?:<[^<>']+>|'[^<>']+'|[>:]|[=!]|[idmnsuxU]+(?:-[idmnsuxU]+)?:?))?/,alias:"punctuation",inside:{"group-name":i}},{pattern:/\)/,alias:"punctuation"}],quantifier:{pattern:/(?:[+*?]|\{\d+(?:,\d*)?\})[?+]?/,alias:"number"},alternation:{pattern:/\|/,alias:"keyword"}}}(Prism);
28 | Prism.languages.sql={comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|(?:--|\/\/|#).*)/,lookbehind:!0},variable:[{pattern:/@(["'`])(?:\\[\s\S]|(?!\1)[^\\])+\1/,greedy:!0},/@[\w.$]+/],string:{pattern:/(^|[^@\\])("|')(?:\\[\s\S]|(?!\2)[^\\]|\2\2)*\2/,greedy:!0,lookbehind:!0},identifier:{pattern:/(^|[^@\\])`(?:\\[\s\S]|[^`\\]|``)*`/,greedy:!0,lookbehind:!0,inside:{punctuation:/^`|`$/}},function:/\b(?:AVG|COUNT|FIRST|FORMAT|LAST|LCASE|LEN|MAX|MID|MIN|MOD|NOW|ROUND|SUM|UCASE)(?=\s*\()/i,keyword:/\b(?:ACTION|ADD|AFTER|ALGORITHM|ALL|ALTER|ANALYZE|ANY|APPLY|AS|ASC|AUTHORIZATION|AUTO_INCREMENT|BACKUP|BDB|BEGIN|BERKELEYDB|BIGINT|BINARY|BIT|BLOB|BOOL|BOOLEAN|BREAK|BROWSE|BTREE|BULK|BY|CALL|CASCADED?|CASE|CHAIN|CHAR(?:ACTER|SET)?|CHECK(?:POINT)?|CLOSE|CLUSTERED|COALESCE|COLLATE|COLUMNS?|COMMENT|COMMIT(?:TED)?|COMPUTE|CONNECT|CONSISTENT|CONSTRAINT|CONTAINS(?:TABLE)?|CONTINUE|CONVERT|CREATE|CROSS|CURRENT(?:_DATE|_TIME|_TIMESTAMP|_USER)?|CURSOR|CYCLE|DATA(?:BASES?)?|DATE(?:TIME)?|DAY|DBCC|DEALLOCATE|DEC|DECIMAL|DECLARE|DEFAULT|DEFINER|DELAYED|DELETE|DELIMITERS?|DENY|DESC|DESCRIBE|DETERMINISTIC|DISABLE|DISCARD|DISK|DISTINCT|DISTINCTROW|DISTRIBUTED|DO|DOUBLE|DROP|DUMMY|DUMP(?:FILE)?|DUPLICATE|ELSE(?:IF)?|ENABLE|ENCLOSED|END|ENGINE|ENUM|ERRLVL|ERRORS|ESCAPED?|EXCEPT|EXEC(?:UTE)?|EXISTS|EXIT|EXPLAIN|EXTENDED|FETCH|FIELDS|FILE|FILLFACTOR|FIRST|FIXED|FLOAT|FOLLOWING|FOR(?: EACH ROW)?|FORCE|FOREIGN|FREETEXT(?:TABLE)?|FROM|FULL|FUNCTION|GEOMETRY(?:COLLECTION)?|GLOBAL|GOTO|GRANT|GROUP|HANDLER|HASH|HAVING|HOLDLOCK|HOUR|IDENTITY(?:COL|_INSERT)?|IF|IGNORE|IMPORT|INDEX|INFILE|INNER|INNODB|INOUT|INSERT|INT|INTEGER|INTERSECT|INTERVAL|INTO|INVOKER|ISOLATION|ITERATE|JOIN|KEYS?|KILL|LANGUAGE|LAST|LEAVE|LEFT|LEVEL|LIMIT|LINENO|LINES|LINESTRING|LOAD|LOCAL|LOCK|LONG(?:BLOB|TEXT)|LOOP|MATCH(?:ED)?|MEDIUM(?:BLOB|INT|TEXT)|MERGE|MIDDLEINT|MINUTE|MODE|MODIFIES|MODIFY|MONTH|MULTI(?:LINESTRING|POINT|POLYGON)|NATIONAL|NATURAL|NCHAR|NEXT|NO|NONCLUSTERED|NULLIF|NUMERIC|OFF?|OFFSETS?|ON|OPEN(?:DATASOURCE|QUERY|ROWSET)?|OPTIMIZE|OPTION(?:ALLY)?|ORDER|OUT(?:ER|FILE)?|OVER|PARTIAL|PARTITION|PERCENT|PIVOT|PLAN|POINT|POLYGON|PRECEDING|PRECISION|PREPARE|PREV|PRIMARY|PRINT|PRIVILEGES|PROC(?:EDURE)?|PUBLIC|PURGE|QUICK|RAISERROR|READS?|REAL|RECONFIGURE|REFERENCES|RELEASE|RENAME|REPEAT(?:ABLE)?|REPLACE|REPLICATION|REQUIRE|RESIGNAL|RESTORE|RESTRICT|RETURN(?:ING|S)?|REVOKE|RIGHT|ROLLBACK|ROUTINE|ROW(?:COUNT|GUIDCOL|S)?|RTREE|RULE|SAVE(?:POINT)?|SCHEMA|SECOND|SELECT|SERIAL(?:IZABLE)?|SESSION(?:_USER)?|SET(?:USER)?|SHARE|SHOW|SHUTDOWN|SIMPLE|SMALLINT|SNAPSHOT|SOME|SONAME|SQL|START(?:ING)?|STATISTICS|STATUS|STRIPED|SYSTEM_USER|TABLES?|TABLESPACE|TEMP(?:ORARY|TABLE)?|TERMINATED|TEXT(?:SIZE)?|THEN|TIME(?:STAMP)?|TINY(?:BLOB|INT|TEXT)|TOP?|TRAN(?:SACTIONS?)?|TRIGGER|TRUNCATE|TSEQUAL|TYPES?|UNBOUNDED|UNCOMMITTED|UNDEFINED|UNION|UNIQUE|UNLOCK|UNPIVOT|UNSIGNED|UPDATE(?:TEXT)?|USAGE|USE|USER|USING|VALUES?|VAR(?:BINARY|CHAR|CHARACTER|YING)|VIEW|WAITFOR|WARNINGS|WHEN|WHERE|WHILE|WITH(?: ROLLUP|IN)?|WORK|WRITE(?:TEXT)?|YEAR)\b/i,boolean:/\b(?:FALSE|NULL|TRUE)\b/i,number:/\b0x[\da-f]+\b|\b\d+(?:\.\d*)?|\B\.\d+\b/i,operator:/[-+*\/=%^~]|&&?|\|\|?|!=?|<(?:=>?|<|>)?|>[>=]?|\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 |
--------------------------------------------------------------------------------