This commit is contained in:
AlexVallat 2015-03-03 08:00:22 +00:00
commit 6debe11315
7 changed files with 190 additions and 24 deletions

View file

@ -35,6 +35,10 @@
"message":"µBlock — Network request log", "message":"µBlock — Network request log",
"description":"Title for the network request log window" "description":"Title for the network request log window"
}, },
"statsFilterPrompt":{
"message":"filter log entries",
"description": "English: filter log entries"
},
"aboutPageName":{ "aboutPageName":{
"message":"About", "message":"About",
"description":"appears as tab name in dashboard" "description":"appears as tab name in dashboard"

View file

@ -10,32 +10,35 @@ body {
width: 100%; width: 100%;
} }
#toolbar { #toolbar {
padding: 8px 0; background-color: white;
border: 0;
box-sizing: border-box;
height: 36px;
margin: 0;
padding: 0;
position: fixed; position: fixed;
text-align: center; text-align: center;
top: 0; top: 0;
width: 4em; width: 100%;
} }
#toolbar .button { #toolbar .button {
background-color: white; background-color: white;
border: none; border: none;
box-sizing: border-box;
cursor: pointer; cursor: pointer;
display: block; display: inline-block;
font-size: large; font-size: 20px;
margin: 0; margin: 0;
padding: 0.5em 0; padding: 8px;
} }
#toolbar .button:hover { #toolbar .button:hover {
background-color: #eee; background-color: #eee;
} }
body.filterOff #toolbar #filterButton {
opacity: 0.25;
}
#content { #content {
width: calc(100% - 4em); margin-top: 36px;
}
body[dir="ltr"] #content {
margin-left: 4em;
}
body[dir="rtl"] #content {
margin-right: 4em;
} }
#content table { #content table {
border: 0; border: 0;
@ -55,6 +58,9 @@ body[dir="rtl"] #content {
#content table tr.maindoc { #content table tr.maindoc {
background-color: #eee; background-color: #eee;
} }
body:not(.filterOff) #content table tr.hidden {
display: none;
}
#content table tr td { #content table tr td {
border: 1px solid #ccc; border: 1px solid #ccc;
padding: 3px; padding: 3px;
@ -63,6 +69,7 @@ body[dir="rtl"] #content {
#content table tr td:nth-of-type(1) { #content table tr td:nth-of-type(1) {
padding: 3px 0; padding: 3px 0;
text-align: center; text-align: center;
white-space: pre;
} }
#content table tr td:nth-of-type(2) { #content table tr td:nth-of-type(2) {
white-space: normal; white-space: normal;

View file

@ -10,12 +10,15 @@
<div id="toolbar"> <div id="toolbar">
<span id="reload" class="button fa">&#xf021;</span> <span id="reload" class="button fa">&#xf021;</span>
<span id="clear" class="button fa">&#xf12d;</span> <span id="clear" class="button fa">&#xf12d;</span>
</div><!-- DO NOT REMOVE --><div id="content"> <span id="filterButton" class="button fa">&#xf0b0;</span><input id="filterExpression" type="text" placeholder="statsFilterPrompt">
</div>
<div id="content">
<table><tbody></tbody></table> <table><tbody></tbody></table>
</div> </div>
<script src="js/vapi-common.js"></script> <script src="js/vapi-common.js"></script>
<script src="js/vapi-client.js"></script> <script src="js/vapi-client.js"></script>
<script src="js/udom.js"></script> <script src="js/udom.js"></script>
<script src="js/i18n.js"></script>
<script src="js/devtool-log.js"></script> <script src="js/devtool-log.js"></script>
</body> </body>
</html> </html>

View file

