vconsole
Advanced tools
Comparing version 3.3.4 to 3.4.0
[English](./CHANGELOG.md) | 简体中文 | ||
#### V3.4.0 (2021-01-14) | ||
- 【特性】支持暗黑模式,配置项 `vConsole.option.theme` 见 [Public Properties & Methods](./doc/public_properties_methods_CN.md)。(by @progrape) | ||
- 【特性】Network 面板支持 `fetch` 网络记录。(by @weiqian93) | ||
- 【特性】Network 面板支持显示 Request Headers。 | ||
- 【特性】Network 面板仅显示简短网址,URL 参数将显示在详细信息中。(issue #291) | ||
- 【特性】System 面板增加显示 `Location` 信息。(issue #343) | ||
- 【特性】开关按钮加入拖拽安全区,避免遮挡全面屏手机底部操作区。(issue #353) | ||
- 【特性】指令输入框键入括号且自动补全括号后,光标将自动移动到括号内部。(issue #293) | ||
- 【特性】新第三方插件 [vconsole-stats-plugin](https://github.com/smackgg/vConsole-Stats)。(by @smackgg) | ||
- 【修复】修复点击开关按钮后位置会被重置的问题。 | ||
- 【修复】修复 `document.documentElement.offsetHeight|offsetWidth` 在新浏览器中不够准确的问题。(by @littlee) | ||
- 【修复】阻止用户事件派发到 readOnly 或 disabled 的 element 上。(by @norux) | ||
- 【修复】修复 nonce 查找不准确的问题。(by @sunderls) | ||
- 【修复】修复一个安全问题。(#345 by @QiAnXinCodeSafe) | ||
- 【修复】屏蔽 "webkitStorageInfo deprecation" 告警。 | ||
- 【修复】删除 `Symbol`、`Array.from` polyfill。(issue #325, #275) | ||
- 【修复】日志中显示对象内所有的 enumerable 和 unenumerable 属性。 (issue #327) | ||
- 【优化】更新 Webpack DevServer 的配置项。(by @QinZhen001) | ||
#### V3.3.4 (2019-08-19) | ||
@@ -4,0 +25,0 @@ |
English | [简体中文](./CHANGELOG_CN.md) | ||
#### V3.4.0 (2021-01-14) | ||
- [FEATURE] Add darkmode theme, see `vConsole.option.theme` in [Public Properties & Methods](./doc/public_properties_methods.md). (by @progrape) | ||
- [FEATURE] Add `fetch` log in Network tab. (by @weiqian93) | ||
- [FEATURE] Add Request Headers to Network tab. | ||
- [FEATURE] Use short URL and display parameters in Network tab. (issue #291) | ||
- [FEATURE] Add `Location` info to System tab. (issue #343) | ||
- [FEATURE] Add safe area to switch button. (issue #353) | ||
- [FEATURE] Auto move input cursor to the bracket after autocomplete command. (issue #293) | ||
- [FEATURE] New plugin [vconsole-stats-plugin](https://github.com/smackgg/vConsole-Stats). (by @smackgg) | ||
- [FIX] The position of the switch button will be reset by mistake when clicked. | ||
- [FIX] Fix `document.documentElement.offsetHeight|offsetWidth` is unreliable in newer browsers. (by @littlee) | ||
- [FIX] Prevent dispatchEvent for disabled or readOnly elements. (by @norux) | ||
- [FIX] Fix nonce searching problem. (by @sunderls) | ||
- [FIX] Fix security issues. (#345 by @QiAnXinCodeSafe) | ||
- [FIX] Prevent "webkitStorageInfo deprecation" warning. | ||
- [FIX] Remove `Symbol`, `Array.from` polyfill. (issue #325, #275) | ||
- [FIX] Show all enumerable and unenumerable properties. (issue #327) | ||
- [IMPROVE] Update Webpack DevServer option. (by @QinZhen001) | ||
#### V3.3.4 (2019-08-19) | ||
@@ -14,3 +35,3 @@ | ||
- [FEATURE] Add TypeScript definition file. (by by @jas0ncn) | ||
- [FEATURE] Add TypeScript definition file. (by @jas0ncn) | ||
- [FIX] Fix switch button position issue. (by @rexschuang) | ||
@@ -17,0 +38,0 @@ - [FIX] Avoid scrolling to bottom when away from bottom edge. (by @ele828) |
@@ -14,2 +14,3 @@ /** | ||
disableLogScrolling?: boolean | ||
theme?: 'light' | 'dark' | ||
} | ||
@@ -16,0 +17,0 @@ |
@@ -19,3 +19,3 @@ 公共属性及方法 | ||
```javascript | ||
vConsole.version // => "3.1.0" | ||
vConsole.version // => "3.4.0" | ||
``` | ||
@@ -38,2 +38,3 @@ | ||
disableLogScrolling | Boolean | true | | 若为 `false`,有新日志时面板将不会自动滚动到底部。 | ||
theme | String | true | 'light' | 主题颜色,可选值为 'light' | 'dark'。 | ||
@@ -40,0 +41,0 @@ 例子: |
@@ -19,3 +19,3 @@ Public Properties & Methods | ||
```javascript | ||
vConsole.version // => "3.1.0" | ||
vConsole.version // => "3.4.0" | ||
``` | ||
@@ -38,2 +38,3 @@ | ||
disableLogScrolling | Boolean | true | | If `false`, panel will not scroll to bottom while printing new logs. | ||
theme | String | true | 'light' | Theme mode, 'light' | 'dark'. | ||
@@ -40,0 +41,0 @@ Example: |
{ | ||
"name": "vconsole", | ||
"version": "3.3.4", | ||
"version": "3.4.0", | ||
"description": "A lightweight, extendable front-end developer tool for mobile web page.", | ||
@@ -10,3 +10,4 @@ "homepage": "https://github.com/Tencent/vConsole", | ||
"test": "mocha", | ||
"build": "webpack" | ||
"build": "webpack", | ||
"dev": "webpack-dev-server --config webpack.dev.config" | ||
}, | ||
@@ -22,23 +23,28 @@ "keywords": [ | ||
}, | ||
"dependencies": {}, | ||
"dependencies": { | ||
"mutation-observer": "^1.0.3", | ||
"transitionEnd": "^1.0.2" | ||
}, | ||
"devDependencies": { | ||
"@babel/core": "^7.5.5", | ||
"@babel/plugin-proposal-class-properties": "^7.5.5", | ||
"@babel/plugin-proposal-export-namespace-from": "^7.5.2", | ||
"@babel/plugin-proposal-object-rest-spread": "^7.5.5", | ||
"@babel/preset-env": "^7.5.5", | ||
"babel-loader": "^8.0.6", | ||
"babel-plugin-add-module-exports": "^1.0.2", | ||
"@babel/core": "^7.12.10", | ||
"@babel/plugin-proposal-class-properties": "^7.12.1", | ||
"@babel/plugin-proposal-export-namespace-from": "^7.12.1", | ||
"@babel/plugin-proposal-object-rest-spread": "^7.12.1", | ||
"@babel/preset-env": "^7.12.11", | ||
"babel-loader": "^8.2.2", | ||
"babel-plugin-add-module-exports": "^1.0.4", | ||
"chai": "^4.2.0", | ||
"copy-webpack-plugin": "^5.0.4", | ||
"css-loader": "^3.2.0", | ||
"copy-webpack-plugin": "^5.1.2", | ||
"css-loader": "^3.6.0", | ||
"html-loader": "^0.5.5", | ||
"jsdom": "^15.1.1", | ||
"jsdom": "^15.2.1", | ||
"json-loader": "^0.5.7", | ||
"less": "^3.10.0", | ||
"less": "^3.13.1", | ||
"less-loader": "^5.0.0", | ||
"mocha": "^5.2.0", | ||
"style-loader": "^1.0.0", | ||
"webpack": "^4.39.2", | ||
"webpack-cli": "^3.3.6" | ||
"style-loader": "^1.3.0", | ||
"webpack": "^4.44.2", | ||
"webpack-cli": "^3.3.12", | ||
"webpack-dev-server": "^3.11.0", | ||
"webpack-merge": "^4.2.2" | ||
}, | ||
@@ -45,0 +51,0 @@ "author": "Tencent", |
@@ -5,3 +5,3 @@ [English](./README.md) | 简体中文 | ||
============================== | ||
[![npm version](https://badge.fury.io/js/vconsole.svg)](https://badge.fury.io/js/vconsole) | ||
[![npm version](https://badge.fury.io/js/vconsole.svg)](https://badge.fury.io/js/vconsole) | ||
@@ -57,3 +57,3 @@ 一个轻量、可拓展、针对手机网页的前端开发者调试面板。 | ||
![](./example/snapshot/log_panel.png) | ||
![](./example/snapshot/panel_log.jpg) ![](./example/snapshot/panel_network.jpg) ![](./example/snapshot/panel_element.jpg) ![](./example/snapshot/panel_storage.jpg) | ||
@@ -83,5 +83,4 @@ | ||
- [vconsole-webpack-plugin](https://github.com/diamont1001/vconsole-webpack-plugin) | ||
- [vconsole-stats-plugin](https://github.com/smackgg/vConsole-Stats) | ||
## 更新记录 | ||
@@ -88,0 +87,0 @@ |
@@ -5,3 +5,3 @@ English | [简体中文](./README_CN.md) | ||
============================== | ||
[![npm version](https://badge.fury.io/js/vconsole.svg)](https://badge.fury.io/js/vconsole) | ||
[![npm version](https://badge.fury.io/js/vconsole.svg)](https://badge.fury.io/js/vconsole) | ||
@@ -57,3 +57,3 @@ A lightweight, extendable front-end developer tool for mobile web page. | ||
![](./example/snapshot/log_panel.png) | ||
![](./example/snapshot/panel_log.jpg) ![](./example/snapshot/panel_network.jpg) ![](./example/snapshot/panel_element.jpg) ![](./example/snapshot/panel_storage.jpg) | ||
@@ -80,3 +80,3 @@ | ||
- [vconsole-webpack-plugin](https://github.com/diamont1001/vconsole-webpack-plugin) | ||
- [vconsole-stats-plugin](https://github.com/smackgg/vConsole-Stats) | ||
@@ -83,0 +83,0 @@ ## Changelog |
@@ -16,2 +16,3 @@ /* | ||
import 'transitionEnd' | ||
import pkg from '../../package.json'; | ||
@@ -61,4 +62,5 @@ import * as tool from '../lib/tool.js'; | ||
this.switchPos = { | ||
x: 10, // right | ||
y: 10, // bottom | ||
hasMoved: false, // exclude click event | ||
x: 0, // right | ||
y: 0, // bottom | ||
startX: 0, | ||
@@ -148,3 +150,3 @@ startY: 0, | ||
if (! $.one(VCONSOLE_ID)) { | ||
let e = document.createElement('div'); | ||
const e = document.createElement('div'); | ||
e.innerHTML = tpl; | ||
@@ -156,27 +158,17 @@ document.documentElement.insertAdjacentElement('beforeend', e.children[0]); | ||
// reposition switch button | ||
let $switch = $.one('.vc-switch', this.$dom); | ||
const $switch = $.one('.vc-switch', this.$dom); | ||
let switchX = tool.getStorage('switch_x') * 1, | ||
switchY = tool.getStorage('switch_y') * 1; | ||
if (switchX || switchY) { | ||
// check edge | ||
if (switchX + $switch.offsetWidth > document.documentElement.offsetWidth) { | ||
switchX = document.documentElement.offsetWidth - $switch.offsetWidth; | ||
} | ||
if (switchY + $switch.offsetHeight > document.documentElement.offsetHeight) { | ||
switchY = document.documentElement.offsetHeight - $switch.offsetHeight; | ||
} | ||
if (switchX < 0) { switchX = 0; } | ||
if (switchY < 0) { switchY = 0; } | ||
this.switchPos.x = switchX; | ||
this.switchPos.y = switchY; | ||
$.one('.vc-switch').style.right = switchX + 'px'; | ||
$.one('.vc-switch').style.bottom = switchY + 'px'; | ||
} | ||
[switchX, switchY] = this._getSwitchButtonSafeAreaXY($switch, switchX, switchY); | ||
this.switchPos.x = switchX; | ||
this.switchPos.y = switchY; | ||
$.one('.vc-switch').style.right = switchX + 'px'; | ||
$.one('.vc-switch').style.bottom = switchY + 'px'; | ||
// modify font-size | ||
let dpr = window.devicePixelRatio || 1; | ||
let viewportEl = document.querySelector('[name="viewport"]'); | ||
const dpr = window.devicePixelRatio || 1; | ||
const viewportEl = document.querySelector('[name="viewport"]'); | ||
if (viewportEl && viewportEl.content) { | ||
let initialScale = viewportEl.content.match(/initial\-scale\=\d+(\.\d+)?/); | ||
let scale = initialScale ? parseFloat(initialScale[0].split('=')[1]) : 1; | ||
const initialScale = viewportEl.content.match(/initial\-scale\=\d+(\.\d+)?/); | ||
const scale = initialScale ? parseFloat(initialScale[0].split('=')[1]) : 1; | ||
if (scale < 1) { | ||
@@ -189,5 +181,29 @@ this.$dom.style.fontSize = 13 * dpr + 'px'; | ||
$.one('.vc-mask', this.$dom).style.display = 'none'; | ||
// set theme | ||
if (this.option.theme) { | ||
this.$dom.setAttribute('data-theme', this.option.theme); | ||
} | ||
}; | ||
/** | ||
* Get an safe [x, y] position for switch button | ||
* @private | ||
*/ | ||
_getSwitchButtonSafeAreaXY($switch, x, y) { | ||
const docWidth = Math.max(document.documentElement.offsetWidth, window.innerWidth); | ||
const docHeight = Math.max(document.documentElement.offsetHeight, window.innerHeight); | ||
// check edge | ||
if (x + $switch.offsetWidth > docWidth) { | ||
x = docWidth - $switch.offsetWidth; | ||
} | ||
if (y + $switch.offsetHeight > docHeight) { | ||
y = docHeight - $switch.offsetHeight; | ||
} | ||
if (x < 0) { x = 0; } | ||
if (y < 20) { y = 20; } // safe area for iOS Home indicator | ||
return [x, y]; | ||
} | ||
/** | ||
* simulate tap event by touchstart & touchend | ||
@@ -248,11 +264,14 @@ * @private | ||
targetElem.focus(); | ||
} else { | ||
} else if (typeof window.getSelection !== 'function' || !getSelection().rangeCount) { | ||
e.preventDefault(); // prevent click 300ms later | ||
} | ||
let touch = e.changedTouches[0]; | ||
let event = document.createEvent('MouseEvents'); | ||
event.initMouseEvent('click', true, true, window, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null); | ||
event.forwardedTouchEvent = true; | ||
event.initEvent('click', true, true); | ||
targetElem.dispatchEvent(event); | ||
if (!targetElem.disabled && !targetElem.readOnly) { | ||
let touch = e.changedTouches[0]; | ||
let event = document.createEvent('MouseEvents'); | ||
event.initMouseEvent('click', true, true, window, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null); | ||
event.forwardedTouchEvent = true; | ||
event.initEvent('click', true, true); | ||
targetElem.dispatchEvent(event); | ||
} | ||
} | ||
@@ -271,11 +290,15 @@ | ||
_bindEvent() { | ||
let that = this; | ||
const that = this; | ||
// drag & drop switch button | ||
let $switch = $.one('.vc-switch', that.$dom); | ||
const $switch = $.one('.vc-switch', that.$dom); | ||
$.bind($switch, 'touchstart', function(e) { | ||
that.switchPos.startX = e.touches[0].pageX; | ||
that.switchPos.startY = e.touches[0].pageY; | ||
that.switchPos.hasMoved = false; | ||
}); | ||
$.bind($switch, 'touchend', function(e) { | ||
if (!that.switchPos.hasMoved) { | ||
return; | ||
} | ||
that.switchPos.x = that.switchPos.endX; | ||
@@ -285,2 +308,3 @@ that.switchPos.y = that.switchPos.endY; | ||
that.switchPos.startY = 0; | ||
that.switchPos.hasMoved = false; | ||
tool.setStorage('switch_x', that.switchPos.x); | ||
@@ -290,22 +314,17 @@ tool.setStorage('switch_y', that.switchPos.y); | ||
$.bind($switch, 'touchmove', function(e) { | ||
if (e.touches.length > 0) { | ||
let offsetX = e.touches[0].pageX - that.switchPos.startX, | ||
if (e.touches.length <= 0) { | ||
return; | ||
} | ||
const offsetX = e.touches[0].pageX - that.switchPos.startX, | ||
offsetY = e.touches[0].pageY - that.switchPos.startY; | ||
let x = that.switchPos.x - offsetX, | ||
y = that.switchPos.y - offsetY; | ||
// check edge | ||
if (x + $switch.offsetWidth > document.documentElement.offsetWidth) { | ||
x = document.documentElement.offsetWidth - $switch.offsetWidth; | ||
} | ||
if (y + $switch.offsetHeight > document.documentElement.offsetHeight) { | ||
y = document.documentElement.offsetHeight - $switch.offsetHeight; | ||
} | ||
if (x < 0) { x = 0; } | ||
if (y < 0) { y = 0; } | ||
$switch.style.right = x + 'px'; | ||
$switch.style.bottom = y + 'px'; | ||
that.switchPos.endX = x; | ||
that.switchPos.endY = y; | ||
e.preventDefault(); | ||
} | ||
let x = Math.floor(that.switchPos.x - offsetX), | ||
y = Math.floor(that.switchPos.y - offsetY); | ||
[x, y] = that._getSwitchButtonSafeAreaXY($switch, x, y); | ||
$switch.style.right = x + 'px'; | ||
$switch.style.bottom = y + 'px'; | ||
that.switchPos.endX = x; | ||
that.switchPos.endY = y; | ||
that.switchPos.hasMoved = true; | ||
console.log(x, y); | ||
e.preventDefault(); | ||
}); | ||
@@ -324,3 +343,15 @@ | ||
// hide console panel when tap background mask | ||
$.bind($.one('.vc-mask', that.$dom), 'click', function(e) { | ||
let $mask = $.one('.vc-mask', this.$dom); | ||
let $panel = $.one('.vc-panel', this.$dom); | ||
const transitionEnd = window.transitionEnd($mask).whichTransitionEnd() | ||
const onMaskTransitionEnd = function() { | ||
$mask.style.display = 'none'; | ||
$panel.style.display = 'none'; | ||
}; | ||
if (transitionEnd) { | ||
$.bind($mask, transitionEnd, onMaskTransitionEnd); | ||
} else { | ||
onMaskTransitionEnd(); | ||
} | ||
$.bind($mask, 'click', function(e) { | ||
if (e.target != $.one('.vc-mask')) { | ||
@@ -342,10 +373,17 @@ return false; | ||
// after console panel, trigger a transitionend event to make panel's property 'display' change from 'block' to 'none' | ||
$.bind($.one('.vc-panel', that.$dom), 'transitionend webkitTransitionEnd oTransitionEnd otransitionend', function(e) { | ||
if (e.target != $.one('.vc-panel')) { | ||
return false; | ||
} | ||
const onPanelTransitionEnd = function(target) { | ||
if (!$.hasClass(that.$dom, 'vc-toggle')) { | ||
e.target.style.display = 'none'; | ||
target.style.display = 'none'; | ||
} | ||
}); | ||
} | ||
if (transitionEnd) { | ||
$.bind($panel, transitionEnd, function(e) { | ||
if (e.target != $panel) { | ||
return false; | ||
} | ||
onPanelTransitionEnd(e.target); | ||
}); | ||
} else { | ||
onPanelTransitionEnd($panel); | ||
} | ||
@@ -648,9 +686,2 @@ // disable background scrolling | ||
this._triggerPluginsEvent('hideConsole'); | ||
let $mask = $.one('.vc-mask', this.$dom), | ||
$panel = $.one('.vc-panel', this.$dom); | ||
$.bind($mask, 'transitionend', function(evnet) { | ||
$mask.style.display = 'none'; | ||
$panel.style.display = 'none'; | ||
}); | ||
} | ||
@@ -657,0 +688,0 @@ |
@@ -16,2 +16,3 @@ /* | ||
import MutationObserver from 'mutation-observer' | ||
import './style.less'; | ||
@@ -37,3 +38,2 @@ import VConsolePlugin from '../lib/plugin.js'; | ||
let MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver; | ||
that.observer = new MutationObserver(function(mutations) { | ||
@@ -106,3 +106,4 @@ for (let i=0; i<mutations.length; i++) { | ||
let $node = $.one('.vcelm-node', $rootView); | ||
$node && $node.click(); | ||
// Before Android WebView 4.4, click is only defined on buttons and inputs | ||
$node && $node.click && $node.click(); | ||
@@ -109,0 +110,0 @@ // start observing |
@@ -67,5 +67,10 @@ /** | ||
let nonce = ''; | ||
if (scriptList.length > 0) { | ||
nonce = scriptList[0].nonce || ''; // get nonce to avoid `unsafe-inline` | ||
// find the first script with nonce | ||
for (let script of scriptList) { | ||
if (script.nonce) { | ||
nonce = script.nonce | ||
break | ||
} | ||
} | ||
let script = document.createElement('SCRIPT'); | ||
@@ -72,0 +77,0 @@ script.innerHTML = codeWrap; |
@@ -40,3 +40,3 @@ /* | ||
const nodeList = (contextElement || document).querySelectorAll(selector); | ||
return Array.from(nodeList); | ||
return [].slice.call(nodeList); | ||
} catch (e) { | ||
@@ -43,0 +43,0 @@ return []; |
@@ -189,10 +189,15 @@ /* | ||
} | ||
if (isArray(obj)) { | ||
const m = []; | ||
obj.forEach((_, index) => { | ||
m.push(index) | ||
}); | ||
return m; | ||
// if (isArray(obj)) { | ||
// const m = []; | ||
// obj.forEach((_, index) => { | ||
// m.push(index) | ||
// }); | ||
// return m; | ||
// } | ||
// return Object.getOwnPropertyNames(obj).sort(); | ||
const keys = []; | ||
for (let k in obj) { | ||
keys.push(k); | ||
} | ||
return Object.getOwnPropertyNames(obj).sort(); | ||
return keys.sort(); | ||
} | ||
@@ -199,0 +204,0 @@ |
@@ -21,3 +21,6 @@ /* | ||
import tplItemCode from './item_code.html'; | ||
let filterText = ""; | ||
const checkFilterInLine = (dom) =>{ | ||
return dom.innerHTML.toUpperCase().indexOf(filterText.toUpperCase()) === -1 | ||
}; | ||
class VConsoleDefaultTab extends VConsoleLogTab { | ||
@@ -29,2 +32,6 @@ | ||
} | ||
formatLine ($line){ | ||
checkFilterInLine($line) ? $.addClass($line,'hide'):$.removeClass($line,'hide') | ||
return $line | ||
} | ||
@@ -35,8 +42,15 @@ onReady() { | ||
// do not traverse these keys to prevent "Deprecation" warning | ||
const keyBlackList = ['webkitStorageInfo']; | ||
window.winKeys = Object.getOwnPropertyNames(window).sort(); | ||
window.keyTypes = {}; | ||
for (let i = 0; i < winKeys.length; i++) { | ||
if (keyBlackList.indexOf(winKeys[i]) > -1) { | ||
continue; | ||
} | ||
keyTypes[winKeys[i]] = typeof window[winKeys[i]]; | ||
} | ||
const cacheObj = {}; | ||
@@ -70,4 +84,11 @@ const ID_REGEX = /[a-zA-Z_0-9\$\-\u00A2-\uFFFF]/; | ||
}; | ||
const moveCursorToPos = ($dom, pos) => { | ||
if ($dom.setSelectionRange) { | ||
$dom.setSelectionRange(pos, pos); | ||
} | ||
}; | ||
$.bind($.one('.vc-cmd-input'), 'keyup', function (e) { | ||
const $input = $.one('.vc-cmd-input'); | ||
$.bind($input, 'keyup', function (e) { | ||
const isDeleteKeyCode = e.keyCode === 8 || e.keyCode === 46; | ||
@@ -81,11 +102,14 @@ const $prompted = $.one('.vc-cmd-prompted'); | ||
if (/\(/.test(value) && !isDeleteKeyCode) { | ||
$.one('.vc-cmd-input').value += ')'; | ||
$input.value += ')'; | ||
moveCursorToPos($input, $input.value.length - 1); | ||
return; | ||
} | ||
if (/\[/.test(value) && !isDeleteKeyCode) { | ||
$.one('.vc-cmd-input').value += ']'; | ||
$input.value += ']'; | ||
moveCursorToPos($input, $input.value.length - 1); | ||
return; | ||
} | ||
if (/\{/.test(value) && !isDeleteKeyCode) { | ||
$.one('.vc-cmd-input').value += '}'; | ||
$input.value += '}'; | ||
moveCursorToPos($input, $input.value.length - 1); | ||
return; | ||
@@ -108,4 +132,4 @@ } | ||
$li.onclick = function () { | ||
$.one('.vc-cmd-input').value = ''; | ||
$.one('.vc-cmd-input').value = tempValue + this.innerHTML; | ||
$input.value = ''; | ||
$input.value = tempValue + this.innerHTML; | ||
$prompted.style.display = 'none'; | ||
@@ -124,6 +148,6 @@ }; | ||
$li.onclick = function () { | ||
$.one('.vc-cmd-input').value = ''; | ||
$.one('.vc-cmd-input').value = this.innerHTML; | ||
$input.value = ''; | ||
$input.value = this.innerHTML; | ||
if (keyTypes[this.innerHTML] == 'function') { | ||
$.one('.vc-cmd-input').value += '()'; | ||
$input.value += '()'; | ||
} | ||
@@ -145,4 +169,4 @@ $prompted.style.display = 'none'; | ||
$li.onclick = function () { | ||
$.one('.vc-cmd-input').value = ''; | ||
$.one('.vc-cmd-input').value = tempValue + this.innerHTML; | ||
$input.value = ''; | ||
$input.value = tempValue + this.innerHTML; | ||
$prompted.style.display = 'none'; | ||
@@ -168,5 +192,5 @@ }; | ||
e.preventDefault(); | ||
let $input = $.one('.vc-cmd-input', e.target), | ||
cmd = $input.value; | ||
$input.value = ''; | ||
let $cmdInput = $.one('.vc-cmd-input', e.target), | ||
cmd = $cmdInput.value; | ||
$cmdInput.value = ''; | ||
if (cmd !== '') { | ||
@@ -180,2 +204,14 @@ that.evalCommand(cmd); | ||
}); | ||
$.bind($.one('.vc-cmd.vc-filter', this.$tabbox), 'submit', function (e) { | ||
e.preventDefault(); | ||
let $cmdInput = $.one('.vc-cmd.vc-filter .vc-cmd-input', e.target); | ||
filterText = $cmdInput.value; | ||
$.all(".vc-log>.vc-item").forEach(el=>{ | ||
if(checkFilterInLine(el)){ | ||
$.addClass(el,'hide') | ||
}else{ | ||
$.removeClass(el,'hide') | ||
} | ||
}) | ||
}); | ||
@@ -190,4 +226,8 @@ // create a global letiable to save custom command's result | ||
let nonce = ''; | ||
if (scriptList.length > 0) { | ||
nonce = scriptList[0].nonce || ''; // get nonce to avoid `unsafe-inline` | ||
// find the first script with nonce | ||
for (let script of scriptList) { | ||
if (script.nonce) { | ||
nonce = script.nonce | ||
break | ||
} | ||
} | ||
@@ -194,0 +234,0 @@ let script = document.createElement('SCRIPT'); |
@@ -526,2 +526,3 @@ /* | ||
// render to panel | ||
if(this.formatLine) $line = this.formatLine($line); | ||
$.one('.vc-log', this.$tabbox).insertAdjacentElement('beforeend', $line); | ||
@@ -528,0 +529,0 @@ |
@@ -36,2 +36,5 @@ /* | ||
logMsg = ''; | ||
// location | ||
console.info('[system]', 'Location:', location.href); | ||
@@ -66,12 +69,2 @@ // device & system | ||
// HTTP protocol | ||
logMsg = 'Unknown'; | ||
if (location.protocol == 'https:') { | ||
logMsg = 'HTTPS'; | ||
} else if (location.protocol == 'http:') { | ||
logMsg = 'HTTP'; | ||
} else { | ||
logMsg = location.protocol.replace(':', ''); | ||
} | ||
templogMsg = logMsg; | ||
// network type | ||
@@ -83,6 +76,3 @@ let network = ua.toLowerCase().match(/ nettype\/([^ ]+)/g); | ||
logMsg = network[1]; | ||
templogMsg += (', ' + logMsg); | ||
console.info('[system]', 'Network:', templogMsg); | ||
} else { | ||
console.info('[system]', 'Protocol:', templogMsg); | ||
console.info('[system]', 'Network:', logMsg); | ||
} | ||
@@ -89,0 +79,0 @@ |
@@ -37,4 +37,6 @@ /* | ||
this._send = undefined; | ||
this._setRequestHeader = undefined; | ||
this.mockAjax(); | ||
this.mockFetch(); | ||
} | ||
@@ -101,4 +103,6 @@ | ||
window.XMLHttpRequest.prototype.send = this._send; | ||
window.XMLHttpRequest.prototype.setRequestHeader = this._setRequestHeader; | ||
this._open = undefined; | ||
this._send = undefined; | ||
this._setRequestHeader = undefined | ||
} | ||
@@ -183,2 +187,3 @@ } | ||
id: id, | ||
name: item.name, | ||
url: item.url, | ||
@@ -189,2 +194,3 @@ status: item.status, | ||
header: item.header || null, | ||
requestHeader: item.requestHeader || null, | ||
getData: item.getData || null, | ||
@@ -268,7 +274,9 @@ postData: item.postData || null, | ||
let that = this; | ||
let _open = window.XMLHttpRequest.prototype.open, | ||
_send = window.XMLHttpRequest.prototype.send; | ||
const that = this; | ||
const _open = window.XMLHttpRequest.prototype.open, | ||
_send = window.XMLHttpRequest.prototype.send, | ||
_setRequestHeader = window.XMLHttpRequest.prototype.setRequestHeader; | ||
that._open = _open; | ||
that._send = _send; | ||
that._setRequestHeader = _setRequestHeader; | ||
@@ -359,2 +367,15 @@ // mock open() | ||
// mock setRequestHeader() | ||
window.XMLHttpRequest.prototype.setRequestHeader = function() { | ||
const XMLReq = this; | ||
const args = [].slice.call(arguments); | ||
const item = that.reqList[XMLReq._requestID]; | ||
if (item) { | ||
if (!item.requestHeader) { item.requestHeader = {}; } | ||
item.requestHeader[args[0]] = args[1]; | ||
} | ||
return _setRequestHeader.apply(XMLReq, args); | ||
}; | ||
// mock send() | ||
@@ -367,8 +388,11 @@ window.XMLHttpRequest.prototype.send = function() { | ||
let item = that.reqList[XMLReq._requestID] || {}; | ||
item.method = XMLReq._method.toUpperCase(); | ||
item.method = XMLReq._method ? XMLReq._method.toUpperCase() : 'GET'; | ||
let query = XMLReq._url.split('?'); // a.php?b=c&d=?e => ['a.php', 'b=c&d=', '?e'] | ||
item.url = query.shift(); // => ['b=c&d=', '?e'] | ||
let query = XMLReq._url ? XMLReq._url.split('?') : []; // a.php?b=c&d=?e => ['a.php', 'b=c&d=', 'e'] | ||
item.url = XMLReq._url || ''; | ||
item.name = query.shift() || ''; // => ['b=c&d=', 'e'] | ||
item.name = item.name.replace(new RegExp('[/]*$'), '').split('/').pop() || ''; | ||
if (query.length > 0) { | ||
item.name += '?' + query; | ||
item.getData = {}; | ||
@@ -395,2 +419,4 @@ query = query.join('?'); // => 'b=c&d=?e' | ||
item.postData = data; | ||
} else { | ||
item.postData = '[object Object]'; | ||
} | ||
@@ -408,3 +434,97 @@ | ||
}; | ||
/** | ||
* mock fetch request | ||
* @private | ||
*/ | ||
mockFetch() { | ||
let _fetch = window.fetch; | ||
if (!_fetch){ return; } | ||
let that = this; | ||
let prevFetch = (input, init) => { | ||
let id = that.getUniqueID(); | ||
that.reqList[id] = {}; | ||
let item = that.reqList[id] || {}; | ||
let query = [], | ||
url = '', | ||
method = 'GET', | ||
requestHeader = null; | ||
// handle `input` content | ||
if (tool.isString(input)) { // when `input` is a string | ||
method = init.method || 'GET'; | ||
url = input; | ||
requestHeader = init.headers; | ||
} else { // when `input` is a `Request` object | ||
method = input.method || 'GET'; | ||
url = input.url; | ||
requestHeader = input.headers; | ||
} | ||
query = url.split('?'); | ||
item.id = id; | ||
item.method = method; | ||
item.requestHeader = requestHeader; | ||
item.url = url; | ||
item.name = query.shift() || ''; | ||
item.name = item.name.replace(new RegExp('[/]*$'), '').split('/').pop() || ''; | ||
if (query.length > 0) { | ||
item.name += '?' + query; | ||
item.getData = {}; | ||
query = query.join('?'); // => 'b=c&d=?e' | ||
query = query.split('&'); // => ['b=c', 'd=?e'] | ||
for (let q of query) { | ||
q = q.split('='); | ||
item.getData[ q[0] ] = q[1]; | ||
} | ||
} | ||
if (item.method === 'POST') { // save POST data | ||
if (tool.isString(input)) { // when `input` is a string | ||
if (tool.isString(init.body)) { | ||
let arr = init.body.split('&'); | ||
item.postData = {}; | ||
for (let q of arr) { | ||
q = q.split('='); | ||
item.postData[ q[0] ] = q[1]; | ||
} | ||
} else if (tool.isPlainObject(init.body)) { | ||
item.postData = init.body; | ||
} else { | ||
item.postData = '[object Object]'; | ||
} | ||
} else { // when `input` is a `Request` object | ||
// cannot get real type of request's body, so just display "[object Object]" | ||
item.postData = '[object Object]'; | ||
} | ||
} | ||
// UNSENT | ||
if (!item.startTime) { | ||
item.startTime = (+new Date()); | ||
} | ||
return _fetch(url, init).then((response) => { | ||
response.clone().json().then((json) => { | ||
item.endTime = +new Date(), | ||
item.costTime = item.endTime - (item.startTime || item.endTime); | ||
item.status = response.status; | ||
item.header = {}; | ||
for (let pair of response.headers.entries()) { | ||
item.header[pair[0]] = pair[1]; | ||
} | ||
item.response = json; | ||
item.readyState = 4; | ||
const contentType = response.headers.get('content-type'); | ||
item.responseType = contentType.includes('application/json') ? 'json' : contentType.includes('text/html') ? 'text' : ''; | ||
return json; | ||
}) | ||
that.updateRequest(id, item); | ||
return response; | ||
}) | ||
} | ||
window.fetch = prevFetch; | ||
} | ||
/** | ||
@@ -411,0 +531,0 @@ * generate an unique id string (32) |
@@ -164,3 +164,4 @@ /* | ||
} catch(e) { | ||
console.log(e, name, value); | ||
// do not print external input directly to prevent forgery (issue #345) | ||
// console.log(e, name, value); | ||
} | ||
@@ -167,0 +168,0 @@ list.push({ |
@@ -14,2 +14,3 @@ /** | ||
disableLogScrolling?: boolean | ||
theme?: 'light' | 'dark' | ||
} | ||
@@ -16,0 +17,0 @@ |
@@ -16,5 +16,2 @@ /* | ||
// global | ||
import './lib/symbol.js'; | ||
// classes | ||
@@ -21,0 +18,0 @@ import VConsole from './core/core.js'; |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
621992
2
21
81
3844
1
+ Addedmutation-observer@^1.0.3
+ AddedtransitionEnd@^1.0.2
+ Addedmutation-observer@1.0.3(transitive)
+ AddedtransitionEnd@1.0.3(transitive)