Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8a70008710 | ||
|
|
376404e235 | ||
|
|
8babafb6d1 | ||
|
|
e5b8c55df7 | ||
|
|
0ae4b9fa66 | ||
|
|
7d9445a59f | ||
|
|
d3476779e6 | ||
|
|
bf08ec381a |
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@@ -1,6 +1,9 @@
|
||||
{
|
||||
"cSpell.words": [
|
||||
"Eruda",
|
||||
"callout",
|
||||
"eval",
|
||||
"licia",
|
||||
"unenumerable"
|
||||
]
|
||||
}
|
||||
@@ -1,3 +1,9 @@
|
||||
## v1.8.0 (13 Oct 2019)
|
||||
|
||||
* feat(network): display optimization
|
||||
* feat: move http view from sources to network
|
||||
* fix(console): group object expansion
|
||||
|
||||
## v1.7.2 (11 Oct 2019)
|
||||
|
||||
* fix(console): blank bottom if js input is disabled
|
||||
|
||||
@@ -26,10 +26,6 @@ Console for Mobile Browsers.
|
||||
|
||||

|
||||
|
||||
## Why
|
||||
|
||||
Logging things out on mobile browser is never an easy stuff. I used to include `window onerror alert` script inside pages to find out JavaScript errors, kind of stupid and inefficient. Desktop browser DevTools is great, and I wish there is a similar one on mobile side, which leads to the creation of Eruda.
|
||||
|
||||
## Demo
|
||||
|
||||