@ -85,7 +85,7 @@ return {
// read-only // read-only
systemSettings: { systemSettings: {
compiledMagic: 'fkaywfqahncj', compiledMagic: 'shztbfhkfjit',
selfieMagic: 'spqmeuaftfra' selfieMagic: 'spqmeuaftfra'
}, },

View file

@ -36,6 +36,7 @@ var doc = document;
var body = doc.body; var body = doc.body;
var tbody = doc.querySelector('#content tbody'); var tbody = doc.querySelector('#content tbody');
var rowJunkyard = []; var rowJunkyard = [];
var reFilter = null;
/******************************************************************************/ /******************************************************************************/
@ -101,15 +102,15 @@ var renderLogEntry = function(entry) {
var tr = createRow(); var tr = createRow();
if ( entry.result.charAt(1) === 'b' ) { if ( entry.result.charAt(1) === 'b' ) {
tr.classList.add('blocked'); tr.classList.add('blocked');
tr.cells[0].textContent = '\u2009\u2212\u2009'; tr.cells[0].textContent = ' \u2212\u00A0';
} else if ( entry.result.charAt(1) === 'a' ) { } else if ( entry.result.charAt(1) === 'a' ) {
tr.classList.add('allowed'); tr.classList.add('allowed');
if ( entry.result.charAt(0) === 'm' ) { if ( entry.result.charAt(0) === 'm' ) {
tr.classList.add('mirrored'); tr.classList.add('mirrored');
} }
tr.cells[0].textContent = '\u2009+\u2009'; tr.cells[0].textContent = ' +\u00A0';
} else { } else {
tr.cells[0].textContent = '\u2009\u00A0\u2009'; tr.cells[0].textContent = ' ';
} }
if ( entry.type === 'main_frame' ) { if ( entry.type === 'main_frame' ) {
tr.classList.add('maindoc'); tr.classList.add('maindoc');
@ -118,9 +119,10 @@ var renderLogEntry = function(entry) {
if ( entry.result.lastIndexOf('sa', 0) === 0 ) { if ( entry.result.lastIndexOf('sa', 0) === 0 ) {
filterText = '@@' + filterText; filterText = '@@' + filterText;
} }
tr.cells[1].textContent = filterText; tr.cells[1].textContent = filterText + ' ';
tr.cells[2].textContent = entry.type; tr.cells[2].textContent = entry.type + ' ';
vAPI.insertHTML(tr.cells[3], renderURL(entry.url, entry.result)); vAPI.insertHTML(tr.cells[3], renderURL(entry.url, entry.result));
applyFilterToRow(tr);
tbody.insertBefore(tr, tbody.firstChild); tbody.insertBefore(tr, tbody.firstChild);
}; };
@ -196,6 +198,102 @@ var reloadTab = function() {
/******************************************************************************/ /******************************************************************************/
var applyFilterToRow = function(row) {
var re = reFilter;
if ( re === null || re.test(row.textContent) ) {
row.classList.remove('hidden');
} else {
row.classList.add('hidden');
}
};
/******************************************************************************/
var applyFilter = function() {
if ( reFilter === null ) {
unapplyFilter();
return;
}
var row = document.querySelector('#content tr');
if ( row === null ) {
return;
}
var re = reFilter;
while ( row !== null ) {
if ( re.test(row.textContent) ) {
row.classList.remove('hidden');
} else {
row.classList.add('hidden');
}
row = row.nextSibling;
}
};
/******************************************************************************/
var unapplyFilter = function() {
var row = document.querySelector('#content tr');
if ( row === null ) {
return;
}
while ( row !== null ) {
row.classList.remove('hidden');
row = row.nextSibling;
}
};
/******************************************************************************/
var onFilterButton = function() {
uDom('body').toggleClass('filterOff');
};
/******************************************************************************/
var onFilterChanged = function() {
var filterRaw = uDom('#filterExpression').val().trim();
if ( filterRaw === '') {
reFilter = null;
unapplyFilter();
return;
}
var filterParts = filterRaw
.replace(/^\s*-(\s+|$)/, '\xA0')
.replace(/^\s*\\+(\s+|$)/, '\\+\xA0')
.split(/\s+/);
var n = filterParts.length;
for ( var i = 0; i < n; i++ ) {
filterParts[i] = filterParts[i].replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}
reFilter = new RegExp(filterParts.join('.*\\s+.*'));
applyFilter();
};
/******************************************************************************/
var onFilterChangedAsync = (function() {
var timer = null;
var commit = function() {
timer = null;
onFilterChanged();
};
var changed = function() {
if ( timer !== null ) {
clearTimeout(timer);
}
timer = setTimeout(commit, 750);
};
return changed;
})();
/******************************************************************************/
uDom.onLoad(function() { uDom.onLoad(function() {
// Extract the tab id of the page we need to pull the log // Extract the tab id of the page we need to pull the log
var matches = window.location.search.match(/[\?&]tabId=([^&]+)/); var matches = window.location.search.match(/[\?&]tabId=([^&]+)/);
@ -207,6 +305,8 @@ uDom.onLoad(function() {
uDom('#reload').on('click', reloadTab); uDom('#reload').on('click', reloadTab);
uDom('#clear').on('click', clearBuffer); uDom('#clear').on('click', clearBuffer);
uDom('#filterButton').on('click', onFilterButton);
uDom('#filterExpression').on('input', onFilterChangedAsync);
}); });
/******************************************************************************/ /******************************************************************************/

View file

@ -36,6 +36,12 @@ uDom.onLoad(function() {
elem.attr('title', title); elem.attr('title', title);
} }
}); });
uDom('[placeholder]').forEach(function(elem) {
var placeholder = vAPI.i18n(elem.attr('placeholder'));
if ( placeholder ) {
elem.attr('placeholder', placeholder);
}
});
uDom('[data-i18n-tip]').forEach(function(elem) { uDom('[data-i18n-tip]').forEach(function(elem) {
elem.attr( elem.attr(
'data-tip', 'data-tip',

View file

@ -921,6 +921,40 @@ FilterGenericHnAnchored.fromSelfie = function(s) {
/******************************************************************************/ /******************************************************************************/
var FilterGenericHnAnchoredHostname = function(s, hostname) {
FilterGenericHnAnchored.call(this, s);
this.hostname = hostname;
};
FilterGenericHnAnchoredHostname.prototype = Object.create(FilterGenericHnAnchored.prototype);
FilterGenericHnAnchoredHostname.prototype.match = function(url) {
if ( pageHostnameRegister.slice(-this.hostname.length) !== this.hostname ) {
return false;
}
return FilterGenericHnAnchored.prototype.match.call(this. url);
};
FilterGenericHnAnchoredHostname.fid = FilterGenericHnAnchoredHostname.prototype.fid = '||_h';
FilterGenericHnAnchoredHostname.prototype.toString = function() {
return '||' + this.s + '$domain=' + this.hostname;
};
FilterGenericHnAnchoredHostname.prototype.toSelfie = function() {
return this.s + '\t' + this.hostname;
};
FilterGenericHnAnchoredHostname.compile = function(details, hostname) {
return details.f + '\t' + hostname;
};
FilterGenericHnAnchoredHostname.fromSelfie = function(s) {
var pos = s.indexOf('\t');
return new FilterGenericHnAnchoredHostname(s.slice(0, pos), s.slice(pos + 1));
};
/******************************************************************************/
// With many wildcards, a regex is best. // With many wildcards, a regex is best.
// Ref: regex escaper taken from: // Ref: regex escaper taken from:
@ -1417,6 +1451,9 @@ var getHostnameBasedFilterClass = function(details) {
var s = details.f; var s = details.f;
var wcOffset = s.indexOf('*'); var wcOffset = s.indexOf('*');
if ( wcOffset !== -1 ) { if ( wcOffset !== -1 ) {
if ( details.hostnameAnchored ) {
return FilterGenericHnAnchoredHostname;
}
if ( s.indexOf('*', wcOffset + 1) !== -1 ) { if ( s.indexOf('*', wcOffset + 1) !== -1 ) {
return details.anchor === 0 ? FilterManyWildcardsHostname : null; return details.anchor === 0 ? FilterManyWildcardsHostname : null;
} }
@ -1735,17 +1772,23 @@ var findFirstGoodToken = function(s) {
reGoodToken.lastIndex = 0; reGoodToken.lastIndex = 0;
var matches; var matches;
while ( matches = reGoodToken.exec(s) ) { while ( matches = reGoodToken.exec(s) ) {
if ( s.charAt(reGoodToken.lastIndex) === '*' ) {
continue;
}
if ( badTokens.hasOwnProperty(matches[0]) ) { if ( badTokens.hasOwnProperty(matches[0]) ) {
continue; continue;
} }
return matches;
}
// No good token found, try again without minding "bad" tokens
reGoodToken.lastIndex = 0;
while ( matches = reGoodToken.exec(s) ) {
if ( s.charAt(reGoodToken.lastIndex) === '*' ) { if ( s.charAt(reGoodToken.lastIndex) === '*' ) {
continue; continue;
} }
return matches; return matches;
} }
// No good token found, just return the first token from left return null;
reGoodToken.lastIndex = 0;
return reGoodToken.exec(s);
}; };
var findHostnameToken = function(s) { var findHostnameToken = function(s) {
@ -1753,6 +1796,8 @@ var findHostnameToken = function(s) {
return reHostnameToken.exec(s); return reHostnameToken.exec(s);
}; };
/******************************************************************************/
FilterParser.prototype.makeToken = function() { FilterParser.prototype.makeToken = function() {
if ( this.isRegex ) { if ( this.isRegex ) {
this.token = '*'; this.token = '*';
@ -1774,7 +1819,7 @@ FilterParser.prototype.makeToken = function() {
} }
matches = findFirstGoodToken(this.f); matches = findFirstGoodToken(this.f);
if ( !matches || matches[0].length === 0 ) { if ( matches === null || matches[0].length === 0 ) {
return; return;
} }
this.tokenBeg = matches.index; this.tokenBeg = matches.index;
@ -1864,7 +1909,8 @@ FilterContainer.prototype.factories = {
'//': FilterRegex, '//': FilterRegex,
'//h': FilterRegexHostname, '//h': FilterRegexHostname,
'{h}': FilterHostnameDict, '{h}': FilterHostnameDict,
'||_': FilterGenericHnAnchored '||_': FilterGenericHnAnchored,
'||_h': FilterGenericHnAnchoredHostname
}; };
/******************************************************************************/ /******************************************************************************/