mirror of https://github.com/gorhill/uBlock.git
this fixes #138, next: thorough code review
This commit is contained in:
parent
56ed6b9f4e
commit
1deae3bfe0
|
@ -36,18 +36,59 @@ ul > li > ul > li {
|
|||
.dim {
|
||||
color: #888;
|
||||
}
|
||||
button.purge {
|
||||
/* I designed the button with: http://charliepark.org/bootstrap_buttons/ */
|
||||
button.reloadAll {
|
||||
border: 1px solid transparent;
|
||||
border-radius: 3px;
|
||||
border-color: #dddddd #dddddd hsl(36, 0%, 85%);
|
||||
padding: 5px;
|
||||
background-color: hsl(36, 0%, 72%) !important;
|
||||
background-repeat: repeat-x;
|
||||
background-image: linear-gradient(#f2f2f2, #dddddd);
|
||||
color: #aaa;
|
||||
}
|
||||
button.reloadAll.enabled {
|
||||
border-color: #ffcc7f #ffcc7f hsl(36, 100%, 73%);
|
||||
color: #222;
|
||||
background-color: hsl(36, 100%, 75%) !important;
|
||||
background-image: linear-gradient(#ffdca8, #ffcc7f);
|
||||
cursor: pointer;
|
||||
opacity: 0.8;
|
||||
}
|
||||
button.reloadAll:hover {
|
||||
opacity: 1.0;
|
||||
}
|
||||
#buttonApply {
|
||||
display: none;
|
||||
position: fixed;
|
||||
right: 1em;
|
||||
top: 1em;
|
||||
}
|
||||
#buttonApply.enabled {
|
||||
display: initial;
|
||||
}
|
||||
span.status {
|
||||
margin: 0;
|
||||
border: 1px solid #ccc;
|
||||
border: 1px solid transparent;
|
||||
padding: 1px 2px;
|
||||
display: inline-block;
|
||||
font-size: 11px;
|
||||
opacity: 0.7;
|
||||
}
|
||||
span.purge {
|
||||
border-color: #ddd;
|
||||
color: #444;
|
||||
background-color: #eee;
|
||||
font-size: 11px;
|
||||
opacity: 0.6;
|
||||
cursor: pointer;
|
||||
}
|
||||
button.purge:hover {
|
||||
span.purge:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
span.obsolete {
|
||||
border-color: hsl(36, 100%, 73%);
|
||||
color: #222;
|
||||
background-color: hsl(36, 100%, 75%);
|
||||
}
|
||||
#externalLists {
|
||||
font-size: smaller;
|
||||
width: 48em;
|
||||
|
@ -59,10 +100,11 @@ button.purge:hover {
|
|||
|
||||
<body>
|
||||
|
||||
<button id="buttonApply" class="reloadAll" data-i18n="3pApplyChanges"></button>
|
||||
<ul id="options">
|
||||
<li><button id="blacklistsApply" disabled="true" data-i18n="3pApplyChanges"></button>
|
||||
<li style="margin-top:0.75em"><input type="checkbox" id="parseAllABPHideFilters"><label data-i18n="3pParseAllABPHideFiltersPrompt1"></label>
|
||||
<span class="dim" id="3pParseAllABPHideFiltersPrompt2"></span>
|
||||
<li><input type="checkbox" id="autoUpdate"><label data-i18n="3pAutoUpdatePrompt1"></label>
|
||||
<button class="reloadAll" id="buttonUpdate" data-i18n="3pUpdateNow"></button>
|
||||
<li><input type="checkbox" id="parseCosmeticFilters"><label data-i18n="3pParseAllABPHideFiltersPrompt1"></label>
|
||||
<button class="whatisthis"></button>
|
||||
<div class="whatisthis-expandable para" data-i18n="3pParseAllABPHideFiltersInfo"></div>
|
||||
<li style="margin-top:0.75em"><p id="listsOfBlockedHostsPrompt"></p>
|
||||
|
|
|
@ -99,13 +99,17 @@
|
|||
"message":"{{used}} benutzt aus {{total}}",
|
||||
"description":"English: {{used}} used out of {{total}}"
|
||||
},
|
||||
"3pAutoUpdatePrompt1":{
|
||||
"message":"Auto-update filter lists.",
|
||||
"description":"English: Auto-update filter lists."
|
||||
},
|
||||
"3pUpdateNow":{
|
||||
"message":"Update now",
|
||||
"description":"English: Update now"
|
||||
},
|
||||
"3pParseAllABPHideFiltersPrompt1":{
|
||||
"message":"Adblock+ Filter zum Verstecken von Elementen analysieren und anwenden.",
|
||||
"description":"English: Parse and enforce Adblock+ element hiding filters."
|
||||
},
|
||||
"3pParseAllABPHideFiltersPrompt2":{
|
||||
"message":"{{abpHideFilterCount}} Filter zum Verstecken von Elementen genutzt.",
|
||||
"description":"English: {{abpHideFilterCount}} element hiding filters used."
|
||||
"description":"English: Parse and enforce cosmetic filters."
|
||||
},
|
||||
"3pParseAllABPHideFiltersInfo":{
|
||||
"message":"<p>Diese Option ermöglicht die Analyse und Anwendung von <a href=\"https:\/\/adblockplus.org\/de\/faq_internal#elemhide\">Adblock Plus-kompatiblen Filtern zum “Verstecken von Elementen” <\/a>. Diese Filter sind in erster Linie kosmetischer Natur und dienen zum Verstecken von Elementen auf einer Webseite, die als optische Belästigung wahrgenommen werden und nicht von den vorhandenen Filtern geblockt werden können.<\/p><p>Das Aktivieren dieser Option erhöht den Speicherbedarf von <i>µBlock<\/i>.<\/p>",
|
||||
|
@ -159,6 +163,14 @@
|
|||
"message":"Leere den Cache",
|
||||
"description":"English: purge cache"
|
||||
},
|
||||
"3pExternalListNew":{
|
||||
"message":"new version available",
|
||||
"description":"English: new version available"
|
||||
},
|
||||
"3pExternalListObsolete":{
|
||||
"message":"may be obsolete",
|
||||
"description":"English: may be obsolete"
|
||||
},
|
||||
"1pFormatHint":{
|
||||
"message":"Eine Regel pro Zeile. Eine Regel kann ein einfacher Host-Name sein oder ein Adblock Plus-kompatibler Filter. Zeilen mit vorangestelltem ‘!’ werden ignoriert.",
|
||||
"description":"English: One filter per line. A filter can be a plain hostname, or an Adblock Plus-compatible filter. Lines prefixed with ‘!’ will be ignored."
|
||||
|
|
|
@ -99,13 +99,17 @@
|
|||
"message":"{{used}} used out of {{total}}",
|
||||
"description":"English: {{used}} used out of {{total}}"
|
||||
},
|
||||
"3pParseAllABPHideFiltersPrompt1":{
|
||||
"message":"Parse and enforce Adblock+ element hiding filters.",
|
||||
"description":"English: Parse and enforce Adblock+ element hiding filters."
|
||||
"3pAutoUpdatePrompt1":{
|
||||
"message":"Auto-update filter lists.",
|
||||
"description":"English: Auto-update filter lists."
|
||||
},
|
||||
"3pParseAllABPHideFiltersPrompt2":{
|
||||
"message":"{{abpHideFilterCount}} element hiding filters used.",
|
||||
"description":"English: {{abpHideFilterCount}} element hiding filters used."
|
||||
"3pUpdateNow":{
|
||||
"message":"Update now",
|
||||
"description":"English: Update now"
|
||||
},
|
||||
"3pParseAllABPHideFiltersPrompt1":{
|
||||
"message":"Parse and enforce cosmetic filters.",
|
||||
"description":"English: Parse and enforce Adblock+ element hiding filters."
|
||||
},
|
||||
"3pParseAllABPHideFiltersInfo":{
|
||||
"message":"<p>This option enables the parsing and enforcing of <a href=\"https:\/\/adblockplus.org\/en\/faq_internal#elemhide\">Adblock Plus-compatible “element hiding” filters<\/a>. These filters are essentially cosmetic, they serve to hide elements in a web page which are deemed to be a visual nuisance, and which can't be blocked by the net request-based filtering engine.<\/p><p>Enabling this feature increases <i>µBlock<\/i>'s memory footprint.<\/p>",
|
||||
|
@ -159,6 +163,14 @@
|
|||
"message":"purge cache",
|
||||
"description":"English: purge cache"
|
||||
},
|
||||
"3pExternalListNew":{
|
||||
"message":"new version available",
|
||||
"description":"English: new version available"
|
||||
},
|
||||
"3pExternalListObsolete":{
|
||||
"message":"may be obsolete",
|
||||
"description":"English: may be obsolete"
|
||||
},
|
||||
"1pFormatHint":{
|
||||
"message":"One filter per line. A filter can be a plain hostname, or an Adblock Plus-compatible filter. Lines prefixed with ‘!’ will be ignored.",
|
||||
"description":"English: One filter per line. A filter can be a plain hostname, or an Adblock Plus-compatible filter. Lines prefixed with ‘!’ will be ignored."
|
||||
|
|
|
@ -99,13 +99,17 @@
|
|||
"message":"{{used}} utilisé(s) sur un total de {{total}}",
|
||||
"description":"English: {{used}} used out of {{total}}"
|
||||
},
|
||||
"3pParseAllABPHideFiltersPrompt1":{
|
||||
"message":"Utiliser en plus les règles Adblock Plus esthétiques",
|
||||
"description":"English: Parse and enforce Adblock+ element hiding filters."
|
||||
"3pAutoUpdatePrompt1":{
|
||||
"message":"Mise à jour automatique des listes",
|
||||
"description":"English: Auto-update filter lists."
|
||||
},
|
||||
"3pParseAllABPHideFiltersPrompt2":{
|
||||
"message":"{{abpHideFilterCount}} règle(s) Adblock Plus esthétique(s) utilisée(s)",
|
||||
"description":"English: {{abpHideFilterCount}} element hiding filters used."
|
||||
"3pUpdateNow":{
|
||||
"message":"Mettre à jour",
|
||||
"description":"English: Update now"
|
||||
},
|
||||
"3pParseAllABPHideFiltersPrompt1":{
|
||||
"message":"Utiliser en plus les règles esthétiques",
|
||||
"description":"English: Parse and enforce cosmetic filters."
|
||||
},
|
||||
"3pParseAllABPHideFiltersInfo":{
|
||||
"message":"<p>Cette option permet de prendre en charge les filtres AdblockPlus de type <a href=\"https:\/\/adblockplus.org\/en\/faq_internal#elemhide\">“element hiding”<\/a>. Ces filtres ont principalement un impact visuel, servant à dissimuler des éléments nuisibles d'une page Web et qui ne sont pas blocables par le filtrage standard.<\/p><p>L'activation de cette fonctionnalité augmente l'empreinte mémoire de <i>µBlock<\/i><\/p>",
|
||||
|
@ -159,6 +163,14 @@
|
|||
"message":"vider le cache",
|
||||
"description":"English: purge cache"
|
||||
},
|
||||
"3pExternalListNew":{
|
||||
"message":"nouvelle version disponible",
|
||||
"description":"English: new version available"
|
||||
},
|
||||
"3pExternalListObsolete":{
|
||||
"message":"potentiellement désuet",
|
||||
"description":"English: may be obsolete"
|
||||
},
|
||||
"1pFormatHint":{
|
||||
"message":"Une règle par ligne. Une règle peut être un simple nom d'hôte, ou encore un filtre respectant la syntaxe des filtres Adblock Plus. Les lignes débutant par ‘!’ seront ignorées.",
|
||||
"description":"English: One filter per line. A filter can be a plain hostname, or an Adblock Plus-compatible filter. Lines prefixed with ‘!’ will be ignored."
|
||||
|
|
74
about.html
74
about.html
|
@ -6,46 +6,8 @@
|
|||
<link rel="stylesheet" type="text/css" href="css/common.css">
|
||||
<link rel="stylesheet" type="text/css" href="css/dashboard-common.css">
|
||||
<style>
|
||||
table th {
|
||||
text-align: left;
|
||||
}
|
||||
table td:first-child {
|
||||
padding-right: 2em;
|
||||
}
|
||||
#allLocalAssetsUpdated {
|
||||
margin-left: 1em;
|
||||
color: green;
|
||||
}
|
||||
#assetList table tr.unchanged {
|
||||
color: gray;
|
||||
}
|
||||
#assetList table tr td:nth-of-type(2) {
|
||||
font-weight: bold;
|
||||
white-space: nowrap;
|
||||
}
|
||||
#assetList table tr.unchanged td:nth-of-type(2) {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
#assetList.ooo > table {
|
||||
display: none;
|
||||
}
|
||||
#assetList.oox > table,
|
||||
#assetList.oxx > table,
|
||||
#assetList.xxx > table {
|
||||
display: block;
|
||||
}
|
||||
#assetList > p {
|
||||
display: none;
|
||||
}
|
||||
#assetList.ooo > p.ooo {
|
||||
display: block;
|
||||
}
|
||||
#assetList.oxx > p.oxx {
|
||||
display: block;
|
||||
}
|
||||
#assetList.xxx > p.xxx {
|
||||
display: block;
|
||||
ul {
|
||||
padding-left: 1em;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
@ -53,38 +15,14 @@ table td:first-child {
|
|||
<body>
|
||||
|
||||
<h2>µBlock <span id="aboutVersion"></span></h2>
|
||||
<div>
|
||||
<a href="https://github.com/gorhill/uBlock/releases" data-i18n="aboutChangelog"></a><br>
|
||||
<a href="https://github.com/gorhill/ublock" data-i18n="aboutCode"></a><br>
|
||||
</div>
|
||||
|
||||
<h2 data-i18n="aboutExtensionDataHeader"></h2>
|
||||
<div>
|
||||
<p class="para" data-i18n="aboutAssetsUpdatePrompt"></p>
|
||||
<div id="assetList">
|
||||
<!--
|
||||
Let's define 'abc' as bit 0 to 2
|
||||
Where bit can be '0' or '1'
|
||||
Bit 0: list => o=absent, x=present
|
||||
Bit 1: list => o=clean, x=dirty
|
||||
Bit 2: update => o=idle, x=updating
|
||||
Therefore:
|
||||
List visible: oox oxx xox
|
||||
Etc.
|
||||
-->
|
||||
<table class="ooo">
|
||||
<tr><th data-i18n="aboutAssetsUpdateColPath"><th data-i18n="aboutAssetsUpdateColStatus">
|
||||
</table>
|
||||
<p class="ooo" style="color:red" data-i18n="aboutAssetsUpdateGetListError"></p>
|
||||
<p class="oxx"><button type="button" id="aboutAssetsUpdateButton" data-i18n="aboutAssetsUpdateButton"></button></p>
|
||||
<p class="xxx"><button type="button" disabled data-i18n="aboutAssetsUpdatingButton"></button></p>
|
||||
</div>
|
||||
</div>
|
||||
<ul>
|
||||
<li><a href="https://github.com/gorhill/uBlock/releases" data-i18n="aboutChangelog"></a><br>
|
||||
<li><a href="https://github.com/gorhill/ublock" data-i18n="aboutCode"></a><br>
|
||||
</ul>
|
||||
|
||||
<script src="js/udom.js"></script>
|
||||
<script src="js/i18n.js"></script>
|
||||
<script src="js/dashboard-common.js"></script>
|
||||
<script src="js/messaging-client.js"></script>
|
||||
<script src="js/about.js"></script>
|
||||
|
||||
</body>
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
# your custom filters
|
|
@ -13,7 +13,6 @@
|
|||
<script src="js/liquid-dict.js"></script>
|
||||
<script src="js/utils.js"></script>
|
||||
<script src="js/assets.js"></script>
|
||||
<script src="js/asset-updater.js"></script>
|
||||
<script src="js/abp-filters.js"></script>
|
||||
<script src="js/abp-hide-filters.js"></script>
|
||||
<script src="js/ublock.js"></script>
|
||||
|
|
109
js/3p-filters.js
109
js/3p-filters.js
|
@ -31,6 +31,7 @@ var userListName = chrome.i18n.getMessage('1pPageName');
|
|||
var listDetails = {};
|
||||
var externalLists = '';
|
||||
var cacheWasPurged = false;
|
||||
var needUpdate = false;
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
|
@ -40,7 +41,6 @@ var onMessage = function(msg) {
|
|||
switch ( msg.what ) {
|
||||
case 'loadUbiquitousBlacklistCompleted':
|
||||
renderBlacklists();
|
||||
selectedBlacklistsChanged();
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -109,6 +109,8 @@ var renderBlacklists = function() {
|
|||
|
||||
var listStatsTemplate = chrome.i18n.getMessage('3pListsOfBlockedHostsPerListStats');
|
||||
var purgeButtontext = chrome.i18n.getMessage('3pExternalListPurge');
|
||||
var updateButtontext = chrome.i18n.getMessage('3pExternalListNew');
|
||||
var obsoleteButtontext = chrome.i18n.getMessage('3pExternalListObsolete');
|
||||
|
||||
var htmlFromBranch = function(groupKey, listKeys, lists) {
|
||||
var html = [
|
||||
|
@ -134,7 +136,7 @@ var renderBlacklists = function() {
|
|||
listStatsTemplate,
|
||||
'</span>'
|
||||
].join('');
|
||||
var listKey, list, listEntry;
|
||||
var listKey, list, listEntry, entryDetails;
|
||||
for ( var i = 0; i < listKeys.length; i++ ) {
|
||||
listKey = listKeys[i];
|
||||
list = lists[listKey];
|
||||
|
@ -146,12 +148,27 @@ var renderBlacklists = function() {
|
|||
.replace('{{total}}', !isNaN(+list.entryCount) ? renderNumber(list.entryCount) : '?');
|
||||
html.push(listEntry);
|
||||
// https://github.com/gorhill/uBlock/issues/104
|
||||
if ( /^https?:\/\/.+/.test(listKey) && listDetails.cache[listKey] ) {
|
||||
entryDetails = listDetails.cache[listKey];
|
||||
if ( entryDetails === undefined ) {
|
||||
continue;
|
||||
}
|
||||
// Update status
|
||||
if ( !list.off && (entryDetails.repoObsolete || entryDetails.cacheObsolete) ) {
|
||||
html.push(
|
||||
' ',
|
||||
'<button type="button" class="purge">',
|
||||
'<span class="status obsolete">',
|
||||
entryDetails.repoObsolete ? updateButtontext : obsoleteButtontext,
|
||||
'</span>'
|
||||
);
|
||||
needUpdate = true;
|
||||
}
|
||||
// In cache
|
||||
else if ( entryDetails.cached ) {
|
||||
html.push(
|
||||
' ',
|
||||
'<span class="status purge">',
|
||||
purgeButtontext,
|
||||
'</button>'
|
||||
'</span>'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -159,6 +176,8 @@ var renderBlacklists = function() {
|
|||
return html.join('');
|
||||
};
|
||||
|
||||
// https://www.youtube.com/watch?v=unCVi4hYRlY#t=30m18s
|
||||
|
||||
var groupsFromLists = function(lists) {
|
||||
var groups = {};
|
||||
var listKeys = Object.keys(lists);
|
||||
|
@ -178,6 +197,7 @@ var renderBlacklists = function() {
|
|||
|
||||
var onListsReceived = function(details) {
|
||||
listDetails = details;
|
||||
needUpdate = false;
|
||||
|
||||
var lists = details.available;
|
||||
var html = [];
|
||||
|
@ -208,13 +228,10 @@ var renderBlacklists = function() {
|
|||
|
||||
uDom('#lists .listDetails').remove();
|
||||
uDom('#lists').html(html.join(''));
|
||||
uDom('#parseAllABPHideFilters').prop('checked', listDetails.cosmetic === true);
|
||||
uDom('#ubiquitousParseAllABPHideFiltersPrompt2').text(
|
||||
chrome.i18n.getMessage("listsParseAllABPHideFiltersPrompt2")
|
||||
.replace('{{abpHideFilterCount}}', renderNumber(µb.abpHideFilters.getFilterCount()))
|
||||
);
|
||||
uDom('#autoUpdate').prop('checked', listDetails.autoUpdate === true);
|
||||
uDom('#parseCosmeticFilters').prop('checked', listDetails.cosmetic === true);
|
||||
uDom('a').attr('target', '_blank');
|
||||
selectedBlacklistsChanged();
|
||||
updateApplyButtons();
|
||||
};
|
||||
|
||||
messaging.ask({ what: 'getLists' }, onListsReceived);
|
||||
|
@ -222,9 +239,9 @@ var renderBlacklists = function() {
|
|||
|
||||
/******************************************************************************/
|
||||
|
||||
// Check whether lists need reloading.
|
||||
// Return whether selection of lists changed.
|
||||
|
||||
var needToReload = function() {
|
||||
var listsSelectionChanged = function() {
|
||||
if ( listDetails.cosmetic !== getµb().userSettings.parseAllABPHideFilters ) {
|
||||
return true;
|
||||
}
|
||||
|
@ -261,10 +278,19 @@ var needToReload = function() {
|
|||
|
||||
/******************************************************************************/
|
||||
|
||||
// Return whether content need update.
|
||||
|
||||
var listsContentChanged = function() {
|
||||
return needUpdate;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// This is to give a visual hint that the selection of blacklists has changed.
|
||||
|
||||
var selectedBlacklistsChanged = function() {
|
||||
uDom('#blacklistsApply').prop('disabled', !needToReload());
|
||||
var updateApplyButtons = function() {
|
||||
uDom('#buttonApply').toggleClass('enabled', listsSelectionChanged());
|
||||
uDom('#buttonUpdate').toggleClass('enabled', listsContentChanged());
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -278,7 +304,7 @@ var onListCheckboxChanged = function() {
|
|||
return;
|
||||
}
|
||||
listDetails.available[href].off = !this.checked;
|
||||
selectedBlacklistsChanged();
|
||||
updateApplyButtons();
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -295,22 +321,22 @@ var onListLinkClicked = function(ev) {
|
|||
|
||||
var onPurgeClicked = function(ev) {
|
||||
var button = uDom(this);
|
||||
var href = button.parent().find('a').first().attr('href');
|
||||
var li = button.parent();
|
||||
var href = li.find('a').first().attr('href');
|
||||
if ( !href ) {
|
||||
return;
|
||||
}
|
||||
messaging.tell({ what: 'purgeCache', path: href });
|
||||
button.remove();
|
||||
cacheWasPurged = true;
|
||||
selectedBlacklistsChanged();
|
||||
if ( li.find('input').first().prop('checked') ) {
|
||||
cacheWasPurged = true;
|
||||
updateApplyButtons();
|
||||
}
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var blacklistsApplyHandler = function() {
|
||||
if ( !needToReload() ) {
|
||||
return;
|
||||
}
|
||||
var reloadAll = function(update) {
|
||||
// Reload blacklists
|
||||
messaging.tell({
|
||||
what: 'userSettings',
|
||||
|
@ -334,17 +360,40 @@ var blacklistsApplyHandler = function() {
|
|||
}
|
||||
messaging.tell({
|
||||
what: 'reloadAllFilters',
|
||||
switches: switches
|
||||
switches: switches,
|
||||
update: update
|
||||
});
|
||||
cacheWasPurged = false;
|
||||
uDom('#blacklistsApply').prop('disabled', true);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var buttonApplyHandler = function() {
|
||||
reloadAll();
|
||||
uDom('#buttonApply').toggleClass('enabled', false);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var buttonUpdateHandler = function() {
|
||||
reloadAll(true);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var autoUpdateCheckboxChanged = function() {
|
||||
messaging.tell({
|
||||
what: 'userSettings',
|
||||
name: 'autoUpdate',
|
||||
value: this.checked
|
||||
});
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var abpHideFiltersCheckboxChanged = function() {
|
||||
listDetails.cosmetic = this.checked;
|
||||
selectedBlacklistsChanged();
|
||||
updateApplyButtons();
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -383,11 +432,13 @@ var externalListsApplyHandler = function() {
|
|||
|
||||
uDom.onLoad(function() {
|
||||
// Handle user interaction
|
||||
uDom('#parseAllABPHideFilters').on('change', abpHideFiltersCheckboxChanged);
|
||||
uDom('#blacklistsApply').on('click', blacklistsApplyHandler);
|
||||
uDom('#autoUpdate').on('change', autoUpdateCheckboxChanged);
|
||||
uDom('#parseCosmeticFilters').on('change', abpHideFiltersCheckboxChanged);
|
||||
uDom('#buttonApply').on('click', buttonApplyHandler);
|
||||
uDom('#buttonUpdate').on('click', buttonUpdateHandler);
|
||||
uDom('#lists').on('change', '.listDetails > input', onListCheckboxChanged);
|
||||
uDom('#lists').on('click', '.listDetails > a:nth-of-type(1)', onListLinkClicked);
|
||||
uDom('#lists').on('click', 'button.purge', onPurgeClicked);
|
||||
uDom('#lists').on('click', 'span.purge', onPurgeClicked);
|
||||
uDom('#externalLists').on('input', externalListsChangeHandler);
|
||||
uDom('#externalListsApply').on('click', externalListsApplyHandler);
|
||||
|
||||
|
|
88
js/about.js
88
js/about.js
|
@ -27,95 +27,7 @@ uDom.onLoad(function() {
|
|||
|
||||
/******************************************************************************/
|
||||
|
||||
var updateList = {};
|
||||
var assetListSwitches = ['o', 'o', 'o'];
|
||||
var commitHistoryURLPrefix = 'https://github.com/gorhill/ublock/commits/master/';
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var setAssetListClassBit = function(bit, state) {
|
||||
assetListSwitches[assetListSwitches.length-1-bit] = !state ? 'o' : 'x';
|
||||
uDom('#assetList')
|
||||
.removeClass()
|
||||
.addClass(assetListSwitches.join(''));
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var renderAssetList = function(details) {
|
||||
var dirty = false;
|
||||
var paths = Object.keys(details.list).sort();
|
||||
if ( paths.length > 0 ) {
|
||||
uDom('#assetList .assetEntry').remove();
|
||||
var i = 0;
|
||||
var path, status, html = [];
|
||||
while ( path = paths[i++] ) {
|
||||
status = details.list[path].status;
|
||||
dirty = dirty || status !== 'Unchanged';
|
||||
html.push(
|
||||
'<tr class="assetEntry ' + status.toLowerCase().replace(/ +/g, '-') + '">',
|
||||
'<td>',
|
||||
'<a href="' + commitHistoryURLPrefix + path + '">',
|
||||
path.replace(/^(assets\/[^/]+\/)(.+)$/, '$1<b>$2</b>'),
|
||||
'</a>',
|
||||
'<td>',
|
||||
chrome.i18n.getMessage('aboutAssetsUpdateStatus' + status)
|
||||
);
|
||||
}
|
||||
uDom('#assetList table tBody').append(html.join(''));
|
||||
uDom('#assetList a').attr('target', '_blank');
|
||||
updateList = details.list;
|
||||
}
|
||||
setAssetListClassBit(0, paths.length !== 0);
|
||||
setAssetListClassBit(1, dirty);
|
||||
setAssetListClassBit(2, false);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var updateAssets = function() {
|
||||
setAssetListClassBit(2, true);
|
||||
var onDone = function(details) {
|
||||
if ( details.changedCount !== 0 ) {
|
||||
messaging.tell({ what: 'loadUpdatableAssets' });
|
||||
}
|
||||
};
|
||||
messaging.ask({ what: 'launchAssetUpdater', list: updateList }, onDone);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var updateAssetsList = function() {
|
||||
messaging.ask({ what: 'getAssetUpdaterList' }, renderAssetList);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// Updating all assets could be done from elsewhere and if so the
|
||||
// list here needs to be updated.
|
||||
|
||||
var onAnnounce = function(msg) {
|
||||
switch ( msg.what ) {
|
||||
case 'allLocalAssetsUpdated':
|
||||
updateAssetsList();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
messaging.start('about.js');
|
||||
messaging.listen(onAnnounce);
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
uDom('#aboutVersion').html(chrome.runtime.getManifest().version);
|
||||
uDom('#aboutAssetsUpdateButton').on('click', updateAssets);
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
updateAssetsList();
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
|
|
|
@ -1,227 +0,0 @@
|
|||
/*******************************************************************************
|
||||
|
||||
µBlock - a Chromium browser extension to block requests.
|
||||
Copyright (C) 2014 Raymond Hill
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see {http://www.gnu.org/licenses/}.
|
||||
|
||||
Home: https://github.com/gorhill/uBlock
|
||||
*/
|
||||
|
||||
/* global chrome, µBlock */
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// Asset update manager
|
||||
|
||||
µBlock.assetUpdater = (function() {
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var getUpdateList = function(callback) {
|
||||
var localChecksumsText = '';
|
||||
var remoteChecksumsText = '';
|
||||
|
||||
var compareChecksums = function() {
|
||||
var parseChecksumsText = function(text) {
|
||||
var result = {};
|
||||
var lines = text.split(/\n+/);
|
||||
var i = lines.length;
|
||||
var fields;
|
||||
while ( i-- ) {
|
||||
fields = lines[i].trim().split(/\s+/);
|
||||
if ( fields.length !== 2 ) {
|
||||
continue;
|
||||
}
|
||||
result[fields[1]] = fields[0];
|
||||
}
|
||||
return result;
|
||||
};
|
||||
if ( remoteChecksumsText === 'Error' || localChecksumsText === 'Error' ) {
|
||||
remoteChecksumsText = localChecksumsText = '';
|
||||
}
|
||||
var localAssetChecksums = parseChecksumsText(localChecksumsText);
|
||||
var remoteAssetChecksums = parseChecksumsText(remoteChecksumsText);
|
||||
|
||||
var toUpdate = {};
|
||||
var path;
|
||||
for ( path in remoteAssetChecksums ) {
|
||||
if ( !remoteAssetChecksums.hasOwnProperty(path) ) {
|
||||
continue;
|
||||
}
|
||||
if ( localAssetChecksums[path] === undefined ) {
|
||||
toUpdate[path] = {
|
||||
status: 'Added',
|
||||
remoteChecksum: remoteAssetChecksums[path],
|
||||
localChecksum: ''
|
||||
};
|
||||
continue;
|
||||
}
|
||||
if ( localAssetChecksums[path] === remoteAssetChecksums[path] ) {
|
||||
toUpdate[path] = {
|
||||
status: 'Unchanged',
|
||||
remoteChecksum: remoteAssetChecksums[path],
|
||||
localChecksum: localAssetChecksums[path]
|
||||
};
|
||||
continue;
|
||||
}
|
||||
toUpdate[path] = {
|
||||
status: 'Changed',
|
||||
remoteChecksum: remoteAssetChecksums[path],
|
||||
localChecksum: localAssetChecksums[path]
|
||||
};
|
||||
}
|
||||
for ( path in localAssetChecksums ) {
|
||||
if ( !localAssetChecksums.hasOwnProperty(path) ) {
|
||||
continue;
|
||||
}
|
||||
if ( remoteAssetChecksums[path] === undefined ) {
|
||||
toUpdate[path] = {
|
||||
status: 'Removed',
|
||||
remoteChecksum: '',
|
||||
localChecksum: localAssetChecksums[path]
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
callback({ 'list': toUpdate });
|
||||
};
|
||||
|
||||
var validateChecksums = function(details) {
|
||||
if ( details.error || details.content === '' ) {
|
||||
return 'Error';
|
||||
}
|
||||
if ( /^(?:[0-9a-f]{32}\s+\S+(\s+|$))+/.test(details.content) ) {
|
||||
return details.content;
|
||||
}
|
||||
return 'Error';
|
||||
};
|
||||
|
||||
var onLocalChecksumsLoaded = function(details) {
|
||||
localChecksumsText = validateChecksums(details);
|
||||
if ( remoteChecksumsText !== '' ) {
|
||||
compareChecksums();
|
||||
}
|
||||
};
|
||||
|
||||
var onRemoteChecksumsLoaded = function(details) {
|
||||
remoteChecksumsText = validateChecksums(details);
|
||||
if ( localChecksumsText !== '' ) {
|
||||
compareChecksums();
|
||||
}
|
||||
};
|
||||
|
||||
µBlock.assets.getRepo('assets/checksums.txt', onRemoteChecksumsLoaded);
|
||||
µBlock.assets.get('assets/checksums.txt', onLocalChecksumsLoaded);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// If `list` is null, it will be fetched internally.
|
||||
|
||||
var update = function(list, callback) {
|
||||
var assetChangedCount = 0;
|
||||
var assetProcessedCount;
|
||||
var updatedAssetChecksums = [];
|
||||
|
||||
var onCompleted = function() {
|
||||
var details = {
|
||||
what: 'allLocalAssetsUpdated',
|
||||
changedCount: assetChangedCount
|
||||
};
|
||||
callback(details);
|
||||
µBlock.messaging.announce(details);
|
||||
};
|
||||
|
||||
var doCountdown = function() {
|
||||
assetProcessedCount -= 1;
|
||||
if ( assetProcessedCount > 0 ) {
|
||||
return;
|
||||
}
|
||||
µBlock.assets.put(
|
||||
'assets/checksums.txt',
|
||||
updatedAssetChecksums.join('\n'),
|
||||
onCompleted
|
||||
);
|
||||
chrome.storage.local.set({ 'assetsUpdateTimestamp': Date.now() });
|
||||
};
|
||||
|
||||
var assetUpdated = function(details) {
|
||||
var path = details.path;
|
||||
var entry = list[path];
|
||||
if ( details.error ) {
|
||||
updatedAssetChecksums.push(entry.localChecksum + ' ' + path);
|
||||
} else {
|
||||
updatedAssetChecksums.push(entry.remoteChecksum + ' ' + path);
|
||||
assetChangedCount += 1;
|
||||
}
|
||||
doCountdown();
|
||||
};
|
||||
|
||||
var processList = function() {
|
||||
assetProcessedCount = Object.keys(list).length;
|
||||
if ( assetProcessedCount === 0 ) {
|
||||
onCompleted();
|
||||
return;
|
||||
}
|
||||
var entry;
|
||||
var details = { path: '', md5: '' };
|
||||
for ( var path in list ) {
|
||||
if ( list.hasOwnProperty(path) === false ) {
|
||||
continue;
|
||||
}
|
||||
entry = list[path];
|
||||
if ( entry.status === 'Added' || entry.status === 'Changed' ) {
|
||||
details.path = path;
|
||||
details.md5 = entry.remoteChecksum;
|
||||
µBlock.assets.update(details, assetUpdated);
|
||||
continue;
|
||||
}
|
||||
if ( entry.status === 'Unchanged' ) {
|
||||
updatedAssetChecksums.push(entry.localChecksum + ' ' + path);
|
||||
}
|
||||
doCountdown();
|
||||
}
|
||||
};
|
||||
|
||||
var listLoaded = function(details) {
|
||||
list = details.list;
|
||||
processList();
|
||||
};
|
||||
|
||||
// Purge obsolete external assets
|
||||
µBlock.assets.purge(/^https?:\/\/.+$/, Date.now() - µBlock.updateAssetsEvery);
|
||||
|
||||
if ( list ) {
|
||||
processList();
|
||||
} else {
|
||||
getUpdateList(listLoaded);
|
||||
}
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// Export API
|
||||
|
||||
return {
|
||||
'getList': getUpdateList,
|
||||
'update': update
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
})();
|
||||
|
||||
/******************************************************************************/
|
||||
|
1007
js/assets.js
1007
js/assets.js
File diff suppressed because it is too large
Load Diff
|
@ -31,6 +31,7 @@ return {
|
|||
manifest: chrome.runtime.getManifest(),
|
||||
|
||||
userSettings: {
|
||||
autoUpdate: true,
|
||||
collapseBlocked: true,
|
||||
externalLists: '',
|
||||
logBlockedRequests: false,
|
||||
|
|
|
@ -250,9 +250,10 @@ var getLists = function(callback) {
|
|||
available: null,
|
||||
current: µb.remoteBlacklists,
|
||||
cosmetic: µb.userSettings.parseAllABPHideFilters,
|
||||
autoUpdate: µb.userSettings.autoUpdate,
|
||||
cache: null
|
||||
};
|
||||
var onEntries = function(entries) {
|
||||
var onMetadataReady = function(entries) {
|
||||
r.cache = entries;
|
||||
if ( r.available ) {
|
||||
callback(r);
|
||||
|
@ -265,7 +266,7 @@ var getLists = function(callback) {
|
|||
}
|
||||
};
|
||||
µb.getAvailableLists(onLists);
|
||||
µb.assets.entries(onEntries);
|
||||
µb.assets.metadata(onMetadataReady);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -475,20 +476,6 @@ var onMessage = function(request, sender, callback) {
|
|||
|
||||
// Async
|
||||
switch ( request.what ) {
|
||||
case 'getAssetUpdaterList':
|
||||
return µb.assetUpdater.getList(callback);
|
||||
|
||||
case 'launchAssetUpdater':
|
||||
return µb.assetUpdater.update(request.list, callback);
|
||||
|
||||
case 'readUserSettings':
|
||||
return chrome.storage.local.get(µb.userSettings, callback);
|
||||
|
||||
case 'readUserFilters':
|
||||
return µb.assets.get(µb.userFiltersPath, callback);
|
||||
|
||||
case 'writeUserFilters':
|
||||
return µb.assets.put(µb.userFiltersPath, request.content, callback);
|
||||
|
||||
default:
|
||||
break;
|
||||
|
@ -498,20 +485,6 @@ var onMessage = function(request, sender, callback) {
|
|||
var response;
|
||||
|
||||
switch ( request.what ) {
|
||||
case 'loadUpdatableAssets':
|
||||
response = µb.loadUpdatableAssets();
|
||||
break;
|
||||
|
||||
case 'readFilterListSelection':
|
||||
response = µb.remoteBlacklists;
|
||||
break;
|
||||
|
||||
case 'getSomeStats':
|
||||
response = {
|
||||
storageQuota: µb.storageQuota,
|
||||
storageUsed: µb.storageUsed
|
||||
};
|
||||
break;
|
||||
|
||||
default:
|
||||
return µb.messaging.defaultHandler(request, sender, callback);
|
||||
|
@ -524,4 +497,6 @@ var onMessage = function(request, sender, callback) {
|
|||
|
||||
})();
|
||||
|
||||
// https://www.youtube.com/watch?v=3_WcygKJP1k
|
||||
|
||||
/******************************************************************************/
|
||||
|
|
|
@ -132,15 +132,12 @@ var onMessage = function(request, port) {
|
|||
|
||||
/******************************************************************************/
|
||||
|
||||
// Default is for commonly used message.
|
||||
// Default is for commonly used messages.
|
||||
|
||||
function defaultHandler(request, sender, callback) {
|
||||
// Async
|
||||
switch ( request.what ) {
|
||||
case 'getAssetContent':
|
||||
if ( /^https?:\/\//.test(request.url) ) {
|
||||
return µBlock.assets.getExternal(request.url, callback);
|
||||
}
|
||||
return µBlock.assets.get(request.url, callback);
|
||||
|
||||
case 'loadUbiquitousAllowRules':
|
||||
|
@ -171,7 +168,7 @@ function defaultHandler(request, sender, callback) {
|
|||
break;
|
||||
|
||||
case 'reloadAllFilters':
|
||||
µBlock.reloadPresetBlacklists(request.switches);
|
||||
µBlock.reloadPresetBlacklists(request.switches, request.update);
|
||||
break;
|
||||
|
||||
case 'userSettings':
|
||||
|
@ -186,6 +183,8 @@ function defaultHandler(request, sender, callback) {
|
|||
callback(response);
|
||||
}
|
||||
|
||||
// https://www.youtube.com/watch?v=rrzRgUAHqc8
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// Port disconnected, relay this information to apropriate listener.
|
||||
|
|
|
@ -218,7 +218,7 @@ PageStore.prototype.updateBadgeFromTab = function(tab) {
|
|||
|
||||
var iconStr = '';
|
||||
if ( µb.userSettings.showIconBadge && netFiltering && this.perLoadBlockedRequestCount ) {
|
||||
iconStr = this.perLoadBlockedRequestCount.toLocaleString();
|
||||
iconStr = µb.utils.formatCount(this.perLoadBlockedRequestCount);
|
||||
}
|
||||
chrome.browserAction.setBadgeText({ tabId: tab.id, text: iconStr });
|
||||
|
||||
|
@ -234,6 +234,8 @@ PageStore.prototype.updateBadge = function() {
|
|||
chrome.tabs.get(this.tabId, this.updateBadgeFromTab.bind(this));
|
||||
};
|
||||
|
||||
// https://www.youtube.com/watch?v=drW8p_dTLD4
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
return {
|
||||
|
|
13
js/start.js
13
js/start.js
|
@ -35,18 +35,17 @@
|
|||
(function() {
|
||||
var µb = µBlock;
|
||||
|
||||
var jobDone = function(details) {
|
||||
if ( details.changedCount === 0 ) {
|
||||
var jobCallback = function() {
|
||||
if ( µb.userSettings.autoUpdate !== true ) {
|
||||
return;
|
||||
}
|
||||
µb.loadUpdatableAssets();
|
||||
};
|
||||
|
||||
var jobCallback = function() {
|
||||
µb.assetUpdater.update(null, jobDone);
|
||||
// TODO: need smarter update, currently blindly reloading all.
|
||||
µb.loadUpdatableAssets(true);
|
||||
};
|
||||
|
||||
µb.asyncJobs.add('autoUpdateAssets', null, jobCallback, µb.updateAssetsEvery, true);
|
||||
})();
|
||||
|
||||
// https://www.youtube.com/watch?v=cIrGQD84F1g
|
||||
|
||||
/******************************************************************************/
|
||||
|
|
|
@ -70,7 +70,7 @@
|
|||
|
||||
/******************************************************************************/
|
||||
|
||||
µBlock.loadUserSettings = function() {
|
||||
µBlock.loadUserSettings = function(callback) {
|
||||
var settingsLoaded = function(store) {
|
||||
var µb = µBlock;
|
||||
// Backward compatibility after fix to #5
|
||||
|
@ -88,6 +88,8 @@
|
|||
µb.userSettings = store;
|
||||
µb.netWhitelist = µb.whitelistFromString(store.netWhitelist);
|
||||
µb.netWhitelistModifyTime = Date.now();
|
||||
|
||||
callback();
|
||||
};
|
||||
|
||||
chrome.storage.local.get(this.userSettings, settingsLoaded);
|
||||
|
@ -265,11 +267,7 @@
|
|||
blacklistLoadCount -= 1;
|
||||
continue;
|
||||
}
|
||||
if ( /^https?:\/\/.+$/.test(location) ) {
|
||||
µb.assets.getExternal(location, mergeBlacklist);
|
||||
} else {
|
||||
µb.assets.get(location, mergeBlacklist);
|
||||
}
|
||||
µb.assets.get(location, mergeBlacklist);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -400,7 +398,7 @@
|
|||
// `switches` contains the preset blacklists for which the switch must be
|
||||
// revisited.
|
||||
|
||||
µBlock.reloadPresetBlacklists = function(switches) {
|
||||
µBlock.reloadPresetBlacklists = function(switches, update) {
|
||||
var presetBlacklists = this.remoteBlacklists;
|
||||
|
||||
// Toggle switches, if any
|
||||
|
@ -420,7 +418,7 @@
|
|||
}
|
||||
|
||||
// Now force reload
|
||||
this.loadUbiquitousBlacklists();
|
||||
this.loadUpdatableAssets(update);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -443,9 +441,11 @@
|
|||
|
||||
// Load updatable assets
|
||||
|
||||
µBlock.loadUpdatableAssets = function() {
|
||||
this.loadUbiquitousBlacklists();
|
||||
µBlock.loadUpdatableAssets = function(update) {
|
||||
this.assets.autoUpdate = update;
|
||||
this.assets.autoUpdateDelay = this.updateAssetsEvery;
|
||||
this.loadPublicSuffixList();
|
||||
this.loadUbiquitousBlacklists();
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -453,11 +453,8 @@
|
|||
// Load all
|
||||
|
||||
µBlock.load = function() {
|
||||
this.loadLocalSettings();
|
||||
this.loadUserSettings();
|
||||
|
||||
// load updatable assets -- after updating them if needed
|
||||
this.assetUpdater.update(null, this.loadUpdatableAssets.bind(this));
|
||||
|
||||
// User settings need to be available for this because we need
|
||||
// µBlock.userSettings.externalLists
|
||||
this.loadUserSettings(this.loadUpdatableAssets.bind(this, this.userSettings.autoUpdate));
|
||||
this.getBytesInUse();
|
||||
};
|
||||
|
|
21
js/ublock.js
21
js/ublock.js
|
@ -233,24 +233,3 @@
|
|||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
µBlock.formatCount = function(count) {
|
||||
if ( typeof count !== 'number' ) {
|
||||
return '';
|
||||
}
|
||||
var s = count.toFixed(0);
|
||||
if ( count >= 1000 ) {
|
||||
if ( count < 10000 ) {
|
||||
s = '>' + s.slice(0,1) + 'K';
|
||||
} else if ( count < 100000 ) {
|
||||
s = s.slice(0,2) + 'K';
|
||||
} else if ( count < 1000000 ) {
|
||||
s = s.slice(0,3) + 'K';
|
||||
} else if ( count < 10000000 ) {
|
||||
s = s.slice(0,1) + 'M';
|
||||
} else {
|
||||
s = s.slice(0,-6) + 'M';
|
||||
}
|
||||
}
|
||||
return s;
|
||||
};
|
||||
|
|
36
js/utils.js
36
js/utils.js
|
@ -29,7 +29,11 @@
|
|||
|
||||
/******************************************************************************/
|
||||
|
||||
var gotoURL = function(details) {
|
||||
var exports = {};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
exports.gotoURL = function(details) {
|
||||
if ( details.tabId ) {
|
||||
chrome.tabs.update(details.tabId, { url: details.url });
|
||||
} else {
|
||||
|
@ -39,7 +43,7 @@ var gotoURL = function(details) {
|
|||
|
||||
/******************************************************************************/
|
||||
|
||||
var gotoExtensionURL = function(url) {
|
||||
exports.gotoExtensionURL = function(url) {
|
||||
|
||||
var hasQuery = function(url) {
|
||||
return url.indexOf('?') >= 0;
|
||||
|
@ -98,11 +102,33 @@ var gotoExtensionURL = function(url) {
|
|||
|
||||
/******************************************************************************/
|
||||
|
||||
return {
|
||||
gotoURL: gotoURL,
|
||||
gotoExtensionURL: gotoExtensionURL
|
||||
exports.formatCount = function(count) {
|
||||
if ( typeof count !== 'number' ) {
|
||||
return '';
|
||||
}
|
||||
var s = count.toFixed(0);
|
||||
if ( count >= 1000 ) {
|
||||
if ( count < 10000 ) {
|
||||
s = '>' + s.slice(0,1) + 'K';
|
||||
} else if ( count < 100000 ) {
|
||||
s = s.slice(0,2) + 'K';
|
||||
} else if ( count < 1000000 ) {
|
||||
s = s.slice(0,3) + 'K';
|
||||
} else if ( count < 10000000 ) {
|
||||
s = s.slice(0,1) + 'M';
|
||||
} else {
|
||||
s = s.slice(0,-6) + 'M';
|
||||
}
|
||||
}
|
||||
return s;
|
||||
};
|
||||
|
||||
// https://www.youtube.com/watch?v=uvUW4ozs7pY
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
return exports;
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
})();
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"manifest_version": 2,
|
||||
"name": "__MSG_extName__",
|
||||
"short_name": "µBlock",
|
||||
"version": "0.4.0.1",
|
||||
"version": "0.4.0.2",
|
||||
"description": "__MSG_extShortDesc__",
|
||||
"icons": {
|
||||
"16": "img/icon_16.png",
|
||||
|
|
Loading…
Reference in New Issue