├── .gitignore
├── FuncNav.php
├── LICENSE
├── README.md
├── README_zh.md
├── composer.json
├── composer.lock
├── favicon.ico
├── img
├── home.png
├── index.png
└── source.png
├── index.html
├── index.php
├── static
├── css
│ └── app.7468d54c44137433a4eabefeea754ff4.css
└── js
│ ├── app.654b05895887cf3afe7a.js
│ ├── manifest.3dff49ac782c8e4820fb.js
│ └── vendor.695f7660217c2e2b3e8b.js
└── webui
├── .babelrc
├── .editorconfig
├── .eslintignore
├── .eslintrc.js
├── .postcssrc.js
├── build
├── build.js
├── check-versions.js
├── dev-client.js
├── dev-server.js
├── utils.js
├── vue-loader.conf.js
├── webpack.base.conf.js
├── webpack.dev.conf.js
└── webpack.prod.conf.js
├── config
├── dev.env.js
├── index.js
└── prod.env.js
├── index.html
├── package-lock.json
├── package.json
├── src
├── App.vue
├── Bus.js
├── assets
│ └── logo.png
├── components
│ ├── BreakpointNav.vue
│ ├── FileNav.vue
│ ├── FuncNav.vue
│ ├── Home.vue
│ ├── Index.vue
│ ├── PopupList.vue
│ ├── Source.vue
│ ├── TracesNav.vue
│ └── wiki
│ │ ├── WikiEn.vue
│ │ └── WikiZh.vue
├── main.js
└── router
│ └── index.js
├── static
└── .gitkeep
└── yarn.lock
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | *.un~
3 | vendor
4 | node_modules
5 | dist/
6 | npm-debug.log*
7 | yarn-debug.log*
8 | yarn-error.log*
9 |
--------------------------------------------------------------------------------
/FuncNav.php:
--------------------------------------------------------------------------------
1 | namespace = $node->name;
21 | return;
22 | }
23 |
24 | if ($node instanceof Class_) {
25 | $this->class = empty($this->namespace) ? $node->name
26 | : $this->namespace . '\\' . $node->name;
27 | return;
28 | }
29 |
30 | if ($node instanceof Function_) {
31 | $params = [];
32 | foreach ($node->params as $param) {
33 | if ($param->byRef) {
34 | $params[] = '&' . $param->name;
35 | } else {
36 | $params[] = $param->name;
37 | }
38 | }
39 | $this->popupList[] = [
40 | 'type' => 'func',
41 | 'name' => $node->name,
42 | 'params' => implode(", ", $params),
43 | 'line' => $node->getLine()
44 | ];
45 | return;
46 | }
47 |
48 | if ($node instanceof ClassMethod) {
49 | $params = [];
50 | foreach ($node->params as $param) {
51 | if ($param->byRef) {
52 | $params[] = '&' . $param->name;
53 | } else {
54 | $params[] = $param->name;
55 | }
56 | }
57 | $this->popupList[] = [
58 | 'type' => 'method',
59 | 'class' => $this->class,
60 | 'name' => $node->name,
61 | 'params' => implode(", ", $params),
62 | 'line' => $node->getLine()
63 | ];
64 | }
65 | }
66 |
67 | public function leaveNode(Node $node)
68 | {
69 | if ($node instanceof Namespace_) {
70 | $this->namespace = '';
71 | return;
72 | }
73 |
74 | if ($node instanceof Class_) {
75 | $this->class = '';
76 | }
77 | }
78 |
79 | public function getPopupList()
80 | {
81 | return $this->popupList;
82 | }
83 | };
84 |
85 | function get_funcNav()
86 | {
87 | $popupList = [];
88 | $filename = $_GET['file'];
89 | if (file_exists($filename)) {
90 | $code = file_get_contents($filename);
91 | if (!empty($code)) {
92 | $parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7);
93 | try {
94 | $ast = $parser->parse($code);
95 | } catch (Error $error) {
96 | header('HTTP/1.0 500 Internal Server Error');
97 | echo "Parse error: {$error->getMessage()}";
98 | return;
99 | }
100 | $funcNav = new FuncNav();
101 | $traverser = new NodeTraverser();
102 | $traverser->addVisitor($funcNav);
103 | $traverser->traverse($ast);
104 | $popupList = $funcNav->getPopupList();
105 | }
106 | }
107 | header('content-type: application/json');
108 | echo json_encode($popupList);
109 | }
110 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [中文README](README_zh.md)
2 |
3 | This is a web ui for [ytrace](https://github.com/yangxikun/ytrace), see also [ytrace_chrome_extension](https://github.com/yangxikun/ytrace_chrome_extension).
4 |
5 | ## Why
6 | I need to take over some project. To understand the code logic, I have to debug the code(many code is dirty but run:-)). I can use var_dump/die(this is inefficient) or the powerful debug tool XDebug(but traces and remote debugging still not so convenient).
7 |
8 | So, I create this tool, make traces combined with step-through debugging. Hope it useful for you.
9 |
10 | ## feature
11 | * step through debugging
12 | * break point
13 | * jump to any executed source code line
14 | * step back through your step history
15 |
16 | 
17 |
18 | 
19 |
20 | 
21 |
22 | ## Install
23 | * git clone this project
24 | * composer install
25 | * in project root dir, run `php -S localhost:8088`
26 |
27 | > By default, ytrace_gui will detect ytrace.output_dir from ini_get. If need, you can edit `index.php`, change `//define('YTRACE_OUTPUT_DIR', '/tmp/ytrace/');`
28 |
29 | ## Wiki
30 | __Home Page__: List all traced files, click on one of the items in the list to open source page.
31 | + Clear Traces: delete all traced files.
32 | + Refresh: update list.
33 | + List field explanation:
34 | - Sapi: cli, fpm-fcgi etc
35 | - Method: http method in fpm-fcgi
36 | - Uri: http request uri in fpm-fcgi
37 | - File: file name
38 | - Size: file size
39 | - Time: created time
40 |
41 | __Source Page__: show detail of traced files.
42 | + source code show in left side, traced value show in right side.
43 | - only assignment and function call will be traced
44 | - ++, --, +=, /=, -=, *=, %= etc, shows the values before these operators execute
45 | - PHP 7 cannot show internal function parameters name (parameter name cannot be found will be showed as $...)
46 | + executed line will be highlight in green, dark green means current execute
47 | - click highlighted line number, can jump current execute to it
48 | - ctrl+click line number, can set/clear a breakpoint (breakpoint will be highlight in red line number)
49 | + execute operation:
50 | - step into: same with gdb
51 | - step back: execute back through your step history
52 | - step over: same with gdb
53 | - step out: same with gdb
54 | - continue: same with gdb, execute to next breakpoint
55 | - reset: reset execute to first entry
56 | + shortcut:
57 | - ctrl+o: open 10 latest traced file popup list
58 | - ctrl+p: open traced source file popup list, only available in source page
59 | - ctrl+r: open current source file function/method popup list, only available in source page
60 | - ctrl+b: open breakpoints popup list, only available in source page
61 |
--------------------------------------------------------------------------------
/README_zh.md:
--------------------------------------------------------------------------------
1 | 本项目为 [ytrace](https://github.com/yangxikun/ytrace)提供了web ui界面,对应的还有[ytrace_chrome_extension](https://github.com/yangxikun/ytrace_chrome_extension).
2 |
3 | ## 背景
4 | 工作上,有时会需要接手一些旧项目或者熟悉新项目。为了理解项目中的代码逻辑,我们需要不断的调试代码(大部分代码都是dirty but run:-)),通常的调试方式是var_dump/die(低效的),或者使用Xdebug的跟踪、单步调试功能,但觉得这些方式还是不够方便。
5 |
6 | 于是,开发了这个工具,将跟踪和单步调试结合起来,目前用起来还挺方便的,希望也对你有用。
7 |
8 | ## 特性
9 | * 单步调试
10 | * 断点
11 | * 跳转到任意执行过的代码行
12 | * 根据单步历史,往回单步执行
13 |
14 | 
15 |
16 | 
17 |
18 | 
19 |
20 | ## 安装
21 | * git clone 当前项目
22 | * composer install
23 | * 在项目的根目录,执行`php -S localhost:8088`
24 |
25 | > 默认的,ytrace_gui会通过ini_get获取ytrace.output_dir的值。如果需要的话,你可以通过编辑`index.php`,修改`//define('YTRACE_OUTPUT_DIR', '/tmp/ytrace/');`,以设置ytrace的输出目录。
26 |
27 | ## Wiki
28 | __Home 页面__: 列出所有的跟踪文件, 通过点击列表中的某行记录打开Source 页面。
29 | + Clear Traces: 删除所有的跟踪文件。
30 | + Refresh: 刷新列表。
31 | + 列表字段说明:
32 | - Sapi: cli, fpm-fcgi 等
33 | - Method: fpm-fcgi中的http 请求方法
34 | - Uri: fpm-fcgi中的http 请求路径及参数
35 | - File: 跟踪文件名
36 | - Size: 跟踪文件大小
37 | - Time: 跟踪文件创建时间
38 |
39 | __Source Page__: 显示跟踪内容详情。
40 | + 左边模块显示源码文件,右边模块显示跟踪到的变量值。
41 | - 只跟踪赋值和函数调用
42 | - ++、--、+=、/=、-=、*=、%=等,显示的值是这些运算符执行之前的值
43 | - PHP 7无法获取到扩展函数的参数名称(无法显示参数名称的会显示为$...)
44 | + 被执行过的代码行,行号会以绿色高亮出来,深绿色表示当前执行所在的行
45 | - 点击高亮的行号,可以将执行跳转至对应行
46 | - ctrl+点击行号,可以设置或取消断点(断点的行号会以红色高亮)
47 | + 执行操作:
48 | - step into: 同gdb
49 | - step back: 根据你的执行历史,往回执行
50 | - step over: 同gdb
51 | - step out: 同gdb
52 | - continue: 同gdb,执行到下一个断点
53 | - reset:重置执行过程
54 | + 快捷键:
55 | - ctrl+o: 打开最新10个跟踪文件的列表浮框
56 | - ctrl+p: 打开被跟踪到的源码文件的列表浮框,只能在Source 页面使用
57 | - ctrl+r: 打开当前显示的源码文件函数/方法的列表浮框,只能在Source 页面使用
58 | - ctrl+b: 打开断点列表浮框,只能在Source 页面使用
59 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "require": {
3 | "nikic/fast-route": "^1.2",
4 | "nikic/php-parser": "3.1.*"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/composer.lock:
--------------------------------------------------------------------------------
1 | {
2 | "_readme": [
3 | "This file locks the dependencies of your project to a known state",
4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
5 | "This file is @generated automatically"
6 | ],
7 | "content-hash": "b53a49287c1526c6d43bc82b7070bed2",
8 | "packages": [
9 | {
10 | "name": "nikic/fast-route",
11 | "version": "v1.2.0",
12 | "source": {
13 | "type": "git",
14 | "url": "https://github.com/nikic/FastRoute.git",
15 | "reference": "b5f95749071c82a8e0f58586987627054400cdf6"
16 | },
17 | "dist": {
18 | "type": "zip",
19 | "url": "https://api.github.com/repos/nikic/FastRoute/zipball/b5f95749071c82a8e0f58586987627054400cdf6",
20 | "reference": "b5f95749071c82a8e0f58586987627054400cdf6",
21 | "shasum": ""
22 | },
23 | "require": {
24 | "php": ">=5.4.0"
25 | },
26 | "type": "library",
27 | "autoload": {
28 | "psr-4": {
29 | "FastRoute\\": "src/"
30 | },
31 | "files": [
32 | "src/functions.php"
33 | ]
34 | },
35 | "notification-url": "https://packagist.org/downloads/",
36 | "license": [
37 | "BSD-3-Clause"
38 | ],
39 | "authors": [
40 | {
41 | "name": "Nikita Popov",
42 | "email": "nikic@php.net"
43 | }
44 | ],
45 | "description": "Fast request router for PHP",
46 | "keywords": [
47 | "router",
48 | "routing"
49 | ],
50 | "time": "2017-01-19T11:35:12+00:00"
51 | },
52 | {
53 | "name": "nikic/php-parser",
54 | "version": "v3.1.2",
55 | "source": {
56 | "type": "git",
57 | "url": "https://github.com/nikic/PHP-Parser.git",
58 | "reference": "08131e7ff29de6bb9f12275c7d35df71f25f4d89"
59 | },
60 | "dist": {
61 | "type": "zip",
62 | "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/08131e7ff29de6bb9f12275c7d35df71f25f4d89",
63 | "reference": "08131e7ff29de6bb9f12275c7d35df71f25f4d89",
64 | "shasum": ""
65 | },
66 | "require": {
67 | "ext-tokenizer": "*",
68 | "php": ">=5.5"
69 | },
70 | "require-dev": {
71 | "phpunit/phpunit": "~4.0|~5.0"
72 | },
73 | "bin": [
74 | "bin/php-parse"
75 | ],
76 | "type": "library",
77 | "extra": {
78 | "branch-alias": {
79 | "dev-master": "3.0-dev"
80 | }
81 | },
82 | "autoload": {
83 | "psr-4": {
84 | "PhpParser\\": "lib/PhpParser"
85 | }
86 | },
87 | "notification-url": "https://packagist.org/downloads/",
88 | "license": [
89 | "BSD-3-Clause"
90 | ],
91 | "authors": [
92 | {
93 | "name": "Nikita Popov"
94 | }
95 | ],
96 | "description": "A PHP parser written in PHP",
97 | "keywords": [
98 | "parser",
99 | "php"
100 | ],
101 | "time": "2017-11-04T11:48:34+00:00"
102 | }
103 | ],
104 | "packages-dev": [],
105 | "aliases": [],
106 | "minimum-stability": "stable",
107 | "stability-flags": [],
108 | "prefer-stable": false,
109 | "prefer-lowest": false,
110 | "platform": [],
111 | "platform-dev": []
112 | }
113 |
--------------------------------------------------------------------------------
/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangxikun/ytrace_gui/052d77b32e698d8d4adba94ef6c66f8489eb2854/favicon.ico
--------------------------------------------------------------------------------
/img/home.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangxikun/ytrace_gui/052d77b32e698d8d4adba94ef6c66f8489eb2854/img/home.png
--------------------------------------------------------------------------------
/img/index.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangxikun/ytrace_gui/052d77b32e698d8d4adba94ef6c66f8489eb2854/img/index.png
--------------------------------------------------------------------------------
/img/source.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangxikun/ytrace_gui/052d77b32e698d8d4adba94ef6c66f8489eb2854/img/source.png
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
ytrace_gui
--------------------------------------------------------------------------------
/index.php:
--------------------------------------------------------------------------------
1 | addRoute('GET', '/trace', 'get_all_trace');
22 | $r->addRoute('DELETE', '/trace', 'clear_trace');
23 | $r->addRoute('GET', '/trace/{id:.+}', 'get_trace');
24 | $r->addRoute('GET', '/source', 'get_source');
25 | $r->addRoute('GET', '/file-nav/{id:.+}', 'get_fileNav');
26 | $r->addRoute('GET', '/func-nav', 'get_funcNav');
27 | $r->addRoute('GET', '/', 'index');
28 | });
29 |
30 | // Fetch method and URI from somewhere
31 | $httpMethod = $_SERVER['REQUEST_METHOD'];
32 | $uri = $_SERVER['REQUEST_URI'];
33 |
34 | // Strip query string (?foo=bar) and decode URI
35 | if (false !== $pos = strpos($uri, '?')) {
36 | $uri = substr($uri, 0, $pos);
37 | }
38 | $uri = rawurldecode($uri);
39 |
40 | $routeInfo = $dispatcher->dispatch($httpMethod, $uri);
41 | switch ($routeInfo[0]) {
42 | case FastRoute\Dispatcher::NOT_FOUND:
43 | // ... 404 Not Found
44 | break;
45 | case FastRoute\Dispatcher::METHOD_NOT_ALLOWED:
46 | $allowedMethods = $routeInfo[1];
47 | // ... 405 Method Not Allowed
48 | break;
49 | case FastRoute\Dispatcher::FOUND:
50 | $handler = $routeInfo[1];
51 | $vars = $routeInfo[2];
52 | // ... call $handler with $vars
53 | call_user_func($handler, $vars);
54 | break;
55 | }
56 |
57 | function index()
58 | {
59 | readfile('index.html');
60 | }
61 |
62 | function get_all_trace()
63 | {
64 | if (!is_dir(YTRACE_OUTPUT_DIR)) {
65 | header("HTTP/1.0 500 Internal Server Error");
66 | echo YTRACE_OUTPUT_DIR . " does not exists.";
67 | return;
68 | }
69 | $res = [];
70 | $files = scandir(YTRACE_OUTPUT_DIR);
71 | foreach ($files as $file) {
72 | $pathinfo = pathinfo($file);
73 | if (isset($pathinfo['extension']) && $pathinfo['extension'] == 'yt') {
74 | $handle = fopen(YTRACE_OUTPUT_DIR . $file, 'r');
75 | $info = explode("\t", rtrim(fgets($handle), "\n"));
76 | $fileSize = filesize(YTRACE_OUTPUT_DIR . $file);
77 | switch (true) {
78 | case $fileSize > 1024 *1024:
79 | $fileSize = round($fileSize / (1024*1024), 2) . 'M';
80 | break;
81 | case $fileSize > 1024:
82 | $fileSize = round($fileSize / 1024, 2) . 'k';
83 | break;
84 | }
85 | $item = [
86 | 'sapi' => $info[0], 'file' => $pathinfo['filename'],
87 | 'time' => date('Y-m-d H:i:s', filectime(YTRACE_OUTPUT_DIR . $file)),
88 | 'size' => $fileSize
89 | ];
90 | if ($info[0] == "fpm-fcgi") {
91 | $item['method'] = $info[1];
92 | $item['uri'] = $info[2];
93 | }
94 | $res[] = $item;
95 | }
96 | }
97 | usort($res, function ($a, $b) {
98 | return $a['time'] < $b['time'] ? 1 : -1;
99 | });
100 | header('content-type: application/json');
101 | echo json_encode($res);
102 | }
103 |
104 | function get_trace($input)
105 | {
106 | $filename = YTRACE_OUTPUT_DIR . $input['id'] . '.yt';
107 | if (file_exists($filename)) {
108 | readfile($filename);
109 | } else {
110 | header("HTTP/1.0 404 Not Found");
111 | }
112 | }
113 |
114 | function get_source()
115 | {
116 | $filename = $_GET['file'];
117 | if (file_exists($filename)) {
118 | readfile($filename);
119 | } else {
120 | header("HTTP/1.0 404 Not Found");
121 | }
122 | }
123 |
124 | function clear_trace()
125 | {
126 | $files = scandir(YTRACE_OUTPUT_DIR);
127 | foreach ($files as $file) {
128 | $pathinfo = pathinfo($file);
129 | if ($pathinfo['extension'] == 'yt') {
130 | unlink(YTRACE_OUTPUT_DIR . $file);
131 | }
132 | }
133 | }
134 |
135 | function get_fileNav($input)
136 | {
137 | $filename = YTRACE_OUTPUT_DIR . $input['id'] . '.yt';
138 | if (file_exists($filename)) {
139 | $f = fopen($filename, "r");
140 | $first = true;
141 | $trace_files = [];
142 | while (true) {
143 | $line = fgets($f);
144 | if ($line === false) break;
145 | if ($first) {
146 | $first = false;
147 | continue;
148 | }
149 | $line = explode("\t", $line);
150 | $trace_files[$line[0]] = null;
151 | }
152 | header('content-type: application/json');
153 | echo json_encode(array_keys($trace_files));
154 | } else {
155 | header("HTTP/1.0 404 Not Found");
156 | }
157 | }
158 |
--------------------------------------------------------------------------------
/static/js/app.654b05895887cf3afe7a.js:
--------------------------------------------------------------------------------
1 | webpackJsonp([1],{"/E90":function(e,t,r){"use strict";var a=function(){var e=this,t=e.$createElement,r=e._self._c||t;return r("b-list-group",{staticStyle:{"max-height":"35rem","overflow-y":"scroll"}},e._l(e.showItems,function(t,a){return r("b-list-group-item",{key:a,class:{active:a===e.select},on:{click:function(r){e.rowClicked(t.line)}}},[e._v("\n "+e._s(t.prototype)+"\n ")])}))},n=[],i={render:a,staticRenderFns:n};t.a=i},"10oB":function(e,t,r){"use strict";var a=function(){var e=this,t=e.$createElement,r=e._self._c||t;return r("div",{staticClass:"container",staticStyle:{"margin-top":"4rem"}},[r("h1",{staticStyle:{"text-align":"center"}},[e._v("Welcome to Ytrace"),r("h5",{staticStyle:{display:"inline-block"}},[r("b-badge",{attrs:{pill:"",variant:"secondary"}},[e._v("alpha")])],1)]),e._v(" "),r("p",{staticStyle:{"text-align":"center"}},[e._v("This is wiki page for Ytrace's gui, chrome extension, php extension.")]),e._v(" "),r("div",[r("b-card",{attrs:{title:"GUI"}},[r("div",{staticClass:"card-text"},[r("vue-markdown",{attrs:{source:e.GUI}})],1)]),e._v(" "),r("b-card",{attrs:{title:"Chrome Extension"}},[r("div",{staticClass:"card-text"},[r("vue-markdown",{attrs:{source:e.ChromeExtension}})],1)]),e._v(" "),r("b-card",{attrs:{title:"PHP Extension"}},[r("div",{staticClass:"card-text"},[r("vue-markdown",{attrs:{source:e.PHPExtension}})],1)])],1)])},n=[],i={render:a,staticRenderFns:n};t.a=i},"1Bj8":function(e,t,r){"use strict";var a=function(){var e=this,t=e.$createElement,r=e._self._c||t;return r("table",{staticClass:"table"},[r("tbody",e._l(e.showFiles,function(t,a){return r("tr",{class:{"table-active":a===e.select},on:{click:function(r){e.rowClicked(t)}}},[r("td",[e._v(e._s(t.sapi))]),e._v(" "),r("td",[e._v(e._s(t.method))]),e._v(" "),r("td",{staticClass:"uri"},[e._v(e._s(t.uri))]),e._v(" "),r("td",[e._v(e._s(t.file))]),e._v(" "),r("td",[e._v(e._s(t.size))]),e._v(" "),r("td",[e._v(e._s(t.time))])])}))])},n=[],i={render:a,staticRenderFns:n};t.a=i},"21zj":function(e,t){},"240R":function(e,t,r){"use strict";var a=r("7+uW");t.a=new a.a({data:function(){return{curSourceFile:""}}})},"42Hy":function(e,t,r){"use strict";function a(e){r("qE0+")}var n=r("DK6z"),i=r("9Ju6"),o=r("VU/8"),s=a,l=o(n.a,i.a,s,"data-v-a79ba2ce",null);t.a=l.exports},"4fNz":function(e,t){e.exports={Aacute:"Á",aacute:"á",Abreve:"Ă",abreve:"ă",ac:"∾",acd:"∿",acE:"∾̳",Acirc:"Â",acirc:"â",acute:"´",Acy:"А",acy:"а",AElig:"Æ",aelig:"æ",af:"",Afr:"𝔄",afr:"𝔞",Agrave:"À",agrave:"à",alefsym:"ℵ",aleph:"ℵ",Alpha:"Α",alpha:"α",Amacr:"Ā",amacr:"ā",amalg:"⨿",amp:"&",AMP:"&",andand:"⩕",And:"⩓",and:"∧",andd:"⩜",andslope:"⩘",andv:"⩚",ang:"∠",ange:"⦤",angle:"∠",angmsdaa:"⦨",angmsdab:"⦩",angmsdac:"⦪",angmsdad:"⦫",angmsdae:"⦬",angmsdaf:"⦭",angmsdag:"⦮",angmsdah:"⦯",angmsd:"∡",angrt:"∟",angrtvb:"⊾",angrtvbd:"⦝",angsph:"∢",angst:"Å",angzarr:"⍼",Aogon:"Ą",aogon:"ą",Aopf:"𝔸",aopf:"𝕒",apacir:"⩯",ap:"≈",apE:"⩰",ape:"≊",apid:"≋",apos:"'",ApplyFunction:"",approx:"≈",approxeq:"≊",Aring:"Å",aring:"å",Ascr:"𝒜",ascr:"𝒶",Assign:"≔",ast:"*",asymp:"≈",asympeq:"≍",Atilde:"Ã",atilde:"ã",Auml:"Ä",auml:"ä",awconint:"∳",awint:"⨑",backcong:"≌",backepsilon:"϶",backprime:"‵",backsim:"∽",backsimeq:"⋍",Backslash:"∖",Barv:"⫧",barvee:"⊽",barwed:"⌅",Barwed:"⌆",barwedge:"⌅",bbrk:"⎵",bbrktbrk:"⎶",bcong:"≌",Bcy:"Б",bcy:"б",bdquo:"„",becaus:"∵",because:"∵",Because:"∵",bemptyv:"⦰",bepsi:"϶",bernou:"ℬ",Bernoullis:"ℬ",Beta:"Β",beta:"β",beth:"ℶ",between:"≬",Bfr:"𝔅",bfr:"𝔟",bigcap:"⋂",bigcirc:"◯",bigcup:"⋃",bigodot:"⨀",bigoplus:"⨁",bigotimes:"⨂",bigsqcup:"⨆",bigstar:"★",bigtriangledown:"▽",bigtriangleup:"△",biguplus:"⨄",bigvee:"⋁",bigwedge:"⋀",bkarow:"⤍",blacklozenge:"⧫",blacksquare:"▪",blacktriangle:"▴",blacktriangledown:"▾",blacktriangleleft:"◂",blacktriangleright:"▸",blank:"␣",blk12:"▒",blk14:"░",blk34:"▓",block:"█",bne:"=⃥",bnequiv:"≡⃥",bNot:"⫭",bnot:"⌐",Bopf:"𝔹",bopf:"𝕓",bot:"⊥",bottom:"⊥",bowtie:"⋈",boxbox:"⧉",boxdl:"┐",boxdL:"╕",boxDl:"╖",boxDL:"╗",boxdr:"┌",boxdR:"╒",boxDr:"╓",boxDR:"╔",boxh:"─",boxH:"═",boxhd:"┬",boxHd:"╤",boxhD:"╥",boxHD:"╦",boxhu:"┴",boxHu:"╧",boxhU:"╨",boxHU:"╩",boxminus:"⊟",boxplus:"⊞",boxtimes:"⊠",boxul:"┘",boxuL:"╛",boxUl:"╜",boxUL:"╝",boxur:"└",boxuR:"╘",boxUr:"╙",boxUR:"╚",boxv:"│",boxV:"║",boxvh:"┼",boxvH:"╪",boxVh:"╫",boxVH:"╬",boxvl:"┤",boxvL:"╡",boxVl:"╢",boxVL:"╣",boxvr:"├",boxvR:"╞",boxVr:"╟",boxVR:"╠",bprime:"‵",breve:"˘",Breve:"˘",brvbar:"¦",bscr:"𝒷",Bscr:"ℬ",bsemi:"⁏",bsim:"∽",bsime:"⋍",bsolb:"⧅",bsol:"\\",bsolhsub:"⟈",bull:"•",bullet:"•",bump:"≎",bumpE:"⪮",bumpe:"≏",Bumpeq:"≎",bumpeq:"≏",Cacute:"Ć",cacute:"ć",capand:"⩄",capbrcup:"⩉",capcap:"⩋",cap:"∩",Cap:"⋒",capcup:"⩇",capdot:"⩀",CapitalDifferentialD:"ⅅ",caps:"∩︀",caret:"⁁",caron:"ˇ",Cayleys:"ℭ",ccaps:"⩍",Ccaron:"Č",ccaron:"č",Ccedil:"Ç",ccedil:"ç",Ccirc:"Ĉ",ccirc:"ĉ",Cconint:"∰",ccups:"⩌",ccupssm:"⩐",Cdot:"Ċ",cdot:"ċ",cedil:"¸",Cedilla:"¸",cemptyv:"⦲",cent:"¢",centerdot:"·",CenterDot:"·",cfr:"𝔠",Cfr:"ℭ",CHcy:"Ч",chcy:"ч",check:"✓",checkmark:"✓",Chi:"Χ",chi:"χ",circ:"ˆ",circeq:"≗",circlearrowleft:"↺",circlearrowright:"↻",circledast:"⊛",circledcirc:"⊚",circleddash:"⊝",CircleDot:"⊙",circledR:"®",circledS:"Ⓢ",CircleMinus:"⊖",CirclePlus:"⊕",CircleTimes:"⊗",cir:"○",cirE:"⧃",cire:"≗",cirfnint:"⨐",cirmid:"⫯",cirscir:"⧂",ClockwiseContourIntegral:"∲",CloseCurlyDoubleQuote:"”",CloseCurlyQuote:"’",clubs:"♣",clubsuit:"♣",colon:":",Colon:"∷",Colone:"⩴",colone:"≔",coloneq:"≔",comma:",",commat:"@",comp:"∁",compfn:"∘",complement:"∁",complexes:"ℂ",cong:"≅",congdot:"⩭",Congruent:"≡",conint:"∮",Conint:"∯",ContourIntegral:"∮",copf:"𝕔",Copf:"ℂ",coprod:"∐",Coproduct:"∐",copy:"©",COPY:"©",copysr:"℗",CounterClockwiseContourIntegral:"∳",crarr:"↵",cross:"✗",Cross:"⨯",Cscr:"𝒞",cscr:"𝒸",csub:"⫏",csube:"⫑",csup:"⫐",csupe:"⫒",ctdot:"⋯",cudarrl:"⤸",cudarrr:"⤵",cuepr:"⋞",cuesc:"⋟",cularr:"↶",cularrp:"⤽",cupbrcap:"⩈",cupcap:"⩆",CupCap:"≍",cup:"∪",Cup:"⋓",cupcup:"⩊",cupdot:"⊍",cupor:"⩅",cups:"∪︀",curarr:"↷",curarrm:"⤼",curlyeqprec:"⋞",curlyeqsucc:"⋟",curlyvee:"⋎",curlywedge:"⋏",curren:"¤",curvearrowleft:"↶",curvearrowright:"↷",cuvee:"⋎",cuwed:"⋏",cwconint:"∲",cwint:"∱",cylcty:"⌭",dagger:"†",Dagger:"‡",daleth:"ℸ",darr:"↓",Darr:"↡",dArr:"⇓",dash:"‐",Dashv:"⫤",dashv:"⊣",dbkarow:"⤏",dblac:"˝",Dcaron:"Ď",dcaron:"ď",Dcy:"Д",dcy:"д",ddagger:"‡",ddarr:"⇊",DD:"ⅅ",dd:"ⅆ",DDotrahd:"⤑",ddotseq:"⩷",deg:"°",Del:"∇",Delta:"Δ",delta:"δ",demptyv:"⦱",dfisht:"⥿",Dfr:"𝔇",dfr:"𝔡",dHar:"⥥",dharl:"⇃",dharr:"⇂",DiacriticalAcute:"´",DiacriticalDot:"˙",DiacriticalDoubleAcute:"˝",DiacriticalGrave:"`",DiacriticalTilde:"˜",diam:"⋄",diamond:"⋄",Diamond:"⋄",diamondsuit:"♦",diams:"♦",die:"¨",DifferentialD:"ⅆ",digamma:"ϝ",disin:"⋲",div:"÷",divide:"÷",divideontimes:"⋇",divonx:"⋇",DJcy:"Ђ",djcy:"ђ",dlcorn:"⌞",dlcrop:"⌍",dollar:"$",Dopf:"𝔻",dopf:"𝕕",Dot:"¨",dot:"˙",DotDot:"⃜",doteq:"≐",doteqdot:"≑",DotEqual:"≐",dotminus:"∸",dotplus:"∔",dotsquare:"⊡",doublebarwedge:"⌆",DoubleContourIntegral:"∯",DoubleDot:"¨",DoubleDownArrow:"⇓",DoubleLeftArrow:"⇐",DoubleLeftRightArrow:"⇔",DoubleLeftTee:"⫤",DoubleLongLeftArrow:"⟸",DoubleLongLeftRightArrow:"⟺",DoubleLongRightArrow:"⟹",DoubleRightArrow:"⇒",DoubleRightTee:"⊨",DoubleUpArrow:"⇑",DoubleUpDownArrow:"⇕",DoubleVerticalBar:"∥",DownArrowBar:"⤓",downarrow:"↓",DownArrow:"↓",Downarrow:"⇓",DownArrowUpArrow:"⇵",DownBreve:"̑",downdownarrows:"⇊",downharpoonleft:"⇃",downharpoonright:"⇂",DownLeftRightVector:"⥐",DownLeftTeeVector:"⥞",DownLeftVectorBar:"⥖",DownLeftVector:"↽",DownRightTeeVector:"⥟",DownRightVectorBar:"⥗",DownRightVector:"⇁",DownTeeArrow:"↧",DownTee:"⊤",drbkarow:"⤐",drcorn:"⌟",drcrop:"⌌",Dscr:"𝒟",dscr:"𝒹",DScy:"Ѕ",dscy:"ѕ",dsol:"⧶",Dstrok:"Đ",dstrok:"đ",dtdot:"⋱",dtri:"▿",dtrif:"▾",duarr:"⇵",duhar:"⥯",dwangle:"⦦",DZcy:"Џ",dzcy:"џ",dzigrarr:"⟿",Eacute:"É",eacute:"é",easter:"⩮",Ecaron:"Ě",ecaron:"ě",Ecirc:"Ê",ecirc:"ê",ecir:"≖",ecolon:"≕",Ecy:"Э",ecy:"э",eDDot:"⩷",Edot:"Ė",edot:"ė",eDot:"≑",ee:"ⅇ",efDot:"≒",Efr:"𝔈",efr:"𝔢",eg:"⪚",Egrave:"È",egrave:"è",egs:"⪖",egsdot:"⪘",el:"⪙",Element:"∈",elinters:"⏧",ell:"ℓ",els:"⪕",elsdot:"⪗",Emacr:"Ē",emacr:"ē",empty:"∅",emptyset:"∅",EmptySmallSquare:"◻",emptyv:"∅",EmptyVerySmallSquare:"▫",emsp13:" ",emsp14:" ",emsp:" ",ENG:"Ŋ",eng:"ŋ",ensp:" ",Eogon:"Ę",eogon:"ę",Eopf:"𝔼",eopf:"𝕖",epar:"⋕",eparsl:"⧣",eplus:"⩱",epsi:"ε",Epsilon:"Ε",epsilon:"ε",epsiv:"ϵ",eqcirc:"≖",eqcolon:"≕",eqsim:"≂",eqslantgtr:"⪖",eqslantless:"⪕",Equal:"⩵",equals:"=",EqualTilde:"≂",equest:"≟",Equilibrium:"⇌",equiv:"≡",equivDD:"⩸",eqvparsl:"⧥",erarr:"⥱",erDot:"≓",escr:"ℯ",Escr:"ℰ",esdot:"≐",Esim:"⩳",esim:"≂",Eta:"Η",eta:"η",ETH:"Ð",eth:"ð",Euml:"Ë",euml:"ë",euro:"€",excl:"!",exist:"∃",Exists:"∃",expectation:"ℰ",exponentiale:"ⅇ",ExponentialE:"ⅇ",fallingdotseq:"≒",Fcy:"Ф",fcy:"ф",female:"♀",ffilig:"ffi",fflig:"ff",ffllig:"ffl",Ffr:"𝔉",ffr:"𝔣",filig:"fi",FilledSmallSquare:"◼",FilledVerySmallSquare:"▪",fjlig:"fj",flat:"♭",fllig:"fl",fltns:"▱",fnof:"ƒ",Fopf:"𝔽",fopf:"𝕗",forall:"∀",ForAll:"∀",fork:"⋔",forkv:"⫙",Fouriertrf:"ℱ",fpartint:"⨍",frac12:"½",frac13:"⅓",frac14:"¼",frac15:"⅕",frac16:"⅙",frac18:"⅛",frac23:"⅔",frac25:"⅖",frac34:"¾",frac35:"⅗",frac38:"⅜",frac45:"⅘",frac56:"⅚",frac58:"⅝",frac78:"⅞",frasl:"⁄",frown:"⌢",fscr:"𝒻",Fscr:"ℱ",gacute:"ǵ",Gamma:"Γ",gamma:"γ",Gammad:"Ϝ",gammad:"ϝ",gap:"⪆",Gbreve:"Ğ",gbreve:"ğ",Gcedil:"Ģ",Gcirc:"Ĝ",gcirc:"ĝ",Gcy:"Г",gcy:"г",Gdot:"Ġ",gdot:"ġ",ge:"≥",gE:"≧",gEl:"⪌",gel:"⋛",geq:"≥",geqq:"≧",geqslant:"⩾",gescc:"⪩",ges:"⩾",gesdot:"⪀",gesdoto:"⪂",gesdotol:"⪄",gesl:"⋛︀",gesles:"⪔",Gfr:"𝔊",gfr:"𝔤",gg:"≫",Gg:"⋙",ggg:"⋙",gimel:"ℷ",GJcy:"Ѓ",gjcy:"ѓ",gla:"⪥",gl:"≷",glE:"⪒",glj:"⪤",gnap:"⪊",gnapprox:"⪊",gne:"⪈",gnE:"≩",gneq:"⪈",gneqq:"≩",gnsim:"⋧",Gopf:"𝔾",gopf:"𝕘",grave:"`",GreaterEqual:"≥",GreaterEqualLess:"⋛",GreaterFullEqual:"≧",GreaterGreater:"⪢",GreaterLess:"≷",GreaterSlantEqual:"⩾",GreaterTilde:"≳",Gscr:"𝒢",gscr:"ℊ",gsim:"≳",gsime:"⪎",gsiml:"⪐",gtcc:"⪧",gtcir:"⩺",gt:">",GT:">",Gt:"≫",gtdot:"⋗",gtlPar:"⦕",gtquest:"⩼",gtrapprox:"⪆",gtrarr:"⥸",gtrdot:"⋗",gtreqless:"⋛",gtreqqless:"⪌",gtrless:"≷",gtrsim:"≳",gvertneqq:"≩︀",gvnE:"≩︀",Hacek:"ˇ",hairsp:" ",half:"½",hamilt:"ℋ",HARDcy:"Ъ",hardcy:"ъ",harrcir:"⥈",harr:"↔",hArr:"⇔",harrw:"↭",Hat:"^",hbar:"ℏ",Hcirc:"Ĥ",hcirc:"ĥ",hearts:"♥",heartsuit:"♥",hellip:"…",hercon:"⊹",hfr:"𝔥",Hfr:"ℌ",HilbertSpace:"ℋ",hksearow:"⤥",hkswarow:"⤦",hoarr:"⇿",homtht:"∻",hookleftarrow:"↩",hookrightarrow:"↪",hopf:"𝕙",Hopf:"ℍ",horbar:"―",HorizontalLine:"─",hscr:"𝒽",Hscr:"ℋ",hslash:"ℏ",Hstrok:"Ħ",hstrok:"ħ",HumpDownHump:"≎",HumpEqual:"≏",hybull:"⁃",hyphen:"‐",Iacute:"Í",iacute:"í",ic:"",Icirc:"Î",icirc:"î",Icy:"И",icy:"и",Idot:"İ",IEcy:"Е",iecy:"е",iexcl:"¡",iff:"⇔",ifr:"𝔦",Ifr:"ℑ",Igrave:"Ì",igrave:"ì",ii:"ⅈ",iiiint:"⨌",iiint:"∭",iinfin:"⧜",iiota:"℩",IJlig:"IJ",ijlig:"ij",Imacr:"Ī",imacr:"ī",image:"ℑ",ImaginaryI:"ⅈ",imagline:"ℐ",imagpart:"ℑ",imath:"ı",Im:"ℑ",imof:"⊷",imped:"Ƶ",Implies:"⇒",incare:"℅",in:"∈",infin:"∞",infintie:"⧝",inodot:"ı",intcal:"⊺",int:"∫",Int:"∬",integers:"ℤ",Integral:"∫",intercal:"⊺",Intersection:"⋂",intlarhk:"⨗",intprod:"⨼",InvisibleComma:"",InvisibleTimes:"",IOcy:"Ё",iocy:"ё",Iogon:"Į",iogon:"į",Iopf:"𝕀",iopf:"𝕚",Iota:"Ι",iota:"ι",iprod:"⨼",iquest:"¿",iscr:"𝒾",Iscr:"ℐ",isin:"∈",isindot:"⋵",isinE:"⋹",isins:"⋴",isinsv:"⋳",isinv:"∈",it:"",Itilde:"Ĩ",itilde:"ĩ",Iukcy:"І",iukcy:"і",Iuml:"Ï",iuml:"ï",Jcirc:"Ĵ",jcirc:"ĵ",Jcy:"Й",jcy:"й",Jfr:"𝔍",jfr:"𝔧",jmath:"ȷ",Jopf:"𝕁",jopf:"𝕛",Jscr:"𝒥",jscr:"𝒿",Jsercy:"Ј",jsercy:"ј",Jukcy:"Є",jukcy:"є",Kappa:"Κ",kappa:"κ",kappav:"ϰ",Kcedil:"Ķ",kcedil:"ķ",Kcy:"К",kcy:"к",Kfr:"𝔎",kfr:"𝔨",kgreen:"ĸ",KHcy:"Х",khcy:"х",KJcy:"Ќ",kjcy:"ќ",Kopf:"𝕂",kopf:"𝕜",Kscr:"𝒦",kscr:"𝓀",lAarr:"⇚",Lacute:"Ĺ",lacute:"ĺ",laemptyv:"⦴",lagran:"ℒ",Lambda:"Λ",lambda:"λ",lang:"⟨",Lang:"⟪",langd:"⦑",langle:"⟨",lap:"⪅",Laplacetrf:"ℒ",laquo:"«",larrb:"⇤",larrbfs:"⤟",larr:"←",Larr:"↞",lArr:"⇐",larrfs:"⤝",larrhk:"↩",larrlp:"↫",larrpl:"⤹",larrsim:"⥳",larrtl:"↢",latail:"⤙",lAtail:"⤛",lat:"⪫",late:"⪭",lates:"⪭︀",lbarr:"⤌",lBarr:"⤎",lbbrk:"❲",lbrace:"{",lbrack:"[",lbrke:"⦋",lbrksld:"⦏",lbrkslu:"⦍",Lcaron:"Ľ",lcaron:"ľ",Lcedil:"Ļ",lcedil:"ļ",lceil:"⌈",lcub:"{",Lcy:"Л",lcy:"л",ldca:"⤶",ldquo:"“",ldquor:"„",ldrdhar:"⥧",ldrushar:"⥋",ldsh:"↲",le:"≤",lE:"≦",LeftAngleBracket:"⟨",LeftArrowBar:"⇤",leftarrow:"←",LeftArrow:"←",Leftarrow:"⇐",LeftArrowRightArrow:"⇆",leftarrowtail:"↢",LeftCeiling:"⌈",LeftDoubleBracket:"⟦",LeftDownTeeVector:"⥡",LeftDownVectorBar:"⥙",LeftDownVector:"⇃",LeftFloor:"⌊",leftharpoondown:"↽",leftharpoonup:"↼",leftleftarrows:"⇇",leftrightarrow:"↔",LeftRightArrow:"↔",Leftrightarrow:"⇔",leftrightarrows:"⇆",leftrightharpoons:"⇋",leftrightsquigarrow:"↭",LeftRightVector:"⥎",LeftTeeArrow:"↤",LeftTee:"⊣",LeftTeeVector:"⥚",leftthreetimes:"⋋",LeftTriangleBar:"⧏",LeftTriangle:"⊲",LeftTriangleEqual:"⊴",LeftUpDownVector:"⥑",LeftUpTeeVector:"⥠",LeftUpVectorBar:"⥘",LeftUpVector:"↿",LeftVectorBar:"⥒",LeftVector:"↼",lEg:"⪋",leg:"⋚",leq:"≤",leqq:"≦",leqslant:"⩽",lescc:"⪨",les:"⩽",lesdot:"⩿",lesdoto:"⪁",lesdotor:"⪃",lesg:"⋚︀",lesges:"⪓",lessapprox:"⪅",lessdot:"⋖",lesseqgtr:"⋚",lesseqqgtr:"⪋",LessEqualGreater:"⋚",LessFullEqual:"≦",LessGreater:"≶",lessgtr:"≶",LessLess:"⪡",lesssim:"≲",LessSlantEqual:"⩽",LessTilde:"≲",lfisht:"⥼",lfloor:"⌊",Lfr:"𝔏",lfr:"𝔩",lg:"≶",lgE:"⪑",lHar:"⥢",lhard:"↽",lharu:"↼",lharul:"⥪",lhblk:"▄",LJcy:"Љ",ljcy:"љ",llarr:"⇇",ll:"≪",Ll:"⋘",llcorner:"⌞",Lleftarrow:"⇚",llhard:"⥫",lltri:"◺",Lmidot:"Ŀ",lmidot:"ŀ",lmoustache:"⎰",lmoust:"⎰",lnap:"⪉",lnapprox:"⪉",lne:"⪇",lnE:"≨",lneq:"⪇",lneqq:"≨",lnsim:"⋦",loang:"⟬",loarr:"⇽",lobrk:"⟦",longleftarrow:"⟵",LongLeftArrow:"⟵",Longleftarrow:"⟸",longleftrightarrow:"⟷",LongLeftRightArrow:"⟷",Longleftrightarrow:"⟺",longmapsto:"⟼",longrightarrow:"⟶",LongRightArrow:"⟶",Longrightarrow:"⟹",looparrowleft:"↫",looparrowright:"↬",lopar:"⦅",Lopf:"𝕃",lopf:"𝕝",loplus:"⨭",lotimes:"⨴",lowast:"∗",lowbar:"_",LowerLeftArrow:"↙",LowerRightArrow:"↘",loz:"◊",lozenge:"◊",lozf:"⧫",lpar:"(",lparlt:"⦓",lrarr:"⇆",lrcorner:"⌟",lrhar:"⇋",lrhard:"⥭",lrm:"",lrtri:"⊿",lsaquo:"‹",lscr:"𝓁",Lscr:"ℒ",lsh:"↰",Lsh:"↰",lsim:"≲",lsime:"⪍",lsimg:"⪏",lsqb:"[",lsquo:"‘",lsquor:"‚",Lstrok:"Ł",lstrok:"ł",ltcc:"⪦",ltcir:"⩹",lt:"<",LT:"<",Lt:"≪",ltdot:"⋖",lthree:"⋋",ltimes:"⋉",ltlarr:"⥶",ltquest:"⩻",ltri:"◃",ltrie:"⊴",ltrif:"◂",ltrPar:"⦖",lurdshar:"⥊",luruhar:"⥦",lvertneqq:"≨︀",lvnE:"≨︀",macr:"¯",male:"♂",malt:"✠",maltese:"✠",Map:"⤅",map:"↦",mapsto:"↦",mapstodown:"↧",mapstoleft:"↤",mapstoup:"↥",marker:"▮",mcomma:"⨩",Mcy:"М",mcy:"м",mdash:"—",mDDot:"∺",measuredangle:"∡",MediumSpace:" ",Mellintrf:"ℳ",Mfr:"𝔐",mfr:"𝔪",mho:"℧",micro:"µ",midast:"*",midcir:"⫰",mid:"∣",middot:"·",minusb:"⊟",minus:"−",minusd:"∸",minusdu:"⨪",MinusPlus:"∓",mlcp:"⫛",mldr:"…",mnplus:"∓",models:"⊧",Mopf:"𝕄",mopf:"𝕞",mp:"∓",mscr:"𝓂",Mscr:"ℳ",mstpos:"∾",Mu:"Μ",mu:"μ",multimap:"⊸",mumap:"⊸",nabla:"∇",Nacute:"Ń",nacute:"ń",nang:"∠⃒",nap:"≉",napE:"⩰̸",napid:"≋̸",napos:"ʼn",napprox:"≉",natural:"♮",naturals:"ℕ",natur:"♮",nbsp:" ",nbump:"≎̸",nbumpe:"≏̸",ncap:"⩃",Ncaron:"Ň",ncaron:"ň",Ncedil:"Ņ",ncedil:"ņ",ncong:"≇",ncongdot:"⩭̸",ncup:"⩂",Ncy:"Н",ncy:"н",ndash:"–",nearhk:"⤤",nearr:"↗",neArr:"⇗",nearrow:"↗",ne:"≠",nedot:"≐̸",NegativeMediumSpace:"",NegativeThickSpace:"",NegativeThinSpace:"",NegativeVeryThinSpace:"",nequiv:"≢",nesear:"⤨",nesim:"≂̸",NestedGreaterGreater:"≫",NestedLessLess:"≪",NewLine:"\n",nexist:"∄",nexists:"∄",Nfr:"𝔑",nfr:"𝔫",ngE:"≧̸",nge:"≱",ngeq:"≱",ngeqq:"≧̸",ngeqslant:"⩾̸",nges:"⩾̸",nGg:"⋙̸",ngsim:"≵",nGt:"≫⃒",ngt:"≯",ngtr:"≯",nGtv:"≫̸",nharr:"↮",nhArr:"⇎",nhpar:"⫲",ni:"∋",nis:"⋼",nisd:"⋺",niv:"∋",NJcy:"Њ",njcy:"њ",nlarr:"↚",nlArr:"⇍",nldr:"‥",nlE:"≦̸",nle:"≰",nleftarrow:"↚",nLeftarrow:"⇍",nleftrightarrow:"↮",nLeftrightarrow:"⇎",nleq:"≰",nleqq:"≦̸",nleqslant:"⩽̸",nles:"⩽̸",nless:"≮",nLl:"⋘̸",nlsim:"≴",nLt:"≪⃒",nlt:"≮",nltri:"⋪",nltrie:"⋬",nLtv:"≪̸",nmid:"∤",NoBreak:"",NonBreakingSpace:" ",nopf:"𝕟",Nopf:"ℕ",Not:"⫬",not:"¬",NotCongruent:"≢",NotCupCap:"≭",NotDoubleVerticalBar:"∦",NotElement:"∉",NotEqual:"≠",NotEqualTilde:"≂̸",NotExists:"∄",NotGreater:"≯",NotGreaterEqual:"≱",NotGreaterFullEqual:"≧̸",NotGreaterGreater:"≫̸",NotGreaterLess:"≹",NotGreaterSlantEqual:"⩾̸",NotGreaterTilde:"≵",NotHumpDownHump:"≎̸",NotHumpEqual:"≏̸",notin:"∉",notindot:"⋵̸",notinE:"⋹̸",notinva:"∉",notinvb:"⋷",notinvc:"⋶",NotLeftTriangleBar:"⧏̸",NotLeftTriangle:"⋪",NotLeftTriangleEqual:"⋬",NotLess:"≮",NotLessEqual:"≰",NotLessGreater:"≸",NotLessLess:"≪̸",NotLessSlantEqual:"⩽̸",NotLessTilde:"≴",NotNestedGreaterGreater:"⪢̸",NotNestedLessLess:"⪡̸",notni:"∌",notniva:"∌",notnivb:"⋾",notnivc:"⋽",NotPrecedes:"⊀",NotPrecedesEqual:"⪯̸",NotPrecedesSlantEqual:"⋠",NotReverseElement:"∌",NotRightTriangleBar:"⧐̸",NotRightTriangle:"⋫",NotRightTriangleEqual:"⋭",NotSquareSubset:"⊏̸",NotSquareSubsetEqual:"⋢",NotSquareSuperset:"⊐̸",NotSquareSupersetEqual:"⋣",NotSubset:"⊂⃒",NotSubsetEqual:"⊈",NotSucceeds:"⊁",NotSucceedsEqual:"⪰̸",NotSucceedsSlantEqual:"⋡",NotSucceedsTilde:"≿̸",NotSuperset:"⊃⃒",NotSupersetEqual:"⊉",NotTilde:"≁",NotTildeEqual:"≄",NotTildeFullEqual:"≇",NotTildeTilde:"≉",NotVerticalBar:"∤",nparallel:"∦",npar:"∦",nparsl:"⫽⃥",npart:"∂̸",npolint:"⨔",npr:"⊀",nprcue:"⋠",nprec:"⊀",npreceq:"⪯̸",npre:"⪯̸",nrarrc:"⤳̸",nrarr:"↛",nrArr:"⇏",nrarrw:"↝̸",nrightarrow:"↛",nRightarrow:"⇏",nrtri:"⋫",nrtrie:"⋭",nsc:"⊁",nsccue:"⋡",nsce:"⪰̸",Nscr:"𝒩",nscr:"𝓃",nshortmid:"∤",nshortparallel:"∦",nsim:"≁",nsime:"≄",nsimeq:"≄",nsmid:"∤",nspar:"∦",nsqsube:"⋢",nsqsupe:"⋣",nsub:"⊄",nsubE:"⫅̸",nsube:"⊈",nsubset:"⊂⃒",nsubseteq:"⊈",nsubseteqq:"⫅̸",nsucc:"⊁",nsucceq:"⪰̸",nsup:"⊅",nsupE:"⫆̸",nsupe:"⊉",nsupset:"⊃⃒",nsupseteq:"⊉",nsupseteqq:"⫆̸",ntgl:"≹",Ntilde:"Ñ",ntilde:"ñ",ntlg:"≸",ntriangleleft:"⋪",ntrianglelefteq:"⋬",ntriangleright:"⋫",ntrianglerighteq:"⋭",Nu:"Ν",nu:"ν",num:"#",numero:"№",numsp:" ",nvap:"≍⃒",nvdash:"⊬",nvDash:"⊭",nVdash:"⊮",nVDash:"⊯",nvge:"≥⃒",nvgt:">⃒",nvHarr:"⤄",nvinfin:"⧞",nvlArr:"⤂",nvle:"≤⃒",nvlt:"<⃒",nvltrie:"⊴⃒",nvrArr:"⤃",nvrtrie:"⊵⃒",nvsim:"∼⃒",nwarhk:"⤣",nwarr:"↖",nwArr:"⇖",nwarrow:"↖",nwnear:"⤧",Oacute:"Ó",oacute:"ó",oast:"⊛",Ocirc:"Ô",ocirc:"ô",ocir:"⊚",Ocy:"О",ocy:"о",odash:"⊝",Odblac:"Ő",odblac:"ő",odiv:"⨸",odot:"⊙",odsold:"⦼",OElig:"Œ",oelig:"œ",ofcir:"⦿",Ofr:"𝔒",ofr:"𝔬",ogon:"˛",Ograve:"Ò",ograve:"ò",ogt:"⧁",ohbar:"⦵",ohm:"Ω",oint:"∮",olarr:"↺",olcir:"⦾",olcross:"⦻",oline:"‾",olt:"⧀",Omacr:"Ō",omacr:"ō",Omega:"Ω",omega:"ω",Omicron:"Ο",omicron:"ο",omid:"⦶",ominus:"⊖",Oopf:"𝕆",oopf:"𝕠",opar:"⦷",OpenCurlyDoubleQuote:"“",OpenCurlyQuote:"‘",operp:"⦹",oplus:"⊕",orarr:"↻",Or:"⩔",or:"∨",ord:"⩝",order:"ℴ",orderof:"ℴ",ordf:"ª",ordm:"º",origof:"⊶",oror:"⩖",orslope:"⩗",orv:"⩛",oS:"Ⓢ",Oscr:"𝒪",oscr:"ℴ",Oslash:"Ø",oslash:"ø",osol:"⊘",Otilde:"Õ",otilde:"õ",otimesas:"⨶",Otimes:"⨷",otimes:"⊗",Ouml:"Ö",ouml:"ö",ovbar:"⌽",OverBar:"‾",OverBrace:"⏞",OverBracket:"⎴",OverParenthesis:"⏜",para:"¶",parallel:"∥",par:"∥",parsim:"⫳",parsl:"⫽",part:"∂",PartialD:"∂",Pcy:"П",pcy:"п",percnt:"%",period:".",permil:"‰",perp:"⊥",pertenk:"‱",Pfr:"𝔓",pfr:"𝔭",Phi:"Φ",phi:"φ",phiv:"ϕ",phmmat:"ℳ",phone:"☎",Pi:"Π",pi:"π",pitchfork:"⋔",piv:"ϖ",planck:"ℏ",planckh:"ℎ",plankv:"ℏ",plusacir:"⨣",plusb:"⊞",pluscir:"⨢",plus:"+",plusdo:"∔",plusdu:"⨥",pluse:"⩲",PlusMinus:"±",plusmn:"±",plussim:"⨦",plustwo:"⨧",pm:"±",Poincareplane:"ℌ",pointint:"⨕",popf:"𝕡",Popf:"ℙ",pound:"£",prap:"⪷",Pr:"⪻",pr:"≺",prcue:"≼",precapprox:"⪷",prec:"≺",preccurlyeq:"≼",Precedes:"≺",PrecedesEqual:"⪯",PrecedesSlantEqual:"≼",PrecedesTilde:"≾",preceq:"⪯",precnapprox:"⪹",precneqq:"⪵",precnsim:"⋨",pre:"⪯",prE:"⪳",precsim:"≾",prime:"′",Prime:"″",primes:"ℙ",prnap:"⪹",prnE:"⪵",prnsim:"⋨",prod:"∏",Product:"∏",profalar:"⌮",profline:"⌒",profsurf:"⌓",prop:"∝",Proportional:"∝",Proportion:"∷",propto:"∝",prsim:"≾",prurel:"⊰",Pscr:"𝒫",pscr:"𝓅",Psi:"Ψ",psi:"ψ",puncsp:" ",Qfr:"𝔔",qfr:"𝔮",qint:"⨌",qopf:"𝕢",Qopf:"ℚ",qprime:"⁗",Qscr:"𝒬",qscr:"𝓆",quaternions:"ℍ",quatint:"⨖",quest:"?",questeq:"≟",quot:'"',QUOT:'"',rAarr:"⇛",race:"∽̱",Racute:"Ŕ",racute:"ŕ",radic:"√",raemptyv:"⦳",rang:"⟩",Rang:"⟫",rangd:"⦒",range:"⦥",rangle:"⟩",raquo:"»",rarrap:"⥵",rarrb:"⇥",rarrbfs:"⤠",rarrc:"⤳",rarr:"→",Rarr:"↠",rArr:"⇒",rarrfs:"⤞",rarrhk:"↪",rarrlp:"↬",rarrpl:"⥅",rarrsim:"⥴",Rarrtl:"⤖",rarrtl:"↣",rarrw:"↝",ratail:"⤚",rAtail:"⤜",ratio:"∶",rationals:"ℚ",rbarr:"⤍",rBarr:"⤏",RBarr:"⤐",rbbrk:"❳",rbrace:"}",rbrack:"]",rbrke:"⦌",rbrksld:"⦎",rbrkslu:"⦐",Rcaron:"Ř",rcaron:"ř",Rcedil:"Ŗ",rcedil:"ŗ",rceil:"⌉",rcub:"}",Rcy:"Р",rcy:"р",rdca:"⤷",rdldhar:"⥩",rdquo:"”",rdquor:"”",rdsh:"↳",real:"ℜ",realine:"ℛ",realpart:"ℜ",reals:"ℝ",Re:"ℜ",rect:"▭",reg:"®",REG:"®",ReverseElement:"∋",ReverseEquilibrium:"⇋",ReverseUpEquilibrium:"⥯",rfisht:"⥽",rfloor:"⌋",rfr:"𝔯",Rfr:"ℜ",rHar:"⥤",rhard:"⇁",rharu:"⇀",rharul:"⥬",Rho:"Ρ",rho:"ρ",rhov:"ϱ",RightAngleBracket:"⟩",RightArrowBar:"⇥",rightarrow:"→",RightArrow:"→",Rightarrow:"⇒",RightArrowLeftArrow:"⇄",rightarrowtail:"↣",RightCeiling:"⌉",RightDoubleBracket:"⟧",RightDownTeeVector:"⥝",RightDownVectorBar:"⥕",RightDownVector:"⇂",RightFloor:"⌋",rightharpoondown:"⇁",rightharpoonup:"⇀",rightleftarrows:"⇄",rightleftharpoons:"⇌",rightrightarrows:"⇉",rightsquigarrow:"↝",RightTeeArrow:"↦",RightTee:"⊢",RightTeeVector:"⥛",rightthreetimes:"⋌",RightTriangleBar:"⧐",RightTriangle:"⊳",RightTriangleEqual:"⊵",RightUpDownVector:"⥏",RightUpTeeVector:"⥜",RightUpVectorBar:"⥔",RightUpVector:"↾",RightVectorBar:"⥓",RightVector:"⇀",ring:"˚",risingdotseq:"≓",rlarr:"⇄",rlhar:"⇌",rlm:"",rmoustache:"⎱",rmoust:"⎱",rnmid:"⫮",roang:"⟭",roarr:"⇾",robrk:"⟧",ropar:"⦆",ropf:"𝕣",Ropf:"ℝ",roplus:"⨮",rotimes:"⨵",RoundImplies:"⥰",rpar:")",rpargt:"⦔",rppolint:"⨒",rrarr:"⇉",Rrightarrow:"⇛",rsaquo:"›",rscr:"𝓇",Rscr:"ℛ",rsh:"↱",Rsh:"↱",rsqb:"]",rsquo:"’",rsquor:"’",rthree:"⋌",rtimes:"⋊",rtri:"▹",rtrie:"⊵",rtrif:"▸",rtriltri:"⧎",RuleDelayed:"⧴",ruluhar:"⥨",rx:"℞",Sacute:"Ś",sacute:"ś",sbquo:"‚",scap:"⪸",Scaron:"Š",scaron:"š",Sc:"⪼",sc:"≻",sccue:"≽",sce:"⪰",scE:"⪴",Scedil:"Ş",scedil:"ş",Scirc:"Ŝ",scirc:"ŝ",scnap:"⪺",scnE:"⪶",scnsim:"⋩",scpolint:"⨓",scsim:"≿",Scy:"С",scy:"с",sdotb:"⊡",sdot:"⋅",sdote:"⩦",searhk:"⤥",searr:"↘",seArr:"⇘",searrow:"↘",sect:"§",semi:";",seswar:"⤩",setminus:"∖",setmn:"∖",sext:"✶",Sfr:"𝔖",sfr:"𝔰",sfrown:"⌢",sharp:"♯",SHCHcy:"Щ",shchcy:"щ",SHcy:"Ш",shcy:"ш",ShortDownArrow:"↓",ShortLeftArrow:"←",shortmid:"∣",shortparallel:"∥",ShortRightArrow:"→",ShortUpArrow:"↑",shy:"",Sigma:"Σ",sigma:"σ",sigmaf:"ς",sigmav:"ς",sim:"∼",simdot:"⩪",sime:"≃",simeq:"≃",simg:"⪞",simgE:"⪠",siml:"⪝",simlE:"⪟",simne:"≆",simplus:"⨤",simrarr:"⥲",slarr:"←",SmallCircle:"∘",smallsetminus:"∖",smashp:"⨳",smeparsl:"⧤",smid:"∣",smile:"⌣",smt:"⪪",smte:"⪬",smtes:"⪬︀",SOFTcy:"Ь",softcy:"ь",solbar:"⌿",solb:"⧄",sol:"/",Sopf:"𝕊",sopf:"𝕤",spades:"♠",spadesuit:"♠",spar:"∥",sqcap:"⊓",sqcaps:"⊓︀",sqcup:"⊔",sqcups:"⊔︀",Sqrt:"√",sqsub:"⊏",sqsube:"⊑",sqsubset:"⊏",sqsubseteq:"⊑",sqsup:"⊐",sqsupe:"⊒",sqsupset:"⊐",sqsupseteq:"⊒",square:"□",Square:"□",SquareIntersection:"⊓",SquareSubset:"⊏",SquareSubsetEqual:"⊑",SquareSuperset:"⊐",SquareSupersetEqual:"⊒",SquareUnion:"⊔",squarf:"▪",squ:"□",squf:"▪",srarr:"→",Sscr:"𝒮",sscr:"𝓈",ssetmn:"∖",ssmile:"⌣",sstarf:"⋆",Star:"⋆",star:"☆",starf:"★",straightepsilon:"ϵ",straightphi:"ϕ",strns:"¯",sub:"⊂",Sub:"⋐",subdot:"⪽",subE:"⫅",sube:"⊆",subedot:"⫃",submult:"⫁",subnE:"⫋",subne:"⊊",subplus:"⪿",subrarr:"⥹",subset:"⊂",Subset:"⋐",subseteq:"⊆",subseteqq:"⫅",SubsetEqual:"⊆",subsetneq:"⊊",subsetneqq:"⫋",subsim:"⫇",subsub:"⫕",subsup:"⫓",succapprox:"⪸",succ:"≻",succcurlyeq:"≽",Succeeds:"≻",SucceedsEqual:"⪰",SucceedsSlantEqual:"≽",SucceedsTilde:"≿",succeq:"⪰",succnapprox:"⪺",succneqq:"⪶",succnsim:"⋩",succsim:"≿",SuchThat:"∋",sum:"∑",Sum:"∑",sung:"♪",sup1:"¹",sup2:"²",sup3:"³",sup:"⊃",Sup:"⋑",supdot:"⪾",supdsub:"⫘",supE:"⫆",supe:"⊇",supedot:"⫄",Superset:"⊃",SupersetEqual:"⊇",suphsol:"⟉",suphsub:"⫗",suplarr:"⥻",supmult:"⫂",supnE:"⫌",supne:"⊋",supplus:"⫀",supset:"⊃",Supset:"⋑",supseteq:"⊇",supseteqq:"⫆",supsetneq:"⊋",supsetneqq:"⫌",supsim:"⫈",supsub:"⫔",supsup:"⫖",swarhk:"⤦",swarr:"↙",swArr:"⇙",swarrow:"↙",swnwar:"⤪",szlig:"ß",Tab:"\t",target:"⌖",Tau:"Τ",tau:"τ",tbrk:"⎴",Tcaron:"Ť",tcaron:"ť",Tcedil:"Ţ",tcedil:"ţ",Tcy:"Т",tcy:"т",tdot:"⃛",telrec:"⌕",Tfr:"𝔗",tfr:"𝔱",there4:"∴",therefore:"∴",Therefore:"∴",Theta:"Θ",theta:"θ",thetasym:"ϑ",thetav:"ϑ",thickapprox:"≈",thicksim:"∼",ThickSpace:" ",ThinSpace:" ",thinsp:" ",thkap:"≈",thksim:"∼",THORN:"Þ",thorn:"þ",tilde:"˜",Tilde:"∼",TildeEqual:"≃",TildeFullEqual:"≅",TildeTilde:"≈",timesbar:"⨱",timesb:"⊠",times:"×",timesd:"⨰",tint:"∭",toea:"⤨",topbot:"⌶",topcir:"⫱",top:"⊤",Topf:"𝕋",topf:"𝕥",topfork:"⫚",tosa:"⤩",tprime:"‴",trade:"™",TRADE:"™",triangle:"▵",triangledown:"▿",triangleleft:"◃",trianglelefteq:"⊴",triangleq:"≜",triangleright:"▹",trianglerighteq:"⊵",tridot:"◬",trie:"≜",triminus:"⨺",TripleDot:"⃛",triplus:"⨹",trisb:"⧍",tritime:"⨻",trpezium:"⏢",Tscr:"𝒯",tscr:"𝓉",TScy:"Ц",tscy:"ц",TSHcy:"Ћ",tshcy:"ћ",Tstrok:"Ŧ",tstrok:"ŧ",twixt:"≬",twoheadleftarrow:"↞",twoheadrightarrow:"↠",Uacute:"Ú",uacute:"ú",uarr:"↑",Uarr:"↟",uArr:"⇑",Uarrocir:"⥉",Ubrcy:"Ў",ubrcy:"ў",Ubreve:"Ŭ",ubreve:"ŭ",Ucirc:"Û",ucirc:"û",Ucy:"У",ucy:"у",udarr:"⇅",Udblac:"Ű",udblac:"ű",udhar:"⥮",ufisht:"⥾",Ufr:"𝔘",ufr:"𝔲",Ugrave:"Ù",ugrave:"ù",uHar:"⥣",uharl:"↿",uharr:"↾",uhblk:"▀",ulcorn:"⌜",ulcorner:"⌜",ulcrop:"⌏",ultri:"◸",Umacr:"Ū",umacr:"ū",uml:"¨",UnderBar:"_",UnderBrace:"⏟",UnderBracket:"⎵",UnderParenthesis:"⏝",Union:"⋃",UnionPlus:"⊎",Uogon:"Ų",uogon:"ų",Uopf:"𝕌",uopf:"𝕦",UpArrowBar:"⤒",uparrow:"↑",UpArrow:"↑",Uparrow:"⇑",UpArrowDownArrow:"⇅",updownarrow:"↕",UpDownArrow:"↕",Updownarrow:"⇕",UpEquilibrium:"⥮",upharpoonleft:"↿",upharpoonright:"↾",uplus:"⊎",UpperLeftArrow:"↖",UpperRightArrow:"↗",upsi:"υ",Upsi:"ϒ",upsih:"ϒ",Upsilon:"Υ",upsilon:"υ",UpTeeArrow:"↥",UpTee:"⊥",upuparrows:"⇈",urcorn:"⌝",urcorner:"⌝",urcrop:"⌎",Uring:"Ů",uring:"ů",urtri:"◹",Uscr:"𝒰",uscr:"𝓊",utdot:"⋰",Utilde:"Ũ",utilde:"ũ",utri:"▵",utrif:"▴",uuarr:"⇈",Uuml:"Ü",uuml:"ü",uwangle:"⦧",vangrt:"⦜",varepsilon:"ϵ",varkappa:"ϰ",varnothing:"∅",varphi:"ϕ",varpi:"ϖ",varpropto:"∝",varr:"↕",vArr:"⇕",varrho:"ϱ",varsigma:"ς",varsubsetneq:"⊊︀",varsubsetneqq:"⫋︀",varsupsetneq:"⊋︀",varsupsetneqq:"⫌︀",vartheta:"ϑ",vartriangleleft:"⊲",vartriangleright:"⊳",vBar:"⫨",Vbar:"⫫",vBarv:"⫩",Vcy:"В",vcy:"в",vdash:"⊢",vDash:"⊨",Vdash:"⊩",VDash:"⊫",Vdashl:"⫦",veebar:"⊻",vee:"∨",Vee:"⋁",veeeq:"≚",vellip:"⋮",verbar:"|",Verbar:"‖",vert:"|",Vert:"‖",VerticalBar:"∣",VerticalLine:"|",VerticalSeparator:"❘",VerticalTilde:"≀",VeryThinSpace:" ",Vfr:"𝔙",vfr:"𝔳",vltri:"⊲",vnsub:"⊂⃒",vnsup:"⊃⃒",Vopf:"𝕍",vopf:"𝕧",vprop:"∝",vrtri:"⊳",Vscr:"𝒱",vscr:"𝓋",vsubnE:"⫋︀",vsubne:"⊊︀",vsupnE:"⫌︀",vsupne:"⊋︀",Vvdash:"⊪",vzigzag:"⦚",Wcirc:"Ŵ",wcirc:"ŵ",wedbar:"⩟",wedge:"∧",Wedge:"⋀",wedgeq:"≙",weierp:"℘",Wfr:"𝔚",wfr:"𝔴",Wopf:"𝕎",wopf:"𝕨",wp:"℘",wr:"≀",wreath:"≀",Wscr:"𝒲",wscr:"𝓌",xcap:"⋂",xcirc:"◯",xcup:"⋃",xdtri:"▽",Xfr:"𝔛",xfr:"𝔵",xharr:"⟷",xhArr:"⟺",Xi:"Ξ",xi:"ξ",xlarr:"⟵",xlArr:"⟸",xmap:"⟼",xnis:"⋻",xodot:"⨀",Xopf:"𝕏",xopf:"𝕩",xoplus:"⨁",xotime:"⨂",xrarr:"⟶",xrArr:"⟹",Xscr:"𝒳",xscr:"𝓍",xsqcup:"⨆",xuplus:"⨄",xutri:"△",xvee:"⋁",xwedge:"⋀",Yacute:"Ý",yacute:"ý",YAcy:"Я",yacy:"я",Ycirc:"Ŷ",ycirc:"ŷ",Ycy:"Ы",ycy:"ы",yen:"¥",Yfr:"𝔜",yfr:"𝔶",YIcy:"Ї",yicy:"ї",Yopf:"𝕐",yopf:"𝕪",Yscr:"𝒴",yscr:"𝓎",YUcy:"Ю",yucy:"ю",yuml:"ÿ",Yuml:"Ÿ",Zacute:"Ź",zacute:"ź",Zcaron:"Ž",zcaron:"ž",Zcy:"З",zcy:"з",Zdot:"Ż",zdot:"ż",zeetrf:"ℨ",ZeroWidthSpace:"",Zeta:"Ζ",zeta:"ζ",zfr:"𝔷",Zfr:"ℨ",ZHcy:"Ж",zhcy:"ж",zigrarr:"⇝",zopf:"𝕫",Zopf:"ℤ",Zscr:"𝒵",zscr:"𝓏",zwj:"",zwnj:""}},"5abi":function(e,t){},"68IZ":function(e,t,r){"use strict";var a=r("mvHQ"),n=r.n(a),i=r("kX7f"),o=r.n(i),s=r("EzsT"),l=(r.n(s),r("eKfU")),c=(r.n(l),r("V71o")),u=r.n(c),h=r("0XFg").sprintf;t.a={name:"Trace-Source",components:{vueLoading:u.a},data:function(){return{loading:!0,initOk:!1,id:"",sourceEditor:null,varEditor:null,file:"",line:0,type:"",level:0,items:[],fileCoverage:{},step:-1,stepHistory:[],codeHeight:0}},watch:{"$route.params.id":function(e){void 0!==e&&""!==this.id&&this.id!==e&&(this.id=e,this.fetchTrace())}},mounted:function(){var e=this,t=document.body,r=document.documentElement,a=Math.max(t.scrollHeight,t.offsetHeight,r.clientHeight,r.scrollHeight,r.offsetHeight);this.codeHeight=a-document.getElementById("head").clientHeight-44,this.sourceEditor=this.initEditor(this.$refs.code,!0),delete this.sourceEditor.keyBinding.$defaultHandler.commandKeyBinding["ctrl-p"],this.sourceEditor.renderer.on("afterRender",function(){var t=e.$refs.code.querySelector("div.ace_gutter-layer").childNodes,r=e.fileCoverage[e.$bus.curSourceFile],a=e.$localStorage.get(e.$bus.curSourceFile);a&&(a=JSON.parse(a));for(var n=0;n=0&&r.stepInto(r.step,s)}},!1),a},fetchTrace:function(){var e=this;this.loading=!0,this.id=this.$route.params.id,this.$http.get("/trace/"+encodeURI(this.id)).then(function(t){var r=t.data.trimRight().split("\n"),a=[],n={};delete r[0];var i={},o=-1;for(var s in r){var l=r[s].split("\t");if(l[3]=Number(l[3]),"F"===l[2]&&(l[5]=Number(l[5])),a.push(l),n[l[0]]||(n[l[0]]={}),n[l[0]][l[1]]||(n[l[0]][l[1]]=Number(s)-1),-1===o){if(!i[l[0]]){var c=e.$localStorage.get(l[0]);c&&(c=JSON.parse(c),i[l[0]]=c)}i[l[0]]&&i[l[0]][l[1]]&&(o=s-1)}}e.items=a,e.fileCoverage=n,e.loading=!1,-1===o&&(o=0),e.reset(o)})},stripslashes:function(e){return(e+"").replace(/\\./g,function(e){return new Function('return "'+e+'"')()||e})},stepInto:function(e,t){var r=this.items[t];if(r)switch(e>=0&&this.stepHistory.push(e),this.step=t,this.line=Number(r[1]),this.type=r[2],this.level=r[3],r[0]!==this.file?(this.file=r[0],this.loadFile()):this.file!==this.$bus.curSourceFile?this.loadFile():this.sourceEditor.gotoLine(this.line),this.type){case"A":this.varEditor.setValue("0&&this.stepInto(-1,this.stepHistory.pop())},_continue:function(){for(var e=this.step+1,t=this.items[e],r={};t;){if(!r[t[0]]){var a=this.$localStorage.get(t[0]);a&&(a=JSON.parse(a),r[t[0]]=a)}if(r[t[0]]&&r[t[0]][t[1]])return void this.stepInto(this.step,e);e++,t=this.items[e]}},reset:function(e){this.file="",this.line=0,this.type="",this.level=0,this.stepHistory=[],this.step=e,this.stepInto(-1,this.step)},loadFile:function(){var e=this;this.$bus.curSourceFile=this.file,this.$http.get("/source?file="+encodeURI(this.file)).then(function(t){var r=e.sourceEditor;r.setValue(t.data),r.gotoLine(e.line)})},justLoadFile:function(e,t){var r=this;this.$bus.curSourceFile=e,this.$http.get("/source?file="+encodeURI(e)).then(function(e){var a=r.sourceEditor;a.setValue(e.data),t?a.gotoLine(t):a.navigateFileEnd()})}}}},"9Ju6":function(e,t,r){"use strict";var a=function(){var e=this,t=e.$createElement,r=e._self._c||t;return r("div",[r("div",[r("b-button",{attrs:{disabled:"en"==e.wiki,size:"sm",variant:"outline-secondary"},on:{click:function(t){e.wiki="en"}}},[e._v("EN")]),e._v(" "),r("b-button",{attrs:{disabled:"zh"==e.wiki,size:"sm",variant:"outline-secondary"},on:{click:function(t){e.wiki="zh"}}},[e._v("ZH")])],1),e._v(" "),r("wiki-en",{directives:[{name:"show",rawName:"v-show",value:"en"==e.wiki,expression:"wiki == 'en'"}]}),e._v(" "),r("wiki-zh",{directives:[{name:"show",rawName:"v-show",value:"zh"==e.wiki,expression:"wiki == 'zh'"}]})],1)},n=[],i={render:a,staticRenderFns:n};t.a=i},"9M+g":function(e,t){},D4uH:function(e,t,r){"use strict";function a(e){r("cCV5")}var n=r("dXrS"),i=r("Txe8"),o=r("VU/8"),s=a,l=o(n.a,i.a,s,null,null);t.a=l.exports},DK6z:function(e,t,r){"use strict";var a=r("XDsQ"),n=r("EuIC");t.a={components:{WikiEn:a.a,WikiZh:n.a},data:function(){return{wiki:"en"}}}},DUku:function(e,t){},EuIC:function(e,t,r){"use strict";function a(e){r("chry")}var n=r("ejnp"),i=r("Nf+p"),o=r("VU/8"),s=a,l=o(n.a,i.a,s,"data-v-22a91784",null);t.a=l.exports},Fs8J:function(e,t,r){"use strict";t.a={name:"Home",data:function(){return{files:[],fields:[{key:"sapi",sortable:!0},{key:"method",sortable:!0},{key:"uri",sortable:!0,tdClass:"uri"},{key:"file",sortable:!0},{key:"size",sortable:!1},{key:"time",sortable:!0}]}},mounted:function(){this.fetchTraces()},methods:{rowClicked:function(e,t,r){this.$router.push({name:"Source",params:{id:e.file}})},fetchTraces:function(){var e=this;this.$http.get("/trace").then(function(t){e.files=t.data})},clearTraces:function(){var e=this;this.$http.delete("/trace").then(function(t){e.fetchTraces()}),this.$bus.$emit("clearTraces")}}}},HCoV:function(e,t){},Icg2:function(e,t){},Jltp:function(e,t,r){"use strict";var a=r("Wq+S"),n=r("UtXa"),i=r("fWJJ"),o=r("lzLh");t.a={components:{TracesNav:a.a,FuncNav:n.a,FileNav:i.a,BreakpointNav:o.a},data:function(){return{search:"",type:"",select:0,enter:!1,showLen:0}},mounted:function(){var e=this;document.onkeydown=function(t){if("Escape"===t.key)return e.type="",void(e.enter=!1);switch(!0){case"o"===t.key&&t.ctrlKey:t.preventDefault(),e.search="",e.select=0,e.type="traces-nav",e.enter=!1,e.$refs.popupList.show();break;case"r"===t.key&&t.ctrlKey&&"Source"===e.$route.name:t.preventDefault(),e.search="",e.select=0,e.type="func-nav",e.enter=!1,e.$refs.popupList.show();break;case"p"===t.key&&t.ctrlKey&&"Source"===e.$route.name:t.preventDefault(),e.search="",e.select=0,e.type="file-nav",e.enter=!1,e.$refs.popupList.show();break;case"b"===t.key&&t.ctrlKey&&"Source"===e.$route.name:t.preventDefault(),e.search="",e.select=0,e.type="breakpoint-nav",e.enter=!1,e.$refs.popupList.show();break;case e.$refs.popupList.is_show&&"ArrowDown"===t.key&&e.showLen>1:e.select===e.showLen-1?e.select=0:e.select+=1;break;case e.$refs.popupList.is_show&&"ArrowUp"===t.key&&e.showLen>1:0===e.select?e.select=e.showLen-1:e.select-=1;break;case e.$refs.popupList.is_show&&"Enter"===t.key&&e.showLen>0:e.enter=!0}}},methods:{searchInputFocus:function(){this.$refs.searchInput.focus()},updateShowLen:function(e){this.showLen=e},close:function(){this.type="",this.enter=!1,this.$refs.popupList.hide()}}}},Jmt5:function(e,t){},K5QJ:function(e,t,r){"use strict";t.a={props:{search:String,select:Number,enter:Boolean},data:function(){return{files:[],showFiles:[]}},mounted:function(){this.fetchTraceFiles()},watch:{search:function(e){var t=[];for(var r in this.files)this.files[r].uri&&this.files[r].uri.indexOf(e)>=0?t.push(this.files[r]):this.files[r].file.indexOf(e)>=0&&t.push(this.files[r]);this.showFiles=t,this.$emit("updateShowLen",this.showFiles.length)},enter:function(e){e&&(this.$emit("close"),this.$router.push({name:"Source",params:{id:this.showFiles[this.select].file}}))}},methods:{fetchTraceFiles:function(){var e=this;this.$http.get("/trace").then(function(t){e.search="",e.files=t.data.slice(0,10),e.showFiles=e.files,e.$emit("updateShowLen",e.showFiles.length)})},rowClicked:function(e){this.$emit("close"),this.$router.push({name:"Source",params:{id:e.file}})}}}},M93x:function(e,t,r){"use strict";function a(e){r("21zj")}var n=r("xJD8"),i=r("hpS7"),o=r("VU/8"),s=a,l=o(n.a,i.a,s,"data-v-025d5711",null);t.a=l.exports},NHnr:function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var a=r("7+uW"),n=r("M93x"),i=r("YaEn"),o=r("mtWM"),s=r.n(o),l=r("sCSS"),c=r("240R"),u=r("UnSZ"),h=r.n(u),_=r("Xoog"),p=r.n(_),d=r("Jmt5"),m=(r.n(d),r("9M+g")),g=(r.n(m),r("nZeE"),r("D4uH"));a.a.component("icon",g.a),a.a.component("VueMarkdown",p.a),a.a.use(h.a),a.a.use(l.a),a.a.prototype.$http=s.a,a.a.prototype.$bus=c.a,a.a.config.productionTip=!1,new a.a({el:"#app",router:i.a,template:" ",components:{App:n.a}})},"Nf+p":function(e,t,r){"use strict";var a=function(){var e=this,t=e.$createElement,r=e._self._c||t;return r("div",{staticClass:"container",staticStyle:{"margin-top":"4rem"}},[r("h1",{staticStyle:{"text-align":"center"}},[e._v("欢迎使用 Ytrace"),r("h5",{staticStyle:{display:"inline-block"}},[r("b-badge",{attrs:{pill:"",variant:"secondary"}},[e._v("alpha")])],1)]),e._v(" "),r("p",{staticStyle:{"text-align":"center"}},[e._v("这是个包含Ytrace的gui、chrome扩展、php扩展相关Wiki的页面")]),e._v(" "),r("div",[r("b-card",{attrs:{title:"GUI"}},[r("div",{staticClass:"card-text"},[r("vue-markdown",{attrs:{source:e.GUI}})],1)]),e._v(" "),r("b-card",{attrs:{title:"Chrome 扩展"}},[r("div",{staticClass:"card-text"},[r("vue-markdown",{attrs:{source:e.ChromeExtension}})],1)]),e._v(" "),r("b-card",{attrs:{title:"PHP 扩展"}},[r("div",{staticClass:"card-text"},[r("vue-markdown",{attrs:{source:e.PHPExtension}})],1)])],1)])},n=[],i={render:a,staticRenderFns:n};t.a=i},OUSy:function(e,t){},RQcw:function(e,t,r){"use strict";var a=function(){var e=this,t=e.$createElement,r=e._self._c||t;return r("b-list-group",{staticStyle:{"max-height":"35rem"}},e._l(e.showItems,function(t,a){return r("b-list-group-item",{key:a,class:{active:a===e.select},on:{click:function(r){e.rowClicked(t)}}},[e._v("\n "+e._s(t)+"\n ")])}))},n=[],i={render:a,staticRenderFns:n};t.a=i},RWjT:function(e,t){e.exports={100:"💯",1234:"🔢",grinning:"😀",smiley:"😃",smile:"😄",grin:"😁",laughing:"😆",satisfied:"😆",sweat_smile:"😅",joy:"😂",rofl:"🤣",relaxed:"☺️",blush:"😊",innocent:"😇",slightly_smiling_face:"🙂",upside_down_face:"🙃",wink:"😉",relieved:"😌",heart_eyes:"😍",kissing_heart:"😘",kissing:"😗",kissing_smiling_eyes:"😙",kissing_closed_eyes:"😚",yum:"😋",stuck_out_tongue_winking_eye:"😜",stuck_out_tongue_closed_eyes:"😝",stuck_out_tongue:"😛",money_mouth_face:"🤑",hugs:"🤗",nerd_face:"🤓",sunglasses:"😎",clown_face:"🤡",cowboy_hat_face:"🤠",smirk:"😏",unamused:"😒",disappointed:"😞",pensive:"😔",worried:"😟",confused:"😕",slightly_frowning_face:"🙁",frowning_face:"☹️",persevere:"😣",confounded:"😖",tired_face:"😫",weary:"😩",triumph:"😤",angry:"😠",rage:"😡",pout:"😡",no_mouth:"😶",neutral_face:"😐",expressionless:"😑",hushed:"😯",frowning:"😦",anguished:"😧",open_mouth:"😮",astonished:"😲",dizzy_face:"😵",flushed:"😳",scream:"😱",fearful:"😨",cold_sweat:"😰",cry:"😢",disappointed_relieved:"😥",drooling_face:"🤤",sob:"😭",sweat:"😓",sleepy:"😪",sleeping:"😴",roll_eyes:"🙄",thinking:"🤔",lying_face:"🤥",grimacing:"😬",zipper_mouth_face:"🤐",nauseated_face:"🤢",sneezing_face:"🤧",mask:"😷",face_with_thermometer:"🤒",face_with_head_bandage:"🤕",smiling_imp:"😈",imp:"👿",japanese_ogre:"👹",japanese_goblin:"👺",hankey:"💩",poop:"💩",shit:"💩",ghost:"👻",skull:"💀",skull_and_crossbones:"☠️",alien:"👽",space_invader:"👾",robot:"🤖",jack_o_lantern:"🎃",smiley_cat:"😺",smile_cat:"😸",joy_cat:"😹",heart_eyes_cat:"😻",smirk_cat:"😼",kissing_cat:"😽",scream_cat:"🙀",crying_cat_face:"😿",pouting_cat:"😾",open_hands:"👐",raised_hands:"🙌",clap:"👏",pray:"🙏",handshake:"🤝","+1":"👍",thumbsup:"👍","-1":"👎",thumbsdown:"👎",fist_oncoming:"👊",facepunch:"👊",punch:"👊",fist_raised:"✊",fist:"✊",fist_left:"🤛",fist_right:"🤜",crossed_fingers:"🤞",v:"✌️",metal:"🤘",ok_hand:"👌",point_left:"👈",point_right:"👉",point_up_2:"👆",point_down:"👇",point_up:"☝️",hand:"✋",raised_hand:"✋",raised_back_of_hand:"🤚",raised_hand_with_fingers_splayed:"🖐",vulcan_salute:"🖖",wave:"👋",call_me_hand:"🤙",muscle:"💪",middle_finger:"🖕",fu:"🖕",writing_hand:"✍️",selfie:"🤳",nail_care:"💅",ring:"💍",lipstick:"💄",kiss:"💋",lips:"👄",tongue:"👅",ear:"👂",nose:"👃",footprints:"👣",eye:"👁",eyes:"👀",speaking_head:"🗣",bust_in_silhouette:"👤",busts_in_silhouette:"👥",baby:"👶",boy:"👦",girl:"👧",man:"👨",woman:"👩",blonde_woman:"👱♀",blonde_man:"👱",person_with_blond_hair:"👱",older_man:"👴",older_woman:"👵",man_with_gua_pi_mao:"👲",woman_with_turban:"👳♀",man_with_turban:"👳",policewoman:"👮♀",policeman:"👮",cop:"👮",construction_worker_woman:"👷♀",construction_worker_man:"👷",construction_worker:"👷",guardswoman:"💂♀",guardsman:"💂",female_detective:"🕵️♀️",male_detective:"🕵",detective:"🕵",woman_health_worker:"👩⚕",man_health_worker:"👨⚕",woman_farmer:"👩🌾",man_farmer:"👨🌾",woman_cook:"👩🍳",man_cook:"👨🍳",woman_student:"👩🎓",man_student:"👨🎓",woman_singer:"👩🎤",man_singer:"👨🎤",woman_teacher:"👩🏫",man_teacher:"👨🏫",woman_factory_worker:"👩🏭",man_factory_worker:"👨🏭",woman_technologist:"👩💻",man_technologist:"👨💻",woman_office_worker:"👩💼",man_office_worker:"👨💼",woman_mechanic:"👩🔧",man_mechanic:"👨🔧",woman_scientist:"👩🔬",man_scientist:"👨🔬",woman_artist:"👩🎨",man_artist:"👨🎨",woman_firefighter:"👩🚒",man_firefighter:"👨🚒",woman_pilot:"👩✈",man_pilot:"👨✈",woman_astronaut:"👩🚀",man_astronaut:"👨🚀",woman_judge:"👩⚖",man_judge:"👨⚖",mrs_claus:"🤶",santa:"🎅",princess:"👸",prince:"🤴",bride_with_veil:"👰",man_in_tuxedo:"🤵",angel:"👼",pregnant_woman:"🤰",bowing_woman:"🙇♀",bowing_man:"🙇",bow:"🙇",tipping_hand_woman:"💁",information_desk_person:"💁",sassy_woman:"💁",tipping_hand_man:"💁♂",sassy_man:"💁♂",no_good_woman:"🙅",no_good:"🙅",ng_woman:"🙅",no_good_man:"🙅♂",ng_man:"🙅♂",ok_woman:"🙆",ok_man:"🙆♂",raising_hand_woman:"🙋",raising_hand:"🙋",raising_hand_man:"🙋♂",woman_facepalming:"🤦♀",man_facepalming:"🤦♂",woman_shrugging:"🤷♀",man_shrugging:"🤷♂",pouting_woman:"🙎",person_with_pouting_face:"🙎",pouting_man:"🙎♂",frowning_woman:"🙍",person_frowning:"🙍",frowning_man:"🙍♂",haircut_woman:"💇",haircut:"💇",haircut_man:"💇♂",massage_woman:"💆",massage:"💆",massage_man:"💆♂",business_suit_levitating:"🕴",dancer:"💃",man_dancing:"🕺",dancing_women:"👯",dancers:"👯",dancing_men:"👯♂",walking_woman:"🚶♀",walking_man:"🚶",walking:"🚶",running_woman:"🏃♀",running_man:"🏃",runner:"🏃",running:"🏃",couple:"👫",two_women_holding_hands:"👭",two_men_holding_hands:"👬",couple_with_heart_woman_man:"💑",couple_with_heart:"💑",couple_with_heart_woman_woman:"👩❤️👩",couple_with_heart_man_man:"👨❤️👨",couplekiss_man_woman:"💏",couplekiss_woman_woman:"👩❤️💋👩",couplekiss_man_man:"👨❤️💋👨",family_man_woman_boy:"👪",family:"👪",family_man_woman_girl:"👨👩👧",family_man_woman_girl_boy:"👨👩👧👦",family_man_woman_boy_boy:"👨👩👦👦",family_man_woman_girl_girl:"👨👩👧👧",family_woman_woman_boy:"👩👩👦",family_woman_woman_girl:"👩👩👧",family_woman_woman_girl_boy:"👩👩👧👦",family_woman_woman_boy_boy:"👩👩👦👦",family_woman_woman_girl_girl:"👩👩👧👧",family_man_man_boy:"👨👨👦",family_man_man_girl:"👨👨👧",family_man_man_girl_boy:"👨👨👧👦",family_man_man_boy_boy:"👨👨👦👦",family_man_man_girl_girl:"👨👨👧👧",family_woman_boy:"👩👦",family_woman_girl:"👩👧",family_woman_girl_boy:"👩👧👦",family_woman_boy_boy:"👩👦👦",family_woman_girl_girl:"👩👧👧",family_man_boy:"👨👦",family_man_girl:"👨👧",family_man_girl_boy:"👨👧👦",family_man_boy_boy:"👨👦👦",family_man_girl_girl:"👨👧👧",womans_clothes:"👚",shirt:"👕",tshirt:"👕",jeans:"👖",necktie:"👔",dress:"👗",bikini:"👙",kimono:"👘",high_heel:"👠",sandal:"👡",boot:"👢",mans_shoe:"👞",shoe:"👞",athletic_shoe:"👟",womans_hat:"👒",tophat:"🎩",mortar_board:"🎓",crown:"👑",rescue_worker_helmet:"⛑",school_satchel:"🎒",pouch:"👝",purse:"👛",handbag:"👜",briefcase:"💼",eyeglasses:"👓",dark_sunglasses:"🕶",closed_umbrella:"🌂",open_umbrella:"☂️",dog:"🐶",cat:"🐱",mouse:"🐭",hamster:"🐹",rabbit:"🐰",fox_face:"🦊",bear:"🐻",panda_face:"🐼",koala:"🐨",tiger:"🐯",lion:"🦁",cow:"🐮",pig:"🐷",pig_nose:"🐽",frog:"🐸",monkey_face:"🐵",see_no_evil:"🙈",hear_no_evil:"🙉",speak_no_evil:"🙊",monkey:"🐒",chicken:"🐔",penguin:"🐧",bird:"🐦",baby_chick:"🐤",hatching_chick:"🐣",hatched_chick:"🐥",duck:"🦆",eagle:"🦅",owl:"🦉",bat:"🦇",wolf:"🐺",boar:"🐗",horse:"🐴",unicorn:"🦄",bee:"🐝",honeybee:"🐝",bug:"🐛",butterfly:"🦋",snail:"🐌",shell:"🐚",beetle:"🐞",ant:"🐜",spider:"🕷",spider_web:"🕸",turtle:"🐢",snake:"🐍",lizard:"🦎",scorpion:"🦂",crab:"🦀",squid:"🦑",octopus:"🐙",shrimp:"🦐",tropical_fish:"🐠",fish:"🐟",blowfish:"🐡",dolphin:"🐬",flipper:"🐬",shark:"🦈",whale:"🐳",whale2:"🐋",crocodile:"🐊",leopard:"🐆",tiger2:"🐅",water_buffalo:"🐃",ox:"🐂",cow2:"🐄",deer:"🦌",dromedary_camel:"🐪",camel:"🐫",elephant:"🐘",rhinoceros:"🦏",gorilla:"🦍",racehorse:"🐎",pig2:"🐖",goat:"🐐",ram:"🐏",sheep:"🐑",dog2:"🐕",poodle:"🐩",cat2:"🐈",rooster:"🐓",turkey:"🦃",dove:"🕊",rabbit2:"🐇",mouse2:"🐁",rat:"🐀",chipmunk:"🐿",feet:"🐾",paw_prints:"🐾",dragon:"🐉",dragon_face:"🐲",cactus:"🌵",christmas_tree:"🎄",evergreen_tree:"🌲",deciduous_tree:"🌳",palm_tree:"🌴",seedling:"🌱",herb:"🌿",shamrock:"☘️",four_leaf_clover:"🍀",bamboo:"🎍",tanabata_tree:"🎋",leaves:"🍃",fallen_leaf:"🍂",maple_leaf:"🍁",mushroom:"🍄",ear_of_rice:"🌾",bouquet:"💐",tulip:"🌷",rose:"🌹",wilted_flower:"🥀",sunflower:"🌻",blossom:"🌼",cherry_blossom:"🌸",hibiscus:"🌺",earth_americas:"🌎",earth_africa:"🌍",earth_asia:"🌏",full_moon:"🌕",waning_gibbous_moon:"🌖",last_quarter_moon:"🌗",waning_crescent_moon:"🌘",new_moon:"🌑",waxing_crescent_moon:"🌒",first_quarter_moon:"🌓",moon:"🌔",waxing_gibbous_moon:"🌔",new_moon_with_face:"🌚",full_moon_with_face:"🌝",sun_with_face:"🌞",first_quarter_moon_with_face:"🌛",last_quarter_moon_with_face:"🌜",crescent_moon:"🌙",dizzy:"💫",star:"⭐️",star2:"🌟",sparkles:"✨",zap:"⚡️",fire:"🔥",boom:"💥",collision:"💥",comet:"☄",sunny:"☀️",sun_behind_small_cloud:"🌤",partly_sunny:"⛅️",sun_behind_large_cloud:"🌥",sun_behind_rain_cloud:"🌦",rainbow:"🌈",cloud:"☁️",cloud_with_rain:"🌧",cloud_with_lightning_and_rain:"⛈",cloud_with_lightning:"🌩",cloud_with_snow:"🌨",snowman_with_snow:"☃️",snowman:"⛄️",snowflake:"❄️",wind_face:"🌬",dash:"💨",tornado:"🌪",fog:"🌫",ocean:"🌊",droplet:"💧",sweat_drops:"💦",umbrella:"☔️",green_apple:"🍏",apple:"🍎",pear:"🍐",tangerine:"🍊",orange:"🍊",mandarin:"🍊",lemon:"🍋",banana:"🍌",watermelon:"🍉",grapes:"🍇",strawberry:"🍓",melon:"🍈",cherries:"🍒",peach:"🍑",pineapple:"🍍",kiwi_fruit:"🥝",avocado:"🥑",tomato:"🍅",eggplant:"🍆",cucumber:"🥒",carrot:"🥕",corn:"🌽",hot_pepper:"🌶",potato:"🥔",sweet_potato:"🍠",chestnut:"🌰",peanuts:"🥜",honey_pot:"🍯",croissant:"🥐",bread:"🍞",baguette_bread:"🥖",cheese:"🧀",egg:"🥚",fried_egg:"🍳",bacon:"🥓",pancakes:"🥞",fried_shrimp:"🍤",poultry_leg:"🍗",meat_on_bone:"🍖",pizza:"🍕",hotdog:"🌭",hamburger:"🍔",fries:"🍟",stuffed_flatbread:"🥙",taco:"🌮",burrito:"🌯",green_salad:"🥗",shallow_pan_of_food:"🥘",spaghetti:"🍝",ramen:"🍜",stew:"🍲",fish_cake:"🍥",sushi:"🍣",bento:"🍱",curry:"🍛",rice:"🍚",rice_ball:"🍙",rice_cracker:"🍘",oden:"🍢",dango:"🍡",shaved_ice:"🍧",ice_cream:"🍨",icecream:"🍦",cake:"🍰",birthday:"🎂",custard:"🍮",lollipop:"🍭",candy:"🍬",chocolate_bar:"🍫",popcorn:"🍿",doughnut:"🍩",cookie:"🍪",milk_glass:"🥛",baby_bottle:"🍼",coffee:"☕️",tea:"🍵",sake:"🍶",beer:"🍺",beers:"🍻",clinking_glasses:"🥂",wine_glass:"🍷",tumbler_glass:"🥃",cocktail:"🍸",tropical_drink:"🍹",champagne:"🍾",spoon:"🥄",fork_and_knife:"🍴",plate_with_cutlery:"🍽",soccer:"⚽️",basketball:"🏀",football:"🏈",baseball:"⚾️",tennis:"🎾",volleyball:"🏐",rugby_football:"🏉","8ball":"🎱",ping_pong:"🏓",badminton:"🏸",goal_net:"🥅",ice_hockey:"🏒",field_hockey:"🏑",cricket:"🏏",golf:"⛳️",bow_and_arrow:"🏹",fishing_pole_and_fish:"🎣",boxing_glove:"🥊",martial_arts_uniform:"🥋",ice_skate:"⛸",ski:"🎿",skier:"⛷",snowboarder:"🏂",weight_lifting_woman:"🏋️♀️",weight_lifting_man:"🏋",person_fencing:"🤺",women_wrestling:"🤼♀",men_wrestling:"🤼♂",woman_cartwheeling:"🤸♀",man_cartwheeling:"🤸♂",basketball_woman:"⛹️♀️",basketball_man:"⛹",woman_playing_handball:"🤾♀",man_playing_handball:"🤾♂",golfing_woman:"🏌️♀️",golfing_man:"🏌",surfing_woman:"🏄♀",surfing_man:"🏄",surfer:"🏄",swimming_woman:"🏊♀",swimming_man:"🏊",swimmer:"🏊",woman_playing_water_polo:"🤽♀",man_playing_water_polo:"🤽♂",rowing_woman:"🚣♀",rowing_man:"🚣",rowboat:"🚣",horse_racing:"🏇",biking_woman:"🚴♀",biking_man:"🚴",bicyclist:"🚴",mountain_biking_woman:"🚵♀",mountain_biking_man:"🚵",mountain_bicyclist:"🚵",running_shirt_with_sash:"🎽",medal_sports:"🏅",medal_military:"🎖","1st_place_medal":"🥇","2nd_place_medal":"🥈","3rd_place_medal":"🥉",trophy:"🏆",rosette:"🏵",reminder_ribbon:"🎗",ticket:"🎫",tickets:"🎟",circus_tent:"🎪",woman_juggling:"🤹♀",man_juggling:"🤹♂",performing_arts:"🎭",art:"🎨",clapper:"🎬",microphone:"🎤",headphones:"🎧",musical_score:"🎼",musical_keyboard:"🎹",drum:"🥁",saxophone:"🎷",trumpet:"🎺",guitar:"🎸",violin:"🎻",game_die:"🎲",dart:"🎯",bowling:"🎳",video_game:"🎮",slot_machine:"🎰",car:"🚗",red_car:"🚗",taxi:"🚕",blue_car:"🚙",bus:"🚌",trolleybus:"🚎",racing_car:"🏎",police_car:"🚓",ambulance:"🚑",fire_engine:"🚒",minibus:"🚐",truck:"🚚",articulated_lorry:"🚛",tractor:"🚜",kick_scooter:"🛴",bike:"🚲",motor_scooter:"🛵",motorcycle:"🏍",rotating_light:"🚨",oncoming_police_car:"🚔",oncoming_bus:"🚍",oncoming_automobile:"🚘",oncoming_taxi:"🚖",aerial_tramway:"🚡",mountain_cableway:"🚠",suspension_railway:"🚟",railway_car:"🚃",train:"🚋",mountain_railway:"🚞",monorail:"🚝",bullettrain_side:"🚄",bullettrain_front:"🚅",light_rail:"🚈",steam_locomotive:"🚂",train2:"🚆",metro:"🚇",tram:"🚊",station:"🚉",helicopter:"🚁",small_airplane:"🛩",airplane:"✈️",flight_departure:"🛫",flight_arrival:"🛬",rocket:"🚀",artificial_satellite:"🛰",seat:"💺",canoe:"🛶",boat:"⛵️",sailboat:"⛵️",motor_boat:"🛥",speedboat:"🚤",passenger_ship:"🛳",ferry:"⛴",ship:"🚢",anchor:"⚓️",construction:"🚧",fuelpump:"⛽️",busstop:"🚏",vertical_traffic_light:"🚦",traffic_light:"🚥",world_map:"🗺",moyai:"🗿",statue_of_liberty:"🗽",fountain:"⛲️",tokyo_tower:"🗼",european_castle:"🏰",japanese_castle:"🏯",stadium:"🏟",ferris_wheel:"🎡",roller_coaster:"🎢",carousel_horse:"🎠",parasol_on_ground:"⛱",beach_umbrella:"🏖",desert_island:"🏝",mountain:"⛰",mountain_snow:"🏔",mount_fuji:"🗻",volcano:"🌋",desert:"🏜",camping:"🏕",tent:"⛺️",railway_track:"🛤",motorway:"🛣",building_construction:"🏗",factory:"🏭",house:"🏠",house_with_garden:"🏡",houses:"🏘",derelict_house:"🏚",office:"🏢",department_store:"🏬",post_office:"🏣",european_post_office:"🏤",hospital:"🏥",bank:"🏦",hotel:"🏨",convenience_store:"🏪",school:"🏫",love_hotel:"🏩",wedding:"💒",classical_building:"🏛",church:"⛪️",mosque:"🕌",synagogue:"🕍",kaaba:"🕋",shinto_shrine:"⛩",japan:"🗾",rice_scene:"🎑",national_park:"🏞",sunrise:"🌅",sunrise_over_mountains:"🌄",stars:"🌠",sparkler:"🎇",fireworks:"🎆",city_sunrise:"🌇",city_sunset:"🌆",cityscape:"🏙",night_with_stars:"🌃",milky_way:"🌌",bridge_at_night:"🌉",foggy:"🌁",watch:"⌚️",iphone:"📱",calling:"📲",computer:"💻",keyboard:"⌨️",desktop_computer:"🖥",printer:"🖨",computer_mouse:"🖱",trackball:"🖲",joystick:"🕹",clamp:"🗜",minidisc:"💽",floppy_disk:"💾",cd:"💿",dvd:"📀",vhs:"📼",camera:"📷",camera_flash:"📸",video_camera:"📹",movie_camera:"🎥",film_projector:"📽",film_strip:"🎞",telephone_receiver:"📞",phone:"☎️",telephone:"☎️",pager:"📟",fax:"📠",tv:"📺",radio:"📻",studio_microphone:"🎙",level_slider:"🎚",control_knobs:"🎛",stopwatch:"⏱",timer_clock:"⏲",alarm_clock:"⏰",mantelpiece_clock:"🕰",hourglass:"⌛️",hourglass_flowing_sand:"⏳",satellite:"📡",battery:"🔋",electric_plug:"🔌",bulb:"💡",flashlight:"🔦",candle:"🕯",wastebasket:"🗑",oil_drum:"🛢",money_with_wings:"💸",dollar:"💵",yen:"💴",euro:"💶",pound:"💷",moneybag:"💰",credit_card:"💳",gem:"💎",balance_scale:"⚖️",wrench:"🔧",hammer:"🔨",hammer_and_pick:"⚒",hammer_and_wrench:"🛠",pick:"⛏",nut_and_bolt:"🔩",gear:"⚙️",chains:"⛓",gun:"🔫",bomb:"💣",hocho:"🔪",knife:"🔪",dagger:"🗡",crossed_swords:"⚔️",shield:"🛡",smoking:"🚬",coffin:"⚰️",funeral_urn:"⚱️",amphora:"🏺",crystal_ball:"🔮",prayer_beads:"📿",barber:"💈",alembic:"⚗️",telescope:"🔭",microscope:"🔬",hole:"🕳",pill:"💊",syringe:"💉",thermometer:"🌡",toilet:"🚽",potable_water:"🚰",shower:"🚿",bathtub:"🛁",bath:"🛀",bellhop_bell:"🛎",key:"🔑",old_key:"🗝",door:"🚪",couch_and_lamp:"🛋",bed:"🛏",sleeping_bed:"🛌",framed_picture:"🖼",shopping:"🛍",shopping_cart:"🛒",gift:"🎁",balloon:"🎈",flags:"🎏",ribbon:"🎀",confetti_ball:"🎊",tada:"🎉",dolls:"🎎",izakaya_lantern:"🏮",lantern:"🏮",wind_chime:"🎐",email:"✉️",envelope:"✉️",envelope_with_arrow:"📩",incoming_envelope:"📨","e-mail":"📧",love_letter:"💌",inbox_tray:"📥",outbox_tray:"📤",package:"📦",label:"🏷",mailbox_closed:"📪",mailbox:"📫",mailbox_with_mail:"📬",mailbox_with_no_mail:"📭",postbox:"📮",postal_horn:"📯",scroll:"📜",page_with_curl:"📃",page_facing_up:"📄",bookmark_tabs:"📑",bar_chart:"📊",chart_with_upwards_trend:"📈",chart_with_downwards_trend:"📉",spiral_notepad:"🗒",spiral_calendar:"🗓",calendar:"📆",date:"📅",card_index:"📇",card_file_box:"🗃",ballot_box:"🗳",file_cabinet:"🗄",clipboard:"📋",file_folder:"📁",open_file_folder:"📂",card_index_dividers:"🗂",newspaper_roll:"🗞",newspaper:"📰",notebook:"📓",notebook_with_decorative_cover:"📔",ledger:"📒",closed_book:"📕",green_book:"📗",blue_book:"📘",orange_book:"📙",books:"📚",book:"📖",open_book:"📖",bookmark:"🔖",link:"🔗",paperclip:"📎",paperclips:"🖇",triangular_ruler:"📐",straight_ruler:"📏",pushpin:"📌",round_pushpin:"📍",scissors:"✂️",pen:"🖊",fountain_pen:"🖋",black_nib:"✒️",paintbrush:"🖌",crayon:"🖍",memo:"📝",pencil:"📝",pencil2:"✏️",mag:"🔍",mag_right:"🔎",lock_with_ink_pen:"🔏",closed_lock_with_key:"🔐",lock:"🔒",unlock:"🔓",heart:"❤️",yellow_heart:"💛",green_heart:"💚",blue_heart:"💙",purple_heart:"💜",black_heart:"🖤",broken_heart:"💔",heavy_heart_exclamation:"❣️",two_hearts:"💕",revolving_hearts:"💞",heartbeat:"💓",heartpulse:"💗",sparkling_heart:"💖",cupid:"💘",gift_heart:"💝",heart_decoration:"💟",peace_symbol:"☮️",latin_cross:"✝️",star_and_crescent:"☪️",om:"🕉",wheel_of_dharma:"☸️",star_of_david:"✡️",six_pointed_star:"🔯",menorah:"🕎",yin_yang:"☯️",orthodox_cross:"☦️",place_of_worship:"🛐",ophiuchus:"⛎",aries:"♈️",taurus:"♉️",gemini:"♊️",cancer:"♋️",leo:"♌️",virgo:"♍️",libra:"♎️",scorpius:"♏️",sagittarius:"♐️",capricorn:"♑️",aquarius:"♒️",pisces:"♓️",id:"🆔",atom_symbol:"⚛️",accept:"🉑",radioactive:"☢️",biohazard:"☣️",mobile_phone_off:"📴",vibration_mode:"📳",eight_pointed_black_star:"✴️",vs:"🆚",white_flower:"💮",ideograph_advantage:"🉐",secret:"㊙️",congratulations:"㊗️",u6e80:"🈵",a:"🅰️",b:"🅱️",ab:"🆎",cl:"🆑",o2:"🅾️",sos:"🆘",x:"❌",o:"⭕️",stop_sign:"🛑",no_entry:"⛔️",name_badge:"📛",no_entry_sign:"🚫",anger:"💢",hotsprings:"♨️",no_pedestrians:"🚷",do_not_litter:"🚯",no_bicycles:"🚳","non-potable_water":"🚱",underage:"🔞",no_mobile_phones:"📵",no_smoking:"🚭",exclamation:"❗️",heavy_exclamation_mark:"❗️",grey_exclamation:"❕",question:"❓",grey_question:"❔",bangbang:"‼️",interrobang:"⁉️",low_brightness:"🔅",high_brightness:"🔆",part_alternation_mark:"〽️",warning:"⚠️",children_crossing:"🚸",trident:"🔱",fleur_de_lis:"⚜️",beginner:"🔰",recycle:"♻️",white_check_mark:"✅",chart:"💹",sparkle:"❇️",eight_spoked_asterisk:"✳️",negative_squared_cross_mark:"❎",globe_with_meridians:"🌐",diamond_shape_with_a_dot_inside:"💠",m:"Ⓜ️",cyclone:"🌀",zzz:"💤",atm:"🏧",wc:"🚾",wheelchair:"♿️",parking:"🅿️",sa:"🈂️",passport_control:"🛂",customs:"🛃",baggage_claim:"🛄",left_luggage:"🛅",mens:"🚹",womens:"🚺",baby_symbol:"🚼",restroom:"🚻",put_litter_in_its_place:"🚮",cinema:"🎦",signal_strength:"📶",koko:"🈁",symbols:"🔣",information_source:"ℹ️",abc:"🔤",abcd:"🔡",capital_abcd:"🔠",ng:"🆖",ok:"🆗",up:"🆙",cool:"🆒",new:"🆕",free:"🆓",zero:"0️⃣",one:"1️⃣",two:"2️⃣",three:"3️⃣",four:"4️⃣",five:"5️⃣",six:"6️⃣",seven:"7️⃣",eight:"8️⃣",nine:"9️⃣",keycap_ten:"🔟",hash:"#️⃣",asterisk:"*️⃣",arrow_forward:"▶️",pause_button:"⏸",play_or_pause_button:"⏯",stop_button:"⏹",record_button:"⏺",next_track_button:"⏭",previous_track_button:"⏮",fast_forward:"⏩",rewind:"⏪",arrow_double_up:"⏫",arrow_double_down:"⏬",arrow_backward:"◀️",arrow_up_small:"🔼",arrow_down_small:"🔽",arrow_right:"➡️",arrow_left:"⬅️",arrow_up:"⬆️",arrow_down:"⬇️",arrow_upper_right:"↗️",arrow_lower_right:"↘️",arrow_lower_left:"↙️",arrow_upper_left:"↖️",arrow_up_down:"↕️",left_right_arrow:"↔️",arrow_right_hook:"↪️",leftwards_arrow_with_hook:"↩️",arrow_heading_up:"⤴️",arrow_heading_down:"⤵️",twisted_rightwards_arrows:"🔀",repeat:"🔁",repeat_one:"🔂",arrows_counterclockwise:"🔄",arrows_clockwise:"🔃",musical_note:"🎵",notes:"🎶",heavy_plus_sign:"➕",heavy_minus_sign:"➖",heavy_division_sign:"➗",heavy_multiplication_x:"✖️",heavy_dollar_sign:"💲",currency_exchange:"💱",tm:"™️",copyright:"©️",registered:"®️",wavy_dash:"〰️",curly_loop:"➰",loop:"➿",end:"🔚",back:"🔙",on:"🔛",top:"🔝",soon:"🔜",heavy_check_mark:"✔️",ballot_box_with_check:"☑️",radio_button:"🔘",white_circle:"⚪️",black_circle:"⚫️",red_circle:"🔴",large_blue_circle:"🔵",small_red_triangle:"🔺",small_red_triangle_down:"🔻",small_orange_diamond:"🔸",small_blue_diamond:"🔹",large_orange_diamond:"🔶",large_blue_diamond:"🔷",white_square_button:"🔳",black_square_button:"🔲",black_small_square:"▪️",white_small_square:"▫️",black_medium_small_square:"◾️",white_medium_small_square:"◽️",black_medium_square:"◼️",white_medium_square:"◻️",black_large_square:"⬛️",white_large_square:"⬜️",speaker:"🔈",mute:"🔇",sound:"🔉",loud_sound:"🔊",bell:"🔔",no_bell:"🔕",mega:"📣",loudspeaker:"📢",eye_speech_bubble:"👁🗨",speech_balloon:"💬",thought_balloon:"💭",right_anger_bubble:"🗯",spades:"♠️",clubs:"♣️",hearts:"♥️",diamonds:"♦️",black_joker:"🃏",flower_playing_cards:"🎴",mahjong:"🀄️",clock1:"🕐",clock2:"🕑",clock3:"🕒",clock4:"🕓",clock5:"🕔",clock6:"🕕",clock7:"🕖",clock8:"🕗",clock9:"🕘",clock10:"🕙",clock11:"🕚",clock12:"🕛",clock130:"🕜",clock230:"🕝",clock330:"🕞",clock430:"🕟",clock530:"🕠",clock630:"🕡",clock730:"🕢",clock830:"🕣",clock930:"🕤",clock1030:"🕥",clock1130:"🕦",clock1230:"🕧",white_flag:"🏳️",black_flag:"🏴",checkered_flag:"🏁",triangular_flag_on_post:"🚩",rainbow_flag:"🏳️🌈",afghanistan:"🇦🇫",aland_islands:"🇦🇽",albania:"🇦🇱",algeria:"🇩🇿",american_samoa:"🇦🇸",andorra:"🇦🇩",angola:"🇦🇴",anguilla:"🇦🇮",antarctica:"🇦🇶",antigua_barbuda:"🇦🇬",argentina:"🇦🇷",armenia:"🇦🇲",aruba:"🇦🇼",australia:"🇦🇺",austria:"🇦🇹",azerbaijan:"🇦🇿",bahamas:"🇧🇸",bahrain:"🇧🇭",bangladesh:"🇧🇩",barbados:"🇧🇧",belarus:"🇧🇾",belgium:"🇧🇪",belize:"🇧🇿",benin:"🇧🇯",bermuda:"🇧🇲",bhutan:"🇧🇹",bolivia:"🇧🇴",caribbean_netherlands:"🇧🇶",bosnia_herzegovina:"🇧🇦",botswana:"🇧🇼",brazil:"🇧🇷",british_indian_ocean_territory:"🇮🇴",british_virgin_islands:"🇻🇬",brunei:"🇧🇳",bulgaria:"🇧🇬",burkina_faso:"🇧🇫",burundi:"🇧🇮",cape_verde:"🇨🇻",cambodia:"🇰🇭",cameroon:"🇨🇲",canada:"🇨🇦",canary_islands:"🇮🇨",cayman_islands:"🇰🇾",central_african_republic:"🇨🇫",chad:"🇹🇩",chile:"🇨🇱",cn:"🇨🇳",christmas_island:"🇨🇽",cocos_islands:"🇨🇨",colombia:"🇨🇴",comoros:"🇰🇲",congo_brazzaville:"🇨🇬",congo_kinshasa:"🇨🇩",cook_islands:"🇨🇰",costa_rica:"🇨🇷",cote_divoire:"🇨🇮",croatia:"🇭🇷",cuba:"🇨🇺",curacao:"🇨🇼",cyprus:"🇨🇾",czech_republic:"🇨🇿",denmark:"🇩🇰",djibouti:"🇩🇯",dominica:"🇩🇲",dominican_republic:"🇩🇴",ecuador:"🇪🇨",egypt:"🇪🇬",el_salvador:"🇸🇻",equatorial_guinea:"🇬🇶",eritrea:"🇪🇷",estonia:"🇪🇪",ethiopia:"🇪🇹",eu:"🇪🇺",european_union:"🇪🇺",falkland_islands:"🇫🇰",faroe_islands:"🇫🇴",fiji:"🇫🇯",finland:"🇫🇮",fr:"🇫🇷",french_guiana:"🇬🇫",french_polynesia:"🇵🇫",french_southern_territories:"🇹🇫",gabon:"🇬🇦",gambia:"🇬🇲",georgia:"🇬🇪",de:"🇩🇪",ghana:"🇬🇭",gibraltar:"🇬🇮",greece:"🇬🇷",greenland:"🇬🇱",grenada:"🇬🇩",guadeloupe:"🇬🇵",guam:"🇬🇺",guatemala:"🇬🇹",guernsey:"🇬🇬",guinea:"🇬🇳",guinea_bissau:"🇬🇼",guyana:"🇬🇾",haiti:"🇭🇹",honduras:"🇭🇳",hong_kong:"🇭🇰",hungary:"🇭🇺",iceland:"🇮🇸",india:"🇮🇳",indonesia:"🇮🇩",iran:"🇮🇷",iraq:"🇮🇶",ireland:"🇮🇪",isle_of_man:"🇮🇲",israel:"🇮🇱",it:"🇮🇹",jamaica:"🇯🇲",jp:"🇯🇵",crossed_flags:"🎌",jersey:"🇯🇪",jordan:"🇯🇴",kazakhstan:"🇰🇿",kenya:"🇰🇪",kiribati:"🇰🇮",kosovo:"🇽🇰",kuwait:"🇰🇼",kyrgyzstan:"🇰🇬",laos:"🇱🇦",latvia:"🇱🇻",lebanon:"🇱🇧",lesotho:"🇱🇸",liberia:"🇱🇷",libya:"🇱🇾",liechtenstein:"🇱🇮",lithuania:"🇱🇹",luxembourg:"🇱🇺",macau:"🇲🇴",macedonia:"🇲🇰",madagascar:"🇲🇬",malawi:"🇲🇼",malaysia:"🇲🇾",maldives:"🇲🇻",mali:"🇲🇱",malta:"🇲🇹",marshall_islands:"🇲🇭",martinique:"🇲🇶",mauritania:"🇲🇷",mauritius:"🇲🇺",mayotte:"🇾🇹",mexico:"🇲🇽",micronesia:"🇫🇲",moldova:"🇲🇩",monaco:"🇲🇨",mongolia:"🇲🇳",montenegro:"🇲🇪",montserrat:"🇲🇸",morocco:"🇲🇦",mozambique:"🇲🇿",myanmar:"🇲🇲",namibia:"🇳🇦",nauru:"🇳🇷",nepal:"🇳🇵",netherlands:"🇳🇱",new_caledonia:"🇳🇨",new_zealand:"🇳🇿",nicaragua:"🇳🇮",niger:"🇳🇪",nigeria:"🇳🇬",niue:"🇳🇺",norfolk_island:"🇳🇫",northern_mariana_islands:"🇲🇵",north_korea:"🇰🇵",norway:"🇳🇴",oman:"🇴🇲",pakistan:"🇵🇰",palau:"🇵🇼",palestinian_territories:"🇵🇸",panama:"🇵🇦",papua_new_guinea:"🇵🇬",paraguay:"🇵🇾",peru:"🇵🇪",philippines:"🇵🇭",pitcairn_islands:"🇵🇳",poland:"🇵🇱",portugal:"🇵🇹",puerto_rico:"🇵🇷",qatar:"🇶🇦",reunion:"🇷🇪",romania:"🇷🇴",ru:"🇷🇺",rwanda:"🇷🇼",st_barthelemy:"🇧🇱",st_helena:"🇸🇭",st_kitts_nevis:"🇰🇳",st_lucia:"🇱🇨",st_pierre_miquelon:"🇵🇲",st_vincent_grenadines:"🇻🇨",samoa:"🇼🇸",san_marino:"🇸🇲",sao_tome_principe:"🇸🇹",saudi_arabia:"🇸🇦",senegal:"🇸🇳",serbia:"🇷🇸",seychelles:"🇸🇨",sierra_leone:"🇸🇱",singapore:"🇸🇬",sint_maarten:"🇸🇽",slovakia:"🇸🇰",slovenia:"🇸🇮",solomon_islands:"🇸🇧",somalia:"🇸🇴",south_africa:"🇿🇦",south_georgia_south_sandwich_islands:"🇬🇸",kr:"🇰🇷",south_sudan:"🇸🇸",es:"🇪🇸",sri_lanka:"🇱🇰",sudan:"🇸🇩",suriname:"🇸🇷",swaziland:"🇸🇿",sweden:"🇸🇪",switzerland:"🇨🇭",syria:"🇸🇾",taiwan:"🇹🇼",tajikistan:"🇹🇯",tanzania:"🇹🇿",thailand:"🇹🇭",timor_leste:"🇹🇱",togo:"🇹🇬",tokelau:"🇹🇰",tonga:"🇹🇴",trinidad_tobago:"🇹🇹",tunisia:"🇹🇳",tr:"🇹🇷",turkmenistan:"🇹🇲",turks_caicos_islands:"🇹🇨",tuvalu:"🇹🇻",uganda:"🇺🇬",ukraine:"🇺🇦",united_arab_emirates:"🇦🇪",gb:"🇬🇧",uk:"🇬🇧",us:"🇺🇸",us_virgin_islands:"🇻🇮",uruguay:"🇺🇾",uzbekistan:"🇺🇿",vanuatu:"🇻🇺",vatican_city:"🇻🇦",venezuela:"🇻🇪",vietnam:"🇻🇳",wallis_futuna:"🇼🇫",western_sahara:"🇪🇭",yemen:"🇾🇪",zambia:"🇿🇲",zimbabwe:"🇿🇼"}},Rzq8:function(e,t,r){"use strict";t.a={props:{search:String,select:Number,enter:Boolean},data:function(){return{showItems:[],items:[]}},mounted:function(){this.fetchFileNav()},watch:{search:function(e){var t=[];for(var r in this.items)this.items[r].name.indexOf(e)>=0&&t.push(this.items[r]);this.showItems=t,this.$emit("updateShowLen",this.showItems.length)},enter:function(e){e&&(this.$emit("close"),this.$bus.$emit("gotoLine",this.showItems[this.select].line))}},methods:{fetchFileNav:function(){var e=this;this.$http.get("/func-nav?file="+encodeURI(this.$bus.curSourceFile)).then(function(t){e.search="";var r=[];for(var a in t.data){var n=t.data[a];n.class?r.push({name:n.name,prototype:n.class+"::"+n.name+"("+n.params+")",line:n.line}):r.push({name:n.name,prototype:n.name+"("+n.params+")",line:n.line})}e.items=r,e.showItems=e.items,e.$emit("updateShowLen",e.showItems.length)})},rowClicked:function(e){this.$emit("close"),this.$bus.$emit("gotoLine",e)}}}},T5h1:function(e,t,r){"use strict";var a=r("mvHQ"),n=r.n(a);t.a={props:{search:String,select:Number,enter:Boolean},data:function(){return{showItems:[],items:[]}},mounted:function(){this.fetchBreakpoints()},watch:{search:function(e){var t=[];for(var r in this.items)this.items[r].file.indexOf(e)>=0&&t.push(this.items[r]);this.showItems=t,this.$emit("updateShowLen",this.showItems.length)},enter:function(e){if(e){this.$emit("close");var t=this.showItems[this.select];this.$bus.$emit("openFile",t.file,t.line)}}},methods:{fetchBreakpoints:function(){var e=[];for(var t in window.localStorage){var r=JSON.parse(window.localStorage[t]);for(var a in r)e.push({file:t,line:a})}this.items=e,this.showItems=this.items,this.$emit("updateShowLen",this.showItems.length)},rowClicked:function(e){this.$emit("close"),this.$bus.$emit("openFile",e.file,e.line)},remove:function(e){var t=this.$localStorage.get(e.file);t&&(t=JSON.parse(t),delete t[e.line],this.$localStorage.set(e.file,n()(t)),this.$bus.$emit("removeBp",e.file,e.line),this.fetchBreakpoints())}}}},Txe8:function(e,t,r){"use strict";var a=function(){var e=this,t=e.$createElement,r=e._self._c||t;return r("svg",{class:e.klass,style:e.style,attrs:{version:"1.1",role:e.label?"img":"presentation","aria-label":e.label,x:e.x,y:e.y,width:e.width,height:e.height,viewBox:e.box}},[e._t("default",[e.icon&&e.icon.paths?e._l(e.icon.paths,function(t,a){return r("path",e._b({key:"path-"+a},"path",t,!1))}):e._e(),e._v(" "),e.icon&&e.icon.polygons?e._l(e.icon.polygons,function(t,a){return r("polygon",e._b({key:"polygon-"+a},"polygon",t,!1))}):e._e(),e._v("\b\n "),e.icon&&e.icon.raw?[r("g",{domProps:{innerHTML:e._s(e.raw)}})]:e._e()])],2)},n=[],i={render:a,staticRenderFns:n};t.a=i},UtXa:function(e,t,r){"use strict";function a(e){r("5abi")}var n=r("Rzq8"),i=r("/E90"),o=r("VU/8"),s=a,l=o(n.a,i.a,s,"data-v-087f4174",null);t.a=l.exports},"Wq+S":function(e,t,r){"use strict";function a(e){r("seGP")}var n=r("K5QJ"),i=r("1Bj8"),o=r("VU/8"),s=a,l=o(n.a,i.a,s,"data-v-24870b3c",null);t.a=l.exports},XDsQ:function(e,t,r){"use strict";function a(e){r("hUBu")}var n=r("px5a"),i=r("10oB"),o=r("VU/8"),s=a,l=o(n.a,i.a,s,"data-v-01b04102",null);t.a=l.exports},YaEn:function(e,t,r){"use strict";var a=r("7+uW"),n=r("/ocq"),i=r("eWLx"),o=r("42Hy"),s=r("lO7g");a.a.use(n.a),t.a=new n.a({routes:[{path:"/trace/source/:id",name:"Source",component:i.a},{path:"/home",name:"Home",component:s.a},{path:"/",name:"Index",component:o.a}]})},aGEy:function(e,t){},bpnn:function(e,t,r){"use strict";var a=function(){var e=this,t=e.$createElement,r=e._self._c||t;return r("b-modal",{ref:"popupList",attrs:{"hide-header":"","hide-footer":"",size:"lg"},on:{shown:e.searchInputFocus}},[r("div",{staticStyle:{padding:"0 10rem","margin-bottom":"1rem"}},[r("b-form-input",{ref:"searchInput",attrs:{type:"text"},model:{value:e.search,callback:function(t){e.search=t},expression:"search"}})],1),e._v(" "),"traces-nav"===e.type?r("traces-nav",{attrs:{enter:e.enter,search:e.search,select:e.select},on:{close:e.close,updateShowLen:e.updateShowLen}}):e._e(),e._v(" "),"func-nav"===e.type?r("func-nav",{attrs:{enter:e.enter,search:e.search,select:e.select},on:{close:e.close,updateShowLen:e.updateShowLen}}):e._e(),e._v(" "),"file-nav"===e.type?r("file-nav",{attrs:{enter:e.enter,search:e.search,select:e.select},on:{close:e.close,updateShowLen:e.updateShowLen}}):e._e(),e._v(" "),"breakpoint-nav"===e.type?r("breakpoint-nav",{attrs:{enter:e.enter,search:e.search,select:e.select},on:{close:e.close,updateShowLen:e.updateShowLen}}):e._e()],1)},n=[],i={render:a,staticRenderFns:n};t.a=i},cCV5:function(e,t){},cUy1:function(e,t,r){"use strict";t.a={props:{search:String,select:Number,enter:Boolean},data:function(){return{showItems:[],items:[]}},mounted:function(){this.fetchFileNav()},watch:{search:function(e){var t=[];for(var r in this.items)this.items[r].indexOf(e)>=0&&t.push(this.items[r]);this.showItems=t,this.$emit("updateShowLen",this.showItems.length)},enter:function(e){e&&(this.$emit("close"),this.$bus.$emit("openFile",this.showItems[this.select]))}},methods:{fetchFileNav:function(){var e=this;this.$http.get("/file-nav/"+this.$route.params.id).then(function(t){e.search="",e.items=t.data,e.showItems=e.items,e.$emit("updateShowLen",e.showItems.length)})},rowClicked:function(e){this.$emit("close"),this.$bus.$emit("openFile",e)}}}},chry:function(e,t){},dXrS:function(e,t,r){"use strict";function a(){return"fa-"+(i++).toString(16)}var n={};t.a={name:"icon",props:{name:{type:String,validator:function(e){return e?e in n||(console.warn('Invalid prop: prop "name" is referring to an unregistered icon "'+e+'".\nPlesase make sure you have imported this icon before using it.'),!1):(console.warn('Invalid prop: prop "name" is required.'),!1)}},scale:[Number,String],spin:Boolean,inverse:Boolean,pulse:Boolean,flip:{validator:function(e){return"horizontal"===e||"vertical"===e}},label:String},data:function(){return{x:!1,y:!1,childrenWidth:0,childrenHeight:0,outerScale:1}},computed:{normalizedScale:function(){var e=this.scale;return e=void 0===e?1:Number(e),isNaN(e)||e<=0?(console.warn('Invalid prop: prop "scale" should be a number over 0.',this),this.outerScale):e*this.outerScale},klass:function(){return{"fa-icon":!0,"fa-spin":this.spin,"fa-flip-horizontal":"horizontal"===this.flip,"fa-flip-vertical":"vertical"===this.flip,"fa-inverse":this.inverse,"fa-pulse":this.pulse}},icon:function(){return this.name?n[this.name]:null},box:function(){return this.icon?"0 0 "+this.icon.width+" "+this.icon.height:"0 0 "+this.width+" "+this.height},ratio:function(){if(!this.icon)return 1;var e=this.icon,t=e.width,r=e.height;return Math.max(t,r)/16},width:function(){return this.childrenWidth||this.icon&&this.icon.width/this.ratio*this.normalizedScale||0},height:function(){return this.childrenHeight||this.icon&&this.icon.height/this.ratio*this.normalizedScale||0},style:function(){return 1!==this.normalizedScale&&{fontSize:this.normalizedScale+"em"}},raw:function(){if(!this.icon||!this.icon.raw)return null;var e=this.icon.raw,t={};return e=e.replace(/\s(?:xml:)?id=["']?([^"')\s]+)/g,function(e,r){var n=a();return t[r]=n,' id="'+n+'"'}),e=e.replace(/#(?:([^'")\s]+)|xpointer\(id\((['"]?)([^')]+)\2\)\))/g,function(e,r,a,n){var i=r||n;return i&&t[i]?"#"+t[i]:e}),e}},mounted:function(){var e=this;if(!this.icon){this.$children.forEach(function(t){t.outerScale=e.normalizedScale});var t=0,r=0;this.$children.forEach(function(e){t=Math.max(t,e.width),r=Math.max(r,e.height)}),this.childrenWidth=t,this.childrenHeight=r,this.$children.forEach(function(e){e.x=(t-e.width)/2,e.y=(r-e.height)/2})}},register:function(e){for(var t in e){var r=e[t];r.paths||(r.paths=[]),r.d&&r.paths.push({d:r.d}),r.polygons||(r.polygons=[]),r.points&&r.polygons.push({points:r.points}),n[t]=r}},icons:n};var i=870711},dcIi:function(e,t,r){"use strict";var a=function(){var e=this,t=e.$createElement,r=e._self._c||t;return r("b-container",{staticStyle:{"text-align":"center"}},[r("b-row",[r("b-col",{staticStyle:{"text-align":"left"}},[r("div",{staticStyle:{margin:"1rem 0"}},[r("b-button",{attrs:{variant:"danger"},on:{click:function(t){e.clearTraces()}}},[e._v("Clear Traces")]),e._v(" "),r("b-button",{attrs:{variant:"outline-primary"},on:{click:function(t){e.fetchTraces()}}},[e._v("Refresh")])],1),e._v(" "),r("b-table",{attrs:{hover:"",items:e.files,fields:e.fields},on:{"row-clicked":e.rowClicked}})],1)],1)],1)},n=[],i={render:a,staticRenderFns:n};t.a=i},eWLx:function(e,t,r){"use strict";function a(e){r("aGEy"),r("y7ny")}var n=r("68IZ"),i=r("rApO"),o=r("VU/8"),s=a,l=o(n.a,i.a,s,"data-v-6dec0ee4",null);t.a=l.exports},ejnp:function(e,t,r){"use strict";t.a={data:function(){return{GUI:"__Home 页面__: 列出所有的跟踪文件, 通过点击列表中的某行记录打开Source 页面。\n+ Clear Traces: 删除所有的跟踪文件。\n+ Refresh: 刷新列表。\n+ 列表字段说明:\n - Sapi: cli, fpm-fcgi 等\n - Method: fpm-fcgi中的http 请求方法\n - Uri: fpm-fcgi中的http 请求路径及参数\n - File: 跟踪文件名\n - Size: 跟踪文件大小\n - Time: 跟踪文件创建时间\n\n__Source Page__: 显示跟踪内容详情。\n+ 左边模块显示源码文件,右边模块显示跟踪到的变量值。\n - 只跟踪赋值和函数调用\n - ++、--、+=、/=、-=、*=、%=等,显示的值是这些运算符执行之前的值\n - PHP 7无法获取到扩展函数的参数名称(无法显示参数名称的会显示为$...)\n+ 被执行过的代码行,行号会以绿色高亮出来,深绿色表示当前执行所在的行\n - 点击高亮的行号,可以将执行跳转至对应行\n - ctrl+点击行号,可以设置或取消断点(断点的行号会以红色高亮)\n+ 执行操作:\n - step into: 同gdb\n - step back: 根据你的执行历史,往回执行\n - step over: 同gdb\n - step out: 同gdb\n - continue: 同gdb,执行到下一个断点\n - reset:重置执行过程\n+ 快捷键:\n - ctrl+o: 打开最新10个跟踪文件的列表浮框\n - ctrl+p: 打开被跟踪到的源码文件的列表浮框,只能在Source 页面使用\n - ctrl+r: 打开当前显示的源码文件函数/方法的列表浮框,只能在Source 页面使用\n - ctrl+b: 打开断点列表浮框,只能在Source 页面使用\n\n[ytrace_gui](https://github.com/yangxikun/ytrace_gui)\n[report issue](https://github.com/yangxikun/ytrace_gui/issues)\n ",ChromeExtension:"__Options__\n+ ytrace.*_name: 配置cookie的名称,必须与ytrace.ini保持一致,通常不需要更改默认值。\n\n__弹框__\n+ 开启/关闭跟踪\n+ 设置跟踪的配置,ytrace PHP扩展会从cookie里检测它们。\n\n[ytrace_chrome_extension](https://github.com/yangxikun/ytrace_chrome_extension)\n[report issue](https://github.com/yangxikun/ytrace_chrome_extension/issues)\n ",PHPExtension:'__INI 配置__\n+ auto_enable: 类型:boolean,默认值:0, PHP_INI_SYSTEM.\n+ enable_trigger: 类型:boolean,默认值:0, PHP_INI_SYSTEM.\n - 当设置为1时,你可以通过名为YTRACE_TRIGGER的GET/POST参数,或cookie,或环境变量来触发跟踪\n+ enable_trigger_name: 类型:string,默认值:YTRACE_TRIGGER, PHP_INI_SYSTEM.\n+ enable_trigger_value: 类型:string,默认值:"", PHP_INI_SYSTEM.\n - 用于限制触发跟踪的值\n - 当为空字符串时,只要检测到有YTRACE_TRIGGER名称的GET/POST参数,或cookie,或环境变量时,就会触发跟踪\n - 当为非空字符串时,名称为YTRACE_TRIGGER的GET/POST参数,或cookie,或环境变量对应的值必须与之匹配\n+ output_dir: 类型:string,默认值: /tmp, PHP_INI_SYSTEM.\n - 确保有写权限\n+ output_format: 类型:string,默认值: trace-%t, PHP_INI_SYSTEM.\n - 跟踪文件命名\n - %t: 秒级时间戳\n - %u: 毫秒级时间戳\n - %p: pid\n - %H: $_SERVER[\'HTTP_HOST\']\n - %U: $_SERVER[\'UNIQUE_ID\']\n - %R: $_SERVER[\'REQUEST_URI\']\n - %%: %字面量\n+ white_list: 类型:string,默认值: "", PHP_INI_ALL.\n - 由逗号分隔的多个字符串组成,大小写敏感\n - 当设置它的值时,例如“controller,model”,那么只有源码文件路径包含“controller”或“model”,才会被跟踪\n - white_list优先级高于black_list\n+ white_list_name: 类型:string,默认值: "YTRACE_WHITE_LIST", PHP_INI_SYSTEM.\n+ black_list: 类型:string,默认值: "", PHP_INI_ALL.\n - 由逗号分隔的多个字符串组成,大小写敏感\n - 当设置它的值时,例如“vendor,lib”,如果源码文件路径包含“vendor”或“lib”,将不会被跟踪\n+ black_list_name: 类型:string,默认值: "YTRACE_BLACK_LIST", PHP_INI_SYSTEM.\n+ var_display_max_children: 类型:integer,默认值: 128, PHP_INI_ALL.\n - Controls the amount of array children and object\'s properties are traced.\n - 控制跟踪到的变量值最大的数组元素个数和对象的属性个数\n - 最大值是 32\n+ var_display_max_children_name 类型:string,默认值: "YTRACE_VAR_DISPLAY_MAX_CHILDREN", PHP_INI_SYSTEM.\n+ var_display_max_data: 类型:integer,默认值: 512, PHP_INI_ALL.\n - Controls the maximum string length that is traced.\n - 控制跟踪到的字符串变量值的最大长度\n - 最大值 1024\n+ var_display_max_data_name 类型:string,默认值: "YTRACE_VAR_DISPLAY_MAX_DATA", PHP_INI_SYSTEM.\n+ var_display_max_depth: 类型:integer,默认值: 3, PHP_INI_ALL.\n - 控制跟踪到的变量值的最大嵌套层级\n - 最大 16\n+ var_display_max_depth_name 类型:string,默认值: "YTRACE_VAR_DISPLAY_MAX_DEPTH", PHP_INI_SYSTEM.\n==通常,你不需要修改*_name配置的默认值。*_name的配置是用于设置cookie、环境变量、GET/POST参数的名称。==\n\n__PHP 函数__\n+ ytrace_enable ([$traced_file_name])\n - 开启跟踪,并写入到$traced_file_name\n+ ytrace_disable ()\n - 停止跟踪,返回跟踪文件名\n\n[ytrace](https://github.com/yangxikun/ytrace)\n[report issue](https://github.com/yangxikun/ytrace/issues)\n '}}}},fWJJ:function(e,t,r){"use strict";function a(e){r("DUku")}var n=r("cUy1"),i=r("RQcw"),o=r("VU/8"),s=a,l=o(n.a,i.a,s,"data-v-2f888d8e",null);t.a=l.exports},h02k:function(e,t,r){"use strict";var a=r("Jltp"),n=r("bpnn"),i=r("VU/8"),o=i(a.a,n.a,null,null,null);t.a=o.exports},hUBu:function(e,t){},hpS7:function(e,t,r){"use strict";var a=function(){var e=this,t=e.$createElement,r=e._self._c||t;return r("div",{attrs:{id:"app"}},[r("div",{attrs:{id:"head"}},[r("b-navbar",{attrs:{toggleable:"md",type:"light",variant:"light"}},[r("b-nav-toggle",{attrs:{target:"nav_collapse"}}),e._v(" "),r("b-navbar-brand",{attrs:{href:"#"}},[r("router-link",{staticClass:"nav-link",attrs:{to:"/"}},[e._v("Ytrace")])],1),e._v(" "),r("b-collapse",{attrs:{"is-nav":"",id:"nav_collapse"}},[r("b-nav",{attrs:{"is-nav-bar":""}},[r("b-nav-item",[r("router-link",{staticClass:"nav-link",class:{active:"Home"==e.nav},attrs:{to:"/home"}},[e._v("Home")])],1),e._v(" "),r("b-nav-item",[r("router-link",{staticClass:"nav-link",class:{disabled:""==e.traceId,active:"Source"==e.nav},attrs:{event:e.traceId?"click":"",to:"/trace/source/"+e.traceId}},[e._v("Source")])],1)],1)],1)],1)],1),e._v(" "),r("keep-alive",{attrs:{exclude:"Home"}},[r("router-view")],1),e._v(" "),r("popup-list")],1)},n=[],i={render:a,staticRenderFns:n};t.a=i},lO7g:function(e,t,r){"use strict";function a(e){r("OUSy"),r("HCoV")}var n=r("Fs8J"),i=r("dcIi"),o=r("VU/8"),s=a,l=o(n.a,i.a,s,"data-v-7eb551e8",null);t.a=l.exports},lzLh:function(e,t,r){"use strict";function a(e){r("Icg2")}var n=r("T5h1"),i=r("wYtO"),o=r("VU/8"),s=a,l=o(n.a,i.a,s,"data-v-59939b8e",null);t.a=l.exports},px5a:function(e,t,r){"use strict";t.a={data:function(){return{GUI:"__Home Page__: List all traced files, click on one of the items in the list to open source page.\n+ Clear Traces: delete all traced files.\n+ Refresh: update list.\n+ List field explanation:\n - Sapi: cli, fpm-fcgi etc\n - Method: http method in fpm-fcgi\n - Uri: http request uri in fpm-fcgi\n - File: file name\n - Size: file size\n - Time: created time\n\n__Source Page__: show detail of traced files.\n+ source code show in left side, traced value show in right side.\n - only assignment and function call will be traced\n - ++, --, +=, /=, -=, *=, %= etc, shows the values before these operators execute\n - PHP 7 cannot show internal function parameters name (parameter name cannot be found will be showed as $...)\n+ executed line will be highlight in green, dark green means current execute\n - click highlighted line number, can jump current execute to it\n - ctrl+click line number, can set/clear a breakpoint (breakpoint will be highlight in red line number)\n+ execute operation:\n - step into: same with gdb\n - step back: execute back through your step history\n - step over: same with gdb\n - step out: same with gdb\n - continue: same with gdb, execute to next breakpoint\n - reset: reset execute to first entry\n+ shortcut:\n - ctrl+o: open 10 latest traced file popup list\n - ctrl+p: open traced source file popup list, only available in source page\n - ctrl+r: open current source file function/method popup list, only available in source page\n - ctrl+b: open breakpoints popup list, only available in source page\n\n[ytrace_gui](https://github.com/yangxikun/ytrace_gui)\n[report issue](https://github.com/yangxikun/ytrace_gui/issues)\n ",ChromeExtension:"__Options__\n+ ytrace.*_name: cookie name will be used, must be same with ytrace.ini config, generally you don't need to change the default config.\n\n__Popup__\n+ enable/disable trace\n+ set trace config, ytrace php extension will detect it from cookie\n\n[ytrace_chrome_extension](https://github.com/yangxikun/ytrace_chrome_extension)\n[report issue](https://github.com/yangxikun/ytrace_chrome_extension/issues)\n ",PHPExtension:'__INI config__\n+ auto_enable: Type: boolean, Default value: 0, PHP_INI_SYSTEM.\n+ enable_trigger: Type: boolean, Default value: 0, PHP_INI_SYSTEM.\n - When this setting is set to 1, you can trigger the generation of trace files by using the YTRACE_TRIGGER GET/POST parameter, or set a cookie with the name YTRACE_TRIGGER, or set an environment variable with the name YTRACE_TRIGGER.\n+ enable_trigger_name: Type: string, Default value: YTRACE_TRIGGER, PHP_INI_SYSTEM.\n+ enable_trigger_value: Type: string, Defalut value: "", PHP_INI_SYSTEM.\n - This setting can be used to restrict who can make use of the YTRACE_TRIGGER functionality as outlined in ytrace.enable_trigger.\n - When changed from its default value of an empty string, the value of the cookie, environment variable, GET or POST argument needs to match the shared secret set with this setting in order for the trace file to be generated.\n+ output_dir: Type: string, Default value: /tmp, PHP_INI_SYSTEM.\n - make sure has write permission.\n+ output_format: Type: string, Default value: trace-%t, PHP_INI_SYSTEM.\n - name format of traced file\n - %t: timestamp (in seconds)\n - %u: timestamp (in microseconds)\n - %p: pid\n - %H: $_SERVER[\'HTTP_HOST\']\n - %U: $_SERVER[\'UNIQUE_ID\']\n - %R: $_SERVER[\'REQUEST_URI\']\n - %%: literal %\n+ white_list: Type: string, Default value: "", PHP_INI_ALL.\n - comma separated string, case sensitive.\n - When set its value, sunch as "controller,model", only executed source file path that contain "controller" or "model" will be traced.\n - white_list takes precedence over black_list.\n+ white_list_name: Type: string, Default value: "YTRACE_WHITE_LIST", PHP_INI_SYSTEM.\n+ black_list: Type: string, Default value: "", PHP_INI_ALL.\n - comma separated string, case sensitive.\n - When set its value, sunch as "vendor,lib", executed source file path that contain "vendor" or "lib" will not be traced.\n+ black_list_name: Type: string, Default value: "YTRACE_BLACK_LIST", PHP_INI_SYSTEM.\n+ var_display_max_children: Type: integer, Default value: 128, PHP_INI_ALL.\n - Controls the amount of array children and object\'s properties are traced.\n - max value 32\n+ var_display_max_children_name Type: string, Default value: "YTRACE_VAR_DISPLAY_MAX_CHILDREN", PHP_INI_SYSTEM.\n+ var_display_max_data: Type: integer, Default value: 512, PHP_INI_ALL.\n - Controls the maximum string length that is traced.\n - max value 1024\n+ var_display_max_data_name Type: string, Default value: "YTRACE_VAR_DISPLAY_MAX_DATA", PHP_INI_SYSTEM.\n+ var_display_max_depth: Type: integer, Default value: 3, PHP_INI_ALL.\n - Controls how many nested levels of array elements and object properties are traced.\n - max value 16\n+ var_display_max_depth_name Type: string, Default value: "YTRACE_VAR_DISPLAY_MAX_DEPTH", PHP_INI_SYSTEM.\n==Generally, you don’t need to change the default config of *_name. The value of *_name is used for the name of cookie, environment variable, GET or POST argument==\n\n__PHP function__\n+ ytrace_enable ([$traced_file_name])\n - enable trace when trace is disable, write trace to $traced_file_name.\n+ ytrace_disable ()\n - disable trace when trace is enable, return traced file.\n\n[ytrace](https://github.com/yangxikun/ytrace)\n[report issue](https://github.com/yangxikun/ytrace/issues)\n '}}}},"qE0+":function(e,t){},rApO:function(e,t,r){"use strict";var a=function(){var e=this,t=e.$createElement,r=e._self._c||t;return r("div",[r("div",{directives:[{name:"show",rawName:"v-show",value:!e.loading,expression:"!loading"}]},[r("div",{staticStyle:{padding:"0.5rem 1rem"}},[r("h6",{directives:[{name:"show",rawName:"v-show",value:e.file,expression:"file"}],staticStyle:{display:"inline-block",color:"rgba(0, 0, 0, 0.5)"}},[e._v(e._s(e.file)+":"+e._s(e.line))]),e._v(" "),r("b-button",{attrs:{size:"sm",variant:"outline-secondary"},on:{click:function(t){e.reset(0)}}},[e._v("reset")]),e._v(" "),r("b-button",{attrs:{disabled:e.step==e.items.length-1,size:"sm",variant:"outline-secondary"},on:{click:function(t){e._continue()}}},[e._v("continue")]),e._v(" "),r("b-button",{attrs:{disabled:e.step==e.items.length-1,size:"sm",variant:"outline-secondary"},on:{click:function(t){e.stepOut()}}},[e._v("step out")]),e._v(" "),r("b-button",{attrs:{disabled:e.step==e.items.length-1,size:"sm",variant:"outline-secondary"},on:{click:function(t){e.stepOver()}}},[e._v("step over")]),e._v(" "),r("b-button",{attrs:{size:"sm",variant:"outline-secondary"},on:{click:function(t){e.stepBack()}}},[e._v("step back")]),e._v(" "),r("b-button",{attrs:{disabled:e.step==e.items.length-1,size:"sm",variant:"outline-secondary"},on:{click:function(t){e.stepInto(e.step,e.step+1)}}},[e._v("step into")])],1),e._v(" "),r("div",{staticClass:"container-fluid"},[r("b-row",[r("b-col",{attrs:{cols:"8"}},[r("div",{ref:"code",staticStyle:{width:"100%","font-size":"1rem"},style:{height:e.codeHeight+"px"}})]),e._v(" "),r("b-col",[r("div",{ref:"var",staticStyle:{width:"100%","font-size":"1rem"},style:{height:e.codeHeight+"px"}})])],1)],1)]),e._v(" "),r("div",{directives:[{name:"show",rawName:"v-show",value:e.loading,expression:"loading"}],staticStyle:{"margin-top":"5%"}},[r("vue-loading",{attrs:{type:"bars",color:"#d9544e",size:{width:"8rem",height:"6rem"}}})],1)])},n=[],i={render:a,staticRenderFns:n};t.a=i},seGP:function(e,t){},wYtO:function(e,t,r){"use strict";var a=function(){var e=this,t=e.$createElement,r=e._self._c||t;return r("b-list-group",{staticStyle:{"max-height":"35rem"}},e._l(e.showItems,function(t,a){return r("b-list-group-item",{key:a,class:{active:a===e.select},on:{click:function(r){e.rowClicked(t)}}},[e._v("\n "+e._s(t.file)+": "+e._s(t.line)+"\n "),r("div",{staticStyle:{display:"inline-block",float:"right"},on:{click:function(r){r.stopPropagation(),e.remove(t)}}},[r("icon",{attrs:{name:"close"}})],1)])}))},n=[],i={render:a,staticRenderFns:n};t.a=i},xJD8:function(e,t,r){"use strict";var a=r("h02k");t.a={name:"app",components:{PopupList:a.a},data:function(){return{nav:"Home",traceId:""}},watch:{$route:"activateNav"},mounted:function(){var e=this;this.$bus.$on("clearTraces",function(){e.traceId=""}),this.activateNav()},methods:{activateNav:function(){this.nav=this.$route.name,this.$route.params.id&&(this.traceId=this.$route.params.id)}}}},y7ny:function(e,t){}},["NHnr"]);
--------------------------------------------------------------------------------
/static/js/manifest.3dff49ac782c8e4820fb.js:
--------------------------------------------------------------------------------
1 | !function(e){function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}var r=window.webpackJsonp;window.webpackJsonp=function(t,c,a){for(var i,u,f,s=0,l=[];s 1%", "last 2 versions", "not ie <= 8"]
7 | }
8 | }],
9 | "stage-2"
10 | ],
11 | "plugins": ["transform-runtime"],
12 | "env": {
13 | "test": {
14 | "presets": ["env", "stage-2"],
15 | "plugins": ["istanbul"]
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/webui/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
--------------------------------------------------------------------------------
/webui/.eslintignore:
--------------------------------------------------------------------------------
1 | build/*.js
2 | config/*.js
3 |
--------------------------------------------------------------------------------
/webui/.eslintrc.js:
--------------------------------------------------------------------------------
1 | // https://eslint.org/docs/user-guide/configuring
2 |
3 | module.exports = {
4 | root: true,
5 | parser: 'babel-eslint',
6 | parserOptions: {
7 | sourceType: 'module'
8 | },
9 | env: {
10 | browser: true,
11 | },
12 | // https://github.com/standard/standard/blob/master/docs/RULES-en.md
13 | extends: 'standard',
14 | // required to lint *.vue files
15 | plugins: [
16 | 'html'
17 | ],
18 | // add your custom rules here
19 | 'rules': {
20 | // allow paren-less arrow functions
21 | 'arrow-parens': 0,
22 | // allow async-await
23 | 'generator-star-spacing': 0,
24 | // allow debugger during development
25 | 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
26 | 'no-new-func': 0
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/webui/.postcssrc.js:
--------------------------------------------------------------------------------
1 | // https://github.com/michael-ciniawsky/postcss-load-config
2 |
3 | module.exports = {
4 | "plugins": {
5 | // to edit target browsers: use "browserslist" field in package.json
6 | "autoprefixer": {}
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/webui/build/build.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | require('./check-versions')()
3 |
4 | process.env.NODE_ENV = 'production'
5 |
6 | const ora = require('ora')
7 | const rm = require('rimraf')
8 | const path = require('path')
9 | const chalk = require('chalk')
10 | const webpack = require('webpack')
11 | const config = require('../config')
12 | const webpackConfig = require('./webpack.prod.conf')
13 |
14 | const spinner = ora('building for production...')
15 | spinner.start()
16 |
17 | rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
18 | if (err) throw err
19 | webpack(webpackConfig, function (err, stats) {
20 | spinner.stop()
21 | if (err) throw err
22 | process.stdout.write(stats.toString({
23 | colors: true,
24 | modules: false,
25 | children: false,
26 | chunks: false,
27 | chunkModules: false
28 | }) + '\n\n')
29 |
30 | if (stats.hasErrors()) {
31 | console.log(chalk.red(' Build failed with errors.\n'))
32 | process.exit(1)
33 | }
34 |
35 | console.log(chalk.cyan(' Build complete.\n'))
36 | console.log(chalk.yellow(
37 | ' Tip: built files are meant to be served over an HTTP server.\n' +
38 | ' Opening index.html over file:// won\'t work.\n'
39 | ))
40 | })
41 | })
42 |
--------------------------------------------------------------------------------
/webui/build/check-versions.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const chalk = require('chalk')
3 | const semver = require('semver')
4 | const packageConfig = require('../package.json')
5 | const shell = require('shelljs')
6 | function exec (cmd) {
7 | return require('child_process').execSync(cmd).toString().trim()
8 | }
9 |
10 | const versionRequirements = [
11 | {
12 | name: 'node',
13 | currentVersion: semver.clean(process.version),
14 | versionRequirement: packageConfig.engines.node
15 | }
16 | ]
17 |
18 | if (shell.which('npm')) {
19 | versionRequirements.push({
20 | name: 'npm',
21 | currentVersion: exec('npm --version'),
22 | versionRequirement: packageConfig.engines.npm
23 | })
24 | }
25 |
26 | module.exports = function () {
27 | const warnings = []
28 | for (let i = 0; i < versionRequirements.length; i++) {
29 | const mod = versionRequirements[i]
30 | if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
31 | warnings.push(mod.name + ': ' +
32 | chalk.red(mod.currentVersion) + ' should be ' +
33 | chalk.green(mod.versionRequirement)
34 | )
35 | }
36 | }
37 |
38 | if (warnings.length) {
39 | console.log('')
40 | console.log(chalk.yellow('To use this template, you must update following to modules:'))
41 | console.log()
42 | for (let i = 0; i < warnings.length; i++) {
43 | const warning = warnings[i]
44 | console.log(' ' + warning)
45 | }
46 | console.log()
47 | process.exit(1)
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/webui/build/dev-client.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | 'use strict'
3 | require('eventsource-polyfill')
4 | const hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true')
5 |
6 | hotClient.subscribe(function (event) {
7 | if (event.action === 'reload') {
8 | window.location.reload()
9 | }
10 | })
11 |
--------------------------------------------------------------------------------
/webui/build/dev-server.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | require('./check-versions')()
3 |
4 | const config = require('../config')
5 | if (!process.env.NODE_ENV) {
6 | process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV)
7 | }
8 |
9 | const opn = require('opn')
10 | const path = require('path')
11 | const express = require('express')
12 | const webpack = require('webpack')
13 | const proxyMiddleware = require('http-proxy-middleware')
14 | const webpackConfig = require('./webpack.dev.conf')
15 |
16 | // default port where dev server listens for incoming traffic
17 | const port = process.env.PORT || config.dev.port
18 | // automatically open browser, if not set will be false
19 | const autoOpenBrowser = !!config.dev.autoOpenBrowser
20 | // Define HTTP proxies to your custom API backend
21 | // https://github.com/chimurai/http-proxy-middleware
22 | const proxyTable = config.dev.proxyTable
23 |
24 | const app = express()
25 | const compiler = webpack(webpackConfig)
26 |
27 | const devMiddleware = require('webpack-dev-middleware')(compiler, {
28 | publicPath: webpackConfig.output.publicPath,
29 | quiet: true
30 | })
31 |
32 | const hotMiddleware = require('webpack-hot-middleware')(compiler, {
33 | log: false,
34 | heartbeat: 2000
35 | })
36 | // force page reload when html-webpack-plugin template changes
37 | // currently disabled until this is resolved:
38 | // https://github.com/jantimon/html-webpack-plugin/issues/680
39 | // compiler.plugin('compilation', function (compilation) {
40 | // compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) {
41 | // hotMiddleware.publish({ action: 'reload' })
42 | // cb()
43 | // })
44 | // })
45 |
46 | // enable hot-reload and state-preserving
47 | // compilation error display
48 | app.use(hotMiddleware)
49 |
50 | // proxy api requests
51 | Object.keys(proxyTable).forEach(function (context) {
52 | const options = proxyTable[context]
53 | if (typeof options === 'string') {
54 | options = { target: options }
55 | }
56 | app.use(proxyMiddleware(options.filter || context, options))
57 | })
58 |
59 | // handle fallback for HTML5 history API
60 | app.use(require('connect-history-api-fallback')())
61 |
62 | // serve webpack bundle output
63 | app.use(devMiddleware)
64 |
65 | // serve pure static assets
66 | const staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory)
67 | app.use(staticPath, express.static('./static'))
68 |
69 | const uri = 'http://localhost:' + port
70 |
71 | var _resolve
72 | var _reject
73 | var readyPromise = new Promise((resolve, reject) => {
74 | _resolve = resolve
75 | _reject = reject
76 | })
77 |
78 | var server
79 | var portfinder = require('portfinder')
80 | portfinder.basePort = port
81 |
82 | console.log('> Starting dev server...')
83 | devMiddleware.waitUntilValid(() => {
84 | portfinder.getPort((err, port) => {
85 | if (err) {
86 | _reject(err)
87 | }
88 | process.env.PORT = port
89 | var uri = 'http://localhost:' + port
90 | console.log('> Listening at ' + uri + '\n')
91 | // when env is testing, don't need open it
92 | if (autoOpenBrowser && process.env.NODE_ENV !== 'testing') {
93 | opn(uri)
94 | }
95 | server = app.listen(port)
96 | _resolve()
97 | })
98 | })
99 |
100 | module.exports = {
101 | ready: readyPromise,
102 | close: () => {
103 | server.close()
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/webui/build/utils.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const path = require('path')
3 | const config = require('../config')
4 | const ExtractTextPlugin = require('extract-text-webpack-plugin')
5 |
6 | exports.assetsPath = function (_path) {
7 | const assetsSubDirectory = process.env.NODE_ENV === 'production'
8 | ? config.build.assetsSubDirectory
9 | : config.dev.assetsSubDirectory
10 | return path.posix.join(assetsSubDirectory, _path)
11 | }
12 |
13 | exports.cssLoaders = function (options) {
14 | options = options || {}
15 |
16 | const cssLoader = {
17 | loader: 'css-loader',
18 | options: {
19 | minimize: process.env.NODE_ENV === 'production',
20 | sourceMap: options.sourceMap
21 | }
22 | }
23 |
24 | // generate loader string to be used with extract text plugin
25 | function generateLoaders (loader, loaderOptions) {
26 | const loaders = [cssLoader]
27 | if (loader) {
28 | loaders.push({
29 | loader: loader + '-loader',
30 | options: Object.assign({}, loaderOptions, {
31 | sourceMap: options.sourceMap
32 | })
33 | })
34 | }
35 |
36 | // Extract CSS when that option is specified
37 | // (which is the case during production build)
38 | if (options.extract) {
39 | return ExtractTextPlugin.extract({
40 | use: loaders,
41 | fallback: 'vue-style-loader'
42 | })
43 | } else {
44 | return ['vue-style-loader'].concat(loaders)
45 | }
46 | }
47 |
48 | // https://vue-loader.vuejs.org/en/configurations/extract-css.html
49 | return {
50 | css: generateLoaders(),
51 | postcss: generateLoaders(),
52 | less: generateLoaders('less'),
53 | sass: generateLoaders('sass', { indentedSyntax: true }),
54 | scss: generateLoaders('sass'),
55 | stylus: generateLoaders('stylus'),
56 | styl: generateLoaders('stylus')
57 | }
58 | }
59 |
60 | // Generate loaders for standalone style files (outside of .vue)
61 | exports.styleLoaders = function (options) {
62 | const output = []
63 | const loaders = exports.cssLoaders(options)
64 | for (const extension in loaders) {
65 | const loader = loaders[extension]
66 | output.push({
67 | test: new RegExp('\\.' + extension + '$'),
68 | use: loader
69 | })
70 | }
71 | return output
72 | }
73 |
--------------------------------------------------------------------------------
/webui/build/vue-loader.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const utils = require('./utils')
3 | const config = require('../config')
4 | const isProduction = process.env.NODE_ENV === 'production'
5 |
6 | module.exports = {
7 | loaders: utils.cssLoaders({
8 | sourceMap: isProduction
9 | ? config.build.productionSourceMap
10 | : config.dev.cssSourceMap,
11 | extract: isProduction
12 | }),
13 | transformToRequire: {
14 | video: 'src',
15 | source: 'src',
16 | img: 'src',
17 | image: 'xlink:href'
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/webui/build/webpack.base.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const path = require('path')
3 | const utils = require('./utils')
4 | const config = require('../config')
5 | const vueLoaderConfig = require('./vue-loader.conf')
6 |
7 | function resolve (dir) {
8 | return path.join(__dirname, '..', dir)
9 | }
10 |
11 | module.exports = {
12 | entry: {
13 | app: './src/main.js'
14 | },
15 | output: {
16 | path: config.build.assetsRoot,
17 | filename: '[name].js',
18 | publicPath: process.env.NODE_ENV === 'production'
19 | ? config.build.assetsPublicPath
20 | : config.dev.assetsPublicPath
21 | },
22 | resolve: {
23 | extensions: ['.js', '.vue', '.json'],
24 | alias: {
25 | 'vue$': 'vue/dist/vue.esm.js',
26 | '@': resolve('src'),
27 | }
28 | },
29 | module: {
30 | rules: [
31 | {
32 | test: /\.(js|vue)$/,
33 | loader: 'eslint-loader',
34 | enforce: 'pre',
35 | include: [resolve('src'), resolve('test')],
36 | options: {
37 | formatter: require('eslint-friendly-formatter')
38 | }
39 | },
40 | {
41 | test: /\.vue$/,
42 | loader: 'vue-loader',
43 | options: vueLoaderConfig
44 | },
45 | {
46 | test: /\.js$/,
47 | loader: 'babel-loader',
48 | include: [resolve('src'), resolve('test')]
49 | },
50 | {
51 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
52 | loader: 'url-loader',
53 | options: {
54 | limit: 10000,
55 | name: utils.assetsPath('img/[name].[hash:7].[ext]')
56 | }
57 | },
58 | {
59 | test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
60 | loader: 'url-loader',
61 | options: {
62 | limit: 10000,
63 | name: utils.assetsPath('media/[name].[hash:7].[ext]')
64 | }
65 | },
66 | {
67 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
68 | loader: 'url-loader',
69 | options: {
70 | limit: 10000,
71 | name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
72 | }
73 | }
74 | ]
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/webui/build/webpack.dev.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const utils = require('./utils')
3 | const webpack = require('webpack')
4 | const config = require('../config')
5 | const merge = require('webpack-merge')
6 | const baseWebpackConfig = require('./webpack.base.conf')
7 | const HtmlWebpackPlugin = require('html-webpack-plugin')
8 | const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
9 |
10 | // add hot-reload related code to entry chunks
11 | Object.keys(baseWebpackConfig.entry).forEach(function (name) {
12 | baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name])
13 | })
14 |
15 | module.exports = merge(baseWebpackConfig, {
16 | module: {
17 | rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap })
18 | },
19 | // cheap-module-eval-source-map is faster for development
20 | devtool: '#cheap-module-eval-source-map',
21 | plugins: [
22 | new webpack.DefinePlugin({
23 | 'process.env': config.dev.env
24 | }),
25 | // https://github.com/glenjamin/webpack-hot-middleware#installation--usage
26 | new webpack.HotModuleReplacementPlugin(),
27 | new webpack.NoEmitOnErrorsPlugin(),
28 | // https://github.com/ampedandwired/html-webpack-plugin
29 | new HtmlWebpackPlugin({
30 | filename: 'index.html',
31 | template: 'index.html',
32 | inject: true
33 | }),
34 | new FriendlyErrorsPlugin()
35 | ]
36 | })
37 |
--------------------------------------------------------------------------------
/webui/build/webpack.prod.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const path = require('path')
3 | const utils = require('./utils')
4 | const webpack = require('webpack')
5 | const config = require('../config')
6 | const merge = require('webpack-merge')
7 | const baseWebpackConfig = require('./webpack.base.conf')
8 | const CopyWebpackPlugin = require('copy-webpack-plugin')
9 | const HtmlWebpackPlugin = require('html-webpack-plugin')
10 | const ExtractTextPlugin = require('extract-text-webpack-plugin')
11 | const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
12 |
13 | const env = config.build.env
14 |
15 | const webpackConfig = merge(baseWebpackConfig, {
16 | module: {
17 | rules: utils.styleLoaders({
18 | sourceMap: config.build.productionSourceMap,
19 | extract: true
20 | })
21 | },
22 | devtool: config.build.productionSourceMap ? '#source-map' : false,
23 | output: {
24 | path: config.build.assetsRoot,
25 | filename: utils.assetsPath('js/[name].[chunkhash].js'),
26 | chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
27 | },
28 | plugins: [
29 | // http://vuejs.github.io/vue-loader/en/workflow/production.html
30 | new webpack.DefinePlugin({
31 | 'process.env': env
32 | }),
33 | // UglifyJs do not support ES6+, you can also use babel-minify for better treeshaking: https://github.com/babel/minify
34 | new webpack.optimize.UglifyJsPlugin({
35 | compress: {
36 | warnings: false
37 | },
38 | sourceMap: true
39 | }),
40 | // extract css into its own file
41 | new ExtractTextPlugin({
42 | filename: utils.assetsPath('css/[name].[contenthash].css')
43 | }),
44 | // Compress extracted CSS. We are using this plugin so that possible
45 | // duplicated CSS from different components can be deduped.
46 | new OptimizeCSSPlugin({
47 | cssProcessorOptions: {
48 | safe: true
49 | }
50 | }),
51 | // generate dist index.html with correct asset hash for caching.
52 | // you can customize output by editing /index.html
53 | // see https://github.com/ampedandwired/html-webpack-plugin
54 | new HtmlWebpackPlugin({
55 | filename: config.build.index,
56 | template: 'index.html',
57 | inject: true,
58 | minify: {
59 | removeComments: true,
60 | collapseWhitespace: true,
61 | removeAttributeQuotes: true
62 | // more options:
63 | // https://github.com/kangax/html-minifier#options-quick-reference
64 | },
65 | // necessary to consistently work with multiple chunks via CommonsChunkPlugin
66 | chunksSortMode: 'dependency'
67 | }),
68 | // keep module.id stable when vender modules does not change
69 | new webpack.HashedModuleIdsPlugin(),
70 | // split vendor js into its own file
71 | new webpack.optimize.CommonsChunkPlugin({
72 | name: 'vendor',
73 | minChunks: function (module) {
74 | // any required modules inside node_modules are extracted to vendor
75 | return (
76 | module.resource &&
77 | /\.js$/.test(module.resource) &&
78 | module.resource.indexOf(
79 | path.join(__dirname, '../node_modules')
80 | ) === 0
81 | )
82 | }
83 | }),
84 | // extract webpack runtime and module manifest to its own file in order to
85 | // prevent vendor hash from being updated whenever app bundle is updated
86 | new webpack.optimize.CommonsChunkPlugin({
87 | name: 'manifest',
88 | chunks: ['vendor']
89 | }),
90 | // copy custom static assets
91 | new CopyWebpackPlugin([
92 | {
93 | from: path.resolve(__dirname, '../static'),
94 | to: config.build.assetsSubDirectory,
95 | ignore: ['.*']
96 | }
97 | ])
98 | ]
99 | })
100 |
101 | if (config.build.productionGzip) {
102 | const CompressionWebpackPlugin = require('compression-webpack-plugin')
103 |
104 | webpackConfig.plugins.push(
105 | new CompressionWebpackPlugin({
106 | asset: '[path].gz[query]',
107 | algorithm: 'gzip',
108 | test: new RegExp(
109 | '\\.(' +
110 | config.build.productionGzipExtensions.join('|') +
111 | ')$'
112 | ),
113 | threshold: 10240,
114 | minRatio: 0.8
115 | })
116 | )
117 | }
118 |
119 | if (config.build.bundleAnalyzerReport) {
120 | const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
121 | webpackConfig.plugins.push(new BundleAnalyzerPlugin())
122 | }
123 |
124 | module.exports = webpackConfig
125 |
--------------------------------------------------------------------------------
/webui/config/dev.env.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const merge = require('webpack-merge')
3 | const prodEnv = require('./prod.env')
4 |
5 | module.exports = merge(prodEnv, {
6 | NODE_ENV: '"development"'
7 | })
8 |
--------------------------------------------------------------------------------
/webui/config/index.js:
--------------------------------------------------------------------------------
1 | 'use stxrict'
2 | // Template version: 1.1.0
3 | // see http://vuejs-templates.github.io/webpack for documentation.
4 |
5 | const path = require('path')
6 |
7 | module.exports = {
8 | build: {
9 | env: require('./prod.env'),
10 | index: path.resolve(__dirname, '../../index.html'),
11 | assetsRoot: path.resolve(__dirname, '../..'),
12 | assetsSubDirectory: 'static',
13 | assetsPublicPath: '/',
14 | productionSourceMap: false,
15 | // Gzip off by default as many popular static hosts such as
16 | // Surge or Netlify already gzip all static assets for you.
17 | // Before setting to `true`, make sure to:
18 | // npm install --save-dev compression-webpack-plugin
19 | productionGzip: false,
20 | productionGzipExtensions: ['js', 'css'],
21 | // Run the build command with an extra argument to
22 | // View the bundle analyzer report after build finishes:
23 | // `npm run build --report`
24 | // Set to `true` or `false` to always turn it on or off
25 | bundleAnalyzerReport: process.env.npm_config_report
26 | },
27 | dev: {
28 | env: require('./dev.env'),
29 | port: process.env.PORT || 8080,
30 | autoOpenBrowser: true,
31 | assetsSubDirectory: 'static',
32 | assetsPublicPath: '/',
33 | proxyTable: {
34 | '/trace': {
35 | target: 'http://localhost:8088',
36 | changeOrigin: true
37 | },
38 | '/source': {
39 | target: 'http://localhost:8088',
40 | changeOrigin: true
41 | },
42 | '/file-nav': {
43 | target: 'http://localhost:8088',
44 | changeOrigin: true
45 | },
46 | '/func-nav': {
47 | target: 'http://localhost:8088',
48 | changeOrigin: true
49 | }
50 | },
51 | // CSS Sourcemaps off by default because relative paths are "buggy"
52 | // with this option, according to the CSS-Loader README
53 | // (https://github.com/webpack/css-loader#sourcemaps)
54 | // In our experience, they generally work as expected,
55 | // just be aware of this issue when enabling this option.
56 | cssSourceMap: false
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/webui/config/prod.env.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | module.exports = {
3 | NODE_ENV: '"production"'
4 | }
5 |
--------------------------------------------------------------------------------
/webui/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | ytrace_gui
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/webui/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ytrace_gui",
3 | "version": "1.0.0",
4 | "lockfileVersion": 1,
5 | "requires": true,
6 | "dependencies": {
7 | "async": {
8 | "version": "2.4.1",
9 | "resolved": "https://registry.npmjs.org/async/-/async-2.4.1.tgz",
10 | "integrity": "sha1-YqVrJ5yYoR0JhwlqAcw+6463u9c=",
11 | "dev": true,
12 | "requires": {
13 | "lodash": "4.17.4"
14 | }
15 | },
16 | "compression-webpack-plugin": {
17 | "version": "1.0.1",
18 | "resolved": "https://registry.npmjs.org/compression-webpack-plugin/-/compression-webpack-plugin-1.0.1.tgz",
19 | "integrity": "sha512-ABF2AFb31gpIBeEy/w6Ct0u+K+jY8jFRfGwjUWGxVTidA9pf7iH/JzjcVBQ+KB1gNMycujMxA56/PznMPUV5jw==",
20 | "dev": true,
21 | "requires": {
22 | "async": "2.4.1",
23 | "webpack-sources": "1.0.2"
24 | }
25 | },
26 | "lodash": {
27 | "version": "4.17.4",
28 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz",
29 | "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=",
30 | "dev": true
31 | },
32 | "source-list-map": {
33 | "version": "2.0.0",
34 | "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.0.tgz",
35 | "integrity": "sha512-I2UmuJSRr/T8jisiROLU3A3ltr+swpniSmNPI4Ml3ZCX6tVnDsuZzK7F2hl5jTqbZBWCEKlj5HRQiPExXLgE8A==",
36 | "dev": true
37 | },
38 | "source-map": {
39 | "version": "0.6.1",
40 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
41 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
42 | "dev": true
43 | },
44 | "webpack-sources": {
45 | "version": "1.0.2",
46 | "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.0.2.tgz",
47 | "integrity": "sha512-Y7UddMCv6dGjy81nBv6nuQeFFIt5aalHm7uyDsAsW86nZwfOVPGRr3XMjEQLaT+WKo8rlzhC9qtbJvYKLtAwaw==",
48 | "dev": true,
49 | "requires": {
50 | "source-list-map": "2.0.0",
51 | "source-map": "0.6.1"
52 | }
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/webui/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ytrace_gui",
3 | "version": "1.0.0",
4 | "description": "ytrace gui",
5 | "author": "yangrokety@gmail.com",
6 | "private": true,
7 | "scripts": {
8 | "dev": "node build/dev-server.js",
9 | "start": "npm run dev",
10 | "build": "node build/build.js",
11 | "lint": "eslint --ext .js,.vue src"
12 | },
13 | "dependencies": {
14 | "axios": "^0.16.2",
15 | "bootstrap-vue": "^1.0.0-beta.9",
16 | "brace": "^0.10.0",
17 | "sprintf-js": "^1.1.1",
18 | "stylus": "^0.54.5",
19 | "stylus-loader": "^3.0.1",
20 | "vue": "^2.4.2",
21 | "vue-awesome": "^2.3.4",
22 | "vue-loading-template": "^0.1.7",
23 | "vue-localstorage": "^0.5.0",
24 | "vue-markdown": "^2.2.4",
25 | "vue-router": "^2.7.0"
26 | },
27 | "devDependencies": {
28 | "autoprefixer": "^7.1.2",
29 | "babel-core": "^6.22.1",
30 | "babel-eslint": "^7.1.1",
31 | "babel-loader": "^7.1.1",
32 | "babel-plugin-transform-runtime": "^6.22.0",
33 | "babel-preset-env": "^1.3.2",
34 | "babel-preset-stage-2": "^6.22.0",
35 | "babel-register": "^6.22.0",
36 | "connect-history-api-fallback": "^1.3.0",
37 | "copy-webpack-plugin": "^4.0.1",
38 | "css-loader": "^0.28.0",
39 | "eslint": "^3.19.0",
40 | "eslint-config-standard": "^10.2.1",
41 | "eslint-friendly-formatter": "^3.0.0",
42 | "eslint-loader": "^1.7.1",
43 | "eslint-plugin-html": "^3.0.0",
44 | "eslint-plugin-import": "^2.7.0",
45 | "eslint-plugin-node": "^5.2.0",
46 | "eslint-plugin-promise": "^3.4.0",
47 | "eslint-plugin-standard": "^3.0.1",
48 | "eventsource-polyfill": "^0.9.6",
49 | "express": "^4.14.1",
50 | "extract-text-webpack-plugin": "^3.0.0",
51 | "file-loader": "^1.1.4",
52 | "friendly-errors-webpack-plugin": "^1.6.1",
53 | "html-webpack-plugin": "^2.30.1",
54 | "http-proxy-middleware": "^0.17.3",
55 | "opn": "^5.1.0",
56 | "optimize-css-assets-webpack-plugin": "^3.2.0",
57 | "ora": "^1.2.0",
58 | "portfinder": "^1.0.13",
59 | "rimraf": "^2.6.0",
60 | "semver": "^5.3.0",
61 | "shelljs": "^0.7.6",
62 | "url-loader": "^0.5.8",
63 | "vue-loader": "^13.0.4",
64 | "vue-style-loader": "^3.0.1",
65 | "vue-template-compiler": "^2.4.2",
66 | "webpack": "^3.6.0",
67 | "webpack-bundle-analyzer": "^2.9.0",
68 | "webpack-dev-middleware": "^1.12.0",
69 | "webpack-hot-middleware": "^2.18.2",
70 | "webpack-merge": "^4.1.0"
71 | },
72 | "engines": {
73 | "node": ">= 4.0.0",
74 | "npm": ">= 3.0.0"
75 | },
76 | "browserslist": [
77 | "> 1%",
78 | "last 2 versions",
79 | "not ie <= 8"
80 | ]
81 | }
82 |
--------------------------------------------------------------------------------
/webui/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Ytrace
10 |
11 |
12 |
13 |
14 |
15 |
16 | Home
17 |
18 |
19 | Source
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
67 |
68 |
72 |
--------------------------------------------------------------------------------
/webui/src/Bus.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 |
3 | export default new Vue({
4 | data () {
5 | return {
6 | curSourceFile: ''
7 | }
8 | }
9 | })
10 |
--------------------------------------------------------------------------------
/webui/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangxikun/ytrace_gui/052d77b32e698d8d4adba94ef6c66f8489eb2854/webui/src/assets/logo.png
--------------------------------------------------------------------------------
/webui/src/components/BreakpointNav.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{item.file}}: {{item.line}}
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
77 |
78 |
82 |
--------------------------------------------------------------------------------
/webui/src/components/FileNav.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{item}}
5 |
6 |
7 |
8 |
9 |
60 |
61 |
65 |
--------------------------------------------------------------------------------
/webui/src/components/FuncNav.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{item.prototype}}
5 |
6 |
7 |
8 |
9 |
77 |
78 |
82 |
--------------------------------------------------------------------------------
/webui/src/components/Home.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Clear Traces
7 | Refresh
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
54 |
55 |
61 |
62 |
67 |
--------------------------------------------------------------------------------
/webui/src/components/Index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | EN
5 | ZH
6 |
7 |
8 |
9 |
10 |
11 |
12 |
28 |
29 |
35 |
--------------------------------------------------------------------------------
/webui/src/components/PopupList.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
109 |
--------------------------------------------------------------------------------
/webui/src/components/Source.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
{{file}}:{{line}}
6 | reset
7 | continue
8 | step out
9 | step over
10 | step back
11 | step into
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
366 |
367 |
377 |
378 |
382 |
--------------------------------------------------------------------------------
/webui/src/components/TracesNav.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{file.sapi}}
6 | {{file.method}}
7 | {{file.uri}}
8 | {{file.file}}
9 | {{file.size}}
10 | {{file.time}}
11 |
12 |
13 |
14 |
15 |
16 |
69 |
70 |
77 |
--------------------------------------------------------------------------------
/webui/src/components/wiki/WikiEn.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Welcome to Ytracealpha
4 |
This is wiki page for Ytrace's gui, chrome extension, php extension.
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
129 |
130 |
134 |
--------------------------------------------------------------------------------
/webui/src/components/wiki/WikiZh.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
欢迎使用 Ytracealpha
4 |
这是个包含Ytrace的gui、chrome扩展、php扩展相关Wiki的页面
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
132 |
133 |
137 |
--------------------------------------------------------------------------------
/webui/src/main.js:
--------------------------------------------------------------------------------
1 | // The Vue build version to load with the `import` command
2 | // (runtime-only or standalone) has been set in webpack.base.conf with an alias.
3 | import Vue from 'vue'
4 | import App from './App'
5 | import router from './router'
6 | import Axios from 'axios'
7 | import BootstrapVue from 'bootstrap-vue'
8 | import Bus from './Bus.js'
9 | import VueLocalStorage from 'vue-localstorage'
10 | import VueMarkdown from 'vue-markdown'
11 |
12 | import 'bootstrap/dist/css/bootstrap.css'
13 | import 'bootstrap-vue/dist/bootstrap-vue.css'
14 |
15 | import 'vue-awesome/icons/close'
16 | import Icon from 'vue-awesome/components/Icon'
17 |
18 | Vue.component('icon', Icon)
19 | Vue.component('VueMarkdown', VueMarkdown)
20 |
21 | Vue.use(VueLocalStorage)
22 |
23 | Vue.use(BootstrapVue)
24 |
25 | Vue.prototype.$http = Axios
26 |
27 | Vue.prototype.$bus = Bus
28 |
29 | Vue.config.productionTip = false
30 |
31 | /* eslint-disable no-new */
32 | new Vue({
33 | el: '#app',
34 | router,
35 | template: ' ',
36 | components: { App }
37 | })
38 |
--------------------------------------------------------------------------------
/webui/src/router/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Router from 'vue-router'
3 | import Source from '@/components/Source'
4 | import Index from '@/components/Index'
5 | import Home from '@/components/Home'
6 |
7 | Vue.use(Router)
8 |
9 | export default new Router({
10 | routes: [
11 | {
12 | path: '/trace/source/:id',
13 | name: 'Source',
14 | component: Source
15 | },
16 | {
17 | path: '/home',
18 | name: 'Home',
19 | component: Home
20 | },
21 | {
22 | path: '/',
23 | name: 'Index',
24 | component: Index
25 | }
26 | ]
27 | })
28 |
--------------------------------------------------------------------------------
/webui/static/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yangxikun/ytrace_gui/052d77b32e698d8d4adba94ef6c66f8489eb2854/webui/static/.gitkeep
--------------------------------------------------------------------------------