|
||||
@@ -107,8 +103,6 @@ eruda.init({
|
||||
|
||||
## Plugins
|
||||
|
||||
It is possible to enhance Eruda with more features by writing plugins. Check source code of plugins below to learn how to write your own custom tool panels. Besides, [eruda-plugin](https://github.com/liriliri/eruda-plugin) is available for plugin initialization.
|
||||
|
||||
* [eruda-fps](https://github.com/liriliri/eruda-fps): Display page fps info.
|
||||
* [eruda-features](https://github.com/liriliri/eruda-features): Browser feature detections.
|
||||
* [eruda-timing](https://github.com/liriliri/eruda-timing): Show performance and resource timing.
|
||||
@@ -119,7 +113,7 @@ It is possible to enhance Eruda with more features by writing plugins. Check sou
|
||||
* [eruda-dom](https://github.com/liriliri/eruda-dom): Navigate dom tree.
|
||||
* [eruda-orientation](https://github.com/liriliri/eruda-orientation): Test orientation api.
|
||||
|
||||
When writing plugins, you can use utilities exposed by Eruda, see [docs](doc/UTIL_API.md) here.
|
||||
If you want to create a plugin yourself, follow the guides [here](./doc/PLUGIN.md).
|
||||
|
||||
## Related Projects
|
||||
|
||||
|
||||
79
doc/PLUGIN.md
Normal file
79
doc/PLUGIN.md
Normal file
@@ -0,0 +1,79 @@
|
||||
# Writing a Plugin
|
||||
|
||||
It is possible to enhance Eruda with more features by writing plugins, which means, creating your own custom panels.
|
||||
|
||||
## Creating a Plugin
|
||||
|
||||
Adding plugins is super easy for eruda. All you have to do is passing an object with a few methods implemented.
|
||||
|
||||
```javascript
|
||||
eruda.add({
|
||||
name: 'test',
|
||||
init($el) {
|
||||
$el.html('Hello, this is my first eruda plugin!');
|
||||
this._$el = $el;
|
||||
},
|
||||
show() {
|
||||
this._$el.show();
|
||||
},
|
||||
hide() {
|
||||
this._$el.hide();
|
||||
},
|
||||
destroy() {}
|
||||
});
|
||||
```
|
||||
|
||||
## Basic Structure
|
||||
|
||||
### name
|
||||
|
||||
Every plugin must have a unique name, which will be shown as the tab name on the top.
|
||||
|
||||
### init
|
||||
|
||||
Called when plugin is added, and a document element used to display content is passed in.
|
||||
|
||||
The element is wrapped as a jQuery like object, provided by the [licia](https://licia.liriliri.io/docs.html) utility library.
|
||||
|
||||
### show
|
||||
|
||||
Called when switch to the panel. Usually all you need to do is to show the container element.
|
||||
|
||||
### hide
|
||||
|
||||
Called when switch to other panel. You should at least hide the container element here.
|
||||
|
||||
### destroy
|
||||
|
||||
Called when plugin is removed using `eruda.remove('plugin name')`.
|
||||
|
||||
## Worth Mentioning
|
||||
|
||||
Apart from passing an object, you can also pass in a function that returns an object. Eruda will automatically invoke the function and use the object it returns.
|
||||
|
||||
When writing plugins, you can use utilities exposed by Eruda, see [docs](./UTIL_API.md) here.
|
||||
|
||||
```javascript
|
||||
eruda.add(function (eruda) {
|
||||
// eruda.Tool implements those four methods.
|
||||
class Test extends eruda.Tool {
|
||||
constructor() {
|
||||
super()
|
||||
this.name = 'test';
|
||||
this.style = eruda.util.evalCss('.eruda-test { background: #000; }');
|
||||
}
|
||||
init($el) {
|
||||
super.init($el);
|
||||
}
|
||||
destroy() {
|
||||
super.destroy();
|
||||
eruda.util.evalCss.remove(this.style);
|
||||
}
|
||||
}
|
||||
|
||||
return new Test();
|
||||
});
|
||||
```
|
||||
|
||||
There is also a tool for plugin initialization, check it out [here](https://github.com/liriliri/eruda-plugin).
|
||||
|
||||
@@ -104,8 +104,6 @@ eruda.init({
|
||||
|
||||
## 插件
|
||||
|
||||
你可以为 Eruda 编写插件来增强功能。关于怎么编写插件,请查看下边官方插件的源码。另外 [eruda-plugin](https://github.com/liriliri/eruda-plugin) 可以用来初始化一个新插件。
|
||||
|
||||
* [eruda-fps](https://github.com/liriliri/eruda-fps):展示页面的 fps 信息。
|
||||
* [eruda-features](https://github.com/liriliri/eruda-features):浏览器特性检测。
|
||||
* [eruda-timing](https://github.com/liriliri/eruda-timing):展示性能资源数据。
|
||||
@@ -116,7 +114,7 @@ eruda.init({
|
||||
* [eruda-dom](https://github.com/liriliri/eruda-dom):浏览 dom 树。
|
||||
* [eruda-orientation](https://github.com/liriliri/eruda-orientation):测试重力感应接口。
|
||||
|
||||
编写插件的时候,你可以使用 Eruda 提供的工具函数,相关文档请点击[这里](doc/UTIL_API.md)查看。
|
||||
如果你想要自己编写插件,可以查看这里的[教程](./PLUGIN.md)。
|
||||
|
||||
## 相关项目
|
||||
|
||||
|
||||
@@ -127,7 +127,7 @@ LocalStorage, sessionStorage, cookies, scripts, styleSheets and images.
|
||||
|
||||
## Sources
|
||||
|
||||
View json, html, js, css and http request detail.
|
||||
View json, html, js, and css.
|
||||
|
||||
### Config
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 195 KiB After Width: | Height: | Size: 193 KiB |
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "eruda",
|
||||
"version": "1.7.2",
|
||||
"version": "1.8.0",
|
||||
"description": "Console for Mobile Browsers",
|
||||
"main": "eruda.js",
|
||||
"scripts": {
|
||||
|
||||
@@ -281,6 +281,8 @@ export default class Log {
|
||||
case 'output':
|
||||
case 'table':
|
||||
case 'dir':
|
||||
case 'group':
|
||||
case 'groupCollapsed':
|
||||
if (log.src) {
|
||||
if (Log.showSrcInSources) {
|
||||
return logger.emit('viewJson', log.src)
|
||||
@@ -300,6 +302,8 @@ export default class Log {
|
||||
Log.click(type, log, $el, logger)
|
||||
delete log.args
|
||||
})
|
||||
} else if (log.type === 'group' || log.type === 'groupCollapsed') {
|
||||
logger.toggleGroup(log)
|
||||
}
|
||||
break
|
||||
case 'error':
|
||||
|
||||
@@ -322,6 +322,10 @@ export default class Logger extends Emitter {
|
||||
|
||||
el.scrollTop = el.scrollHeight - el.offsetHeight
|
||||
}
|
||||
toggleGroup(log) {
|
||||
const { targetGroup } = log
|
||||
targetGroup.collapsed ? this._openGroup(log) : this._collapseGroup(log)
|
||||
}
|
||||
_injectGlobal() {
|
||||
each(this._global, (val, name) => {
|
||||
if (window[name]) return
|
||||
|
||||
@@ -4,20 +4,5 @@
|
||||
<span {{{class 'icon-clear'}}}></span>
|
||||
</div>
|
||||
</div>
|
||||
<ul {{{class 'requests'}}}>
|
||||
{{#if requests}}
|
||||
{{#each requests}}
|
||||
<li class="eruda-request {{#if hasErr}}eruda-error{{/if}}" data-id="{{@key}}">
|
||||
<span>{{name}}</span>
|
||||
<span>{{status}}</span>
|
||||
<span>{{method}}</span>
|
||||
<span>{{subType}}</span>
|
||||
<span>{{size}}</span>
|
||||
<span>{{displayTime}}</span>
|
||||
<span {{{class 'blue'}}}>{{url}}</span>
|
||||
</li>
|
||||
{{/each}}
|
||||
{{else}}
|
||||
<li><span>Empty</span></li>
|
||||
{{/if}}
|
||||
</ul>
|
||||
<ul {{{class 'requests'}}}></ul>
|
||||
<div {{{class 'detail'}}}></div>
|
||||
|
||||
@@ -10,7 +10,8 @@ import {
|
||||
extend,
|
||||
isEmpty,
|
||||
$,
|
||||
ms
|
||||
ms,
|
||||
trim
|
||||
} from '../lib/util'
|
||||
|
||||
export default class Network extends Tool {
|
||||
@@ -22,6 +23,9 @@ export default class Network extends Tool {
|
||||
this.name = 'network'
|
||||
this._requests = {}
|
||||
this._tpl = require('./Network.hbs')
|
||||
this._detailTpl = require('./detail.hbs')
|
||||
this._requestsTpl = require('./requests.hbs')
|
||||
this._datailData = {}
|
||||
this._isFetchSupported = false
|
||||
if (window.fetch) this._isFetchSupported = isNative(window.fetch)
|
||||
}
|
||||
@@ -32,6 +36,7 @@ export default class Network extends Tool {
|
||||
this._bindEvent()
|
||||
this._initCfg()
|
||||
this.overrideXhr()
|
||||
this._appendTpl()
|
||||
}
|
||||
show() {
|
||||
super.show()
|
||||
@@ -166,9 +171,29 @@ export default class Network extends Tool {
|
||||
|
||||
if (!data.done) return
|
||||
|
||||
showSources('http', data)
|
||||
self._showDetail(data)
|
||||
})
|
||||
.on('click', '.eruda-clear-request', () => this.clear())
|
||||
.on('click', '.eruda-back', () => this._hideDetail())
|
||||
.on('click', '.eruda-http .eruda-response', () => {
|
||||
const data = this._detailData
|
||||
const resTxt = data.resTxt
|
||||
|
||||
switch (data.subType) {
|
||||
case 'css':
|
||||
return showSources('css', resTxt)
|
||||
case 'html':
|
||||
return showSources('html', resTxt)
|
||||
case 'javascript':
|
||||
return showSources('js', resTxt)
|
||||
case 'json':
|
||||
return showSources('json', resTxt)
|
||||
}
|
||||
switch (data.type) {
|
||||
case 'image':
|
||||
return showSources('img', data.url)
|
||||
}
|
||||
})
|
||||
|
||||
function showSources(type, data) {
|
||||
const sources = container.get('sources')
|
||||
@@ -187,6 +212,15 @@ export default class Network extends Tool {
|
||||
this.restoreFetch()
|
||||
this._rmCfg()
|
||||
}
|
||||
_showDetail(data) {
|
||||
if (data.resTxt && trim(data.resTxt) === '') delete data.resTxt
|
||||
if (isEmpty(data.resHeaders)) delete data.resHeaders
|
||||
this._$detail.html(this._detailTpl(data)).show()
|
||||
this._detailData = data
|
||||
}
|
||||
_hideDetail() {
|
||||
this._$detail.hide()
|
||||
}
|
||||
_rmCfg() {
|
||||
const cfg = this.config
|
||||
|
||||
@@ -196,6 +230,12 @@ export default class Network extends Tool {
|
||||
|
||||
settings.remove(cfg, 'overrideFetch').remove('Network')
|
||||
}
|
||||
_appendTpl() {
|
||||
const $el = this._$el
|
||||
$el.html(this._tpl())
|
||||
this._$detail = $el.find('.eruda-detail')
|
||||
this._$requests = $el.find('.eruda-requests')
|
||||
}
|
||||
_initCfg() {
|
||||
const cfg = (this.config = Settings.createCfg('network', {
|
||||
overrideFetch: true
|
||||
@@ -223,11 +263,11 @@ export default class Network extends Tool {
|
||||
|
||||
if (!isEmpty(this._requests)) renderData.requests = this._requests
|
||||
|
||||
this._renderHtml(this._tpl(renderData))
|
||||
this._renderHtml(this._requestsTpl(renderData))
|
||||
}
|
||||
_renderHtml(html) {
|
||||
if (html === this._lastHtml) return
|
||||
this._lastHtml = html
|
||||
this._$el.html(html)
|
||||
this._$requests.html(html)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,8 @@
|
||||
border-bottom: 1px solid $gray-light;
|
||||
margin-bottom: 10px;
|
||||
li {
|
||||
@include overflow-auto(x);
|
||||
display: flex;
|
||||
width: 100%;
|
||||
cursor: pointer;
|
||||
border-top: 1px solid $gray-light;
|
||||
height: 41px;
|
||||
@@ -27,18 +28,103 @@
|
||||
}
|
||||
}
|
||||
span {
|
||||
display: inline-block;
|
||||
display: block;
|
||||
line-height: 40px;
|
||||
height: 40px;
|
||||
padding: 0 10px;
|
||||
padding: 0 5px;
|
||||
font-size: $font-size-s;
|
||||
vertical-align: top;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
}
|
||||
.name {
|
||||
flex: 1;
|
||||
padding-left: $padding;
|
||||
}
|
||||
.status {
|
||||
width: 40px;
|
||||
}
|
||||
.method,
|
||||
.type {
|
||||
width: 50px;
|
||||
}
|
||||
.size {
|
||||
width: 70px;
|
||||
}
|
||||
.time {
|
||||
width: 60px;
|
||||
padding-right: $padding;
|
||||
}
|
||||
&:nth-child(even) {
|
||||
background: $gray-light;
|
||||
}
|
||||
}
|
||||
}
|
||||
.detail {
|
||||
@include absolute();
|
||||
z-index: 10;
|
||||
display: none;
|
||||
padding-bottom: 40px;
|
||||
background: #f8f9fa;
|
||||
.http {
|
||||
@include overflow-auto(y);
|
||||
height: 100%;
|
||||
.breadcrumb {
|
||||
@include breadcrumb();
|
||||
}
|
||||
.section {
|
||||
background: #fff;
|
||||
h2 {
|
||||
background: $blue;
|
||||
padding: $padding;
|
||||
color: #fff;
|
||||
font-size: $font-size;
|
||||
}
|
||||
margin-bottom: 10px;
|
||||
table {
|
||||
* {
|
||||
user-select: text;
|
||||
}
|
||||
td {
|
||||
font-size: $font-size-s;
|
||||
padding: 5px 10px;
|
||||
word-break: break-all;
|
||||
}
|
||||
.key {
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
}
|
||||
.response,
|
||||
.data {
|
||||
user-select: text;
|
||||
@include overflow-auto(x);
|
||||
background: #fff;
|
||||
padding: $padding;
|
||||
font-size: $font-size-s;
|
||||
margin-bottom: 10px;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
}
|
||||
.back {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
color: #fff;
|
||||
width: 100%;
|
||||
background: $blue;
|
||||
display: block;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
text-decoration: none;
|
||||
text-align: center;
|
||||
margin-top: 10px;
|
||||
transition: background 0.3s;
|
||||
&:active {
|
||||
background: $blue-dark;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,4 +42,5 @@
|
||||
{{#if resTxt}}
|
||||
<pre {{{class 'response'}}}>{{resTxt}}</pre>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
<div {{{class 'back'}}}>Back to the List</div>
|
||||
14
src/Network/requests.hbs
Normal file
14
src/Network/requests.hbs
Normal file
@@ -0,0 +1,14 @@
|
||||
{{#if requests}}
|
||||
{{#each requests}}
|
||||
<li class="eruda-request {{#if hasErr}}eruda-error{{/if}}" data-id="{{@key}}">
|
||||
<span {{{class 'name'}}}>{{name}}</span>
|
||||
<span {{{class 'status'}}}>{{status}}</span>
|
||||
<span {{{class 'method'}}}>{{method}}</span>
|
||||
<span {{{class 'type'}}}>{{subType}}</span>
|
||||
<span {{{class 'size'}}}>{{size}}</span>
|
||||
<span {{{class 'time'}}}>{{displayTime}}</span>
|
||||
</li>
|
||||
{{/each}}
|
||||
{{else}}
|
||||
<li><span>Empty</span></li>
|
||||
{{/if}}
|
||||
@@ -2,15 +2,7 @@ import Tool from '../DevTools/Tool'
|
||||
import beautify from 'js-beautify'
|
||||
import JsonViewer from '../lib/JsonViewer'
|
||||
import Settings from '../Settings/Settings'
|
||||
import {
|
||||
evalCss,
|
||||
ajax,
|
||||
isEmpty,
|
||||
escape,
|
||||
trim,
|
||||
isStr,
|
||||
highlight
|
||||
} from '../lib/util'
|
||||
import { evalCss, ajax, escape, trim, isStr, highlight } from '../lib/util'
|
||||
|
||||
export default class Sources extends Tool {
|
||||
constructor() {
|
||||
@@ -112,31 +104,10 @@ export default class Sources extends Tool {
|
||||
delete this._data
|
||||
}
|
||||
})
|
||||
|
||||
this._$el.on('click', '.eruda-http .eruda-response', () => {
|
||||
const data = this._data.val
|
||||
const resTxt = data.resTxt
|
||||
|
||||
switch (data.subType) {
|
||||
case 'css':
|
||||
return this.set('css', resTxt)
|
||||
case 'html':
|
||||
return this.set('html', resTxt)
|
||||
case 'javascript':
|
||||
return this.set('js', resTxt)
|
||||
case 'json':
|
||||
return this.set('json', resTxt)
|
||||
}
|
||||
switch (data.type) {
|
||||
case 'image':
|
||||
return this.set('img', data.url)
|
||||
}
|
||||
})
|
||||
}
|
||||
_loadTpl() {
|
||||
this._codeTpl = require('./code.hbs')
|
||||
this._imgTpl = require('./image.hbs')
|
||||
this._httpTpl = require('./http.hbs')
|
||||
this._jsonTpl = require('./json.hbs')
|
||||
this._rawTpl = require('./raw.hbs')
|
||||
this._iframeTpl = require('./iframe.hbs')
|
||||
@@ -192,8 +163,6 @@ export default class Sources extends Tool {
|
||||
return this._renderCode()
|
||||
case 'img':
|
||||
return this._renderImg()
|
||||
case 'http':
|
||||
return this._renderHttp()
|
||||
case 'json':
|
||||
return this._renderJson()
|
||||
case 'raw':
|
||||
@@ -205,14 +174,6 @@ export default class Sources extends Tool {
|
||||
_renderImg() {
|
||||
this._renderHtml(this._imgTpl(this._data.val))
|
||||
}
|
||||
_renderHttp() {
|
||||
const val = this._data.val
|
||||
|
||||
if (val.resTxt.trim() === '') delete val.resTxt
|
||||
if (isEmpty(val.resHeaders)) delete val.resHeaders
|
||||
|
||||
this._renderHtml(this._httpTpl(this._data.val))
|
||||
}
|
||||
_renderCode() {
|
||||
const data = this._data
|
||||
|
||||
|
||||
@@ -66,44 +66,6 @@
|
||||
user-select: text;
|
||||
}
|
||||
}
|
||||
.http {
|
||||
.breadcrumb {
|
||||
@include breadcrumb();
|
||||
}
|
||||
.section {
|
||||
background: #fff;
|
||||
h2 {
|
||||
background: $blue;
|
||||
padding: $padding;
|
||||
color: #fff;
|
||||
font-size: $font-size;
|
||||
}
|
||||
margin-bottom: 10px;
|
||||
table {
|
||||
* {
|
||||
user-select: text;
|
||||
}
|
||||
td {
|
||||
font-size: $font-size-s;
|
||||
padding: 5px 10px;
|
||||
word-break: break-all;
|
||||
}
|
||||
.key {
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
}
|
||||
.response,
|
||||
.data {
|
||||
user-select: text;
|
||||
@include overflow-auto(x);
|
||||
background: #fff;
|
||||
padding: $padding;
|
||||
font-size: $font-size-s;
|
||||
margin-bottom: 10px;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
}
|
||||
iframe {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
1571
src/lib/util.js
1571
src/lib/util.js
File diff suppressed because it is too large
Load Diff
@@ -39,6 +39,9 @@
|
||||
<li>
|
||||
<a href="#" id="stringify-timing">Stringify Timing</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" id="log">Log</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<script>
|
||||
@@ -123,7 +126,42 @@
|
||||
console.time('stringify window')
|
||||
eruda.util.stringifyAll(window)
|
||||
console.timeEnd('stringify window')
|
||||
})
|
||||
});
|
||||
addClickEvent('log', () => {
|
||||
console.clear();
|
||||
console.log('log');
|
||||
console.warn('warn');
|
||||
console.error(Error('test'));
|
||||
console.info('info');
|
||||
console.debug('debug');
|
||||
console.dir(document.createElement('div'));
|
||||
console.time('test');
|
||||
console.timeEnd('test');
|
||||
console.count('eruda');
|
||||
console.count('eruda');
|
||||
console.assert(true, 'assert msg');
|
||||
var site1 = { name: 'Runoob', site: 'www.runoob.com' };
|
||||
var site2 = { name: 'Google', site: 'www.google.com' };
|
||||
var site3 = { name: 'Taobao', site: 'www.taobao.com' };
|
||||
console.table([site1, site2, site3], ['site']);
|
||||
console.log('%c Oh my heavens!', 'background: #222; color: #bada55');
|
||||
console.log('This is the outer level');
|
||||
console.group();
|
||||
console.log('Level 2');
|
||||
console.group();
|
||||
console.log('Level 3');
|
||||
console.warn('More of level 3');
|
||||
console.groupEnd();
|
||||
console.log('Back to level 2');
|
||||
console.groupEnd();
|
||||
console.log('Back to the outer level');
|
||||
console.log(navigator);
|
||||
console.log(location);
|
||||
console.log(performance);
|
||||
var arr = [];
|
||||
for (var i = 0; i < 10000; i++) arr.push(i);
|
||||
console.log(arr);
|
||||
});
|
||||
</script>
|
||||
<script>
|
||||
eruda.init();
|
||||
|
||||
Reference in New Issue
Block a user